diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client.gen.ts new file mode 100644 index 0000000000..cab3c70195 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client.gen.ts @@ -0,0 +1,16 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { type ClientOptions, type Config, createClient, createConfig } from './client'; +import type { ClientOptions as ClientOptions2 } from './types.gen'; + +/** + * 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 = (override?: Config) => Config & T>; + +export const client = createClient(createConfig()); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client/client.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client/client.gen.ts new file mode 100644 index 0000000000..fc3f037f16 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client/client.gen.ts @@ -0,0 +1,277 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { createSseClient } from '../core/serverSentEvents.gen'; +import type { HttpMethod } from '../core/types.gen'; +import { getValidRequestBody } from '../core/utils.gen'; +import type { Client, Config, RequestOptions, ResolvedRequestOptions } from './types.gen'; +import { + buildUrl, + createConfig, + createInterceptors, + getParseAs, + mergeConfigs, + mergeHeaders, + setAuthParams, +} from './utils.gen'; + +type ReqInit = Omit & { + body?: any; + headers: ReturnType; +}; + +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(); + + const beforeRequest = async < + TData = unknown, + TResponseStyle extends 'data' | 'fields' = 'fields', + ThrowOnError extends boolean = boolean, + Url extends string = string, + >( + options: RequestOptions, + ) => { + const opts = { + ..._config, + ...options, + fetch: options.fetch ?? _config.fetch ?? globalThis.fetch, + headers: mergeHeaders(_config.headers, options.headers), + serializedBody: undefined as string | undefined, + }; + + if (opts.security) { + await setAuthParams(opts); + } + + if (opts.requestValidator) { + await opts.requestValidator(opts); + } + + if (opts.body !== undefined && opts.bodySerializer) { + opts.serializedBody = opts.bodySerializer(opts.body) as string | undefined; + } + + // 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 resolvedOpts = opts as typeof opts & + ResolvedRequestOptions; + const url = buildUrl(resolvedOpts); + + return { opts: resolvedOpts, url }; + }; + + const request: Client['request'] = async (options) => { + const throwOnError = options.throwOnError ?? _config.throwOnError; + const responseStyle = options.responseStyle ?? _config.responseStyle; + + let request: Request | undefined; + let response: Response | undefined; + + try { + const { opts, url } = await beforeRequest(options); + const requestInit: ReqInit = { + redirect: 'follow', + ...opts, + body: getValidRequestBody(opts), + }; + + 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!; + + response = await _fetch(request); + + for (const fn of interceptors.response.fns) { + if (fn) { + response = await fn(response, request, opts); + } + } + + const result = { + request, + response, + }; + + if (response.ok) { + 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 'text': + data = await response[parseAs](); + break; + case 'json': { + // Some servers return 200 with no Content-Length and empty body. + // response.json() would throw; read as text and parse if non-empty. + const text = await response.text(); + data = text ? JSON.parse(text) : {}; + 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 + } + + throw jsonError ?? textError; + } catch (error) { + let finalError = error; + + for (const fn of interceptors.error.fns) { + if (fn) { + finalError = await fn(finalError, response, request, options as ResolvedRequestOptions); + } + } + + finalError = finalError || {}; + + if (throwOnError) { + throw finalError; + } + + // TODO: we probably want to return error and improve types + return responseStyle === 'data' + ? undefined + : { + error: finalError, + request, + response, + }; + } + }; + + const makeMethodFn = (method: Uppercase) => (options: RequestOptions) => + request({ ...options, method }); + + const makeSseFn = (method: Uppercase) => async (options: RequestOptions) => { + const { opts, url } = await beforeRequest(options); + return createSseClient({ + ...opts, + body: opts.body as BodyInit | null | undefined, + 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; + }, + serializedBody: getValidRequestBody(opts) as BodyInit | null | undefined, + url, + }); + }; + + const _buildUrl: Client['buildUrl'] = (options) => buildUrl({ ..._config, ...options }); + + return { + buildUrl: _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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client/index.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client/index.ts new file mode 100644 index 0000000000..b295edeca0 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client/index.ts @@ -0,0 +1,25 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type { Auth } from '../core/auth.gen'; +export type { QuerySerializerOptions } from '../core/bodySerializer.gen'; +export { + formDataBodySerializer, + jsonBodySerializer, + urlSearchParamsBodySerializer, +} from '../core/bodySerializer.gen'; +export { buildClientParams } from '../core/params.gen'; +export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen'; +export { createClient } from './client.gen'; +export type { + Client, + ClientOptions, + Config, + CreateClientConfig, + Options, + RequestOptions, + RequestResult, + ResolvedRequestOptions, + ResponseStyle, + TDataShape, +} from './types.gen'; +export { createConfig, mergeHeaders } from './utils.gen'; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client/types.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client/types.gen.ts new file mode 100644 index 0000000000..193646cddf --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client/types.gen.ts @@ -0,0 +1,218 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth } from '../core/auth.gen'; +import type { + ServerSentEventsOptions, + ServerSentEventsResult, +} from '../core/serverSentEvents.gen'; +import type { Client as CoreClient, Config as CoreConfig } from '../core/types.gen'; +import type { Middleware } from './utils.gen'; + +export type ResponseStyle = 'data' | 'fields'; + +export interface Config + extends Omit, 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, + | 'onRequest' + | '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; + query?: Record; + /** + * Security mechanism(s) to use for the request. + */ + security?: ReadonlyArray; + url: Url; +} + +export interface ResolvedRequestOptions< + TResponseStyle extends ResponseStyle = 'fields', + ThrowOnError extends boolean = boolean, + Url extends string = string, +> extends RequestOptions { + headers: Headers; + 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 + ? TData[keyof TData] + : TData + : { + data: TData extends Record ? TData[keyof TData] : TData; + request: Request; + response: Response; + } + > + : Promise< + TResponseStyle extends 'data' + ? (TData extends Record ? TData[keyof TData] : TData) | undefined + : ( + | { + data: TData extends Record ? TData[keyof TData] : TData; + error: undefined; + } + | { + data: undefined; + error: TError extends Record ? TError[keyof TError] : TError; + } + ) & { + /** request may be undefined, because error may be from building the request object itself */ + request?: Request; + /** response may be undefined, because error may be from building the request object itself or from a network error */ + 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, 'method'>, +) => RequestResult; + +type SseFn = < + TData = unknown, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = 'fields', +>( + options: Omit, 'method'>, +) => Promise>; + +type RequestFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = 'fields', +>( + options: Omit, 'method'> & + Pick>, 'method'>, +) => RequestResult; + +type BuildUrlFn = < + TData extends { + body?: unknown; + path?: Record; + query?: Record; + url: string; + }, +>( + options: TData & Options, +) => string; + +export type Client = CoreClient & { + interceptors: Middleware; +}; + +/** + * 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 = ( + override?: Config, +) => Config & T>; + +export interface TDataShape { + body?: unknown; + headers?: unknown; + path?: unknown; + query?: unknown; + url: string; +} + +type OmitKeys = Pick>; + +export type Options< + TData extends TDataShape = TDataShape, + ThrowOnError extends boolean = boolean, + TResponse = unknown, + TResponseStyle extends ResponseStyle = 'fields', +> = OmitKeys< + RequestOptions, + 'body' | 'path' | 'query' | 'url' +> & + ([TData] extends [never] ? unknown : Omit); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client/utils.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client/utils.gen.ts new file mode 100644 index 0000000000..7800fe4b9d --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/client/utils.gen.ts @@ -0,0 +1,316 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { getAuthToken } from '../core/auth.gen'; +import type { QuerySerializerOptions } from '../core/bodySerializer.gen'; +import { jsonBodySerializer } from '../core/bodySerializer.gen'; +import { + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from '../core/pathSerializer.gen'; +import { getUrl } from '../core/utils.gen'; +import type { Client, ClientOptions, Config, RequestOptions } from './types.gen'; + +export const createQuerySerializer = ({ + 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, + ...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 => { + 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 & { + 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 async function setAuthParams( + options: Pick & { + headers: Headers; + }, +): Promise { + for (const auth of options.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['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 = ( + error: Err, + /** response may be undefined due to a network error where no response object is produced */ + response: Res | undefined, + /** request may be undefined, because error may be from building the request object itself */ + request: Req | undefined, + options: Options, +) => Err | Promise; + +type ReqInterceptor = (request: Req, options: Options) => Req | Promise; + +type ResInterceptor = ( + response: Res, + request: Req, + options: Options, +) => Res | Promise; + +class Interceptors { + fns: Array = []; + + 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 { + error: Interceptors>; + request: Interceptors>; + response: Interceptors>; +} + +export const createInterceptors = (): Middleware< + Req, + Res, + Err, + Options +> => ({ + error: new Interceptors>(), + request: new Interceptors>(), + response: new Interceptors>(), +}); + +const defaultQuerySerializer = createQuerySerializer({ + allowReserved: false, + array: { + explode: true, + style: 'form', + }, + object: { + explode: true, + style: 'deepObject', + }, +}); + +const defaultHeaders = { + 'Content-Type': 'application/json', +}; + +export const createConfig = ( + override: Config & T> = {}, +): Config & T> => ({ + ...jsonBodySerializer, + headers: defaultHeaders, + parseAs: 'auto', + querySerializer: defaultQuerySerializer, + ...override, +}); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/auth.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/auth.gen.ts new file mode 100644 index 0000000000..3ebf994788 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/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, +): Promise => { + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/bodySerializer.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/bodySerializer.gen.ts new file mode 100644 index 0000000000..67daca60f8 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/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'; + +export type QuerySerializer = (query: Record) => string; + +export type BodySerializer = (body: unknown) => unknown; + +type QuerySerializerOptionsObject = { + allowReserved?: boolean; + array?: Partial>; + object?: Partial>; +}; + +export type QuerySerializerOptions = QuerySerializerOptionsObject & { + /** + * Per-parameter serialization overrides. When provided, these settings + * override the global array/object settings for specific parameter names. + */ + parameters?: Record; +}; + +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: (body: unknown): FormData => { + const data = new FormData(); + + Object.entries(body as Record).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: (body: unknown): string => + JSON.stringify(body, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)), +}; + +export const urlSearchParamsBodySerializer = { + bodySerializer: (body: unknown): string => { + const data = new URLSearchParams(); + + Object.entries(body as Record).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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/params.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/params.gen.ts new file mode 100644 index 0000000000..6478519bcb --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/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; + /** + * 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; + /** + * 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>; + args?: ReadonlyArray; +} + +export type FieldsConfig = ReadonlyArray; + +const extraPrefixesMap: Record = { + $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; + path: Record; + query: Record; +} + +const stripEmptySlots = (params: Params) => { + for (const [slot, value] of Object.entries(params)) { + if (value && typeof value === 'object' && !Array.isArray(value) && !Object.keys(value).length) { + delete params[slot as Slot]; + } + } +}; + +export const buildClientParams = (args: ReadonlyArray, fields: FieldsConfig) => { + const params: Params = { + body: Object.create(null), + headers: Object.create(null), + path: Object.create(null), + query: Object.create(null), + }; + + 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)[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)[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)[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)[key] = value; + break; + } + } + } + } + } + } + } + + stripEmptySlots(params); + + return params; +}; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/pathSerializer.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/pathSerializer.gen.ts new file mode 100644 index 0000000000..994b2848c6 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/pathSerializer.gen.ts @@ -0,0 +1,171 @@ +// This file is auto-generated by @hey-api/openapi-ts + +interface SerializeOptions extends SerializePrimitiveOptions, SerializerOptions {} + +interface SerializePrimitiveOptions { + allowReserved?: boolean; + name: string; +} + +export interface SerializerOptions { + /** + * @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 & { + 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 & { + value: Record | 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/queryKeySerializer.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/queryKeySerializer.gen.ts new file mode 100644 index 0000000000..5000df606f --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/queryKeySerializer.gen.ts @@ -0,0 +1,117 @@ +// 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 => { + 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 = {}; + + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/serverSentEvents.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/serverSentEvents.gen.ts new file mode 100644 index 0000000000..ddf3c4d13a --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/serverSentEvents.gen.ts @@ -0,0 +1,242 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Config } from './types.gen'; + +export type ServerSentEventsOptions = Omit & + Pick & { + /** + * 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; + /** + * 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) => 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; + url: string; + }; + +export interface StreamEvent { + data: TData; + event?: string; + id?: string; + retry?: number; +} + +export type ServerSentEventsResult = { + stream: AsyncGenerator< + TData extends Record ? TData[keyof TData] : TData, + TReturn, + TNext + >; +}; + +export function createSseClient({ + onRequest, + onSseError, + onSseEvent, + responseTransformer, + responseValidator, + sseDefaultRetryDelay, + sseMaxRetryAttempts, + sseMaxRetryDelay, + sseSleepFn, + url, + ...options +}: ServerSentEventsOptions): ServerSentEventsResult { + 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 | 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; + buffer = buffer.replace(/\r\n?/g, '\n'); // normalize line endings + + const chunks = buffer.split('\n\n'); + buffer = chunks.pop() ?? ''; + + for (const chunk of chunks) { + const lines = chunk.split('\n'); + const dataLines: Array = []; + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/types.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/types.gen.ts new file mode 100644 index 0000000000..9efe71d4c1 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/types.gen.ts @@ -0,0 +1,104 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth, AuthToken } from './auth.gen'; +import type { BodySerializer, QuerySerializer, QuerySerializerOptions } from './bodySerializer.gen'; + +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; + /** + * 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; + /** + * 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; + /** + * 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; + /** + * 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; +} + +type IsExactlyNeverOrNeverUndefined = [T] extends [never] + ? true + : [T] extends [never | undefined] + ? [undefined] extends [T] + ? false + : true + : false; + +export type OmitNever> = { + [K in keyof T as IsExactlyNeverOrNeverUndefined extends true ? never : K]: T[K]; +}; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/utils.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/utils.gen.ts new file mode 100644 index 0000000000..9a4fec7830 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/core/utils.gen.ts @@ -0,0 +1,140 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { BodySerializer, QuerySerializer } from './bodySerializer.gen'; +import { + type ArraySeparatorStyle, + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from './pathSerializer.gen'; + +export interface PathSerializer { + path: Record; + 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, + 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; + query?: Record; + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/index.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/index.ts new file mode 100644 index 0000000000..c5551b9aa3 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/index.ts @@ -0,0 +1,4 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export { App, Auth as Auth2, Auth2 as Auth22, Command as Command2, Config as Config2, Control, Default, Event_, File_, Find, Formatter, Global, Instance, Lsp, Mcp, Oauth, type Options, Part as Part2, Path as Path2, Permission, Project as Project2, Provider as Provider2, Pty as Pty2, Session as Session2, Session2 as Session22, Session3, Tool, Tui, Vcs } from './sdk.gen'; +export type { Agent, AgentConfig, AgentPart, AgentPartInput, ApiAuth, ApiError, AppAgentsData, AppAgentsResponse, AppAgentsResponses, AppLogData, AppLogError, AppLogErrors, AppLogResponse, AppLogResponses, AssistantMessage, Auth, AuthSetData, AuthSetError, AuthSetErrors, AuthSetResponse, AuthSetResponses, BadRequestError, ClientOptions, Command, CommandListData, CommandListResponse, CommandListResponses, CompactionPart, Config, ConfigGetData, ConfigGetResponse, ConfigGetResponses, ConfigProvidersData, ConfigProvidersResponse, ConfigProvidersResponses, ConfigUpdateData, ConfigUpdateError, ConfigUpdateErrors, ConfigUpdateResponse, ConfigUpdateResponses, Event, EventCommandExecuted, EventFileEdited, EventFileWatcherUpdated, EventGlobalDisposed, EventInstallationUpdateAvailable, EventInstallationUpdated, EventLspClientDiagnostics, EventLspUpdated, EventMcpToolsChanged, EventMessagePartRemoved, EventMessagePartUpdated, EventMessageRemoved, EventMessageUpdated, EventPermissionAsked, EventPermissionReplied, EventProjectUpdated, EventPtyCreated, EventPtyDeleted, EventPtyExited, EventPtyUpdated, EventServerConnected, EventServerInstanceDisposed, EventSessionCompacted, EventSessionCreated, EventSessionDeleted, EventSessionDiff, EventSessionError, EventSessionIdle, EventSessionStatus, EventSessionUpdated, EventSubscribeData, EventSubscribeResponse, EventSubscribeResponses, EventTodoUpdated, EventTuiCommandExecute, EventTuiPromptAppend, EventTuiToastShow, EventVcsBranchUpdated, File, FileContent, FileDiff, FileListData, FileListResponse, FileListResponses, FileNode, FilePart, FilePartInput, FilePartSource, FilePartSourceText, FileReadData, FileReadResponse, FileReadResponses, FileSource, FileStatusData, FileStatusResponse, FileStatusResponses, FindFilesData, FindFilesResponse, FindFilesResponses, FindSymbolsData, FindSymbolsResponse, FindSymbolsResponses, FindTextData, FindTextResponse, FindTextResponses, FormatterStatus, FormatterStatusData, FormatterStatusResponse, FormatterStatusResponses, GlobalDisposeData, GlobalDisposeResponse, GlobalDisposeResponses, GlobalEvent, GlobalEventData, GlobalEventResponse, GlobalEventResponses, GlobalHealthData, GlobalHealthResponse, GlobalHealthResponses, InstanceDisposeData, InstanceDisposeResponse, InstanceDisposeResponses, KeybindsConfig, LayoutConfig, LogLevel, LspStatus, LspStatusData, LspStatusResponse, LspStatusResponses, McpAddData, McpAddError, McpAddErrors, McpAddResponse, McpAddResponses, McpAuthAuthenticateData, McpAuthAuthenticateError, McpAuthAuthenticateErrors, McpAuthAuthenticateResponse, McpAuthAuthenticateResponses, McpAuthCallbackData, McpAuthCallbackError, McpAuthCallbackErrors, McpAuthCallbackResponse, McpAuthCallbackResponses, McpAuthRemoveData, McpAuthRemoveError, McpAuthRemoveErrors, McpAuthRemoveResponse, McpAuthRemoveResponses, McpAuthStartData, McpAuthStartError, McpAuthStartErrors, McpAuthStartResponse, McpAuthStartResponses, McpConnectData, McpConnectResponse, McpConnectResponses, McpDisconnectData, McpDisconnectResponse, McpDisconnectResponses, McpLocalConfig, McpOAuthConfig, McpRemoteConfig, McpStatus, McpStatusConnected, McpStatusData, McpStatusDisabled, McpStatusFailed, McpStatusNeedsAuth, McpStatusNeedsClientRegistration, McpStatusResponse, McpStatusResponses, Message, MessageAbortedError, MessageOutputLengthError, Model, NotFoundError, OAuth, Part, PartDeleteData, PartDeleteError, PartDeleteErrors, PartDeleteResponse, PartDeleteResponses, PartUpdateData, PartUpdateError, PartUpdateErrors, PartUpdateResponse, PartUpdateResponses, PatchPart, Path, PathGetData, PathGetResponse, PathGetResponses, PermissionAction, PermissionActionConfig, PermissionConfig, PermissionListData, PermissionListResponse, PermissionListResponses, PermissionObjectConfig, PermissionReplyData, PermissionReplyError, PermissionReplyErrors, PermissionReplyResponse, PermissionReplyResponses, PermissionRequest, PermissionRespondData, PermissionRespondError, PermissionRespondErrors, PermissionRespondResponse, PermissionRespondResponses, PermissionRule, PermissionRuleConfig, PermissionRuleset, Project, ProjectCurrentData, ProjectCurrentResponse, ProjectCurrentResponses, ProjectListData, ProjectListResponse, ProjectListResponses, ProjectUpdateData, ProjectUpdateError, ProjectUpdateErrors, ProjectUpdateResponse, ProjectUpdateResponses, Provider, ProviderAuthAuthorization, ProviderAuthData, ProviderAuthError, ProviderAuthMethod, ProviderAuthResponse, ProviderAuthResponses, ProviderConfig, ProviderListData, ProviderListResponse, ProviderListResponses, ProviderOauthAuthorizeData, ProviderOauthAuthorizeError, ProviderOauthAuthorizeErrors, ProviderOauthAuthorizeResponse, ProviderOauthAuthorizeResponses, ProviderOauthCallbackData, ProviderOauthCallbackError, ProviderOauthCallbackErrors, ProviderOauthCallbackResponse, ProviderOauthCallbackResponses, Pty, PtyConnectData, PtyConnectError, PtyConnectErrors, PtyConnectResponse, PtyConnectResponses, PtyCreateData, PtyCreateError, PtyCreateErrors, PtyCreateResponse, PtyCreateResponses, PtyGetData, PtyGetError, PtyGetErrors, PtyGetResponse, PtyGetResponses, PtyListData, PtyListResponse, PtyListResponses, PtyRemoveData, PtyRemoveError, PtyRemoveErrors, PtyRemoveResponse, PtyRemoveResponses, PtyUpdateData, PtyUpdateError, PtyUpdateErrors, PtyUpdateResponse, PtyUpdateResponses, Range, ReasoningPart, RetryPart, ServerConfig, Session, SessionAbortData, SessionAbortError, SessionAbortErrors, SessionAbortResponse, SessionAbortResponses, SessionChildrenData, SessionChildrenError, SessionChildrenErrors, SessionChildrenResponse, SessionChildrenResponses, SessionCommandData, SessionCommandError, SessionCommandErrors, SessionCommandResponse, SessionCommandResponses, SessionCreateData, SessionCreateError, SessionCreateErrors, SessionCreateResponse, SessionCreateResponses, SessionDeleteData, SessionDeleteError, SessionDeleteErrors, SessionDeleteResponse, SessionDeleteResponses, SessionDiffData, SessionDiffError, SessionDiffErrors, SessionDiffResponse, SessionDiffResponses, SessionForkData, SessionForkResponse, SessionForkResponses, SessionGetData, SessionGetError, SessionGetErrors, SessionGetResponse, SessionGetResponses, SessionInitData, SessionInitError, SessionInitErrors, SessionInitResponse, SessionInitResponses, SessionListData, SessionListResponse, SessionListResponses, SessionMessageData, SessionMessageError, SessionMessageErrors, SessionMessageResponse, SessionMessageResponses, SessionMessagesData, SessionMessagesError, SessionMessagesErrors, SessionMessagesResponse, SessionMessagesResponses, SessionPromptAsyncData, SessionPromptAsyncError, SessionPromptAsyncErrors, SessionPromptAsyncResponse, SessionPromptAsyncResponses, SessionPromptData, SessionPromptError, SessionPromptErrors, SessionPromptResponse, SessionPromptResponses, SessionRevertData, SessionRevertError, SessionRevertErrors, SessionRevertResponse, SessionRevertResponses, SessionShareData, SessionShareError, SessionShareErrors, SessionShareResponse, SessionShareResponses, SessionShellData, SessionShellError, SessionShellErrors, SessionShellResponse, SessionShellResponses, SessionStatus, SessionStatusData, SessionStatusError, SessionStatusErrors, SessionStatusResponse, SessionStatusResponses, SessionSummarizeData, SessionSummarizeError, SessionSummarizeErrors, SessionSummarizeResponse, SessionSummarizeResponses, SessionTodoData, SessionTodoError, SessionTodoErrors, SessionTodoResponse, SessionTodoResponses, SessionUnrevertData, SessionUnrevertError, SessionUnrevertErrors, SessionUnrevertResponse, SessionUnrevertResponses, SessionUnshareData, SessionUnshareError, SessionUnshareErrors, SessionUnshareResponse, SessionUnshareResponses, SessionUpdateData, SessionUpdateError, SessionUpdateErrors, SessionUpdateResponse, SessionUpdateResponses, SnapshotPart, StepFinishPart, StepStartPart, SubtaskPartInput, Symbol, SymbolSource, TextPart, TextPartInput, Todo, ToolIds, ToolIdsData, ToolIdsError, ToolIdsErrors, ToolIdsResponse, ToolIdsResponses, ToolList, ToolListData, ToolListError, ToolListErrors, ToolListItem, ToolListResponse, ToolListResponses, ToolPart, ToolState, ToolStateCompleted, ToolStateError, ToolStatePending, ToolStateRunning, TuiAppendPromptData, TuiAppendPromptError, TuiAppendPromptErrors, TuiAppendPromptResponse, TuiAppendPromptResponses, TuiClearPromptData, TuiClearPromptResponse, TuiClearPromptResponses, TuiControlNextData, TuiControlNextResponse, TuiControlNextResponses, TuiControlResponseData, TuiControlResponseResponse, TuiControlResponseResponses, TuiExecuteCommandData, TuiExecuteCommandError, TuiExecuteCommandErrors, TuiExecuteCommandResponse, TuiExecuteCommandResponses, TuiOpenHelpData, TuiOpenHelpResponse, TuiOpenHelpResponses, TuiOpenModelsData, TuiOpenModelsResponse, TuiOpenModelsResponses, TuiOpenSessionsData, TuiOpenSessionsResponse, TuiOpenSessionsResponses, TuiOpenThemesData, TuiOpenThemesResponse, TuiOpenThemesResponses, TuiPublishData, TuiPublishError, TuiPublishErrors, TuiPublishResponse, TuiPublishResponses, TuiShowToastData, TuiShowToastResponse, TuiShowToastResponses, TuiSubmitPromptData, TuiSubmitPromptResponse, TuiSubmitPromptResponses, UnknownError, UserMessage, VcsGetData, VcsGetResponse, VcsGetResponses, VcsInfo, WellKnownAuth } from './types.gen'; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/sdk.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/sdk.gen.ts new file mode 100644 index 0000000000..9a02df1545 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/sdk.gen.ts @@ -0,0 +1,2855 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import * as z from 'zod'; + +import { buildClientParams, type Client, type Options as Options2, type TDataShape } from './client'; +import { client } from './client.gen'; +import type { AgentPartInput, AppAgentsResponses, AppLogErrors, AppLogResponses, Auth as Auth3, AuthSetErrors, AuthSetResponses, CommandListResponses, Config as Config2, ConfigGetResponses, ConfigProvidersResponses, ConfigUpdateErrors, ConfigUpdateResponses, EventSubscribeResponse, EventSubscribeResponses, EventTuiCommandExecute, EventTuiPromptAppend, EventTuiToastShow, FileListResponses, FilePartInput, FileReadResponses, FileStatusResponses, FindFilesResponses, FindSymbolsResponses, FindTextResponses, FormatterStatusResponses, GlobalDisposeResponses, GlobalEventResponse, GlobalEventResponses, GlobalHealthResponses, InstanceDisposeResponses, LspStatusResponses, McpAddErrors, McpAddResponses, McpAuthAuthenticateErrors, McpAuthAuthenticateResponses, McpAuthCallbackErrors, McpAuthCallbackResponses, McpAuthRemoveErrors, McpAuthRemoveResponses, McpAuthStartErrors, McpAuthStartResponses, McpConnectResponses, McpDisconnectResponses, McpLocalConfig, McpRemoteConfig, McpStatusResponses, Part as Part2, PartDeleteErrors, PartDeleteResponses, PartUpdateErrors, PartUpdateResponses, PathGetResponses, PermissionListResponses, PermissionReplyErrors, PermissionReplyResponses, PermissionRespondErrors, PermissionRespondResponses, PermissionRuleset, ProjectCurrentResponses, ProjectListResponses, ProjectUpdateErrors, ProjectUpdateResponses, 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'; +import { zAppAgentsQuery, zAppAgentsResponse, zAppLogBody, zAppLogQuery, zAppLogResponse, zAuthSetBody, zAuthSetPath, zAuthSetQuery, zAuthSetResponse, zCommandListQuery, zCommandListResponse, zConfigGetQuery, zConfigGetResponse, zConfigProvidersQuery, zConfigProvidersResponse, zConfigUpdateBody, zConfigUpdateQuery, zConfigUpdateResponse, zEventSubscribeQuery, zEventSubscribeResponse, zFileListQuery, zFileListResponse, zFileReadQuery, zFileReadResponse, zFileStatusQuery, zFileStatusResponse, zFindFilesQuery, zFindFilesResponse, zFindSymbolsQuery, zFindSymbolsResponse, zFindTextQuery, zFindTextResponse, zFormatterStatusQuery, zFormatterStatusResponse, zGlobalDisposeResponse, zGlobalEventResponse, zGlobalHealthResponse, zInstanceDisposeQuery, zInstanceDisposeResponse, zLspStatusQuery, zLspStatusResponse, zMcpAddBody, zMcpAddQuery, zMcpAddResponse, zMcpAuthAuthenticatePath, zMcpAuthAuthenticateQuery, zMcpAuthAuthenticateResponse, zMcpAuthCallbackBody, zMcpAuthCallbackPath, zMcpAuthCallbackQuery, zMcpAuthCallbackResponse, zMcpAuthRemovePath, zMcpAuthRemoveQuery, zMcpAuthRemoveResponse, zMcpAuthStartPath, zMcpAuthStartQuery, zMcpAuthStartResponse, zMcpConnectPath, zMcpConnectQuery, zMcpConnectResponse, zMcpDisconnectPath, zMcpDisconnectQuery, zMcpDisconnectResponse, zMcpStatusQuery, zMcpStatusResponse, zPartDeletePath, zPartDeleteQuery, zPartDeleteResponse, zPartUpdateBody, zPartUpdatePath, zPartUpdateQuery, zPartUpdateResponse, zPathGetQuery, zPathGetResponse, zPermissionListQuery, zPermissionListResponse, zPermissionReplyBody, zPermissionReplyPath, zPermissionReplyQuery, zPermissionReplyResponse, zPermissionRespondBody, zPermissionRespondPath, zPermissionRespondQuery, zPermissionRespondResponse, zProjectCurrentQuery, zProjectCurrentResponse, zProjectListQuery, zProjectListResponse, zProjectUpdateBody, zProjectUpdatePath, zProjectUpdateQuery, zProjectUpdateResponse, zProviderAuthQuery, zProviderAuthResponse, zProviderListQuery, zProviderListResponse, zProviderOauthAuthorizeBody, zProviderOauthAuthorizePath, zProviderOauthAuthorizeQuery, zProviderOauthAuthorizeResponse, zProviderOauthCallbackBody, zProviderOauthCallbackPath, zProviderOauthCallbackQuery, zProviderOauthCallbackResponse, zPtyConnectPath, zPtyConnectQuery, zPtyConnectResponse, zPtyCreateBody, zPtyCreateQuery, zPtyCreateResponse, zPtyGetPath, zPtyGetQuery, zPtyGetResponse, zPtyListQuery, zPtyListResponse, zPtyRemovePath, zPtyRemoveQuery, zPtyRemoveResponse, zPtyUpdateBody, zPtyUpdatePath, zPtyUpdateQuery, zPtyUpdateResponse, zSessionAbortPath, zSessionAbortQuery, zSessionAbortResponse, zSessionChildrenPath, zSessionChildrenQuery, zSessionChildrenResponse, zSessionCommandBody, zSessionCommandPath, zSessionCommandQuery, zSessionCommandResponse, zSessionCreateBody, zSessionCreateQuery, zSessionCreateResponse, zSessionDeletePath, zSessionDeleteQuery, zSessionDeleteResponse, zSessionDiffPath, zSessionDiffQuery, zSessionDiffResponse, zSessionForkBody, zSessionForkPath, zSessionForkQuery, zSessionForkResponse, zSessionGetPath, zSessionGetQuery, zSessionGetResponse, zSessionInitBody, zSessionInitPath, zSessionInitQuery, zSessionInitResponse, zSessionListQuery, zSessionListResponse, zSessionMessagePath, zSessionMessageQuery, zSessionMessageResponse, zSessionMessagesPath, zSessionMessagesQuery, zSessionMessagesResponse, zSessionPromptAsyncBody, zSessionPromptAsyncPath, zSessionPromptAsyncQuery, zSessionPromptAsyncResponse, zSessionPromptBody, zSessionPromptPath, zSessionPromptQuery, zSessionPromptResponse, zSessionRevertBody, zSessionRevertPath, zSessionRevertQuery, zSessionRevertResponse, zSessionSharePath, zSessionShareQuery, zSessionShareResponse, zSessionShellBody, zSessionShellPath, zSessionShellQuery, zSessionShellResponse, zSessionStatusQuery, zSessionStatusResponse, zSessionSummarizeBody, zSessionSummarizePath, zSessionSummarizeQuery, zSessionSummarizeResponse, zSessionTodoPath, zSessionTodoQuery, zSessionTodoResponse, zSessionUnrevertPath, zSessionUnrevertQuery, zSessionUnrevertResponse, zSessionUnsharePath, zSessionUnshareQuery, zSessionUnshareResponse, zSessionUpdateBody, zSessionUpdatePath, zSessionUpdateQuery, zSessionUpdateResponse, zToolIdsQuery, zToolIdsResponse, zToolListQuery, zToolListResponse, zTuiAppendPromptBody, zTuiAppendPromptQuery, zTuiAppendPromptResponse, zTuiClearPromptQuery, zTuiClearPromptResponse, zTuiControlNextQuery, zTuiControlNextResponse, zTuiControlResponseBody, zTuiControlResponseQuery, zTuiControlResponseResponse, zTuiExecuteCommandBody, zTuiExecuteCommandQuery, zTuiExecuteCommandResponse, zTuiOpenHelpQuery, zTuiOpenHelpResponse, zTuiOpenModelsQuery, zTuiOpenModelsResponse, zTuiOpenSessionsQuery, zTuiOpenSessionsResponse, zTuiOpenThemesQuery, zTuiOpenThemesResponse, zTuiPublishBody, zTuiPublishQuery, zTuiPublishResponse, zTuiShowToastBody, zTuiShowToastQuery, zTuiShowToastResponse, zTuiSubmitPromptQuery, zTuiSubmitPromptResponse, zVcsGetQuery, zVcsGetResponse } from './zod.gen'; + +export type Options = Options2 & { + /** + * You can provide a client instance returned by `createClient()` instead of + * individual options. This might be also useful if you want to implement a + * custom client. + */ + client?: Client; + /** + * You can pass arbitrary values through the `meta` object. This can be + * used to access values that aren't defined as part of the SDK function. + */ + meta?: Record; +}; + +export class Global { + /** + * Get health + * + * Get health information about the OpenCode server. + */ + public static health = Object.assign((options?: Options) => (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: z.never().optional() + }).parseAsync(data), + responseValidator: async (data) => await zGlobalHealthResponse.parseAsync(data), + url: '/global/health', + ...options + }), { + id: 'globalHealth', + method: 'get', + responseSchema: zGlobalHealthResponse, + url: '/global/health' + }); + + /** + * Get global events + * + * Subscribe to global events from the OpenCode system using server-sent events. + */ + public static event = Object.assign((options?: Options) => (options?.client ?? client).sse.get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: z.never().optional() + }).parseAsync(data), + responseValidator: async (data) => await zGlobalEventResponse.parseAsync(data), + url: '/global/event', + ...options + }), { + id: 'globalEvent', + method: 'get', + responseSchema: zGlobalEventResponse, + url: '/global/event' + }); + + /** + * Dispose instance + * + * Clean up and dispose all OpenCode instances, releasing all resources. + */ + public static dispose = Object.assign((options?: Options) => (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: z.never().optional() + }).parseAsync(data), + responseValidator: async (data) => await zGlobalDisposeResponse.parseAsync(data), + url: '/global/dispose', + ...options + }), { + id: 'globalDispose', + method: 'post', + responseSchema: zGlobalDisposeResponse, + url: '/global/dispose' + }); +} + +export class Project { + /** + * List all projects + * + * Get a list of projects that have been opened with OpenCode. + */ + public static list = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProjectListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProjectListResponse.parseAsync(data), + url: '/project', + ...options, + ...params + }); + }, { + id: 'projectList', + method: 'get', + responseSchema: zProjectListResponse, + url: '/project' + }); + + /** + * Get current project + * + * Retrieve the currently active project that OpenCode is working with. + */ + public static current = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProjectCurrentQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProjectCurrentResponse.parseAsync(data), + url: '/project/current', + ...options, + ...params + }); + }, { + id: 'projectCurrent', + method: 'get', + responseSchema: zProjectCurrentResponse, + url: '/project/current' + }); + + /** + * Update project + * + * Update project properties such as name, icon and color. + */ + public static update = Object.assign((parameters: { + projectID: string; + directory?: string; + name?: string; + icon?: { + url?: string; + color?: string; + }; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'projectID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'name' }, + { in: 'body', key: 'icon' } + ] }]); + return (options?.client ?? client).patch({ + requestValidator: async (data) => await z.object({ + body: zProjectUpdateBody.optional(), + path: zProjectUpdatePath, + query: zProjectUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProjectUpdateResponse.parseAsync(data), + url: '/project/{projectID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'projectUpdate', + method: 'patch', + responseSchema: zProjectUpdateResponse, + url: '/project/{projectID}' + }); +} + +export class Pty { + /** + * List PTY sessions + * + * Get a list of all active pseudo-terminal (PTY) sessions managed by OpenCode. + */ + public static list = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zPtyListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyListResponse.parseAsync(data), + url: '/pty', + ...options, + ...params + }); + }, { + id: 'ptyList', + method: 'get', + responseSchema: zPtyListResponse, + url: '/pty' + }); + + /** + * Create PTY session + * + * Create a new pseudo-terminal (PTY) session for running shell commands and processes. + */ + public static create = Object.assign((parameters?: { + directory?: string; + command?: string; + args?: Array; + cwd?: string; + title?: string; + env?: { + [key: string]: string; + }; + }, options?: Options) => { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zPtyCreateBody.optional(), + path: z.never().optional(), + query: zPtyCreateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyCreateResponse.parseAsync(data), + url: '/pty', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'ptyCreate', + method: 'post', + responseSchema: zPtyCreateResponse, + url: '/pty' + }); + + /** + * Remove PTY session + * + * Remove and terminate a specific pseudo-terminal (PTY) session. + */ + public static remove = Object.assign((parameters: { + ptyID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'ptyID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPtyRemovePath, + query: zPtyRemoveQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyRemoveResponse.parseAsync(data), + url: '/pty/{ptyID}', + ...options, + ...params + }); + }, { + id: 'ptyRemove', + method: 'delete', + responseSchema: zPtyRemoveResponse, + url: '/pty/{ptyID}' + }); + + /** + * Get PTY session + * + * Retrieve detailed information about a specific pseudo-terminal (PTY) session. + */ + public static get = Object.assign((parameters: { + ptyID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'ptyID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPtyGetPath, + query: zPtyGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyGetResponse.parseAsync(data), + url: '/pty/{ptyID}', + ...options, + ...params + }); + }, { + id: 'ptyGet', + method: 'get', + responseSchema: zPtyGetResponse, + url: '/pty/{ptyID}' + }); + + /** + * Update PTY session + * + * Update properties of an existing pseudo-terminal (PTY) session. + */ + public static update = Object.assign((parameters: { + ptyID: string; + directory?: string; + title?: string; + size?: { + rows: number; + cols: number; + }; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'ptyID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'title' }, + { in: 'body', key: 'size' } + ] }]); + return (options?.client ?? client).put({ + requestValidator: async (data) => await z.object({ + body: zPtyUpdateBody.optional(), + path: zPtyUpdatePath, + query: zPtyUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyUpdateResponse.parseAsync(data), + url: '/pty/{ptyID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'ptyUpdate', + method: 'put', + responseSchema: zPtyUpdateResponse, + url: '/pty/{ptyID}' + }); + + /** + * Connect to PTY session + * + * Establish a WebSocket connection to interact with a pseudo-terminal (PTY) session in real-time. + */ + public static connect = Object.assign((parameters: { + ptyID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'ptyID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPtyConnectPath, + query: zPtyConnectQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyConnectResponse.parseAsync(data), + url: '/pty/{ptyID}/connect', + ...options, + ...params + }); + }, { + id: 'ptyConnect', + method: 'get', + responseSchema: zPtyConnectResponse, + url: '/pty/{ptyID}/connect' + }); +} + +export class Config { + /** + * Get configuration + * + * Retrieve the current OpenCode configuration settings and preferences. + */ + public static get = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zConfigGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zConfigGetResponse.parseAsync(data), + url: '/config', + ...options, + ...params + }); + }, { + id: 'configGet', + method: 'get', + responseSchema: zConfigGetResponse, + url: '/config' + }); + + /** + * Update configuration + * + * Update OpenCode configuration settings and preferences. + */ + public static update = Object.assign((parameters?: { + directory?: string; + config?: Config2; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { key: 'config', map: 'body' }] }]); + return (options?.client ?? client).patch({ + requestValidator: async (data) => await z.object({ + body: zConfigUpdateBody.optional(), + path: z.never().optional(), + query: zConfigUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zConfigUpdateResponse.parseAsync(data), + url: '/config', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'configUpdate', + method: 'patch', + responseSchema: zConfigUpdateResponse, + url: '/config' + }); + + /** + * List config providers + * + * Get a list of all configured AI providers and their default models. + */ + public static providers = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zConfigProvidersQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zConfigProvidersResponse.parseAsync(data), + url: '/config/providers', + ...options, + ...params + }); + }, { + id: 'configProviders', + method: 'get', + responseSchema: zConfigProvidersResponse, + url: '/config/providers' + }); +} + +export class Tool { + /** + * List tool IDs + * + * Get a list of all available tool IDs, including both built-in tools and dynamically registered tools. + */ + public static ids = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zToolIdsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zToolIdsResponse.parseAsync(data), + url: '/experimental/tool/ids', + ...options, + ...params + }); + }, { + id: 'toolIds', + method: 'get', + responseSchema: zToolIdsResponse, + url: '/experimental/tool/ids' + }); + + /** + * List tools + * + * Get a list of available tools with their JSON schema parameters for a specific provider and model combination. + */ + public static list = Object.assign((parameters: { + directory?: string; + provider: string; + model: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'query', key: 'provider' }, + { in: 'query', key: 'model' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zToolListQuery + }).parseAsync(data), + responseValidator: async (data) => await zToolListResponse.parseAsync(data), + url: '/experimental/tool', + ...options, + ...params + }); + }, { + id: 'toolList', + method: 'get', + responseSchema: zToolListResponse, + url: '/experimental/tool' + }); +} + +export class Instance { + /** + * Dispose instance + * + * Clean up and dispose the current OpenCode instance, releasing all resources. + */ + public static dispose = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zInstanceDisposeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zInstanceDisposeResponse.parseAsync(data), + url: '/instance/dispose', + ...options, + ...params + }); + }, { + id: 'instanceDispose', + method: 'post', + responseSchema: zInstanceDisposeResponse, + url: '/instance/dispose' + }); +} + +export class Path { + /** + * Get paths + * + * Retrieve the current working directory and related path information for the OpenCode instance. + */ + public static get = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zPathGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPathGetResponse.parseAsync(data), + url: '/path', + ...options, + ...params + }); + }, { + id: 'pathGet', + method: 'get', + responseSchema: zPathGetResponse, + url: '/path' + }); +} + +export class Vcs { + /** + * Get VCS info + * + * Retrieve version control system (VCS) information for the current project, such as git branch. + */ + public static get = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zVcsGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zVcsGetResponse.parseAsync(data), + url: '/vcs', + ...options, + ...params + }); + }, { + id: 'vcsGet', + method: 'get', + responseSchema: zVcsGetResponse, + url: '/vcs' + }); +} + +export class Session { + /** + * List sessions + * + * Get a list of all OpenCode sessions, sorted by most recently updated. + */ + public static list = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zSessionListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionListResponse.parseAsync(data), + url: '/session', + ...options, + ...params + }); + }, { + id: 'sessionList', + method: 'get', + responseSchema: zSessionListResponse, + url: '/session' + }); + + /** + * Create session + * + * Create a new OpenCode session for interacting with AI assistants and managing conversations. + */ + public static create = Object.assign((parameters?: { + directory?: string; + parentID?: string; + title?: string; + permission?: PermissionRuleset; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'body', key: 'parentID' }, + { in: 'body', key: 'title' }, + { in: 'body', key: 'permission' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionCreateBody.optional(), + path: z.never().optional(), + query: zSessionCreateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionCreateResponse.parseAsync(data), + url: '/session', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionCreate', + method: 'post', + responseSchema: zSessionCreateResponse, + url: '/session' + }); + + /** + * Get session status + * + * Retrieve the current status of all sessions, including active, idle, and completed states. + */ + public static status = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zSessionStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionStatusResponse.parseAsync(data), + url: '/session/status', + ...options, + ...params + }); + }, { + id: 'sessionStatus', + method: 'get', + responseSchema: zSessionStatusResponse, + url: '/session/status' + }); + + /** + * Delete session + * + * Delete a session and permanently remove all associated data, including messages and history. + */ + public static delete = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionDeletePath, + query: zSessionDeleteQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionDeleteResponse.parseAsync(data), + url: '/session/{sessionID}', + ...options, + ...params + }); + }, { + id: 'sessionDelete', + method: 'delete', + responseSchema: zSessionDeleteResponse, + url: '/session/{sessionID}' + }); + + /** + * Update session + * + * Update properties of an existing session, such as title or other metadata. + */ + public static update = Object.assign((parameters: { + sessionID: string; + directory?: string; + title?: string; + time?: { + archived?: number; + }; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'title' }, + { in: 'body', key: 'time' } + ] }]); + return (options?.client ?? client).patch({ + requestValidator: async (data) => await z.object({ + body: zSessionUpdateBody.optional(), + path: zSessionUpdatePath, + query: zSessionUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionUpdateResponse.parseAsync(data), + url: '/session/{sessionID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionUpdate', + method: 'patch', + responseSchema: zSessionUpdateResponse, + url: '/session/{sessionID}' + }); + + /** + * Get session todos + * + * Retrieve the todo list associated with a specific session, showing tasks and action items. + */ + public static todo = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionTodoPath, + query: zSessionTodoQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionTodoResponse.parseAsync(data), + url: '/session/{sessionID}/todo', + ...options, + ...params + }); + }, { + id: 'sessionTodo', + method: 'get', + responseSchema: zSessionTodoResponse, + url: '/session/{sessionID}/todo' + }); + + /** + * Initialize session + * + * Analyze the current application and create an AGENTS.md file with project-specific agent configurations. + */ + public static init = Object.assign((parameters: { + sessionID: string; + directory?: string; + modelID: string; + providerID: string; + messageID: string; + }, options?: Options) => { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionInitBody.optional(), + path: zSessionInitPath, + query: zSessionInitQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionInitResponse.parseAsync(data), + url: '/session/{sessionID}/init', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionInit', + method: 'post', + responseSchema: zSessionInitResponse, + url: '/session/{sessionID}/init' + }); + + /** + * Fork session + * + * Create a new session by forking an existing session at a specific message point. + */ + public static fork = Object.assign((parameters: { + sessionID: string; + directory?: string; + messageID?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'messageID' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionForkBody.optional(), + path: zSessionForkPath, + query: zSessionForkQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionForkResponse.parseAsync(data), + url: '/session/{sessionID}/fork', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionFork', + method: 'post', + responseSchema: zSessionForkResponse, + url: '/session/{sessionID}/fork' + }); + + /** + * Abort session + * + * Abort an active session and stop any ongoing AI processing or command execution. + */ + public static abort = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionAbortPath, + query: zSessionAbortQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionAbortResponse.parseAsync(data), + url: '/session/{sessionID}/abort', + ...options, + ...params + }); + }, { + id: 'sessionAbort', + method: 'post', + responseSchema: zSessionAbortResponse, + url: '/session/{sessionID}/abort' + }); + + /** + * Unshare session + * + * Remove the shareable link for a session, making it private again. + */ + public static unshare = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionUnsharePath, + query: zSessionUnshareQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionUnshareResponse.parseAsync(data), + url: '/session/{sessionID}/share', + ...options, + ...params + }); + }, { + id: 'sessionUnshare', + method: 'delete', + responseSchema: zSessionUnshareResponse, + url: '/session/{sessionID}/share' + }); + + /** + * Share session + * + * Create a shareable link for a session, allowing others to view the conversation. + */ + public static share = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionSharePath, + query: zSessionShareQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionShareResponse.parseAsync(data), + url: '/session/{sessionID}/share', + ...options, + ...params + }); + }, { + id: 'sessionShare', + method: 'post', + responseSchema: zSessionShareResponse, + url: '/session/{sessionID}/share' + }); + + /** + * Get session diff + * + * Get all file changes (diffs) made during this session. + */ + public static diff = Object.assign((parameters: { + sessionID: string; + directory?: string; + messageID?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'query', key: 'messageID' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionDiffPath, + query: zSessionDiffQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionDiffResponse.parseAsync(data), + url: '/session/{sessionID}/diff', + ...options, + ...params + }); + }, { + id: 'sessionDiff', + method: 'get', + responseSchema: zSessionDiffResponse, + url: '/session/{sessionID}/diff' + }); + + /** + * Summarize session + * + * Generate a concise summary of the session using AI compaction to preserve key information. + */ + public static summarize = Object.assign((parameters: { + sessionID: string; + directory?: string; + providerID: string; + modelID: string; + auto?: boolean; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'providerID' }, + { in: 'body', key: 'modelID' }, + { in: 'body', key: 'auto' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionSummarizeBody.optional(), + path: zSessionSummarizePath, + query: zSessionSummarizeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionSummarizeResponse.parseAsync(data), + url: '/session/{sessionID}/summarize', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionSummarize', + method: 'post', + responseSchema: zSessionSummarizeResponse, + url: '/session/{sessionID}/summarize' + }); + + /** + * Get session messages + * + * Retrieve all messages in a session, including user prompts and AI responses. + */ + public static messages = Object.assign((parameters: { + sessionID: string; + directory?: string; + limit?: number; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'query', key: 'limit' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionMessagesPath, + query: zSessionMessagesQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionMessagesResponse.parseAsync(data), + url: '/session/{sessionID}/message', + ...options, + ...params + }); + }, { + id: 'sessionMessages', + method: 'get', + responseSchema: zSessionMessagesResponse, + url: '/session/{sessionID}/message' + }); + + /** + * Send message + * + * Create and send a new message to a session, streaming the AI response. + */ + public static prompt = Object.assign((parameters: { + sessionID: string; + directory?: string; + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; + }, options?: Options) => { + 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: 'tools' }, + { in: 'body', key: 'system' }, + { in: 'body', key: 'variant' }, + { in: 'body', key: 'parts' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionPromptBody.optional(), + path: zSessionPromptPath, + query: zSessionPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionPromptResponse.parseAsync(data), + url: '/session/{sessionID}/message', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionPrompt', + method: 'post', + responseSchema: zSessionPromptResponse, + url: '/session/{sessionID}/message' + }); + + /** + * Get message + * + * Retrieve a specific message from a session by its message ID. + */ + public static message = Object.assign((parameters: { + sessionID: string; + messageID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'messageID' }, + { in: 'query', key: 'directory' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionMessagePath, + query: zSessionMessageQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionMessageResponse.parseAsync(data), + url: '/session/{sessionID}/message/{messageID}', + ...options, + ...params + }); + }, { + id: 'sessionMessage', + method: 'get', + responseSchema: zSessionMessageResponse, + url: '/session/{sessionID}/message/{messageID}' + }); + + /** + * Send async message + * + * Create and send a new message to a session asynchronously, starting the session if needed and returning immediately. + */ + public static promptAsync = Object.assign((parameters: { + sessionID: string; + directory?: string; + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; + }, options?: Options) => { + 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: 'tools' }, + { in: 'body', key: 'system' }, + { in: 'body', key: 'variant' }, + { in: 'body', key: 'parts' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionPromptAsyncBody.optional(), + path: zSessionPromptAsyncPath, + query: zSessionPromptAsyncQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionPromptAsyncResponse.parseAsync(data), + url: '/session/{sessionID}/prompt_async', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionPromptAsync', + method: 'post', + responseSchema: zSessionPromptAsyncResponse, + url: '/session/{sessionID}/prompt_async' + }); + + /** + * Send command + * + * Send a new command to a session for execution by the AI assistant. + */ + public static command = Object.assign((parameters: { + sessionID: string; + directory?: string; + messageID?: string; + agent?: string; + model?: string; + arguments: string; + command: string; + variant?: string; + }, options?: Options) => { + 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' }, + { in: 'body', key: 'variant' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionCommandBody.optional(), + path: zSessionCommandPath, + query: zSessionCommandQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionCommandResponse.parseAsync(data), + url: '/session/{sessionID}/command', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionCommand', + method: 'post', + responseSchema: zSessionCommandResponse, + url: '/session/{sessionID}/command' + }); + + /** + * Run shell command + * + * Execute a shell command within the session context and return the AI's response. + */ + public static shell = Object.assign((parameters: { + sessionID: string; + directory?: string; + agent: string; + model?: { + providerID: string; + modelID: string; + }; + command: string; + }, options?: Options) => { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionShellBody.optional(), + path: zSessionShellPath, + query: zSessionShellQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionShellResponse.parseAsync(data), + url: '/session/{sessionID}/shell', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionShell', + method: 'post', + responseSchema: zSessionShellResponse, + url: '/session/{sessionID}/shell' + }); + + /** + * Revert message + * + * Revert a specific message in a session, undoing its effects and restoring the previous state. + */ + public static revert = Object.assign((parameters: { + sessionID: string; + directory?: string; + messageID: string; + partID?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'messageID' }, + { in: 'body', key: 'partID' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionRevertBody.optional(), + path: zSessionRevertPath, + query: zSessionRevertQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionRevertResponse.parseAsync(data), + url: '/session/{sessionID}/revert', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionRevert', + method: 'post', + responseSchema: zSessionRevertResponse, + url: '/session/{sessionID}/revert' + }); + + /** + * Restore reverted messages + * + * Restore all previously reverted messages in a session. + */ + public static unrevert = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionUnrevertPath, + query: zSessionUnrevertQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionUnrevertResponse.parseAsync(data), + url: '/session/{sessionID}/unrevert', + ...options, + ...params + }); + }, { + id: 'sessionUnrevert', + method: 'post', + responseSchema: zSessionUnrevertResponse, + url: '/session/{sessionID}/unrevert' + }); +} + +export class Part { + /** + * Delete a part from a message + */ + public static delete = Object.assign((parameters: { + sessionID: string; + messageID: string; + partID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'messageID' }, + { in: 'path', key: 'partID' }, + { in: 'query', key: 'directory' } + ] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPartDeletePath, + query: zPartDeleteQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPartDeleteResponse.parseAsync(data), + url: '/session/{sessionID}/message/{messageID}/part/{partID}', + ...options, + ...params + }); + }, { + id: 'partDelete', + method: 'delete', + responseSchema: zPartDeleteResponse, + url: '/session/{sessionID}/message/{messageID}/part/{partID}' + }); + + /** + * Update a part in a message + */ + public static update = Object.assign((parameters: { + sessionID: string; + messageID: string; + partID: string; + directory?: string; + part?: Part2; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'messageID' }, + { in: 'path', key: 'partID' }, + { in: 'query', key: 'directory' }, + { key: 'part', map: 'body' } + ] }]); + return (options?.client ?? client).patch({ + requestValidator: async (data) => await z.object({ + body: zPartUpdateBody.optional(), + path: zPartUpdatePath, + query: zPartUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPartUpdateResponse.parseAsync(data), + url: '/session/{sessionID}/message/{messageID}/part/{partID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'partUpdate', + method: 'patch', + responseSchema: zPartUpdateResponse, + url: '/session/{sessionID}/message/{messageID}/part/{partID}' + }); +} + +export class Permission { + /** + * Respond to permission + * + * Approve or deny a permission request from the AI assistant. + * + * @deprecated + */ + public static respond = Object.assign((parameters: { + sessionID: string; + permissionID: string; + directory?: string; + response: 'once' | 'always' | 'reject'; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'permissionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'response' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zPermissionRespondBody.optional(), + path: zPermissionRespondPath, + query: zPermissionRespondQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPermissionRespondResponse.parseAsync(data), + url: '/session/{sessionID}/permissions/{permissionID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'permissionRespond', + method: 'post', + responseSchema: zPermissionRespondResponse, + url: '/session/{sessionID}/permissions/{permissionID}' + }); + + /** + * Respond to permission request + * + * Approve or deny a permission request from the AI assistant. + */ + public static reply = Object.assign((parameters: { + requestID: string; + directory?: string; + reply: 'once' | 'always' | 'reject'; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'requestID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'reply' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zPermissionReplyBody.optional(), + path: zPermissionReplyPath, + query: zPermissionReplyQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPermissionReplyResponse.parseAsync(data), + url: '/permission/{requestID}/reply', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'permissionReply', + method: 'post', + responseSchema: zPermissionReplyResponse, + url: '/permission/{requestID}/reply' + }); + + /** + * List pending permissions + * + * Get all pending permission requests across all sessions. + */ + public static list = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zPermissionListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPermissionListResponse.parseAsync(data), + url: '/permission', + ...options, + ...params + }); + }, { + id: 'permissionList', + method: 'get', + responseSchema: zPermissionListResponse, + url: '/permission' + }); +} + +export class Command { + /** + * List commands + * + * Get a list of all available commands in the OpenCode system. + */ + public static list = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zCommandListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zCommandListResponse.parseAsync(data), + url: '/command', + ...options, + ...params + }); + }, { + id: 'commandList', + method: 'get', + responseSchema: zCommandListResponse, + url: '/command' + }); +} + +export class Oauth { + /** + * OAuth authorize + * + * Initiate OAuth authorization for a specific AI provider to get an authorization URL. + */ + public static authorize = Object.assign((parameters: { + providerID: string; + directory?: string; + method: number; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'providerID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'method' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zProviderOauthAuthorizeBody.optional(), + path: zProviderOauthAuthorizePath, + query: zProviderOauthAuthorizeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderOauthAuthorizeResponse.parseAsync(data), + url: '/provider/{providerID}/oauth/authorize', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'providerOauthAuthorize', + method: 'post', + responseSchema: zProviderOauthAuthorizeResponse, + url: '/provider/{providerID}/oauth/authorize' + }); + + /** + * OAuth callback + * + * Handle the OAuth callback from a provider after user authorization. + */ + public static callback = Object.assign((parameters: { + providerID: string; + directory?: string; + method: number; + code?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'providerID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'method' }, + { in: 'body', key: 'code' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zProviderOauthCallbackBody.optional(), + path: zProviderOauthCallbackPath, + query: zProviderOauthCallbackQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderOauthCallbackResponse.parseAsync(data), + url: '/provider/{providerID}/oauth/callback', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'providerOauthCallback', + method: 'post', + responseSchema: zProviderOauthCallbackResponse, + url: '/provider/{providerID}/oauth/callback' + }); +} + +export class Provider { + /** + * List providers + * + * Get a list of all available AI providers, including both available and connected ones. + */ + public static list = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProviderListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderListResponse.parseAsync(data), + url: '/provider', + ...options, + ...params + }); + }, { + id: 'providerList', + method: 'get', + responseSchema: zProviderListResponse, + url: '/provider' + }); + + /** + * Get provider auth methods + * + * Retrieve available authentication methods for all AI providers. + */ + public static auth = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProviderAuthQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderAuthResponse.parseAsync(data), + url: '/provider/auth', + ...options, + ...params + }); + }, { + id: 'providerAuth', + method: 'get', + responseSchema: zProviderAuthResponse, + url: '/provider/auth' + }); + + static oauth = Oauth; +} + +export class Find { + /** + * Find text + * + * Search for text patterns across files in the project using ripgrep. + */ + public static text = Object.assign((parameters: { + directory?: string; + pattern: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'pattern' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFindTextQuery + }).parseAsync(data), + responseValidator: async (data) => await zFindTextResponse.parseAsync(data), + url: '/find', + ...options, + ...params + }); + }, { + id: 'findText', + method: 'get', + responseSchema: zFindTextResponse, + url: '/find' + }); + + /** + * Find files + * + * Search for files or directories by name or pattern in the project directory. + */ + public static files = Object.assign((parameters: { + directory?: string; + query: string; + dirs?: 'true' | 'false'; + type?: 'file' | 'directory'; + limit?: number; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'query', key: 'query' }, + { in: 'query', key: 'dirs' }, + { in: 'query', key: 'type' }, + { in: 'query', key: 'limit' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFindFilesQuery + }).parseAsync(data), + responseValidator: async (data) => await zFindFilesResponse.parseAsync(data), + url: '/find/file', + ...options, + ...params + }); + }, { + id: 'findFiles', + method: 'get', + responseSchema: zFindFilesResponse, + url: '/find/file' + }); + + /** + * Find symbols + * + * Search for workspace symbols like functions, classes, and variables using LSP. + */ + public static symbols = Object.assign((parameters: { + directory?: string; + query: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'query' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFindSymbolsQuery + }).parseAsync(data), + responseValidator: async (data) => await zFindSymbolsResponse.parseAsync(data), + url: '/find/symbol', + ...options, + ...params + }); + }, { + id: 'findSymbols', + method: 'get', + responseSchema: zFindSymbolsResponse, + url: '/find/symbol' + }); +} + +export class File_ { + /** + * List files + * + * List files and directories in a specified path. + */ + public static list = Object.assign((parameters: { + directory?: string; + path: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'path' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFileListQuery + }).parseAsync(data), + responseValidator: async (data) => await zFileListResponse.parseAsync(data), + url: '/file', + ...options, + ...params + }); + }, { + id: 'fileList', + method: 'get', + responseSchema: zFileListResponse, + url: '/file' + }); + + /** + * Read file + * + * Read the content of a specified file. + */ + public static read = Object.assign((parameters: { + directory?: string; + path: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'path' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFileReadQuery + }).parseAsync(data), + responseValidator: async (data) => await zFileReadResponse.parseAsync(data), + url: '/file/content', + ...options, + ...params + }); + }, { + id: 'fileRead', + method: 'get', + responseSchema: zFileReadResponse, + url: '/file/content' + }); + + /** + * Get file status + * + * Get the git status of all files in the project. + */ + public static status = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFileStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zFileStatusResponse.parseAsync(data), + url: '/file/status', + ...options, + ...params + }); + }, { + id: 'fileStatus', + method: 'get', + responseSchema: zFileStatusResponse, + url: '/file/status' + }); +} + +export class App { + /** + * Write log + * + * Write a log entry to the server logs with specified level and metadata. + */ + public static log = Object.assign((parameters: { + directory?: string; + service: string; + level: 'debug' | 'info' | 'error' | 'warn'; + message: string; + extra?: { + [key: string]: unknown; + }; + }, options?: Options) => { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zAppLogBody.optional(), + path: z.never().optional(), + query: zAppLogQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zAppLogResponse.parseAsync(data), + url: '/log', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'appLog', + method: 'post', + responseSchema: zAppLogResponse, + url: '/log' + }); + + /** + * List agents + * + * Get a list of all available AI agents in the OpenCode system. + */ + public static agents = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zAppAgentsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zAppAgentsResponse.parseAsync(data), + url: '/agent', + ...options, + ...params + }); + }, { + id: 'appAgents', + method: 'get', + responseSchema: zAppAgentsResponse, + url: '/agent' + }); +} + +export class Auth { + /** + * Remove MCP OAuth + * + * Remove OAuth credentials for an MCP server + */ + public static remove = Object.assign((parameters: { + name: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpAuthRemovePath, + query: zMcpAuthRemoveQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthRemoveResponse.parseAsync(data), + url: '/mcp/{name}/auth', + ...options, + ...params + }); + }, { + id: 'mcpAuthRemove', + method: 'delete', + responseSchema: zMcpAuthRemoveResponse, + url: '/mcp/{name}/auth' + }); + + /** + * Start MCP OAuth + * + * Start OAuth authentication flow for a Model Context Protocol (MCP) server. + */ + public static start = Object.assign((parameters: { + name: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpAuthStartPath, + query: zMcpAuthStartQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthStartResponse.parseAsync(data), + url: '/mcp/{name}/auth', + ...options, + ...params + }); + }, { + id: 'mcpAuthStart', + method: 'post', + responseSchema: zMcpAuthStartResponse, + url: '/mcp/{name}/auth' + }); + + /** + * Complete MCP OAuth + * + * Complete OAuth authentication for a Model Context Protocol (MCP) server using the authorization code. + */ + public static callback = Object.assign((parameters: { + name: string; + directory?: string; + code: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'name' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'code' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zMcpAuthCallbackBody.optional(), + path: zMcpAuthCallbackPath, + query: zMcpAuthCallbackQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthCallbackResponse.parseAsync(data), + url: '/mcp/{name}/auth/callback', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'mcpAuthCallback', + method: 'post', + responseSchema: zMcpAuthCallbackResponse, + url: '/mcp/{name}/auth/callback' + }); + + /** + * Authenticate MCP OAuth + * + * Start OAuth flow and wait for callback (opens browser) + */ + public static authenticate = Object.assign((parameters: { + name: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpAuthAuthenticatePath, + query: zMcpAuthAuthenticateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthAuthenticateResponse.parseAsync(data), + url: '/mcp/{name}/auth/authenticate', + ...options, + ...params + }); + }, { + id: 'mcpAuthAuthenticate', + method: 'post', + responseSchema: zMcpAuthAuthenticateResponse, + url: '/mcp/{name}/auth/authenticate' + }); +} + +export class Mcp { + /** + * Get MCP status + * + * Get the status of all Model Context Protocol (MCP) servers. + */ + public static status = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zMcpStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpStatusResponse.parseAsync(data), + url: '/mcp', + ...options, + ...params + }); + }, { + id: 'mcpStatus', + method: 'get', + responseSchema: zMcpStatusResponse, + url: '/mcp' + }); + + /** + * Add MCP server + * + * Dynamically add a new Model Context Protocol (MCP) server to the system. + */ + public static add = Object.assign((parameters: { + directory?: string; + name: string; + config: McpLocalConfig | McpRemoteConfig; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'body', key: 'name' }, + { in: 'body', key: 'config' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zMcpAddBody.optional(), + path: z.never().optional(), + query: zMcpAddQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAddResponse.parseAsync(data), + url: '/mcp', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'mcpAdd', + method: 'post', + responseSchema: zMcpAddResponse, + url: '/mcp' + }); + + /** + * Connect an MCP server + */ + public static connect = Object.assign((parameters: { + name: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpConnectPath, + query: zMcpConnectQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpConnectResponse.parseAsync(data), + url: '/mcp/{name}/connect', + ...options, + ...params + }); + }, { + id: 'mcpConnect', + method: 'post', + responseSchema: zMcpConnectResponse, + url: '/mcp/{name}/connect' + }); + + /** + * Disconnect an MCP server + */ + public static disconnect = Object.assign((parameters: { + name: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpDisconnectPath, + query: zMcpDisconnectQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpDisconnectResponse.parseAsync(data), + url: '/mcp/{name}/disconnect', + ...options, + ...params + }); + }, { + id: 'mcpDisconnect', + method: 'post', + responseSchema: zMcpDisconnectResponse, + url: '/mcp/{name}/disconnect' + }); + + static auth = Auth; +} + +export class Lsp { + /** + * Get LSP status + * + * Get LSP server status + */ + public static status = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zLspStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zLspStatusResponse.parseAsync(data), + url: '/lsp', + ...options, + ...params + }); + }, { + id: 'lspStatus', + method: 'get', + responseSchema: zLspStatusResponse, + url: '/lsp' + }); +} + +export class Formatter { + /** + * Get formatter status + * + * Get formatter status + */ + public static status = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFormatterStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zFormatterStatusResponse.parseAsync(data), + url: '/formatter', + ...options, + ...params + }); + }, { + id: 'formatterStatus', + method: 'get', + responseSchema: zFormatterStatusResponse, + url: '/formatter' + }); +} + +export class Control { + /** + * Get next TUI request + * + * Retrieve the next TUI (Terminal User Interface) request from the queue for processing. + */ + public static next = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiControlNextQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiControlNextResponse.parseAsync(data), + url: '/tui/control/next', + ...options, + ...params + }); + }, { + id: 'tuiControlNext', + method: 'get', + responseSchema: zTuiControlNextResponse, + url: '/tui/control/next' + }); + + /** + * Submit TUI response + * + * Submit a response to the TUI request queue to complete a pending request. + */ + public static response = Object.assign((parameters?: { + directory?: string; + body?: unknown; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { key: 'body', map: 'body' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiControlResponseBody.optional(), + path: z.never().optional(), + query: zTuiControlResponseQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiControlResponseResponse.parseAsync(data), + url: '/tui/control/response', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'tuiControlResponse', + method: 'post', + responseSchema: zTuiControlResponseResponse, + url: '/tui/control/response' + }); +} + +export class Tui { + /** + * Append TUI prompt + * + * Append prompt to the TUI + */ + public static appendPrompt = Object.assign((parameters: { + directory?: string; + text: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'body', key: 'text' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiAppendPromptBody.optional(), + path: z.never().optional(), + query: zTuiAppendPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiAppendPromptResponse.parseAsync(data), + url: '/tui/append-prompt', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'tuiAppendPrompt', + method: 'post', + responseSchema: zTuiAppendPromptResponse, + url: '/tui/append-prompt' + }); + + /** + * Open help dialog + * + * Open the help dialog in the TUI to display user assistance information. + */ + public static openHelp = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenHelpQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenHelpResponse.parseAsync(data), + url: '/tui/open-help', + ...options, + ...params + }); + }, { + id: 'tuiOpenHelp', + method: 'post', + responseSchema: zTuiOpenHelpResponse, + url: '/tui/open-help' + }); + + /** + * Open sessions dialog + * + * Open the session dialog + */ + public static openSessions = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenSessionsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenSessionsResponse.parseAsync(data), + url: '/tui/open-sessions', + ...options, + ...params + }); + }, { + id: 'tuiOpenSessions', + method: 'post', + responseSchema: zTuiOpenSessionsResponse, + url: '/tui/open-sessions' + }); + + /** + * Open themes dialog + * + * Open the theme dialog + */ + public static openThemes = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenThemesQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenThemesResponse.parseAsync(data), + url: '/tui/open-themes', + ...options, + ...params + }); + }, { + id: 'tuiOpenThemes', + method: 'post', + responseSchema: zTuiOpenThemesResponse, + url: '/tui/open-themes' + }); + + /** + * Open models dialog + * + * Open the model dialog + */ + public static openModels = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenModelsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenModelsResponse.parseAsync(data), + url: '/tui/open-models', + ...options, + ...params + }); + }, { + id: 'tuiOpenModels', + method: 'post', + responseSchema: zTuiOpenModelsResponse, + url: '/tui/open-models' + }); + + /** + * Submit TUI prompt + * + * Submit the prompt + */ + public static submitPrompt = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiSubmitPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiSubmitPromptResponse.parseAsync(data), + url: '/tui/submit-prompt', + ...options, + ...params + }); + }, { + id: 'tuiSubmitPrompt', + method: 'post', + responseSchema: zTuiSubmitPromptResponse, + url: '/tui/submit-prompt' + }); + + /** + * Clear TUI prompt + * + * Clear the prompt + */ + public static clearPrompt = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiClearPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiClearPromptResponse.parseAsync(data), + url: '/tui/clear-prompt', + ...options, + ...params + }); + }, { + id: 'tuiClearPrompt', + method: 'post', + responseSchema: zTuiClearPromptResponse, + url: '/tui/clear-prompt' + }); + + /** + * Execute TUI command + * + * Execute a TUI command (e.g. agent_cycle) + */ + public static executeCommand = Object.assign((parameters: { + directory?: string; + command: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'body', key: 'command' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiExecuteCommandBody.optional(), + path: z.never().optional(), + query: zTuiExecuteCommandQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiExecuteCommandResponse.parseAsync(data), + url: '/tui/execute-command', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'tuiExecuteCommand', + method: 'post', + responseSchema: zTuiExecuteCommandResponse, + url: '/tui/execute-command' + }); + + /** + * Show TUI toast + * + * Show a toast notification in the TUI + */ + public static showToast = Object.assign((parameters: { + directory?: string; + title?: string; + message: string; + variant: 'info' | 'success' | 'warning' | 'error'; + duration?: number; + }, options?: Options) => { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiShowToastBody.optional(), + path: z.never().optional(), + query: zTuiShowToastQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiShowToastResponse.parseAsync(data), + url: '/tui/show-toast', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'tuiShowToast', + method: 'post', + responseSchema: zTuiShowToastResponse, + url: '/tui/show-toast' + }); + + /** + * Publish TUI event + * + * Publish a TUI event + */ + public static publish = Object.assign((parameters?: { + directory?: string; + body?: EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { key: 'body', map: 'body' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiPublishBody.optional(), + path: z.never().optional(), + query: zTuiPublishQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiPublishResponse.parseAsync(data), + url: '/tui/publish', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'tuiPublish', + method: 'post', + responseSchema: zTuiPublishResponse, + url: '/tui/publish' + }); + + static control = Control; +} + +export class Auth2 { + /** + * Set auth credentials + * + * Set authentication credentials + */ + public static set = Object.assign((parameters: { + providerID: string; + directory?: string; + auth?: Auth3; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'providerID' }, + { in: 'query', key: 'directory' }, + { key: 'auth', map: 'body' } + ] }]); + return (options?.client ?? client).put({ + requestValidator: async (data) => await z.object({ + body: zAuthSetBody.optional(), + path: zAuthSetPath, + query: zAuthSetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zAuthSetResponse.parseAsync(data), + url: '/auth/{providerID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'authSet', + method: 'put', + responseSchema: zAuthSetResponse, + url: '/auth/{providerID}' + }); +} + +export class Event_ { + /** + * Subscribe to events + * + * Get events + */ + public static subscribe = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).sse.get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zEventSubscribeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zEventSubscribeResponse.parseAsync(data), + url: '/event', + ...options, + ...params + }); + }, { + id: 'eventSubscribe', + method: 'get', + responseSchema: zEventSubscribeResponse, + url: '/event' + }); +} + +export class Default { + static global = Global; + + static project = Project; + + static pty = Pty; + + static config = Config; + + static tool = Tool; + + static instance = Instance; + + static path = Path; + + static vcs = Vcs; + + static session = Session; + + static part = Part; + + static permission = Permission; + + static command = Command; + + static provider = Provider; + + static find = Find; + + static file = File_; + + static app = App; + + static mcp = Mcp; + + static lsp = Lsp; + + static formatter = Formatter; + + static tui = Tui; + + static auth = Auth2; + + static event = Event_; +} + +export class Session2 { + /** + * Get session + * + * Retrieve detailed information about a specific OpenCode session. + */ + public static get = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionGetPath, + query: zSessionGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionGetResponse.parseAsync(data), + url: '/session/{sessionID}', + ...options, + ...params + }); + }, { + id: 'sessionGet', + method: 'get', + responseSchema: zSessionGetResponse, + tags: ['Session'], + url: '/session/{sessionID}' + }); + + /** + * Get session children + * + * Retrieve all child sessions that were forked from the specified parent session. + */ + public static children = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionChildrenPath, + query: zSessionChildrenQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionChildrenResponse.parseAsync(data), + url: '/session/{sessionID}/children', + ...options, + ...params + }); + }, { + id: 'sessionChildren', + method: 'get', + responseSchema: zSessionChildrenResponse, + tags: ['Session'], + url: '/session/{sessionID}/children' + }); +} + +export class Session3 { + static session = Session2; +} diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/types.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/types.gen.ts new file mode 100644 index 0000000000..ccae410e61 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/types.gen.ts @@ -0,0 +1,4322 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type ClientOptions = { + baseUrl: `${string}://${string}` | (string & {}); +}; + +export type EventInstallationUpdated = { + type: 'installation.updated'; + properties: { + version: string; + }; +}; + +export type EventInstallationUpdateAvailable = { + type: 'installation.update-available'; + properties: { + version: string; + }; +}; + +export type Project = { + id: string; + worktree: string; + vcs?: 'git'; + name?: string; + icon?: { + url?: string; + color?: string; + }; + time: { + created: number; + updated: number; + initialized?: number; + }; +}; + +export type EventProjectUpdated = { + type: 'project.updated'; + properties: Project; +}; + +export type EventServerInstanceDisposed = { + type: 'server.instance.disposed'; + properties: { + directory: 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; + }; + agent: string; + model: { + providerID: string; + modelID: string; + }; + system?: string; + tools?: { + [key: string]: boolean; + }; + variant?: string; +}; + +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; + metadata?: { + [key: string]: 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; + agent: 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; +}; + +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; +}; + +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; + command?: 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 PermissionRequest = { + id: string; + sessionID: string; + permission: string; + patterns: Array; + metadata: { + [key: string]: unknown; + }; + always: Array; + tool?: { + messageID: string; + callID: string; + }; +}; + +export type EventPermissionAsked = { + type: 'permission.asked'; + properties: PermissionRequest; +}; + +export type EventPermissionReplied = { + type: 'permission.replied'; + properties: { + sessionID: string; + requestID: string; + reply: 'once' | 'always' | 'reject'; + }; +}; + +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; + }; +}; + +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 EventMcpToolsChanged = { + type: 'mcp.tools.changed'; + properties: { + server: string; + }; +}; + +export type EventCommandExecuted = { + type: 'command.executed'; + properties: { + name: string; + sessionID: string; + arguments: string; + messageID: string; + }; +}; + +export type PermissionAction = 'allow' | 'deny' | 'ask'; + +export type PermissionRule = { + permission: string; + pattern: string; + action: PermissionAction; +}; + +export type PermissionRuleset = Array; + +export type Session = { + id: string; + projectID: string; + directory: string; + parentID?: string; + summary?: { + additions: number; + deletions: number; + files: number; + diffs?: Array; + }; + share?: { + url: string; + }; + title: string; + version: string; + time: { + created: number; + updated: number; + compacting?: number; + archived?: number; + }; + permission?: PermissionRuleset; + 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; + }; +}; + +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 Pty = { + id: string; + title: string; + command: string; + args: Array; + 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 EventGlobalDisposed = { + type: 'global.disposed'; + properties: { + [key: string]: unknown; + }; +}; + +export type Event = EventInstallationUpdated | EventInstallationUpdateAvailable | EventProjectUpdated | EventServerInstanceDisposed | EventLspClientDiagnostics | EventLspUpdated | EventMessageUpdated | EventMessageRemoved | EventMessagePartUpdated | EventMessagePartRemoved | EventPermissionAsked | EventPermissionReplied | EventSessionStatus | EventSessionIdle | EventSessionCompacted | EventFileEdited | EventTodoUpdated | EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow | EventMcpToolsChanged | EventCommandExecuted | EventSessionCreated | EventSessionUpdated | EventSessionDeleted | EventSessionDiff | EventSessionError | EventFileWatcherUpdated | EventVcsBranchUpdated | EventPtyCreated | EventPtyUpdated | EventPtyExited | EventPtyDeleted | EventServerConnected | EventGlobalDisposed; + +export type GlobalEvent = { + directory: string; + payload: Event; +}; + +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; + /** + * Fork session from message + */ + session_fork?: string; + /** + * Rename session + */ + session_rename?: 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 next message + */ + messages_next?: string; + /** + * Navigate to previous message + */ + messages_previous?: 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; + /** + * Next favorite model + */ + model_cycle_favorite?: string; + /** + * Previous favorite model + */ + model_cycle_favorite_reverse?: string; + /** + * List available commands + */ + command_list?: string; + /** + * List agents + */ + agent_list?: string; + /** + * Next agent + */ + agent_cycle?: string; + /** + * Previous agent + */ + agent_cycle_reverse?: string; + /** + * Cycle model variants + */ + variant_cycle?: string; + /** + * Clear input field + */ + input_clear?: string; + /** + * Paste from clipboard + */ + input_paste?: string; + /** + * Submit input + */ + input_submit?: string; + /** + * Insert newline in input + */ + input_newline?: string; + /** + * Move cursor left in input + */ + input_move_left?: string; + /** + * Move cursor right in input + */ + input_move_right?: string; + /** + * Move cursor up in input + */ + input_move_up?: string; + /** + * Move cursor down in input + */ + input_move_down?: string; + /** + * Select left in input + */ + input_select_left?: string; + /** + * Select right in input + */ + input_select_right?: string; + /** + * Select up in input + */ + input_select_up?: string; + /** + * Select down in input + */ + input_select_down?: string; + /** + * Move to start of line in input + */ + input_line_home?: string; + /** + * Move to end of line in input + */ + input_line_end?: string; + /** + * Select to start of line in input + */ + input_select_line_home?: string; + /** + * Select to end of line in input + */ + input_select_line_end?: string; + /** + * Move to start of visual line in input + */ + input_visual_line_home?: string; + /** + * Move to end of visual line in input + */ + input_visual_line_end?: string; + /** + * Select to start of visual line in input + */ + input_select_visual_line_home?: string; + /** + * Select to end of visual line in input + */ + input_select_visual_line_end?: string; + /** + * Move to start of buffer in input + */ + input_buffer_home?: string; + /** + * Move to end of buffer in input + */ + input_buffer_end?: string; + /** + * Select to start of buffer in input + */ + input_select_buffer_home?: string; + /** + * Select to end of buffer in input + */ + input_select_buffer_end?: string; + /** + * Delete line in input + */ + input_delete_line?: string; + /** + * Delete to end of line in input + */ + input_delete_to_line_end?: string; + /** + * Delete to start of line in input + */ + input_delete_to_line_start?: string; + /** + * Backspace in input + */ + input_backspace?: string; + /** + * Delete character in input + */ + input_delete?: string; + /** + * Undo in input + */ + input_undo?: string; + /** + * Redo in input + */ + input_redo?: string; + /** + * Move word forward in input + */ + input_word_forward?: string; + /** + * Move word backward in input + */ + input_word_backward?: string; + /** + * Select word forward in input + */ + input_select_word_forward?: string; + /** + * Select word backward in input + */ + input_select_word_backward?: string; + /** + * Delete word forward in input + */ + input_delete_word_forward?: string; + /** + * Delete word backward in input + */ + input_delete_word_backward?: 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; + /** + * Go to parent session + */ + session_parent?: string; + /** + * Suspend terminal + */ + terminal_suspend?: string; + /** + * Toggle terminal title + */ + terminal_title_toggle?: string; + /** + * Toggle tips on home screen + */ + tips_toggle?: string; +}; + +/** + * Log level + */ +export type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR'; + +/** + * Server configuration for opencode serve and web commands + */ +export type ServerConfig = { + /** + * Port to listen on + */ + port?: number; + /** + * Hostname to listen on + */ + hostname?: string; + /** + * Enable mDNS service discovery + */ + mdns?: boolean; + /** + * Additional domains to allow for CORS + */ + cors?: Array; +}; + +export type PermissionActionConfig = 'ask' | 'allow' | 'deny'; + +export type PermissionObjectConfig = { + [key: string]: PermissionActionConfig; +}; + +export type PermissionRuleConfig = PermissionActionConfig | PermissionObjectConfig; + +export type PermissionConfig = { + read?: PermissionRuleConfig; + edit?: PermissionRuleConfig; + glob?: PermissionRuleConfig; + grep?: PermissionRuleConfig; + list?: PermissionRuleConfig; + bash?: PermissionRuleConfig; + task?: PermissionRuleConfig; + external_directory?: PermissionRuleConfig; + todowrite?: PermissionActionConfig; + todoread?: PermissionActionConfig; + webfetch?: PermissionActionConfig; + websearch?: PermissionActionConfig; + codesearch?: PermissionActionConfig; + lsp?: PermissionRuleConfig; + doom_loop?: PermissionActionConfig; + [key: string]: PermissionRuleConfig | PermissionActionConfig | undefined; +} | PermissionActionConfig; + +export type AgentConfig = { + model?: string; + temperature?: number; + top_p?: number; + prompt?: string; + /** + * @deprecated Use 'permission' field instead + */ + tools?: { + [key: string]: boolean; + }; + disable?: boolean; + /** + * Description of when to use the agent + */ + description?: string; + mode?: 'subagent' | 'primary' | 'all'; + options?: { + [key: string]: unknown; + }; + /** + * Hex color code for the agent (e.g., #FF5733) + */ + color?: string; + /** + * Maximum number of agentic iterations before forcing text-only response + */ + steps?: number; + /** + * @deprecated Use 'steps' field instead. + */ + maxSteps?: number; + permission?: PermissionConfig; + [key: string]: unknown; +}; + +export type ProviderConfig = { + api?: string; + name?: string; + env?: Array; + id?: string; + npm?: string; + models?: { + [key: string]: { + id?: string; + name?: string; + family?: string; + release_date?: string; + attachment?: boolean; + reasoning?: boolean; + temperature?: boolean; + tool_call?: boolean; + interleaved?: true | { + field: 'reasoning_content' | 'reasoning_details'; + }; + 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; + }; + /** + * Variant-specific configuration + */ + variants?: { + [key: string]: { + /** + * Disable this variant for the model + */ + disabled?: boolean; + [key: string]: unknown; + }; + }; + }; + }; + whitelist?: Array; + blacklist?: Array; + 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; + }; +}; + +export type McpLocalConfig = { + /** + * Type of MCP server connection + */ + type: 'local'; + /** + * Command and arguments to run the MCP server + */ + command: Array; + /** + * Environment variables to set when running the MCP server + */ + environment?: { + [key: string]: string; + }; + /** + * Enable or disable the MCP server on startup + */ + enabled?: boolean; + /** + * 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; + logLevel?: LogLevel; + /** + * 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'; + }; + server?: ServerConfig; + /** + * Command configuration, see https://opencode.ai/docs/commands + */ + command?: { + [key: string]: { + template: string; + description?: string; + agent?: string; + model?: string; + subtask?: boolean; + }; + }; + watcher?: { + ignore?: Array; + }; + plugin?: Array; + 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; + /** + * When set, ONLY these providers will be enabled. All other providers will be ignored + */ + enabled_providers?: Array; + /** + * 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; + /** + * Default agent to use when none is specified. Must be a primary agent. Falls back to 'build' if not set or if the specified agent is invalid. + */ + default_agent?: 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; + title?: AgentConfig; + summary?: AgentConfig; + compaction?: 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; + environment?: { + [key: string]: string; + }; + extensions?: Array; + }; + }; + lsp?: false | { + [key: string]: { + disabled: true; + } | { + command: Array; + extensions?: Array; + disabled?: boolean; + env?: { + [key: string]: string; + }; + initialization?: { + [key: string]: unknown; + }; + }; + }; + /** + * Additional instruction files or patterns to include + */ + instructions?: Array; + layout?: LayoutConfig; + permission?: PermissionConfig; + tools?: { + [key: string]: boolean; + }; + enterprise?: { + /** + * Enterprise URL + */ + url?: string; + }; + compaction?: { + /** + * Enable automatic compaction when context is full (default: true) + */ + auto?: boolean; + /** + * Enable pruning of old tool outputs (default: true) + */ + prune?: boolean; + }; + experimental?: { + hook?: { + file_edited?: { + [key: string]: Array<{ + command: Array; + environment?: { + [key: string]: string; + }; + }>; + }; + session_completed?: Array<{ + command: Array; + 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; + /** + * Continue the agent loop when a tool call is denied + */ + continue_loop_on_deny?: boolean; + /** + * Timeout in milliseconds for model context protocol (MCP) requests + */ + mcp_timeout?: number; + }; +}; + +export type ToolIds = Array; + +export type ToolListItem = { + id: string; + description: string; + parameters: unknown; +}; + +export type ToolList = Array; + +export type Path = { + home: string; + 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; + command?: string; +}; + +export type Command = { + name: string; + description?: string; + agent?: string; + model?: string; + mcp?: boolean; + template: string; + subtask?: boolean; + hints: Array; +}; + +export type Model = { + id: string; + providerID: string; + api: { + id: string; + url: string; + npm: string; + }; + name: string; + family?: 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; + }; + interleaved: boolean | { + field: 'reasoning_content' | 'reasoning_details'; + }; + }; + 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; + }; + release_date: string; + variants?: { + [key: string]: { + [key: string]: unknown; + }; + }; +}; + +export type Provider = { + id: string; + name: string; + source: 'env' | 'config' | 'custom' | 'api'; + env: Array; + 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; + }>; + 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'; + native?: boolean; + hidden?: boolean; + topP?: number; + temperature?: number; + color?: string; + permission: PermissionRuleset; + model?: { + modelID: string; + providerID: string; + }; + prompt?: string; + options: { + [key: string]: unknown; + }; + steps?: 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; + 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 GlobalHealthData = { + body?: never; + path?: never; + query?: never; + url: '/global/health'; +}; + +export type GlobalHealthResponses = { + /** + * Health information + */ + 200: { + healthy: true; + version: string; + }; +}; + +export type GlobalHealthResponse = GlobalHealthResponses[keyof GlobalHealthResponses]; + +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 GlobalDisposeData = { + body?: never; + path?: never; + query?: never; + url: '/global/dispose'; +}; + +export type GlobalDisposeResponses = { + /** + * Global disposed + */ + 200: boolean; +}; + +export type GlobalDisposeResponse = GlobalDisposeResponses[keyof GlobalDisposeResponses]; + +export type ProjectListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/project'; +}; + +export type ProjectListResponses = { + /** + * List of projects + */ + 200: Array; +}; + +export type ProjectListResponse = ProjectListResponses[keyof ProjectListResponses]; + +export type ProjectCurrentData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/project/current'; +}; + +export type ProjectCurrentResponses = { + /** + * Current project information + */ + 200: Project; +}; + +export type ProjectCurrentResponse = ProjectCurrentResponses[keyof ProjectCurrentResponses]; + +export type ProjectUpdateData = { + body?: { + name?: string; + icon?: { + url?: string; + color?: string; + }; + }; + path: { + projectID: string; + }; + query?: { + directory?: string; + }; + url: '/project/{projectID}'; +}; + +export type ProjectUpdateErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type ProjectUpdateError = ProjectUpdateErrors[keyof ProjectUpdateErrors]; + +export type ProjectUpdateResponses = { + /** + * Updated project information + */ + 200: Project; +}; + +export type ProjectUpdateResponse = ProjectUpdateResponses[keyof ProjectUpdateResponses]; + +export type PtyListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/pty'; +}; + +export type PtyListResponses = { + /** + * List of sessions + */ + 200: Array; +}; + +export type PtyListResponse = PtyListResponses[keyof PtyListResponses]; + +export type PtyCreateData = { + body?: { + command?: string; + args?: Array; + 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; +}; + +export type SessionListResponse = SessionListResponses[keyof SessionListResponses]; + +export type SessionCreateData = { + body?: { + parentID?: string; + title?: string; + permission?: PermissionRuleset; + }; + 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; + time?: { + archived?: number; + }; + }; + 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; +}; + +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; +}; + +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; +}; + +export type SessionDiffResponse = SessionDiffResponses[keyof SessionDiffResponses]; + +export type SessionSummarizeData = { + body?: { + providerID: string; + modelID: string; + auto?: boolean; + }; + 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; + }>; +}; + +export type SessionMessagesResponse = SessionMessagesResponses[keyof SessionMessagesResponses]; + +export type SessionPromptData = { + body?: { + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + /** + * @deprecated tools and permissions have been merged, you can set permissions on the session itself now + */ + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; + }; + 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; + }; +}; + +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; + }; +}; + +export type SessionMessageResponse = SessionMessageResponses[keyof SessionMessageResponses]; + +export type PartDeleteData = { + body?: never; + path: { + /** + * Session ID + */ + sessionID: string; + /** + * Message ID + */ + messageID: string; + /** + * Part ID + */ + partID: string; + }; + query?: { + directory?: string; + }; + url: '/session/{sessionID}/message/{messageID}/part/{partID}'; +}; + +export type PartDeleteErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type PartDeleteError = PartDeleteErrors[keyof PartDeleteErrors]; + +export type PartDeleteResponses = { + /** + * Successfully deleted part + */ + 200: boolean; +}; + +export type PartDeleteResponse = PartDeleteResponses[keyof PartDeleteResponses]; + +export type PartUpdateData = { + body?: Part; + path: { + /** + * Session ID + */ + sessionID: string; + /** + * Message ID + */ + messageID: string; + /** + * Part ID + */ + partID: string; + }; + query?: { + directory?: string; + }; + url: '/session/{sessionID}/message/{messageID}/part/{partID}'; +}; + +export type PartUpdateErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type PartUpdateError = PartUpdateErrors[keyof PartUpdateErrors]; + +export type PartUpdateResponses = { + /** + * Successfully updated part + */ + 200: Part; +}; + +export type PartUpdateResponse = PartUpdateResponses[keyof PartUpdateResponses]; + +export type SessionPromptAsyncData = { + body?: { + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + /** + * @deprecated tools and permissions have been merged, you can set permissions on the session itself now + */ + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; + }; + 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; + variant?: 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; + }; +}; + +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 PermissionReplyData = { + body?: { + reply: 'once' | 'always' | 'reject'; + }; + path: { + requestID: string; + }; + query?: { + directory?: string; + }; + url: '/permission/{requestID}/reply'; +}; + +export type PermissionReplyErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type PermissionReplyError = PermissionReplyErrors[keyof PermissionReplyErrors]; + +export type PermissionReplyResponses = { + /** + * Permission processed successfully + */ + 200: boolean; +}; + +export type PermissionReplyResponse = PermissionReplyResponses[keyof PermissionReplyResponses]; + +export type PermissionListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/permission'; +}; + +export type PermissionListResponses = { + /** + * List of pending permissions + */ + 200: Array; +}; + +export type PermissionListResponse = PermissionListResponses[keyof PermissionListResponses]; + +export type CommandListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/command'; +}; + +export type CommandListResponses = { + /** + * List of commands + */ + 200: Array; +}; + +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; + 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; + id: string; + npm?: string; + models: { + [key: string]: { + id: string; + name: string; + family?: string; + release_date: string; + attachment: boolean; + reasoning: boolean; + temperature: boolean; + tool_call: boolean; + interleaved?: true | { + field: 'reasoning_content' | 'reasoning_details'; + }; + 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; + }; + variants?: { + [key: string]: { + [key: string]: unknown; + }; + }; + }; + }; + }>; + default: { + [key: string]: string; + }; + connected: Array; + }; +}; + +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; + }; +}; + +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'; + type?: 'file' | 'directory'; + limit?: number; + }; + url: '/find/file'; +}; + +export type FindFilesResponses = { + /** + * File paths + */ + 200: Array; +}; + +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; +}; + +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; +}; + +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; +}; + +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; +}; + +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 McpConnectData = { + body?: never; + path: { + name: string; + }; + query?: { + directory?: string; + }; + url: '/mcp/{name}/connect'; +}; + +export type McpConnectResponses = { + /** + * MCP server connected successfully + */ + 200: boolean; +}; + +export type McpConnectResponse = McpConnectResponses[keyof McpConnectResponses]; + +export type McpDisconnectData = { + body?: never; + path: { + name: string; + }; + query?: { + directory?: string; + }; + url: '/mcp/{name}/disconnect'; +}; + +export type McpDisconnectResponses = { + /** + * MCP server disconnected successfully + */ + 200: boolean; +}; + +export type McpDisconnectResponse = McpDisconnectResponses[keyof McpDisconnectResponses]; + +export type LspStatusData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/lsp'; +}; + +export type LspStatusResponses = { + /** + * LSP server status + */ + 200: Array; +}; + +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; +}; + +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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/zod.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/zod.gen.ts new file mode 100644 index 0000000000..3d21c8726b --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-by-tags/zod.gen.ts @@ -0,0 +1,2749 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import * as z from 'zod'; + +export const zEventInstallationUpdated = z.object({ + type: z.literal('installation.updated'), + properties: z.object({ + version: z.string() + }) +}); + +export const zEventInstallationUpdateAvailable = z.object({ + type: z.literal('installation.update-available'), + properties: z.object({ + version: z.string() + }) +}); + +export const zProject = z.object({ + id: z.string(), + worktree: z.string(), + vcs: z.literal('git').optional(), + name: z.string().optional(), + icon: z.object({ + url: z.string().optional(), + color: z.string().optional() + }).optional(), + time: z.object({ + created: z.number(), + updated: z.number(), + initialized: z.number().optional() + }) +}); + +export const zEventProjectUpdated = z.object({ + type: z.literal('project.updated'), + properties: zProject +}); + +export const zEventServerInstanceDisposed = z.object({ + type: z.literal('server.instance.disposed'), + properties: z.object({ + directory: z.string() + }) +}); + +export const zEventLspClientDiagnostics = z.object({ + type: z.literal('lsp.client.diagnostics'), + properties: z.object({ + serverID: z.string(), + path: z.string() + }) +}); + +export const zEventLspUpdated = z.object({ + type: z.literal('lsp.updated'), + properties: z.record(z.string(), z.unknown()) +}); + +export const zFileDiff = z.object({ + file: z.string(), + before: z.string(), + after: z.string(), + additions: z.number(), + deletions: z.number() +}); + +export const zUserMessage = z.object({ + id: z.string(), + sessionID: z.string(), + role: z.literal('user'), + time: z.object({ + created: z.number() + }), + summary: z.object({ + title: z.string().optional(), + body: z.string().optional(), + diffs: z.array(zFileDiff) + }).optional(), + agent: z.string(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }), + system: z.string().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + variant: z.string().optional() +}); + +export const zProviderAuthError = z.object({ + name: z.literal('ProviderAuthError'), + data: z.object({ + providerID: z.string(), + message: z.string() + }) +}); + +export const zUnknownError = z.object({ + name: z.literal('UnknownError'), + data: z.object({ + message: z.string() + }) +}); + +export const zMessageOutputLengthError = z.object({ + name: z.literal('MessageOutputLengthError'), + data: z.record(z.string(), z.unknown()) +}); + +export const zMessageAbortedError = z.object({ + name: z.literal('MessageAbortedError'), + data: z.object({ + message: z.string() + }) +}); + +export const zApiError = z.object({ + name: z.literal('APIError'), + data: z.object({ + message: z.string(), + statusCode: z.number().optional(), + isRetryable: z.boolean(), + responseHeaders: z.record(z.string(), z.string()).optional(), + responseBody: z.string().optional(), + metadata: z.record(z.string(), z.string()).optional() + }) +}); + +export const zAssistantMessage = z.object({ + id: z.string(), + sessionID: z.string(), + role: z.literal('assistant'), + time: z.object({ + created: z.number(), + completed: z.number().optional() + }), + error: z.union([ + zProviderAuthError, + zUnknownError, + zMessageOutputLengthError, + zMessageAbortedError, + zApiError + ]).optional(), + parentID: z.string(), + modelID: z.string(), + providerID: z.string(), + mode: z.string(), + agent: z.string(), + path: z.object({ + cwd: z.string(), + root: z.string() + }), + summary: z.boolean().optional(), + cost: z.number(), + tokens: z.object({ + input: z.number(), + output: z.number(), + reasoning: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }) + }), + finish: z.string().optional() +}); + +export const zMessage = z.union([ + zUserMessage, + zAssistantMessage +]); + +export const zEventMessageUpdated = z.object({ + type: z.literal('message.updated'), + properties: z.object({ + info: zMessage + }) +}); + +export const zEventMessageRemoved = z.object({ + type: z.literal('message.removed'), + properties: z.object({ + sessionID: z.string(), + messageID: z.string() + }) +}); + +export const zTextPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('text'), + text: z.string(), + synthetic: z.boolean().optional(), + ignored: z.boolean().optional(), + time: z.object({ + start: z.number(), + end: z.number().optional() + }).optional(), + metadata: z.record(z.string(), z.unknown()).optional() +}); + +export const zReasoningPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('reasoning'), + text: z.string(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number(), + end: z.number().optional() + }) +}); + +export const zFilePartSourceText = z.object({ + value: z.string(), + start: z.int().gte(-9007199254740991).lte(9007199254740991), + end: z.int().gte(-9007199254740991).lte(9007199254740991) +}); + +export const zFileSource = z.object({ + text: zFilePartSourceText, + type: z.literal('file'), + path: z.string() +}); + +export const zRange = z.object({ + start: z.object({ + line: z.number(), + character: z.number() + }), + end: z.object({ + line: z.number(), + character: z.number() + }) +}); + +export const zSymbolSource = z.object({ + text: zFilePartSourceText, + type: z.literal('symbol'), + path: z.string(), + range: zRange, + name: z.string(), + kind: z.int().gte(-9007199254740991).lte(9007199254740991) +}); + +export const zFilePartSource = z.union([ + zFileSource, + zSymbolSource +]); + +export const zFilePart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('file'), + mime: z.string(), + filename: z.string().optional(), + url: z.string(), + source: zFilePartSource.optional() +}); + +export const zToolStatePending = z.object({ + status: z.literal('pending'), + input: z.record(z.string(), z.unknown()), + raw: z.string() +}); + +export const zToolStateRunning = z.object({ + status: z.literal('running'), + input: z.record(z.string(), z.unknown()), + title: z.string().optional(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number() + }) +}); + +export const zToolStateCompleted = z.object({ + status: z.literal('completed'), + input: z.record(z.string(), z.unknown()), + output: z.string(), + title: z.string(), + metadata: z.record(z.string(), z.unknown()), + time: z.object({ + start: z.number(), + end: z.number(), + compacted: z.number().optional() + }), + attachments: z.array(zFilePart).optional() +}); + +export const zToolStateError = z.object({ + status: z.literal('error'), + input: z.record(z.string(), z.unknown()), + error: z.string(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number(), + end: z.number() + }) +}); + +export const zToolState = z.union([ + zToolStatePending, + zToolStateRunning, + zToolStateCompleted, + zToolStateError +]); + +export const zToolPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('tool'), + callID: z.string(), + tool: z.string(), + state: zToolState, + metadata: z.record(z.string(), z.unknown()).optional() +}); + +export const zStepStartPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('step-start'), + snapshot: z.string().optional() +}); + +export const zStepFinishPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('step-finish'), + reason: z.string(), + snapshot: z.string().optional(), + cost: z.number(), + tokens: z.object({ + input: z.number(), + output: z.number(), + reasoning: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }) + }) +}); + +export const zSnapshotPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('snapshot'), + snapshot: z.string() +}); + +export const zPatchPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('patch'), + hash: z.string(), + files: z.array(z.string()) +}); + +export const zAgentPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('agent'), + name: z.string(), + source: z.object({ + value: z.string(), + start: z.int().gte(-9007199254740991).lte(9007199254740991), + end: z.int().gte(-9007199254740991).lte(9007199254740991) + }).optional() +}); + +export const zRetryPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('retry'), + attempt: z.number(), + error: zApiError, + time: z.object({ + created: z.number() + }) +}); + +export const zCompactionPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('compaction'), + auto: z.boolean() +}); + +export const zPart = z.union([ + zTextPart, + z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('subtask'), + prompt: z.string(), + description: z.string(), + agent: z.string(), + command: z.string().optional() + }), + zReasoningPart, + zFilePart, + zToolPart, + zStepStartPart, + zStepFinishPart, + zSnapshotPart, + zPatchPart, + zAgentPart, + zRetryPart, + zCompactionPart +]); + +export const zEventMessagePartUpdated = z.object({ + type: z.literal('message.part.updated'), + properties: z.object({ + part: zPart, + delta: z.string().optional() + }) +}); + +export const zEventMessagePartRemoved = z.object({ + type: z.literal('message.part.removed'), + properties: z.object({ + sessionID: z.string(), + messageID: z.string(), + partID: z.string() + }) +}); + +export const zPermissionRequest = z.object({ + id: z.string().regex(/^per.*/), + sessionID: z.string().regex(/^ses.*/), + permission: z.string(), + patterns: z.array(z.string()), + metadata: z.record(z.string(), z.unknown()), + always: z.array(z.string()), + tool: z.object({ + messageID: z.string(), + callID: z.string() + }).optional() +}); + +export const zEventPermissionAsked = z.object({ + type: z.literal('permission.asked'), + properties: zPermissionRequest +}); + +export const zEventPermissionReplied = z.object({ + type: z.literal('permission.replied'), + properties: z.object({ + sessionID: z.string(), + requestID: z.string(), + reply: z.enum([ + 'once', + 'always', + 'reject' + ]) + }) +}); + +export const zSessionStatus = z.union([ + z.object({ + type: z.literal('idle') + }), + z.object({ + type: z.literal('retry'), + attempt: z.number(), + message: z.string(), + next: z.number() + }), + z.object({ + type: z.literal('busy') + }) +]); + +export const zEventSessionStatus = z.object({ + type: z.literal('session.status'), + properties: z.object({ + sessionID: z.string(), + status: zSessionStatus + }) +}); + +export const zEventSessionIdle = z.object({ + type: z.literal('session.idle'), + properties: z.object({ + sessionID: z.string() + }) +}); + +export const zEventSessionCompacted = z.object({ + type: z.literal('session.compacted'), + properties: z.object({ + sessionID: z.string() + }) +}); + +export const zEventFileEdited = z.object({ + type: z.literal('file.edited'), + properties: z.object({ + file: z.string() + }) +}); + +export const zTodo = z.object({ + content: z.string(), + status: z.string(), + priority: z.string(), + id: z.string() +}); + +export const zEventTodoUpdated = z.object({ + type: z.literal('todo.updated'), + properties: z.object({ + sessionID: z.string(), + todos: z.array(zTodo) + }) +}); + +export const zEventTuiPromptAppend = z.object({ + type: z.literal('tui.prompt.append'), + properties: z.object({ + text: z.string() + }) +}); + +export const zEventTuiCommandExecute = z.object({ + type: z.literal('tui.command.execute'), + properties: z.object({ + command: z.union([ + z.enum([ + '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' + ]), + z.string() + ]) + }) +}); + +export const zEventTuiToastShow = z.object({ + type: z.literal('tui.toast.show'), + properties: z.object({ + title: z.string().optional(), + message: z.string(), + variant: z.enum([ + 'info', + 'success', + 'warning', + 'error' + ]), + duration: z.number().optional().default(5000) + }) +}); + +export const zEventMcpToolsChanged = z.object({ + type: z.literal('mcp.tools.changed'), + properties: z.object({ + server: z.string() + }) +}); + +export const zEventCommandExecuted = z.object({ + type: z.literal('command.executed'), + properties: z.object({ + name: z.string(), + sessionID: z.string().regex(/^ses.*/), + arguments: z.string(), + messageID: z.string().regex(/^msg.*/) + }) +}); + +export const zPermissionAction = z.enum([ + 'allow', + 'deny', + 'ask' +]); + +export const zPermissionRule = z.object({ + permission: z.string(), + pattern: z.string(), + action: zPermissionAction +}); + +export const zPermissionRuleset = z.array(zPermissionRule); + +export const zSession = z.object({ + id: z.string().regex(/^ses.*/), + projectID: z.string(), + directory: z.string(), + parentID: z.string().regex(/^ses.*/).optional(), + summary: z.object({ + additions: z.number(), + deletions: z.number(), + files: z.number(), + diffs: z.array(zFileDiff).optional() + }).optional(), + share: z.object({ + url: z.string() + }).optional(), + title: z.string(), + version: z.string(), + time: z.object({ + created: z.number(), + updated: z.number(), + compacting: z.number().optional(), + archived: z.number().optional() + }), + permission: zPermissionRuleset.optional(), + revert: z.object({ + messageID: z.string(), + partID: z.string().optional(), + snapshot: z.string().optional(), + diff: z.string().optional() + }).optional() +}); + +export const zEventSessionCreated = z.object({ + type: z.literal('session.created'), + properties: z.object({ + info: zSession + }) +}); + +export const zEventSessionUpdated = z.object({ + type: z.literal('session.updated'), + properties: z.object({ + info: zSession + }) +}); + +export const zEventSessionDeleted = z.object({ + type: z.literal('session.deleted'), + properties: z.object({ + info: zSession + }) +}); + +export const zEventSessionDiff = z.object({ + type: z.literal('session.diff'), + properties: z.object({ + sessionID: z.string(), + diff: z.array(zFileDiff) + }) +}); + +export const zEventSessionError = z.object({ + type: z.literal('session.error'), + properties: z.object({ + sessionID: z.string().optional(), + error: z.union([ + zProviderAuthError, + zUnknownError, + zMessageOutputLengthError, + zMessageAbortedError, + zApiError + ]).optional() + }) +}); + +export const zEventFileWatcherUpdated = z.object({ + type: z.literal('file.watcher.updated'), + properties: z.object({ + file: z.string(), + event: z.union([ + z.literal('add'), + z.literal('change'), + z.literal('unlink') + ]) + }) +}); + +export const zEventVcsBranchUpdated = z.object({ + type: z.literal('vcs.branch.updated'), + properties: z.object({ + branch: z.string().optional() + }) +}); + +export const zPty = z.object({ + id: z.string().regex(/^pty.*/), + title: z.string(), + command: z.string(), + args: z.array(z.string()), + cwd: z.string(), + status: z.enum(['running', 'exited']), + pid: z.number() +}); + +export const zEventPtyCreated = z.object({ + type: z.literal('pty.created'), + properties: z.object({ + info: zPty + }) +}); + +export const zEventPtyUpdated = z.object({ + type: z.literal('pty.updated'), + properties: z.object({ + info: zPty + }) +}); + +export const zEventPtyExited = z.object({ + type: z.literal('pty.exited'), + properties: z.object({ + id: z.string().regex(/^pty.*/), + exitCode: z.number() + }) +}); + +export const zEventPtyDeleted = z.object({ + type: z.literal('pty.deleted'), + properties: z.object({ + id: z.string().regex(/^pty.*/) + }) +}); + +export const zEventServerConnected = z.object({ + type: z.literal('server.connected'), + properties: z.record(z.string(), z.unknown()) +}); + +export const zEventGlobalDisposed = z.object({ + type: z.literal('global.disposed'), + properties: z.record(z.string(), z.unknown()) +}); + +export const zEvent = z.union([ + zEventInstallationUpdated, + zEventInstallationUpdateAvailable, + zEventProjectUpdated, + zEventServerInstanceDisposed, + zEventLspClientDiagnostics, + zEventLspUpdated, + zEventMessageUpdated, + zEventMessageRemoved, + zEventMessagePartUpdated, + zEventMessagePartRemoved, + zEventPermissionAsked, + zEventPermissionReplied, + zEventSessionStatus, + zEventSessionIdle, + zEventSessionCompacted, + zEventFileEdited, + zEventTodoUpdated, + zEventTuiPromptAppend, + zEventTuiCommandExecute, + zEventTuiToastShow, + zEventMcpToolsChanged, + zEventCommandExecuted, + zEventSessionCreated, + zEventSessionUpdated, + zEventSessionDeleted, + zEventSessionDiff, + zEventSessionError, + zEventFileWatcherUpdated, + zEventVcsBranchUpdated, + zEventPtyCreated, + zEventPtyUpdated, + zEventPtyExited, + zEventPtyDeleted, + zEventServerConnected, + zEventGlobalDisposed +]); + +export const zGlobalEvent = z.object({ + directory: z.string(), + payload: zEvent +}); + +export const zBadRequestError = z.object({ + data: z.unknown(), + errors: z.array(z.record(z.string(), z.unknown())), + success: z.literal(false) +}); + +export const zNotFoundError = z.object({ + name: z.literal('NotFoundError'), + data: z.object({ + message: z.string() + }) +}); + +/** + * Custom keybind configurations + */ +export const zKeybindsConfig = z.object({ + leader: z.string().optional().default('ctrl+x'), + app_exit: z.string().optional().default('ctrl+c,ctrl+d,q'), + editor_open: z.string().optional().default('e'), + theme_list: z.string().optional().default('t'), + sidebar_toggle: z.string().optional().default('b'), + scrollbar_toggle: z.string().optional().default('none'), + username_toggle: z.string().optional().default('none'), + status_view: z.string().optional().default('s'), + session_export: z.string().optional().default('x'), + session_new: z.string().optional().default('n'), + session_list: z.string().optional().default('l'), + session_timeline: z.string().optional().default('g'), + session_fork: z.string().optional().default('none'), + session_rename: z.string().optional().default('none'), + session_share: z.string().optional().default('none'), + session_unshare: z.string().optional().default('none'), + session_interrupt: z.string().optional().default('escape'), + session_compact: z.string().optional().default('c'), + messages_page_up: z.string().optional().default('pageup'), + messages_page_down: z.string().optional().default('pagedown'), + messages_half_page_up: z.string().optional().default('ctrl+alt+u'), + messages_half_page_down: z.string().optional().default('ctrl+alt+d'), + messages_first: z.string().optional().default('ctrl+g,home'), + messages_last: z.string().optional().default('ctrl+alt+g,end'), + messages_next: z.string().optional().default('none'), + messages_previous: z.string().optional().default('none'), + messages_last_user: z.string().optional().default('none'), + messages_copy: z.string().optional().default('y'), + messages_undo: z.string().optional().default('u'), + messages_redo: z.string().optional().default('r'), + messages_toggle_conceal: z.string().optional().default('h'), + tool_details: z.string().optional().default('none'), + model_list: z.string().optional().default('m'), + model_cycle_recent: z.string().optional().default('f2'), + model_cycle_recent_reverse: z.string().optional().default('shift+f2'), + model_cycle_favorite: z.string().optional().default('none'), + model_cycle_favorite_reverse: z.string().optional().default('none'), + command_list: z.string().optional().default('ctrl+p'), + agent_list: z.string().optional().default('a'), + agent_cycle: z.string().optional().default('tab'), + agent_cycle_reverse: z.string().optional().default('shift+tab'), + variant_cycle: z.string().optional().default('ctrl+t'), + input_clear: z.string().optional().default('ctrl+c'), + input_paste: z.string().optional().default('ctrl+v'), + input_submit: z.string().optional().default('return'), + input_newline: z.string().optional().default('shift+return,ctrl+return,alt+return,ctrl+j'), + input_move_left: z.string().optional().default('left,ctrl+b'), + input_move_right: z.string().optional().default('right,ctrl+f'), + input_move_up: z.string().optional().default('up'), + input_move_down: z.string().optional().default('down'), + input_select_left: z.string().optional().default('shift+left'), + input_select_right: z.string().optional().default('shift+right'), + input_select_up: z.string().optional().default('shift+up'), + input_select_down: z.string().optional().default('shift+down'), + input_line_home: z.string().optional().default('ctrl+a'), + input_line_end: z.string().optional().default('ctrl+e'), + input_select_line_home: z.string().optional().default('ctrl+shift+a'), + input_select_line_end: z.string().optional().default('ctrl+shift+e'), + input_visual_line_home: z.string().optional().default('alt+a'), + input_visual_line_end: z.string().optional().default('alt+e'), + input_select_visual_line_home: z.string().optional().default('alt+shift+a'), + input_select_visual_line_end: z.string().optional().default('alt+shift+e'), + input_buffer_home: z.string().optional().default('home'), + input_buffer_end: z.string().optional().default('end'), + input_select_buffer_home: z.string().optional().default('shift+home'), + input_select_buffer_end: z.string().optional().default('shift+end'), + input_delete_line: z.string().optional().default('ctrl+shift+d'), + input_delete_to_line_end: z.string().optional().default('ctrl+k'), + input_delete_to_line_start: z.string().optional().default('ctrl+u'), + input_backspace: z.string().optional().default('backspace,shift+backspace'), + input_delete: z.string().optional().default('ctrl+d,delete,shift+delete'), + input_undo: z.string().optional().default('ctrl+-,super+z'), + input_redo: z.string().optional().default('ctrl+.,super+shift+z'), + input_word_forward: z.string().optional().default('alt+f,alt+right,ctrl+right'), + input_word_backward: z.string().optional().default('alt+b,alt+left,ctrl+left'), + input_select_word_forward: z.string().optional().default('alt+shift+f,alt+shift+right'), + input_select_word_backward: z.string().optional().default('alt+shift+b,alt+shift+left'), + input_delete_word_forward: z.string().optional().default('alt+d,alt+delete,ctrl+delete'), + input_delete_word_backward: z.string().optional().default('ctrl+w,ctrl+backspace,alt+backspace'), + history_previous: z.string().optional().default('up'), + history_next: z.string().optional().default('down'), + session_child_cycle: z.string().optional().default('right'), + session_child_cycle_reverse: z.string().optional().default('left'), + session_parent: z.string().optional().default('up'), + terminal_suspend: z.string().optional().default('ctrl+z'), + terminal_title_toggle: z.string().optional().default('none'), + tips_toggle: z.string().optional().default('h') +}); + +/** + * Log level + */ +export const zLogLevel = z.enum([ + 'DEBUG', + 'INFO', + 'WARN', + 'ERROR' +]); + +/** + * Server configuration for opencode serve and web commands + */ +export const zServerConfig = z.object({ + port: z.int().gt(0).lte(9007199254740991).optional(), + hostname: z.string().optional(), + mdns: z.boolean().optional(), + cors: z.array(z.string()).optional() +}); + +export const zPermissionActionConfig = z.enum([ + 'ask', + 'allow', + 'deny' +]); + +export const zPermissionObjectConfig = z.record(z.string(), zPermissionActionConfig); + +export const zPermissionRuleConfig = z.union([ + zPermissionActionConfig, + zPermissionObjectConfig +]); + +export const zPermissionConfig = z.union([ + z.object({ + read: zPermissionRuleConfig.optional(), + edit: zPermissionRuleConfig.optional(), + glob: zPermissionRuleConfig.optional(), + grep: zPermissionRuleConfig.optional(), + list: zPermissionRuleConfig.optional(), + bash: zPermissionRuleConfig.optional(), + task: zPermissionRuleConfig.optional(), + external_directory: zPermissionRuleConfig.optional(), + todowrite: zPermissionActionConfig.optional(), + todoread: zPermissionActionConfig.optional(), + webfetch: zPermissionActionConfig.optional(), + websearch: zPermissionActionConfig.optional(), + codesearch: zPermissionActionConfig.optional(), + lsp: zPermissionRuleConfig.optional(), + doom_loop: zPermissionActionConfig.optional() + }), + zPermissionActionConfig +]); + +export const zAgentConfig = z.object({ + model: z.string().optional(), + temperature: z.number().optional(), + top_p: z.number().optional(), + prompt: z.string().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + disable: z.boolean().optional(), + description: z.string().optional(), + mode: z.enum([ + 'subagent', + 'primary', + 'all' + ]).optional(), + options: z.record(z.string(), z.unknown()).optional(), + color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional(), + steps: z.int().gt(0).lte(9007199254740991).optional(), + maxSteps: z.int().gt(0).lte(9007199254740991).optional(), + permission: zPermissionConfig.optional() +}); + +export const zProviderConfig = z.object({ + api: z.string().optional(), + name: z.string().optional(), + env: z.array(z.string()).optional(), + id: z.string().optional(), + npm: z.string().optional(), + models: z.record(z.string(), z.object({ + id: z.string().optional(), + name: z.string().optional(), + family: z.string().optional(), + release_date: z.string().optional(), + attachment: z.boolean().optional(), + reasoning: z.boolean().optional(), + temperature: z.boolean().optional(), + tool_call: z.boolean().optional(), + interleaved: z.union([ + z.literal(true), + z.object({ + field: z.enum(['reasoning_content', 'reasoning_details']) + }) + ]).optional(), + cost: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional(), + context_over_200k: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional() + }).optional() + }).optional(), + limit: z.object({ + context: z.number(), + output: z.number() + }).optional(), + modalities: z.object({ + input: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])), + output: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])) + }).optional(), + experimental: z.boolean().optional(), + status: z.enum([ + 'alpha', + 'beta', + 'deprecated' + ]).optional(), + options: z.record(z.string(), z.unknown()).optional(), + headers: z.record(z.string(), z.string()).optional(), + provider: z.object({ + npm: z.string() + }).optional(), + variants: z.record(z.string(), z.object({ + disabled: z.boolean().optional() + })).optional() + })).optional(), + whitelist: z.array(z.string()).optional(), + blacklist: z.array(z.string()).optional(), + options: z.object({ + apiKey: z.string().optional(), + baseURL: z.string().optional(), + enterpriseUrl: z.string().optional(), + setCacheKey: z.boolean().optional(), + timeout: z.union([ + z.int().gt(0).lte(9007199254740991), + z.literal(false) + ]).optional() + }).optional() +}); + +export const zMcpLocalConfig = z.object({ + type: z.literal('local'), + command: z.array(z.string()), + environment: z.record(z.string(), z.string()).optional(), + enabled: z.boolean().optional(), + timeout: z.int().gt(0).lte(9007199254740991).optional() +}); + +export const zMcpOAuthConfig = z.object({ + clientId: z.string().optional(), + clientSecret: z.string().optional(), + scope: z.string().optional() +}); + +export const zMcpRemoteConfig = z.object({ + type: z.literal('remote'), + url: z.string(), + enabled: z.boolean().optional(), + headers: z.record(z.string(), z.string()).optional(), + oauth: z.union([ + zMcpOAuthConfig, + z.literal(false) + ]).optional(), + timeout: z.int().gt(0).lte(9007199254740991).optional() +}); + +/** + * @deprecated Always uses stretch layout. + */ +export const zLayoutConfig = z.enum(['auto', 'stretch']); + +export const zConfig = z.object({ + $schema: z.string().optional(), + theme: z.string().optional(), + keybinds: zKeybindsConfig.optional(), + logLevel: zLogLevel.optional(), + tui: z.object({ + scroll_speed: z.number().gte(0.001).optional(), + scroll_acceleration: z.object({ + enabled: z.boolean() + }).optional(), + diff_style: z.enum(['auto', 'stacked']).optional() + }).optional(), + server: zServerConfig.optional(), + command: z.record(z.string(), z.object({ + template: z.string(), + description: z.string().optional(), + agent: z.string().optional(), + model: z.string().optional(), + subtask: z.boolean().optional() + })).optional(), + watcher: z.object({ + ignore: z.array(z.string()).optional() + }).optional(), + plugin: z.array(z.string()).optional(), + snapshot: z.boolean().optional(), + share: z.enum([ + 'manual', + 'auto', + 'disabled' + ]).optional(), + autoshare: z.boolean().optional(), + autoupdate: z.union([ + z.boolean(), + z.literal('notify') + ]).optional(), + disabled_providers: z.array(z.string()).optional(), + enabled_providers: z.array(z.string()).optional(), + model: z.string().optional(), + small_model: z.string().optional(), + default_agent: z.string().optional(), + username: z.string().optional(), + mode: z.object({ + build: zAgentConfig.optional(), + plan: zAgentConfig.optional() + }).optional(), + agent: z.object({ + plan: zAgentConfig.optional(), + build: zAgentConfig.optional(), + general: zAgentConfig.optional(), + explore: zAgentConfig.optional(), + title: zAgentConfig.optional(), + summary: zAgentConfig.optional(), + compaction: zAgentConfig.optional() + }).optional(), + provider: z.record(z.string(), zProviderConfig).optional(), + mcp: z.record(z.string(), z.union([ + zMcpLocalConfig, + zMcpRemoteConfig + ])).optional(), + formatter: z.union([ + z.literal(false), + z.record(z.string(), z.object({ + disabled: z.boolean().optional(), + command: z.array(z.string()).optional(), + environment: z.record(z.string(), z.string()).optional(), + extensions: z.array(z.string()).optional() + })) + ]).optional(), + lsp: z.union([ + z.literal(false), + z.record(z.string(), z.union([ + z.object({ + disabled: z.literal(true) + }), + z.object({ + command: z.array(z.string()), + extensions: z.array(z.string()).optional(), + disabled: z.boolean().optional(), + env: z.record(z.string(), z.string()).optional(), + initialization: z.record(z.string(), z.unknown()).optional() + }) + ])) + ]).optional(), + instructions: z.array(z.string()).optional(), + layout: zLayoutConfig.optional(), + permission: zPermissionConfig.optional(), + tools: z.record(z.string(), z.boolean()).optional(), + enterprise: z.object({ + url: z.string().optional() + }).optional(), + compaction: z.object({ + auto: z.boolean().optional(), + prune: z.boolean().optional() + }).optional(), + experimental: z.object({ + hook: z.object({ + file_edited: z.record(z.string(), z.array(z.object({ + command: z.array(z.string()), + environment: z.record(z.string(), z.string()).optional() + }))).optional(), + session_completed: z.array(z.object({ + command: z.array(z.string()), + environment: z.record(z.string(), z.string()).optional() + })).optional() + }).optional(), + chatMaxRetries: z.number().optional(), + disable_paste_summary: z.boolean().optional(), + batch_tool: z.boolean().optional(), + openTelemetry: z.boolean().optional(), + primary_tools: z.array(z.string()).optional(), + continue_loop_on_deny: z.boolean().optional(), + mcp_timeout: z.int().gt(0).lte(9007199254740991).optional() + }).optional() +}); + +export const zToolIds = z.array(z.string()); + +export const zToolListItem = z.object({ + id: z.string(), + description: z.string(), + parameters: z.unknown() +}); + +export const zToolList = z.array(zToolListItem); + +export const zPath = z.object({ + home: z.string(), + state: z.string(), + config: z.string(), + worktree: z.string(), + directory: z.string() +}); + +export const zVcsInfo = z.object({ + branch: z.string() +}); + +export const zTextPartInput = z.object({ + id: z.string().optional(), + type: z.literal('text'), + text: z.string(), + synthetic: z.boolean().optional(), + ignored: z.boolean().optional(), + time: z.object({ + start: z.number(), + end: z.number().optional() + }).optional(), + metadata: z.record(z.string(), z.unknown()).optional() +}); + +export const zFilePartInput = z.object({ + id: z.string().optional(), + type: z.literal('file'), + mime: z.string(), + filename: z.string().optional(), + url: z.string(), + source: zFilePartSource.optional() +}); + +export const zAgentPartInput = z.object({ + id: z.string().optional(), + type: z.literal('agent'), + name: z.string(), + source: z.object({ + value: z.string(), + start: z.int().gte(-9007199254740991).lte(9007199254740991), + end: z.int().gte(-9007199254740991).lte(9007199254740991) + }).optional() +}); + +export const zSubtaskPartInput = z.object({ + id: z.string().optional(), + type: z.literal('subtask'), + prompt: z.string(), + description: z.string(), + agent: z.string(), + command: z.string().optional() +}); + +export const zCommand = z.object({ + name: z.string(), + description: z.string().optional(), + agent: z.string().optional(), + model: z.string().optional(), + mcp: z.boolean().optional(), + template: z.string(), + subtask: z.boolean().optional(), + hints: z.array(z.string()) +}); + +export const zModel = z.object({ + id: z.string(), + providerID: z.string(), + api: z.object({ + id: z.string(), + url: z.string(), + npm: z.string() + }), + name: z.string(), + family: z.string().optional(), + capabilities: z.object({ + temperature: z.boolean(), + reasoning: z.boolean(), + attachment: z.boolean(), + toolcall: z.boolean(), + input: z.object({ + text: z.boolean(), + audio: z.boolean(), + image: z.boolean(), + video: z.boolean(), + pdf: z.boolean() + }), + output: z.object({ + text: z.boolean(), + audio: z.boolean(), + image: z.boolean(), + video: z.boolean(), + pdf: z.boolean() + }), + interleaved: z.union([ + z.boolean(), + z.object({ + field: z.enum(['reasoning_content', 'reasoning_details']) + }) + ]) + }), + cost: z.object({ + input: z.number(), + output: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }), + experimentalOver200K: z.object({ + input: z.number(), + output: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }) + }).optional() + }), + limit: z.object({ + context: z.number(), + output: z.number() + }), + status: z.enum([ + 'alpha', + 'beta', + 'deprecated', + 'active' + ]), + options: z.record(z.string(), z.unknown()), + headers: z.record(z.string(), z.string()), + release_date: z.string(), + variants: z.record(z.string(), z.record(z.string(), z.unknown())).optional() +}); + +export const zProvider = z.object({ + id: z.string(), + name: z.string(), + source: z.enum([ + 'env', + 'config', + 'custom', + 'api' + ]), + env: z.array(z.string()), + key: z.string().optional(), + options: z.record(z.string(), z.unknown()), + models: z.record(z.string(), zModel) +}); + +export const zProviderAuthMethod = z.object({ + type: z.union([ + z.literal('oauth'), + z.literal('api') + ]), + label: z.string() +}); + +export const zProviderAuthAuthorization = z.object({ + url: z.string(), + method: z.union([ + z.literal('auto'), + z.literal('code') + ]), + instructions: z.string() +}); + +export const zSymbol = z.object({ + name: z.string(), + kind: z.number(), + location: z.object({ + uri: z.string(), + range: zRange + }) +}); + +export const zFileNode = z.object({ + name: z.string(), + path: z.string(), + absolute: z.string(), + type: z.enum(['file', 'directory']), + ignored: z.boolean() +}); + +export const zFileContent = z.object({ + type: z.literal('text'), + content: z.string(), + diff: z.string().optional(), + patch: z.object({ + oldFileName: z.string(), + newFileName: z.string(), + oldHeader: z.string().optional(), + newHeader: z.string().optional(), + hunks: z.array(z.object({ + oldStart: z.number(), + oldLines: z.number(), + newStart: z.number(), + newLines: z.number(), + lines: z.array(z.string()) + })), + index: z.string().optional() + }).optional(), + encoding: z.literal('base64').optional(), + mimeType: z.string().optional() +}); + +export const zFile = z.object({ + path: z.string(), + added: z.int().gte(-9007199254740991).lte(9007199254740991), + removed: z.int().gte(-9007199254740991).lte(9007199254740991), + status: z.enum([ + 'added', + 'deleted', + 'modified' + ]) +}); + +export const zAgent = z.object({ + name: z.string(), + description: z.string().optional(), + mode: z.enum([ + 'subagent', + 'primary', + 'all' + ]), + native: z.boolean().optional(), + hidden: z.boolean().optional(), + topP: z.number().optional(), + temperature: z.number().optional(), + color: z.string().optional(), + permission: zPermissionRuleset, + model: z.object({ + modelID: z.string(), + providerID: z.string() + }).optional(), + prompt: z.string().optional(), + options: z.record(z.string(), z.unknown()), + steps: z.int().gt(0).lte(9007199254740991).optional() +}); + +export const zMcpStatusConnected = z.object({ + status: z.literal('connected') +}); + +export const zMcpStatusDisabled = z.object({ + status: z.literal('disabled') +}); + +export const zMcpStatusFailed = z.object({ + status: z.literal('failed'), + error: z.string() +}); + +export const zMcpStatusNeedsAuth = z.object({ + status: z.literal('needs_auth') +}); + +export const zMcpStatusNeedsClientRegistration = z.object({ + status: z.literal('needs_client_registration'), + error: z.string() +}); + +export const zMcpStatus = z.union([ + zMcpStatusConnected, + zMcpStatusDisabled, + zMcpStatusFailed, + zMcpStatusNeedsAuth, + zMcpStatusNeedsClientRegistration +]); + +export const zLspStatus = z.object({ + id: z.string(), + name: z.string(), + root: z.string(), + status: z.union([ + z.literal('connected'), + z.literal('error') + ]) +}); + +export const zFormatterStatus = z.object({ + name: z.string(), + extensions: z.array(z.string()), + enabled: z.boolean() +}); + +export const zOAuth = z.object({ + type: z.literal('oauth'), + refresh: z.string(), + access: z.string(), + expires: z.number(), + enterpriseUrl: z.string().optional() +}); + +export const zApiAuth = z.object({ + type: z.literal('api'), + key: z.string() +}); + +export const zWellKnownAuth = z.object({ + type: z.literal('wellknown'), + key: z.string(), + token: z.string() +}); + +export const zAuth = z.union([ + zOAuth, + zApiAuth, + zWellKnownAuth +]); + +/** + * Health information + */ +export const zGlobalHealthResponse = z.object({ + healthy: z.literal(true), + version: z.string() +}); + +/** + * Event stream + */ +export const zGlobalEventResponse = zGlobalEvent; + +/** + * Global disposed + */ +export const zGlobalDisposeResponse = z.boolean(); + +export const zProjectListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of projects + */ +export const zProjectListResponse = z.array(zProject); + +export const zProjectCurrentQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Current project information + */ +export const zProjectCurrentResponse = zProject; + +export const zProjectUpdateBody = z.object({ + name: z.string().optional(), + icon: z.object({ + url: z.string().optional(), + color: z.string().optional() + }).optional() +}); + +export const zProjectUpdatePath = z.object({ + projectID: z.string() +}); + +export const zProjectUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated project information + */ +export const zProjectUpdateResponse = zProject; + +export const zPtyListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of sessions + */ +export const zPtyListResponse = z.array(zPty); + +export const zPtyCreateBody = z.object({ + command: z.string().optional(), + args: z.array(z.string()).optional(), + cwd: z.string().optional(), + title: z.string().optional(), + env: z.record(z.string(), z.string()).optional() +}); + +export const zPtyCreateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created session + */ +export const zPtyCreateResponse = zPty; + +export const zPtyRemovePath = z.object({ + ptyID: z.string() +}); + +export const zPtyRemoveQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Session removed + */ +export const zPtyRemoveResponse = z.boolean(); + +export const zPtyGetPath = z.object({ + ptyID: z.string() +}); + +export const zPtyGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Session info + */ +export const zPtyGetResponse = zPty; + +export const zPtyUpdateBody = z.object({ + title: z.string().optional(), + size: z.object({ + rows: z.number(), + cols: z.number() + }).optional() +}); + +export const zPtyUpdatePath = z.object({ + ptyID: z.string() +}); + +export const zPtyUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated session + */ +export const zPtyUpdateResponse = zPty; + +export const zPtyConnectPath = z.object({ + ptyID: z.string() +}); + +export const zPtyConnectQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Connected session + */ +export const zPtyConnectResponse = z.boolean(); + +export const zConfigGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Get config info + */ +export const zConfigGetResponse = zConfig; + +export const zConfigUpdateBody = zConfig; + +export const zConfigUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully updated config + */ +export const zConfigUpdateResponse = zConfig; + +export const zToolIdsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Tool IDs + */ +export const zToolIdsResponse = zToolIds; + +export const zToolListQuery = z.object({ + directory: z.string().optional(), + provider: z.string(), + model: z.string() +}); + +/** + * Tools + */ +export const zToolListResponse = zToolList; + +export const zInstanceDisposeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Instance disposed + */ +export const zInstanceDisposeResponse = z.boolean(); + +export const zPathGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Path + */ +export const zPathGetResponse = zPath; + +export const zVcsGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * VCS info + */ +export const zVcsGetResponse = zVcsInfo; + +export const zSessionListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of sessions + */ +export const zSessionListResponse = z.array(zSession); + +export const zSessionCreateBody = z.object({ + parentID: z.string().regex(/^ses.*/).optional(), + title: z.string().optional(), + permission: zPermissionRuleset.optional() +}); + +export const zSessionCreateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully created session + */ +export const zSessionCreateResponse = zSession; + +export const zSessionStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Get session status + */ +export const zSessionStatusResponse = z.record(z.string(), zSessionStatus); + +export const zSessionDeletePath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionDeleteQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully deleted session + */ +export const zSessionDeleteResponse = z.boolean(); + +export const zSessionGetPath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Get session + */ +export const zSessionGetResponse = zSession; + +export const zSessionUpdateBody = z.object({ + title: z.string().optional(), + time: z.object({ + archived: z.number().optional() + }).optional() +}); + +export const zSessionUpdatePath = z.object({ + sessionID: z.string() +}); + +export const zSessionUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully updated session + */ +export const zSessionUpdateResponse = zSession; + +export const zSessionChildrenPath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionChildrenQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of children + */ +export const zSessionChildrenResponse = z.array(zSession); + +export const zSessionTodoPath = z.object({ + sessionID: z.string() +}); + +export const zSessionTodoQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Todo list + */ +export const zSessionTodoResponse = z.array(zTodo); + +export const zSessionInitBody = z.object({ + modelID: z.string(), + providerID: z.string(), + messageID: z.string().regex(/^msg.*/) +}); + +export const zSessionInitPath = z.object({ + sessionID: z.string() +}); + +export const zSessionInitQuery = z.object({ + directory: z.string().optional() +}); + +/** + * 200 + */ +export const zSessionInitResponse = z.boolean(); + +export const zSessionForkBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional() +}); + +export const zSessionForkPath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionForkQuery = z.object({ + directory: z.string().optional() +}); + +/** + * 200 + */ +export const zSessionForkResponse = zSession; + +export const zSessionAbortPath = z.object({ + sessionID: z.string() +}); + +export const zSessionAbortQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Aborted session + */ +export const zSessionAbortResponse = z.boolean(); + +export const zSessionUnsharePath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionUnshareQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully unshared session + */ +export const zSessionUnshareResponse = zSession; + +export const zSessionSharePath = z.object({ + sessionID: z.string() +}); + +export const zSessionShareQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully shared session + */ +export const zSessionShareResponse = zSession; + +export const zSessionDiffPath = z.object({ + sessionID: z.string() +}); + +export const zSessionDiffQuery = z.object({ + directory: z.string().optional(), + messageID: z.string().regex(/^msg.*/).optional() +}); + +/** + * List of diffs + */ +export const zSessionDiffResponse = z.array(zFileDiff); + +export const zSessionSummarizeBody = z.object({ + providerID: z.string(), + modelID: z.string(), + auto: z.boolean().optional().default(false) +}); + +export const zSessionSummarizePath = z.object({ + sessionID: z.string() +}); + +export const zSessionSummarizeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Summarized session + */ +export const zSessionSummarizeResponse = z.boolean(); + +export const zSessionMessagesPath = z.object({ + sessionID: z.string() +}); + +export const zSessionMessagesQuery = z.object({ + directory: z.string().optional(), + limit: z.number().optional() +}); + +/** + * List of messages + */ +export const zSessionMessagesResponse = z.array(z.object({ + info: zMessage, + parts: z.array(zPart) +})); + +export const zSessionPromptBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }).optional(), + agent: z.string().optional(), + noReply: z.boolean().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + system: z.string().optional(), + variant: z.string().optional(), + parts: z.array(z.union([ + zTextPartInput, + zFilePartInput, + zAgentPartInput, + zSubtaskPartInput + ])) +}); + +export const zSessionPromptPath = z.object({ + sessionID: z.string() +}); + +export const zSessionPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created message + */ +export const zSessionPromptResponse = z.object({ + info: zAssistantMessage, + parts: z.array(zPart) +}); + +export const zSessionMessagePath = z.object({ + sessionID: z.string(), + messageID: z.string() +}); + +export const zSessionMessageQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Message + */ +export const zSessionMessageResponse = z.object({ + info: zMessage, + parts: z.array(zPart) +}); + +export const zPartDeletePath = z.object({ + sessionID: z.string(), + messageID: z.string(), + partID: z.string() +}); + +export const zPartDeleteQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully deleted part + */ +export const zPartDeleteResponse = z.boolean(); + +export const zPartUpdateBody = zPart; + +export const zPartUpdatePath = z.object({ + sessionID: z.string(), + messageID: z.string(), + partID: z.string() +}); + +export const zPartUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully updated part + */ +export const zPartUpdateResponse = zPart; + +export const zSessionPromptAsyncBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }).optional(), + agent: z.string().optional(), + noReply: z.boolean().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + system: z.string().optional(), + variant: z.string().optional(), + parts: z.array(z.union([ + zTextPartInput, + zFilePartInput, + zAgentPartInput, + zSubtaskPartInput + ])) +}); + +export const zSessionPromptAsyncPath = z.object({ + sessionID: z.string() +}); + +export const zSessionPromptAsyncQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt accepted + */ +export const zSessionPromptAsyncResponse = z.void(); + +export const zSessionCommandBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional(), + agent: z.string().optional(), + model: z.string().optional(), + arguments: z.string(), + command: z.string(), + variant: z.string().optional() +}); + +export const zSessionCommandPath = z.object({ + sessionID: z.string() +}); + +export const zSessionCommandQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created message + */ +export const zSessionCommandResponse = z.object({ + info: zAssistantMessage, + parts: z.array(zPart) +}); + +export const zSessionShellBody = z.object({ + agent: z.string(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }).optional(), + command: z.string() +}); + +export const zSessionShellPath = z.object({ + sessionID: z.string() +}); + +export const zSessionShellQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created message + */ +export const zSessionShellResponse = zAssistantMessage; + +export const zSessionRevertBody = z.object({ + messageID: z.string().regex(/^msg.*/), + partID: z.string().regex(/^prt.*/).optional() +}); + +export const zSessionRevertPath = z.object({ + sessionID: z.string() +}); + +export const zSessionRevertQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated session + */ +export const zSessionRevertResponse = zSession; + +export const zSessionUnrevertPath = z.object({ + sessionID: z.string() +}); + +export const zSessionUnrevertQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated session + */ +export const zSessionUnrevertResponse = zSession; + +export const zPermissionRespondBody = z.object({ + response: z.enum([ + 'once', + 'always', + 'reject' + ]) +}); + +export const zPermissionRespondPath = z.object({ + sessionID: z.string(), + permissionID: z.string() +}); + +export const zPermissionRespondQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Permission processed successfully + */ +export const zPermissionRespondResponse = z.boolean(); + +export const zPermissionReplyBody = z.object({ + reply: z.enum([ + 'once', + 'always', + 'reject' + ]) +}); + +export const zPermissionReplyPath = z.object({ + requestID: z.string() +}); + +export const zPermissionReplyQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Permission processed successfully + */ +export const zPermissionReplyResponse = z.boolean(); + +export const zPermissionListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of pending permissions + */ +export const zPermissionListResponse = z.array(zPermissionRequest); + +export const zCommandListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of commands + */ +export const zCommandListResponse = z.array(zCommand); + +export const zConfigProvidersQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of providers + */ +export const zConfigProvidersResponse = z.object({ + providers: z.array(zProvider), + default: z.record(z.string(), z.string()) +}); + +export const zProviderListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of providers + */ +export const zProviderListResponse = z.object({ + all: z.array(z.object({ + api: z.string().optional(), + name: z.string(), + env: z.array(z.string()), + id: z.string(), + npm: z.string().optional(), + models: z.record(z.string(), z.object({ + id: z.string(), + name: z.string(), + family: z.string().optional(), + release_date: z.string(), + attachment: z.boolean(), + reasoning: z.boolean(), + temperature: z.boolean(), + tool_call: z.boolean(), + interleaved: z.union([ + z.literal(true), + z.object({ + field: z.enum(['reasoning_content', 'reasoning_details']) + }) + ]).optional(), + cost: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional(), + context_over_200k: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional() + }).optional() + }).optional(), + limit: z.object({ + context: z.number(), + output: z.number() + }), + modalities: z.object({ + input: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])), + output: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])) + }).optional(), + experimental: z.boolean().optional(), + status: z.enum([ + 'alpha', + 'beta', + 'deprecated' + ]).optional(), + options: z.record(z.string(), z.unknown()), + headers: z.record(z.string(), z.string()).optional(), + provider: z.object({ + npm: z.string() + }).optional(), + variants: z.record(z.string(), z.record(z.string(), z.unknown())).optional() + })) + })), + default: z.record(z.string(), z.string()), + connected: z.array(z.string()) +}); + +export const zProviderAuthQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Provider auth methods + */ +export const zProviderAuthResponse = z.record(z.string(), z.array(zProviderAuthMethod)); + +export const zProviderOauthAuthorizeBody = z.object({ + method: z.number() +}); + +export const zProviderOauthAuthorizePath = z.object({ + providerID: z.string() +}); + +export const zProviderOauthAuthorizeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Authorization URL and method + */ +export const zProviderOauthAuthorizeResponse = zProviderAuthAuthorization; + +export const zProviderOauthCallbackBody = z.object({ + method: z.number(), + code: z.string().optional() +}); + +export const zProviderOauthCallbackPath = z.object({ + providerID: z.string() +}); + +export const zProviderOauthCallbackQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth callback processed successfully + */ +export const zProviderOauthCallbackResponse = z.boolean(); + +export const zFindTextQuery = z.object({ + directory: z.string().optional(), + pattern: z.string() +}); + +/** + * Matches + */ +export const zFindTextResponse = z.array(z.object({ + path: z.object({ + text: z.string() + }), + lines: z.object({ + text: z.string() + }), + line_number: z.number(), + absolute_offset: z.number(), + submatches: z.array(z.object({ + match: z.object({ + text: z.string() + }), + start: z.number(), + end: z.number() + })) +})); + +export const zFindFilesQuery = z.object({ + directory: z.string().optional(), + query: z.string(), + dirs: z.enum(['true', 'false']).optional(), + type: z.enum(['file', 'directory']).optional(), + limit: z.int().gte(1).lte(200).optional() +}); + +/** + * File paths + */ +export const zFindFilesResponse = z.array(z.string()); + +export const zFindSymbolsQuery = z.object({ + directory: z.string().optional(), + query: z.string() +}); + +/** + * Symbols + */ +export const zFindSymbolsResponse = z.array(zSymbol); + +export const zFileListQuery = z.object({ + directory: z.string().optional(), + path: z.string() +}); + +/** + * Files and directories + */ +export const zFileListResponse = z.array(zFileNode); + +export const zFileReadQuery = z.object({ + directory: z.string().optional(), + path: z.string() +}); + +/** + * File content + */ +export const zFileReadResponse = zFileContent; + +export const zFileStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * File status + */ +export const zFileStatusResponse = z.array(zFile); + +export const zAppLogBody = z.object({ + service: z.string(), + level: z.enum([ + 'debug', + 'info', + 'error', + 'warn' + ]), + message: z.string(), + extra: z.record(z.string(), z.unknown()).optional() +}); + +export const zAppLogQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Log entry written successfully + */ +export const zAppLogResponse = z.boolean(); + +export const zAppAgentsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of agents + */ +export const zAppAgentsResponse = z.array(zAgent); + +export const zMcpStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server status + */ +export const zMcpStatusResponse = z.record(z.string(), zMcpStatus); + +export const zMcpAddBody = z.object({ + name: z.string(), + config: z.union([ + zMcpLocalConfig, + zMcpRemoteConfig + ]) +}); + +export const zMcpAddQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server added successfully + */ +export const zMcpAddResponse = z.record(z.string(), zMcpStatus); + +export const zMcpAuthRemovePath = z.object({ + name: z.string() +}); + +export const zMcpAuthRemoveQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth credentials removed + */ +export const zMcpAuthRemoveResponse = z.object({ + success: z.literal(true) +}); + +export const zMcpAuthStartPath = z.object({ + name: z.string() +}); + +export const zMcpAuthStartQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth flow started + */ +export const zMcpAuthStartResponse = z.object({ + authorizationUrl: z.string() +}); + +export const zMcpAuthCallbackBody = z.object({ + code: z.string() +}); + +export const zMcpAuthCallbackPath = z.object({ + name: z.string() +}); + +export const zMcpAuthCallbackQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth authentication completed + */ +export const zMcpAuthCallbackResponse = zMcpStatus; + +export const zMcpAuthAuthenticatePath = z.object({ + name: z.string() +}); + +export const zMcpAuthAuthenticateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth authentication completed + */ +export const zMcpAuthAuthenticateResponse = zMcpStatus; + +export const zMcpConnectPath = z.object({ + name: z.string() +}); + +export const zMcpConnectQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server connected successfully + */ +export const zMcpConnectResponse = z.boolean(); + +export const zMcpDisconnectPath = z.object({ + name: z.string() +}); + +export const zMcpDisconnectQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server disconnected successfully + */ +export const zMcpDisconnectResponse = z.boolean(); + +export const zLspStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * LSP server status + */ +export const zLspStatusResponse = z.array(zLspStatus); + +export const zFormatterStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Formatter status + */ +export const zFormatterStatusResponse = z.array(zFormatterStatus); + +export const zTuiAppendPromptBody = z.object({ + text: z.string() +}); + +export const zTuiAppendPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt processed successfully + */ +export const zTuiAppendPromptResponse = z.boolean(); + +export const zTuiOpenHelpQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Help dialog opened successfully + */ +export const zTuiOpenHelpResponse = z.boolean(); + +export const zTuiOpenSessionsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Session dialog opened successfully + */ +export const zTuiOpenSessionsResponse = z.boolean(); + +export const zTuiOpenThemesQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Theme dialog opened successfully + */ +export const zTuiOpenThemesResponse = z.boolean(); + +export const zTuiOpenModelsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Model dialog opened successfully + */ +export const zTuiOpenModelsResponse = z.boolean(); + +export const zTuiSubmitPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt submitted successfully + */ +export const zTuiSubmitPromptResponse = z.boolean(); + +export const zTuiClearPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt cleared successfully + */ +export const zTuiClearPromptResponse = z.boolean(); + +export const zTuiExecuteCommandBody = z.object({ + command: z.string() +}); + +export const zTuiExecuteCommandQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Command executed successfully + */ +export const zTuiExecuteCommandResponse = z.boolean(); + +export const zTuiShowToastBody = z.object({ + title: z.string().optional(), + message: z.string(), + variant: z.enum([ + 'info', + 'success', + 'warning', + 'error' + ]), + duration: z.number().optional().default(5000) +}); + +export const zTuiShowToastQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Toast notification shown successfully + */ +export const zTuiShowToastResponse = z.boolean(); + +export const zTuiPublishBody = z.union([ + zEventTuiPromptAppend, + zEventTuiCommandExecute, + zEventTuiToastShow +]); + +export const zTuiPublishQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Event published successfully + */ +export const zTuiPublishResponse = z.boolean(); + +export const zTuiControlNextQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Next TUI request + */ +export const zTuiControlNextResponse = z.object({ + path: z.string(), + body: z.unknown() +}); + +export const zTuiControlResponseBody = z.unknown(); + +export const zTuiControlResponseQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Response submitted successfully + */ +export const zTuiControlResponseResponse = z.boolean(); + +export const zAuthSetBody = zAuth; + +export const zAuthSetPath = z.object({ + providerID: z.string() +}); + +export const zAuthSetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully set authentication credentials + */ +export const zAuthSetResponse = z.boolean(); + +export const zEventSubscribeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Event stream + */ +export const zEventSubscribeResponse = zEvent; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client.gen.ts new file mode 100644 index 0000000000..cab3c70195 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client.gen.ts @@ -0,0 +1,16 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { type ClientOptions, type Config, createClient, createConfig } from './client'; +import type { ClientOptions as ClientOptions2 } from './types.gen'; + +/** + * 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 = (override?: Config) => Config & T>; + +export const client = createClient(createConfig()); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client/client.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client/client.gen.ts new file mode 100644 index 0000000000..fc3f037f16 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client/client.gen.ts @@ -0,0 +1,277 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { createSseClient } from '../core/serverSentEvents.gen'; +import type { HttpMethod } from '../core/types.gen'; +import { getValidRequestBody } from '../core/utils.gen'; +import type { Client, Config, RequestOptions, ResolvedRequestOptions } from './types.gen'; +import { + buildUrl, + createConfig, + createInterceptors, + getParseAs, + mergeConfigs, + mergeHeaders, + setAuthParams, +} from './utils.gen'; + +type ReqInit = Omit & { + body?: any; + headers: ReturnType; +}; + +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(); + + const beforeRequest = async < + TData = unknown, + TResponseStyle extends 'data' | 'fields' = 'fields', + ThrowOnError extends boolean = boolean, + Url extends string = string, + >( + options: RequestOptions, + ) => { + const opts = { + ..._config, + ...options, + fetch: options.fetch ?? _config.fetch ?? globalThis.fetch, + headers: mergeHeaders(_config.headers, options.headers), + serializedBody: undefined as string | undefined, + }; + + if (opts.security) { + await setAuthParams(opts); + } + + if (opts.requestValidator) { + await opts.requestValidator(opts); + } + + if (opts.body !== undefined && opts.bodySerializer) { + opts.serializedBody = opts.bodySerializer(opts.body) as string | undefined; + } + + // 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 resolvedOpts = opts as typeof opts & + ResolvedRequestOptions; + const url = buildUrl(resolvedOpts); + + return { opts: resolvedOpts, url }; + }; + + const request: Client['request'] = async (options) => { + const throwOnError = options.throwOnError ?? _config.throwOnError; + const responseStyle = options.responseStyle ?? _config.responseStyle; + + let request: Request | undefined; + let response: Response | undefined; + + try { + const { opts, url } = await beforeRequest(options); + const requestInit: ReqInit = { + redirect: 'follow', + ...opts, + body: getValidRequestBody(opts), + }; + + 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!; + + response = await _fetch(request); + + for (const fn of interceptors.response.fns) { + if (fn) { + response = await fn(response, request, opts); + } + } + + const result = { + request, + response, + }; + + if (response.ok) { + 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 'text': + data = await response[parseAs](); + break; + case 'json': { + // Some servers return 200 with no Content-Length and empty body. + // response.json() would throw; read as text and parse if non-empty. + const text = await response.text(); + data = text ? JSON.parse(text) : {}; + 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 + } + + throw jsonError ?? textError; + } catch (error) { + let finalError = error; + + for (const fn of interceptors.error.fns) { + if (fn) { + finalError = await fn(finalError, response, request, options as ResolvedRequestOptions); + } + } + + finalError = finalError || {}; + + if (throwOnError) { + throw finalError; + } + + // TODO: we probably want to return error and improve types + return responseStyle === 'data' + ? undefined + : { + error: finalError, + request, + response, + }; + } + }; + + const makeMethodFn = (method: Uppercase) => (options: RequestOptions) => + request({ ...options, method }); + + const makeSseFn = (method: Uppercase) => async (options: RequestOptions) => { + const { opts, url } = await beforeRequest(options); + return createSseClient({ + ...opts, + body: opts.body as BodyInit | null | undefined, + 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; + }, + serializedBody: getValidRequestBody(opts) as BodyInit | null | undefined, + url, + }); + }; + + const _buildUrl: Client['buildUrl'] = (options) => buildUrl({ ..._config, ...options }); + + return { + buildUrl: _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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client/index.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client/index.ts new file mode 100644 index 0000000000..b295edeca0 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client/index.ts @@ -0,0 +1,25 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type { Auth } from '../core/auth.gen'; +export type { QuerySerializerOptions } from '../core/bodySerializer.gen'; +export { + formDataBodySerializer, + jsonBodySerializer, + urlSearchParamsBodySerializer, +} from '../core/bodySerializer.gen'; +export { buildClientParams } from '../core/params.gen'; +export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen'; +export { createClient } from './client.gen'; +export type { + Client, + ClientOptions, + Config, + CreateClientConfig, + Options, + RequestOptions, + RequestResult, + ResolvedRequestOptions, + ResponseStyle, + TDataShape, +} from './types.gen'; +export { createConfig, mergeHeaders } from './utils.gen'; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client/types.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client/types.gen.ts new file mode 100644 index 0000000000..193646cddf --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client/types.gen.ts @@ -0,0 +1,218 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth } from '../core/auth.gen'; +import type { + ServerSentEventsOptions, + ServerSentEventsResult, +} from '../core/serverSentEvents.gen'; +import type { Client as CoreClient, Config as CoreConfig } from '../core/types.gen'; +import type { Middleware } from './utils.gen'; + +export type ResponseStyle = 'data' | 'fields'; + +export interface Config + extends Omit, 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, + | 'onRequest' + | '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; + query?: Record; + /** + * Security mechanism(s) to use for the request. + */ + security?: ReadonlyArray; + url: Url; +} + +export interface ResolvedRequestOptions< + TResponseStyle extends ResponseStyle = 'fields', + ThrowOnError extends boolean = boolean, + Url extends string = string, +> extends RequestOptions { + headers: Headers; + 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 + ? TData[keyof TData] + : TData + : { + data: TData extends Record ? TData[keyof TData] : TData; + request: Request; + response: Response; + } + > + : Promise< + TResponseStyle extends 'data' + ? (TData extends Record ? TData[keyof TData] : TData) | undefined + : ( + | { + data: TData extends Record ? TData[keyof TData] : TData; + error: undefined; + } + | { + data: undefined; + error: TError extends Record ? TError[keyof TError] : TError; + } + ) & { + /** request may be undefined, because error may be from building the request object itself */ + request?: Request; + /** response may be undefined, because error may be from building the request object itself or from a network error */ + 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, 'method'>, +) => RequestResult; + +type SseFn = < + TData = unknown, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = 'fields', +>( + options: Omit, 'method'>, +) => Promise>; + +type RequestFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = 'fields', +>( + options: Omit, 'method'> & + Pick>, 'method'>, +) => RequestResult; + +type BuildUrlFn = < + TData extends { + body?: unknown; + path?: Record; + query?: Record; + url: string; + }, +>( + options: TData & Options, +) => string; + +export type Client = CoreClient & { + interceptors: Middleware; +}; + +/** + * 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 = ( + override?: Config, +) => Config & T>; + +export interface TDataShape { + body?: unknown; + headers?: unknown; + path?: unknown; + query?: unknown; + url: string; +} + +type OmitKeys = Pick>; + +export type Options< + TData extends TDataShape = TDataShape, + ThrowOnError extends boolean = boolean, + TResponse = unknown, + TResponseStyle extends ResponseStyle = 'fields', +> = OmitKeys< + RequestOptions, + 'body' | 'path' | 'query' | 'url' +> & + ([TData] extends [never] ? unknown : Omit); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client/utils.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client/utils.gen.ts new file mode 100644 index 0000000000..7800fe4b9d --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/client/utils.gen.ts @@ -0,0 +1,316 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { getAuthToken } from '../core/auth.gen'; +import type { QuerySerializerOptions } from '../core/bodySerializer.gen'; +import { jsonBodySerializer } from '../core/bodySerializer.gen'; +import { + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from '../core/pathSerializer.gen'; +import { getUrl } from '../core/utils.gen'; +import type { Client, ClientOptions, Config, RequestOptions } from './types.gen'; + +export const createQuerySerializer = ({ + 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, + ...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 => { + 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 & { + 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 async function setAuthParams( + options: Pick & { + headers: Headers; + }, +): Promise { + for (const auth of options.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['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 = ( + error: Err, + /** response may be undefined due to a network error where no response object is produced */ + response: Res | undefined, + /** request may be undefined, because error may be from building the request object itself */ + request: Req | undefined, + options: Options, +) => Err | Promise; + +type ReqInterceptor = (request: Req, options: Options) => Req | Promise; + +type ResInterceptor = ( + response: Res, + request: Req, + options: Options, +) => Res | Promise; + +class Interceptors { + fns: Array = []; + + 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 { + error: Interceptors>; + request: Interceptors>; + response: Interceptors>; +} + +export const createInterceptors = (): Middleware< + Req, + Res, + Err, + Options +> => ({ + error: new Interceptors>(), + request: new Interceptors>(), + response: new Interceptors>(), +}); + +const defaultQuerySerializer = createQuerySerializer({ + allowReserved: false, + array: { + explode: true, + style: 'form', + }, + object: { + explode: true, + style: 'deepObject', + }, +}); + +const defaultHeaders = { + 'Content-Type': 'application/json', +}; + +export const createConfig = ( + override: Config & T> = {}, +): Config & T> => ({ + ...jsonBodySerializer, + headers: defaultHeaders, + parseAs: 'auto', + querySerializer: defaultQuerySerializer, + ...override, +}); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/auth.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/auth.gen.ts new file mode 100644 index 0000000000..3ebf994788 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/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, +): Promise => { + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/bodySerializer.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/bodySerializer.gen.ts new file mode 100644 index 0000000000..67daca60f8 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/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'; + +export type QuerySerializer = (query: Record) => string; + +export type BodySerializer = (body: unknown) => unknown; + +type QuerySerializerOptionsObject = { + allowReserved?: boolean; + array?: Partial>; + object?: Partial>; +}; + +export type QuerySerializerOptions = QuerySerializerOptionsObject & { + /** + * Per-parameter serialization overrides. When provided, these settings + * override the global array/object settings for specific parameter names. + */ + parameters?: Record; +}; + +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: (body: unknown): FormData => { + const data = new FormData(); + + Object.entries(body as Record).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: (body: unknown): string => + JSON.stringify(body, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)), +}; + +export const urlSearchParamsBodySerializer = { + bodySerializer: (body: unknown): string => { + const data = new URLSearchParams(); + + Object.entries(body as Record).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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/params.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/params.gen.ts new file mode 100644 index 0000000000..6478519bcb --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/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; + /** + * 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; + /** + * 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>; + args?: ReadonlyArray; +} + +export type FieldsConfig = ReadonlyArray; + +const extraPrefixesMap: Record = { + $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; + path: Record; + query: Record; +} + +const stripEmptySlots = (params: Params) => { + for (const [slot, value] of Object.entries(params)) { + if (value && typeof value === 'object' && !Array.isArray(value) && !Object.keys(value).length) { + delete params[slot as Slot]; + } + } +}; + +export const buildClientParams = (args: ReadonlyArray, fields: FieldsConfig) => { + const params: Params = { + body: Object.create(null), + headers: Object.create(null), + path: Object.create(null), + query: Object.create(null), + }; + + 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)[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)[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)[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)[key] = value; + break; + } + } + } + } + } + } + } + + stripEmptySlots(params); + + return params; +}; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/pathSerializer.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/pathSerializer.gen.ts new file mode 100644 index 0000000000..994b2848c6 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/pathSerializer.gen.ts @@ -0,0 +1,171 @@ +// This file is auto-generated by @hey-api/openapi-ts + +interface SerializeOptions extends SerializePrimitiveOptions, SerializerOptions {} + +interface SerializePrimitiveOptions { + allowReserved?: boolean; + name: string; +} + +export interface SerializerOptions { + /** + * @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 & { + 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 & { + value: Record | 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/queryKeySerializer.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/queryKeySerializer.gen.ts new file mode 100644 index 0000000000..5000df606f --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/queryKeySerializer.gen.ts @@ -0,0 +1,117 @@ +// 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 => { + 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 = {}; + + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/serverSentEvents.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/serverSentEvents.gen.ts new file mode 100644 index 0000000000..ddf3c4d13a --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/serverSentEvents.gen.ts @@ -0,0 +1,242 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Config } from './types.gen'; + +export type ServerSentEventsOptions = Omit & + Pick & { + /** + * 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; + /** + * 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) => 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; + url: string; + }; + +export interface StreamEvent { + data: TData; + event?: string; + id?: string; + retry?: number; +} + +export type ServerSentEventsResult = { + stream: AsyncGenerator< + TData extends Record ? TData[keyof TData] : TData, + TReturn, + TNext + >; +}; + +export function createSseClient({ + onRequest, + onSseError, + onSseEvent, + responseTransformer, + responseValidator, + sseDefaultRetryDelay, + sseMaxRetryAttempts, + sseMaxRetryDelay, + sseSleepFn, + url, + ...options +}: ServerSentEventsOptions): ServerSentEventsResult { + 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 | 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; + buffer = buffer.replace(/\r\n?/g, '\n'); // normalize line endings + + const chunks = buffer.split('\n\n'); + buffer = chunks.pop() ?? ''; + + for (const chunk of chunks) { + const lines = chunk.split('\n'); + const dataLines: Array = []; + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/types.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/types.gen.ts new file mode 100644 index 0000000000..9efe71d4c1 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/types.gen.ts @@ -0,0 +1,104 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth, AuthToken } from './auth.gen'; +import type { BodySerializer, QuerySerializer, QuerySerializerOptions } from './bodySerializer.gen'; + +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; + /** + * 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; + /** + * 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; + /** + * 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; + /** + * 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; +} + +type IsExactlyNeverOrNeverUndefined = [T] extends [never] + ? true + : [T] extends [never | undefined] + ? [undefined] extends [T] + ? false + : true + : false; + +export type OmitNever> = { + [K in keyof T as IsExactlyNeverOrNeverUndefined extends true ? never : K]: T[K]; +}; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/utils.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/utils.gen.ts new file mode 100644 index 0000000000..9a4fec7830 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/core/utils.gen.ts @@ -0,0 +1,140 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { BodySerializer, QuerySerializer } from './bodySerializer.gen'; +import { + type ArraySeparatorStyle, + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from './pathSerializer.gen'; + +export interface PathSerializer { + path: Record; + 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, + 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; + query?: Record; + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/index.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/index.ts new file mode 100644 index 0000000000..c1f98cb47e --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/index.ts @@ -0,0 +1,4 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export { appAgents, appLog, authSet, commandList, configGet, configProviders, configUpdate, eventSubscribe, fileList, fileRead, fileStatus, findFiles, findSymbols, findText, formatterStatus, globalDispose, globalEvent, globalHealth, instanceDispose, lspStatus, mcpAdd, mcpAuthAuthenticate, mcpAuthCallback, mcpAuthRemove, mcpAuthStart, mcpConnect, mcpDisconnect, mcpStatus, type Options, partDelete, partUpdate, pathGet, permissionList, permissionReply, permissionRespond, projectCurrent, projectList, projectUpdate, providerAuth, providerList, providerOauthAuthorize, providerOauthCallback, ptyConnect, ptyCreate, ptyGet, ptyList, ptyRemove, ptyUpdate, sessionAbort, sessionChildren, sessionCommand, sessionCreate, sessionDelete, sessionDiff, sessionFork, sessionGet, sessionInit, sessionList, sessionMessage, sessionMessages, sessionPrompt, sessionPromptAsync, sessionRevert, sessionShare, sessionShell, sessionStatus, sessionSummarize, sessionTodo, sessionUnrevert, sessionUnshare, sessionUpdate, toolIds, toolList, tuiAppendPrompt, tuiClearPrompt, tuiControlNext, tuiControlResponse, tuiExecuteCommand, tuiOpenHelp, tuiOpenModels, tuiOpenSessions, tuiOpenThemes, tuiPublish, tuiShowToast, tuiSubmitPrompt, vcsGet } from './sdk.gen'; +export type { Agent, AgentConfig, AgentPart, AgentPartInput, ApiAuth, ApiError, AppAgentsData, AppAgentsResponse, AppAgentsResponses, AppLogData, AppLogError, AppLogErrors, AppLogResponse, AppLogResponses, AssistantMessage, Auth, AuthSetData, AuthSetError, AuthSetErrors, AuthSetResponse, AuthSetResponses, BadRequestError, ClientOptions, Command, CommandListData, CommandListResponse, CommandListResponses, CompactionPart, Config, ConfigGetData, ConfigGetResponse, ConfigGetResponses, ConfigProvidersData, ConfigProvidersResponse, ConfigProvidersResponses, ConfigUpdateData, ConfigUpdateError, ConfigUpdateErrors, ConfigUpdateResponse, ConfigUpdateResponses, Event, EventCommandExecuted, EventFileEdited, EventFileWatcherUpdated, EventGlobalDisposed, EventInstallationUpdateAvailable, EventInstallationUpdated, EventLspClientDiagnostics, EventLspUpdated, EventMcpToolsChanged, EventMessagePartRemoved, EventMessagePartUpdated, EventMessageRemoved, EventMessageUpdated, EventPermissionAsked, EventPermissionReplied, EventProjectUpdated, EventPtyCreated, EventPtyDeleted, EventPtyExited, EventPtyUpdated, EventServerConnected, EventServerInstanceDisposed, EventSessionCompacted, EventSessionCreated, EventSessionDeleted, EventSessionDiff, EventSessionError, EventSessionIdle, EventSessionStatus, EventSessionUpdated, EventSubscribeData, EventSubscribeResponse, EventSubscribeResponses, EventTodoUpdated, EventTuiCommandExecute, EventTuiPromptAppend, EventTuiToastShow, EventVcsBranchUpdated, File, FileContent, FileDiff, FileListData, FileListResponse, FileListResponses, FileNode, FilePart, FilePartInput, FilePartSource, FilePartSourceText, FileReadData, FileReadResponse, FileReadResponses, FileSource, FileStatusData, FileStatusResponse, FileStatusResponses, FindFilesData, FindFilesResponse, FindFilesResponses, FindSymbolsData, FindSymbolsResponse, FindSymbolsResponses, FindTextData, FindTextResponse, FindTextResponses, FormatterStatus, FormatterStatusData, FormatterStatusResponse, FormatterStatusResponses, GlobalDisposeData, GlobalDisposeResponse, GlobalDisposeResponses, GlobalEvent, GlobalEventData, GlobalEventResponse, GlobalEventResponses, GlobalHealthData, GlobalHealthResponse, GlobalHealthResponses, InstanceDisposeData, InstanceDisposeResponse, InstanceDisposeResponses, KeybindsConfig, LayoutConfig, LogLevel, LspStatus, LspStatusData, LspStatusResponse, LspStatusResponses, McpAddData, McpAddError, McpAddErrors, McpAddResponse, McpAddResponses, McpAuthAuthenticateData, McpAuthAuthenticateError, McpAuthAuthenticateErrors, McpAuthAuthenticateResponse, McpAuthAuthenticateResponses, McpAuthCallbackData, McpAuthCallbackError, McpAuthCallbackErrors, McpAuthCallbackResponse, McpAuthCallbackResponses, McpAuthRemoveData, McpAuthRemoveError, McpAuthRemoveErrors, McpAuthRemoveResponse, McpAuthRemoveResponses, McpAuthStartData, McpAuthStartError, McpAuthStartErrors, McpAuthStartResponse, McpAuthStartResponses, McpConnectData, McpConnectResponse, McpConnectResponses, McpDisconnectData, McpDisconnectResponse, McpDisconnectResponses, McpLocalConfig, McpOAuthConfig, McpRemoteConfig, McpStatus, McpStatusConnected, McpStatusData, McpStatusDisabled, McpStatusFailed, McpStatusNeedsAuth, McpStatusNeedsClientRegistration, McpStatusResponse, McpStatusResponses, Message, MessageAbortedError, MessageOutputLengthError, Model, NotFoundError, OAuth, Part, PartDeleteData, PartDeleteError, PartDeleteErrors, PartDeleteResponse, PartDeleteResponses, PartUpdateData, PartUpdateError, PartUpdateErrors, PartUpdateResponse, PartUpdateResponses, PatchPart, Path, PathGetData, PathGetResponse, PathGetResponses, PermissionAction, PermissionActionConfig, PermissionConfig, PermissionListData, PermissionListResponse, PermissionListResponses, PermissionObjectConfig, PermissionReplyData, PermissionReplyError, PermissionReplyErrors, PermissionReplyResponse, PermissionReplyResponses, PermissionRequest, PermissionRespondData, PermissionRespondError, PermissionRespondErrors, PermissionRespondResponse, PermissionRespondResponses, PermissionRule, PermissionRuleConfig, PermissionRuleset, Project, ProjectCurrentData, ProjectCurrentResponse, ProjectCurrentResponses, ProjectListData, ProjectListResponse, ProjectListResponses, ProjectUpdateData, ProjectUpdateError, ProjectUpdateErrors, ProjectUpdateResponse, ProjectUpdateResponses, Provider, ProviderAuthAuthorization, ProviderAuthData, ProviderAuthError, ProviderAuthMethod, ProviderAuthResponse, ProviderAuthResponses, ProviderConfig, ProviderListData, ProviderListResponse, ProviderListResponses, ProviderOauthAuthorizeData, ProviderOauthAuthorizeError, ProviderOauthAuthorizeErrors, ProviderOauthAuthorizeResponse, ProviderOauthAuthorizeResponses, ProviderOauthCallbackData, ProviderOauthCallbackError, ProviderOauthCallbackErrors, ProviderOauthCallbackResponse, ProviderOauthCallbackResponses, Pty, PtyConnectData, PtyConnectError, PtyConnectErrors, PtyConnectResponse, PtyConnectResponses, PtyCreateData, PtyCreateError, PtyCreateErrors, PtyCreateResponse, PtyCreateResponses, PtyGetData, PtyGetError, PtyGetErrors, PtyGetResponse, PtyGetResponses, PtyListData, PtyListResponse, PtyListResponses, PtyRemoveData, PtyRemoveError, PtyRemoveErrors, PtyRemoveResponse, PtyRemoveResponses, PtyUpdateData, PtyUpdateError, PtyUpdateErrors, PtyUpdateResponse, PtyUpdateResponses, Range, ReasoningPart, RetryPart, ServerConfig, Session, SessionAbortData, SessionAbortError, SessionAbortErrors, SessionAbortResponse, SessionAbortResponses, SessionChildrenData, SessionChildrenError, SessionChildrenErrors, SessionChildrenResponse, SessionChildrenResponses, SessionCommandData, SessionCommandError, SessionCommandErrors, SessionCommandResponse, SessionCommandResponses, SessionCreateData, SessionCreateError, SessionCreateErrors, SessionCreateResponse, SessionCreateResponses, SessionDeleteData, SessionDeleteError, SessionDeleteErrors, SessionDeleteResponse, SessionDeleteResponses, SessionDiffData, SessionDiffError, SessionDiffErrors, SessionDiffResponse, SessionDiffResponses, SessionForkData, SessionForkResponse, SessionForkResponses, SessionGetData, SessionGetError, SessionGetErrors, SessionGetResponse, SessionGetResponses, SessionInitData, SessionInitError, SessionInitErrors, SessionInitResponse, SessionInitResponses, SessionListData, SessionListResponse, SessionListResponses, SessionMessageData, SessionMessageError, SessionMessageErrors, SessionMessageResponse, SessionMessageResponses, SessionMessagesData, SessionMessagesError, SessionMessagesErrors, SessionMessagesResponse, SessionMessagesResponses, SessionPromptAsyncData, SessionPromptAsyncError, SessionPromptAsyncErrors, SessionPromptAsyncResponse, SessionPromptAsyncResponses, SessionPromptData, SessionPromptError, SessionPromptErrors, SessionPromptResponse, SessionPromptResponses, SessionRevertData, SessionRevertError, SessionRevertErrors, SessionRevertResponse, SessionRevertResponses, SessionShareData, SessionShareError, SessionShareErrors, SessionShareResponse, SessionShareResponses, SessionShellData, SessionShellError, SessionShellErrors, SessionShellResponse, SessionShellResponses, SessionStatus, SessionStatusData, SessionStatusError, SessionStatusErrors, SessionStatusResponse, SessionStatusResponses, SessionSummarizeData, SessionSummarizeError, SessionSummarizeErrors, SessionSummarizeResponse, SessionSummarizeResponses, SessionTodoData, SessionTodoError, SessionTodoErrors, SessionTodoResponse, SessionTodoResponses, SessionUnrevertData, SessionUnrevertError, SessionUnrevertErrors, SessionUnrevertResponse, SessionUnrevertResponses, SessionUnshareData, SessionUnshareError, SessionUnshareErrors, SessionUnshareResponse, SessionUnshareResponses, SessionUpdateData, SessionUpdateError, SessionUpdateErrors, SessionUpdateResponse, SessionUpdateResponses, SnapshotPart, StepFinishPart, StepStartPart, SubtaskPartInput, Symbol, SymbolSource, TextPart, TextPartInput, Todo, ToolIds, ToolIdsData, ToolIdsError, ToolIdsErrors, ToolIdsResponse, ToolIdsResponses, ToolList, ToolListData, ToolListError, ToolListErrors, ToolListItem, ToolListResponse, ToolListResponses, ToolPart, ToolState, ToolStateCompleted, ToolStateError, ToolStatePending, ToolStateRunning, TuiAppendPromptData, TuiAppendPromptError, TuiAppendPromptErrors, TuiAppendPromptResponse, TuiAppendPromptResponses, TuiClearPromptData, TuiClearPromptResponse, TuiClearPromptResponses, TuiControlNextData, TuiControlNextResponse, TuiControlNextResponses, TuiControlResponseData, TuiControlResponseResponse, TuiControlResponseResponses, TuiExecuteCommandData, TuiExecuteCommandError, TuiExecuteCommandErrors, TuiExecuteCommandResponse, TuiExecuteCommandResponses, TuiOpenHelpData, TuiOpenHelpResponse, TuiOpenHelpResponses, TuiOpenModelsData, TuiOpenModelsResponse, TuiOpenModelsResponses, TuiOpenSessionsData, TuiOpenSessionsResponse, TuiOpenSessionsResponses, TuiOpenThemesData, TuiOpenThemesResponse, TuiOpenThemesResponses, TuiPublishData, TuiPublishError, TuiPublishErrors, TuiPublishResponse, TuiPublishResponses, TuiShowToastData, TuiShowToastResponse, TuiShowToastResponses, TuiSubmitPromptData, TuiSubmitPromptResponse, TuiSubmitPromptResponses, UnknownError, UserMessage, VcsGetData, VcsGetResponse, VcsGetResponses, VcsInfo, WellKnownAuth } from './types.gen'; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/sdk.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/sdk.gen.ts new file mode 100644 index 0000000000..f71e545a6d --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/sdk.gen.ts @@ -0,0 +1,2753 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import * as z from 'zod'; + +import { buildClientParams, type Client, type Options as Options2, type TDataShape } from './client'; +import { client } from './client.gen'; +import type { AgentPartInput, AppAgentsResponses, AppLogErrors, AppLogResponses, Auth, AuthSetErrors, AuthSetResponses, CommandListResponses, Config, ConfigGetResponses, ConfigProvidersResponses, ConfigUpdateErrors, ConfigUpdateResponses, EventSubscribeResponse, EventSubscribeResponses, EventTuiCommandExecute, EventTuiPromptAppend, EventTuiToastShow, FileListResponses, FilePartInput, FileReadResponses, FileStatusResponses, FindFilesResponses, FindSymbolsResponses, FindTextResponses, FormatterStatusResponses, GlobalDisposeResponses, GlobalEventResponse, GlobalEventResponses, GlobalHealthResponses, InstanceDisposeResponses, LspStatusResponses, McpAddErrors, McpAddResponses, McpAuthAuthenticateErrors, McpAuthAuthenticateResponses, McpAuthCallbackErrors, McpAuthCallbackResponses, McpAuthRemoveErrors, McpAuthRemoveResponses, McpAuthStartErrors, McpAuthStartResponses, McpConnectResponses, McpDisconnectResponses, McpLocalConfig, McpRemoteConfig, McpStatusResponses, Part, PartDeleteErrors, PartDeleteResponses, PartUpdateErrors, PartUpdateResponses, PathGetResponses, PermissionListResponses, PermissionReplyErrors, PermissionReplyResponses, PermissionRespondErrors, PermissionRespondResponses, PermissionRuleset, ProjectCurrentResponses, ProjectListResponses, ProjectUpdateErrors, ProjectUpdateResponses, 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'; +import { zAppAgentsQuery, zAppAgentsResponse, zAppLogBody, zAppLogQuery, zAppLogResponse, zAuthSetBody, zAuthSetPath, zAuthSetQuery, zAuthSetResponse, zCommandListQuery, zCommandListResponse, zConfigGetQuery, zConfigGetResponse, zConfigProvidersQuery, zConfigProvidersResponse, zConfigUpdateBody, zConfigUpdateQuery, zConfigUpdateResponse, zEventSubscribeQuery, zEventSubscribeResponse, zFileListQuery, zFileListResponse, zFileReadQuery, zFileReadResponse, zFileStatusQuery, zFileStatusResponse, zFindFilesQuery, zFindFilesResponse, zFindSymbolsQuery, zFindSymbolsResponse, zFindTextQuery, zFindTextResponse, zFormatterStatusQuery, zFormatterStatusResponse, zGlobalDisposeResponse, zGlobalEventResponse, zGlobalHealthResponse, zInstanceDisposeQuery, zInstanceDisposeResponse, zLspStatusQuery, zLspStatusResponse, zMcpAddBody, zMcpAddQuery, zMcpAddResponse, zMcpAuthAuthenticatePath, zMcpAuthAuthenticateQuery, zMcpAuthAuthenticateResponse, zMcpAuthCallbackBody, zMcpAuthCallbackPath, zMcpAuthCallbackQuery, zMcpAuthCallbackResponse, zMcpAuthRemovePath, zMcpAuthRemoveQuery, zMcpAuthRemoveResponse, zMcpAuthStartPath, zMcpAuthStartQuery, zMcpAuthStartResponse, zMcpConnectPath, zMcpConnectQuery, zMcpConnectResponse, zMcpDisconnectPath, zMcpDisconnectQuery, zMcpDisconnectResponse, zMcpStatusQuery, zMcpStatusResponse, zPartDeletePath, zPartDeleteQuery, zPartDeleteResponse, zPartUpdateBody, zPartUpdatePath, zPartUpdateQuery, zPartUpdateResponse, zPathGetQuery, zPathGetResponse, zPermissionListQuery, zPermissionListResponse, zPermissionReplyBody, zPermissionReplyPath, zPermissionReplyQuery, zPermissionReplyResponse, zPermissionRespondBody, zPermissionRespondPath, zPermissionRespondQuery, zPermissionRespondResponse, zProjectCurrentQuery, zProjectCurrentResponse, zProjectListQuery, zProjectListResponse, zProjectUpdateBody, zProjectUpdatePath, zProjectUpdateQuery, zProjectUpdateResponse, zProviderAuthQuery, zProviderAuthResponse, zProviderListQuery, zProviderListResponse, zProviderOauthAuthorizeBody, zProviderOauthAuthorizePath, zProviderOauthAuthorizeQuery, zProviderOauthAuthorizeResponse, zProviderOauthCallbackBody, zProviderOauthCallbackPath, zProviderOauthCallbackQuery, zProviderOauthCallbackResponse, zPtyConnectPath, zPtyConnectQuery, zPtyConnectResponse, zPtyCreateBody, zPtyCreateQuery, zPtyCreateResponse, zPtyGetPath, zPtyGetQuery, zPtyGetResponse, zPtyListQuery, zPtyListResponse, zPtyRemovePath, zPtyRemoveQuery, zPtyRemoveResponse, zPtyUpdateBody, zPtyUpdatePath, zPtyUpdateQuery, zPtyUpdateResponse, zSessionAbortPath, zSessionAbortQuery, zSessionAbortResponse, zSessionChildrenPath, zSessionChildrenQuery, zSessionChildrenResponse, zSessionCommandBody, zSessionCommandPath, zSessionCommandQuery, zSessionCommandResponse, zSessionCreateBody, zSessionCreateQuery, zSessionCreateResponse, zSessionDeletePath, zSessionDeleteQuery, zSessionDeleteResponse, zSessionDiffPath, zSessionDiffQuery, zSessionDiffResponse, zSessionForkBody, zSessionForkPath, zSessionForkQuery, zSessionForkResponse, zSessionGetPath, zSessionGetQuery, zSessionGetResponse, zSessionInitBody, zSessionInitPath, zSessionInitQuery, zSessionInitResponse, zSessionListQuery, zSessionListResponse, zSessionMessagePath, zSessionMessageQuery, zSessionMessageResponse, zSessionMessagesPath, zSessionMessagesQuery, zSessionMessagesResponse, zSessionPromptAsyncBody, zSessionPromptAsyncPath, zSessionPromptAsyncQuery, zSessionPromptAsyncResponse, zSessionPromptBody, zSessionPromptPath, zSessionPromptQuery, zSessionPromptResponse, zSessionRevertBody, zSessionRevertPath, zSessionRevertQuery, zSessionRevertResponse, zSessionSharePath, zSessionShareQuery, zSessionShareResponse, zSessionShellBody, zSessionShellPath, zSessionShellQuery, zSessionShellResponse, zSessionStatusQuery, zSessionStatusResponse, zSessionSummarizeBody, zSessionSummarizePath, zSessionSummarizeQuery, zSessionSummarizeResponse, zSessionTodoPath, zSessionTodoQuery, zSessionTodoResponse, zSessionUnrevertPath, zSessionUnrevertQuery, zSessionUnrevertResponse, zSessionUnsharePath, zSessionUnshareQuery, zSessionUnshareResponse, zSessionUpdateBody, zSessionUpdatePath, zSessionUpdateQuery, zSessionUpdateResponse, zToolIdsQuery, zToolIdsResponse, zToolListQuery, zToolListResponse, zTuiAppendPromptBody, zTuiAppendPromptQuery, zTuiAppendPromptResponse, zTuiClearPromptQuery, zTuiClearPromptResponse, zTuiControlNextQuery, zTuiControlNextResponse, zTuiControlResponseBody, zTuiControlResponseQuery, zTuiControlResponseResponse, zTuiExecuteCommandBody, zTuiExecuteCommandQuery, zTuiExecuteCommandResponse, zTuiOpenHelpQuery, zTuiOpenHelpResponse, zTuiOpenModelsQuery, zTuiOpenModelsResponse, zTuiOpenSessionsQuery, zTuiOpenSessionsResponse, zTuiOpenThemesQuery, zTuiOpenThemesResponse, zTuiPublishBody, zTuiPublishQuery, zTuiPublishResponse, zTuiShowToastBody, zTuiShowToastQuery, zTuiShowToastResponse, zTuiSubmitPromptQuery, zTuiSubmitPromptResponse, zVcsGetQuery, zVcsGetResponse } from './zod.gen'; + +export type Options = Options2 & { + /** + * 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; +}; + +/** + * Get health + * + * Get health information about the OpenCode server. + */ +export const globalHealth = Object.assign(function globalHealth2(options?: Options) { + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: z.never().optional() + }).parseAsync(data), + responseValidator: async (data) => await zGlobalHealthResponse.parseAsync(data), + url: '/global/health', + ...options + }); +}, { + id: 'globalHealth', + method: 'get', + responseSchema: zGlobalHealthResponse, + url: '/global/health' +}); + +/** + * Get global events + * + * Subscribe to global events from the OpenCode system using server-sent events. + */ +export const globalEvent = Object.assign(function globalEvent2(options?: Options) { + return (options?.client ?? client).sse.get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: z.never().optional() + }).parseAsync(data), + responseValidator: async (data) => await zGlobalEventResponse.parseAsync(data), + url: '/global/event', + ...options + }); +}, { + id: 'globalEvent', + method: 'get', + responseSchema: zGlobalEventResponse, + url: '/global/event' +}); + +/** + * Dispose instance + * + * Clean up and dispose all OpenCode instances, releasing all resources. + */ +export const globalDispose = Object.assign(function globalDispose2(options?: Options) { + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: z.never().optional() + }).parseAsync(data), + responseValidator: async (data) => await zGlobalDisposeResponse.parseAsync(data), + url: '/global/dispose', + ...options + }); +}, { + id: 'globalDispose', + method: 'post', + responseSchema: zGlobalDisposeResponse, + url: '/global/dispose' +}); + +/** + * List all projects + * + * Get a list of projects that have been opened with OpenCode. + */ +export const projectList = Object.assign(function projectList2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProjectListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProjectListResponse.parseAsync(data), + url: '/project', + ...options, + ...params + }); +}, { + id: 'projectList', + method: 'get', + responseSchema: zProjectListResponse, + url: '/project' +}); + +/** + * Get current project + * + * Retrieve the currently active project that OpenCode is working with. + */ +export const projectCurrent = Object.assign(function projectCurrent2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProjectCurrentQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProjectCurrentResponse.parseAsync(data), + url: '/project/current', + ...options, + ...params + }); +}, { + id: 'projectCurrent', + method: 'get', + responseSchema: zProjectCurrentResponse, + url: '/project/current' +}); + +/** + * Update project + * + * Update project properties such as name, icon and color. + */ +export const projectUpdate = Object.assign(function projectUpdate2(parameters: { + projectID: string; + directory?: string; + name?: string; + icon?: { + url?: string; + color?: string; + }; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'projectID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'name' }, + { in: 'body', key: 'icon' } + ] }]); + return (options?.client ?? client).patch({ + requestValidator: async (data) => await z.object({ + body: zProjectUpdateBody.optional(), + path: zProjectUpdatePath, + query: zProjectUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProjectUpdateResponse.parseAsync(data), + url: '/project/{projectID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'projectUpdate', + method: 'patch', + responseSchema: zProjectUpdateResponse, + url: '/project/{projectID}' +}); + +/** + * List PTY sessions + * + * Get a list of all active pseudo-terminal (PTY) sessions managed by OpenCode. + */ +export const ptyList = Object.assign(function ptyList2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zPtyListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyListResponse.parseAsync(data), + url: '/pty', + ...options, + ...params + }); +}, { + id: 'ptyList', + method: 'get', + responseSchema: zPtyListResponse, + url: '/pty' +}); + +/** + * Create PTY session + * + * Create a new pseudo-terminal (PTY) session for running shell commands and processes. + */ +export const ptyCreate = Object.assign(function ptyCreate2(parameters?: { + directory?: string; + command?: string; + args?: Array; + cwd?: string; + title?: string; + env?: { + [key: string]: string; + }; +}, options?: Options) { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zPtyCreateBody.optional(), + path: z.never().optional(), + query: zPtyCreateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyCreateResponse.parseAsync(data), + url: '/pty', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'ptyCreate', + method: 'post', + responseSchema: zPtyCreateResponse, + url: '/pty' +}); + +/** + * Remove PTY session + * + * Remove and terminate a specific pseudo-terminal (PTY) session. + */ +export const ptyRemove = Object.assign(function ptyRemove2(parameters: { + ptyID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'ptyID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPtyRemovePath, + query: zPtyRemoveQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyRemoveResponse.parseAsync(data), + url: '/pty/{ptyID}', + ...options, + ...params + }); +}, { + id: 'ptyRemove', + method: 'delete', + responseSchema: zPtyRemoveResponse, + url: '/pty/{ptyID}' +}); + +/** + * Get PTY session + * + * Retrieve detailed information about a specific pseudo-terminal (PTY) session. + */ +export const ptyGet = Object.assign(function ptyGet2(parameters: { + ptyID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'ptyID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPtyGetPath, + query: zPtyGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyGetResponse.parseAsync(data), + url: '/pty/{ptyID}', + ...options, + ...params + }); +}, { + id: 'ptyGet', + method: 'get', + responseSchema: zPtyGetResponse, + url: '/pty/{ptyID}' +}); + +/** + * Update PTY session + * + * Update properties of an existing pseudo-terminal (PTY) session. + */ +export const ptyUpdate = Object.assign(function ptyUpdate2(parameters: { + ptyID: string; + directory?: string; + title?: string; + size?: { + rows: number; + cols: number; + }; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'ptyID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'title' }, + { in: 'body', key: 'size' } + ] }]); + return (options?.client ?? client).put({ + requestValidator: async (data) => await z.object({ + body: zPtyUpdateBody.optional(), + path: zPtyUpdatePath, + query: zPtyUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyUpdateResponse.parseAsync(data), + url: '/pty/{ptyID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'ptyUpdate', + method: 'put', + responseSchema: zPtyUpdateResponse, + url: '/pty/{ptyID}' +}); + +/** + * Connect to PTY session + * + * Establish a WebSocket connection to interact with a pseudo-terminal (PTY) session in real-time. + */ +export const ptyConnect = Object.assign(function ptyConnect2(parameters: { + ptyID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'ptyID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPtyConnectPath, + query: zPtyConnectQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyConnectResponse.parseAsync(data), + url: '/pty/{ptyID}/connect', + ...options, + ...params + }); +}, { + id: 'ptyConnect', + method: 'get', + responseSchema: zPtyConnectResponse, + url: '/pty/{ptyID}/connect' +}); + +/** + * Get configuration + * + * Retrieve the current OpenCode configuration settings and preferences. + */ +export const configGet = Object.assign(function configGet2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zConfigGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zConfigGetResponse.parseAsync(data), + url: '/config', + ...options, + ...params + }); +}, { + id: 'configGet', + method: 'get', + responseSchema: zConfigGetResponse, + url: '/config' +}); + +/** + * Update configuration + * + * Update OpenCode configuration settings and preferences. + */ +export const configUpdate = Object.assign(function configUpdate2(parameters?: { + directory?: string; + config?: Config; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { key: 'config', map: 'body' }] }]); + return (options?.client ?? client).patch({ + requestValidator: async (data) => await z.object({ + body: zConfigUpdateBody.optional(), + path: z.never().optional(), + query: zConfigUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zConfigUpdateResponse.parseAsync(data), + url: '/config', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'configUpdate', + method: 'patch', + responseSchema: zConfigUpdateResponse, + url: '/config' +}); + +/** + * List tool IDs + * + * Get a list of all available tool IDs, including both built-in tools and dynamically registered tools. + */ +export const toolIds = Object.assign(function toolIds2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zToolIdsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zToolIdsResponse.parseAsync(data), + url: '/experimental/tool/ids', + ...options, + ...params + }); +}, { + id: 'toolIds', + method: 'get', + responseSchema: zToolIdsResponse, + url: '/experimental/tool/ids' +}); + +/** + * List tools + * + * Get a list of available tools with their JSON schema parameters for a specific provider and model combination. + */ +export const toolList = Object.assign(function toolList2(parameters: { + directory?: string; + provider: string; + model: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'query', key: 'provider' }, + { in: 'query', key: 'model' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zToolListQuery + }).parseAsync(data), + responseValidator: async (data) => await zToolListResponse.parseAsync(data), + url: '/experimental/tool', + ...options, + ...params + }); +}, { + id: 'toolList', + method: 'get', + responseSchema: zToolListResponse, + url: '/experimental/tool' +}); + +/** + * Dispose instance + * + * Clean up and dispose the current OpenCode instance, releasing all resources. + */ +export const instanceDispose = Object.assign(function instanceDispose2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zInstanceDisposeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zInstanceDisposeResponse.parseAsync(data), + url: '/instance/dispose', + ...options, + ...params + }); +}, { + id: 'instanceDispose', + method: 'post', + responseSchema: zInstanceDisposeResponse, + url: '/instance/dispose' +}); + +/** + * Get paths + * + * Retrieve the current working directory and related path information for the OpenCode instance. + */ +export const pathGet = Object.assign(function pathGet2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zPathGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPathGetResponse.parseAsync(data), + url: '/path', + ...options, + ...params + }); +}, { + id: 'pathGet', + method: 'get', + responseSchema: zPathGetResponse, + url: '/path' +}); + +/** + * Get VCS info + * + * Retrieve version control system (VCS) information for the current project, such as git branch. + */ +export const vcsGet = Object.assign(function vcsGet2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zVcsGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zVcsGetResponse.parseAsync(data), + url: '/vcs', + ...options, + ...params + }); +}, { + id: 'vcsGet', + method: 'get', + responseSchema: zVcsGetResponse, + url: '/vcs' +}); + +/** + * List sessions + * + * Get a list of all OpenCode sessions, sorted by most recently updated. + */ +export const sessionList = Object.assign(function sessionList2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zSessionListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionListResponse.parseAsync(data), + url: '/session', + ...options, + ...params + }); +}, { + id: 'sessionList', + method: 'get', + responseSchema: zSessionListResponse, + url: '/session' +}); + +/** + * Create session + * + * Create a new OpenCode session for interacting with AI assistants and managing conversations. + */ +export const sessionCreate = Object.assign(function sessionCreate2(parameters?: { + directory?: string; + parentID?: string; + title?: string; + permission?: PermissionRuleset; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'body', key: 'parentID' }, + { in: 'body', key: 'title' }, + { in: 'body', key: 'permission' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionCreateBody.optional(), + path: z.never().optional(), + query: zSessionCreateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionCreateResponse.parseAsync(data), + url: '/session', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'sessionCreate', + method: 'post', + responseSchema: zSessionCreateResponse, + url: '/session' +}); + +/** + * Get session status + * + * Retrieve the current status of all sessions, including active, idle, and completed states. + */ +export const sessionStatus = Object.assign(function sessionStatus2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zSessionStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionStatusResponse.parseAsync(data), + url: '/session/status', + ...options, + ...params + }); +}, { + id: 'sessionStatus', + method: 'get', + responseSchema: zSessionStatusResponse, + url: '/session/status' +}); + +/** + * Delete session + * + * Delete a session and permanently remove all associated data, including messages and history. + */ +export const sessionDelete = Object.assign(function sessionDelete2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionDeletePath, + query: zSessionDeleteQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionDeleteResponse.parseAsync(data), + url: '/session/{sessionID}', + ...options, + ...params + }); +}, { + id: 'sessionDelete', + method: 'delete', + responseSchema: zSessionDeleteResponse, + url: '/session/{sessionID}' +}); + +/** + * Get session + * + * Retrieve detailed information about a specific OpenCode session. + */ +export const sessionGet = Object.assign(function sessionGet2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionGetPath, + query: zSessionGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionGetResponse.parseAsync(data), + url: '/session/{sessionID}', + ...options, + ...params + }); +}, { + id: 'sessionGet', + method: 'get', + responseSchema: zSessionGetResponse, + tags: ['Session'], + url: '/session/{sessionID}' +}); + +/** + * Update session + * + * Update properties of an existing session, such as title or other metadata. + */ +export const sessionUpdate = Object.assign(function sessionUpdate2(parameters: { + sessionID: string; + directory?: string; + title?: string; + time?: { + archived?: number; + }; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'title' }, + { in: 'body', key: 'time' } + ] }]); + return (options?.client ?? client).patch({ + requestValidator: async (data) => await z.object({ + body: zSessionUpdateBody.optional(), + path: zSessionUpdatePath, + query: zSessionUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionUpdateResponse.parseAsync(data), + url: '/session/{sessionID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'sessionUpdate', + method: 'patch', + responseSchema: zSessionUpdateResponse, + url: '/session/{sessionID}' +}); + +/** + * Get session children + * + * Retrieve all child sessions that were forked from the specified parent session. + */ +export const sessionChildren = Object.assign(function sessionChildren2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionChildrenPath, + query: zSessionChildrenQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionChildrenResponse.parseAsync(data), + url: '/session/{sessionID}/children', + ...options, + ...params + }); +}, { + id: 'sessionChildren', + method: 'get', + responseSchema: zSessionChildrenResponse, + tags: ['Session'], + url: '/session/{sessionID}/children' +}); + +/** + * Get session todos + * + * Retrieve the todo list associated with a specific session, showing tasks and action items. + */ +export const sessionTodo = Object.assign(function sessionTodo2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionTodoPath, + query: zSessionTodoQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionTodoResponse.parseAsync(data), + url: '/session/{sessionID}/todo', + ...options, + ...params + }); +}, { + id: 'sessionTodo', + method: 'get', + responseSchema: zSessionTodoResponse, + url: '/session/{sessionID}/todo' +}); + +/** + * Initialize session + * + * Analyze the current application and create an AGENTS.md file with project-specific agent configurations. + */ +export const sessionInit = Object.assign(function sessionInit2(parameters: { + sessionID: string; + directory?: string; + modelID: string; + providerID: string; + messageID: string; +}, options?: Options) { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionInitBody.optional(), + path: zSessionInitPath, + query: zSessionInitQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionInitResponse.parseAsync(data), + url: '/session/{sessionID}/init', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'sessionInit', + method: 'post', + responseSchema: zSessionInitResponse, + url: '/session/{sessionID}/init' +}); + +/** + * Fork session + * + * Create a new session by forking an existing session at a specific message point. + */ +export const sessionFork = Object.assign(function sessionFork2(parameters: { + sessionID: string; + directory?: string; + messageID?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'messageID' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionForkBody.optional(), + path: zSessionForkPath, + query: zSessionForkQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionForkResponse.parseAsync(data), + url: '/session/{sessionID}/fork', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'sessionFork', + method: 'post', + responseSchema: zSessionForkResponse, + url: '/session/{sessionID}/fork' +}); + +/** + * Abort session + * + * Abort an active session and stop any ongoing AI processing or command execution. + */ +export const sessionAbort = Object.assign(function sessionAbort2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionAbortPath, + query: zSessionAbortQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionAbortResponse.parseAsync(data), + url: '/session/{sessionID}/abort', + ...options, + ...params + }); +}, { + id: 'sessionAbort', + method: 'post', + responseSchema: zSessionAbortResponse, + url: '/session/{sessionID}/abort' +}); + +/** + * Unshare session + * + * Remove the shareable link for a session, making it private again. + */ +export const sessionUnshare = Object.assign(function sessionUnshare2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionUnsharePath, + query: zSessionUnshareQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionUnshareResponse.parseAsync(data), + url: '/session/{sessionID}/share', + ...options, + ...params + }); +}, { + id: 'sessionUnshare', + method: 'delete', + responseSchema: zSessionUnshareResponse, + url: '/session/{sessionID}/share' +}); + +/** + * Share session + * + * Create a shareable link for a session, allowing others to view the conversation. + */ +export const sessionShare = Object.assign(function sessionShare2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionSharePath, + query: zSessionShareQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionShareResponse.parseAsync(data), + url: '/session/{sessionID}/share', + ...options, + ...params + }); +}, { + id: 'sessionShare', + method: 'post', + responseSchema: zSessionShareResponse, + url: '/session/{sessionID}/share' +}); + +/** + * Get session diff + * + * Get all file changes (diffs) made during this session. + */ +export const sessionDiff = Object.assign(function sessionDiff2(parameters: { + sessionID: string; + directory?: string; + messageID?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'query', key: 'messageID' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionDiffPath, + query: zSessionDiffQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionDiffResponse.parseAsync(data), + url: '/session/{sessionID}/diff', + ...options, + ...params + }); +}, { + id: 'sessionDiff', + method: 'get', + responseSchema: zSessionDiffResponse, + url: '/session/{sessionID}/diff' +}); + +/** + * Summarize session + * + * Generate a concise summary of the session using AI compaction to preserve key information. + */ +export const sessionSummarize = Object.assign(function sessionSummarize2(parameters: { + sessionID: string; + directory?: string; + providerID: string; + modelID: string; + auto?: boolean; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'providerID' }, + { in: 'body', key: 'modelID' }, + { in: 'body', key: 'auto' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionSummarizeBody.optional(), + path: zSessionSummarizePath, + query: zSessionSummarizeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionSummarizeResponse.parseAsync(data), + url: '/session/{sessionID}/summarize', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'sessionSummarize', + method: 'post', + responseSchema: zSessionSummarizeResponse, + url: '/session/{sessionID}/summarize' +}); + +/** + * Get session messages + * + * Retrieve all messages in a session, including user prompts and AI responses. + */ +export const sessionMessages = Object.assign(function sessionMessages2(parameters: { + sessionID: string; + directory?: string; + limit?: number; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'query', key: 'limit' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionMessagesPath, + query: zSessionMessagesQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionMessagesResponse.parseAsync(data), + url: '/session/{sessionID}/message', + ...options, + ...params + }); +}, { + id: 'sessionMessages', + method: 'get', + responseSchema: zSessionMessagesResponse, + url: '/session/{sessionID}/message' +}); + +/** + * Send message + * + * Create and send a new message to a session, streaming the AI response. + */ +export const sessionPrompt = Object.assign(function sessionPrompt2(parameters: { + sessionID: string; + directory?: string; + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; +}, options?: Options) { + 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: 'tools' }, + { in: 'body', key: 'system' }, + { in: 'body', key: 'variant' }, + { in: 'body', key: 'parts' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionPromptBody.optional(), + path: zSessionPromptPath, + query: zSessionPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionPromptResponse.parseAsync(data), + url: '/session/{sessionID}/message', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'sessionPrompt', + method: 'post', + responseSchema: zSessionPromptResponse, + url: '/session/{sessionID}/message' +}); + +/** + * Get message + * + * Retrieve a specific message from a session by its message ID. + */ +export const sessionMessage = Object.assign(function sessionMessage2(parameters: { + sessionID: string; + messageID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'messageID' }, + { in: 'query', key: 'directory' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionMessagePath, + query: zSessionMessageQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionMessageResponse.parseAsync(data), + url: '/session/{sessionID}/message/{messageID}', + ...options, + ...params + }); +}, { + id: 'sessionMessage', + method: 'get', + responseSchema: zSessionMessageResponse, + url: '/session/{sessionID}/message/{messageID}' +}); + +/** + * Delete a part from a message + */ +export const partDelete = Object.assign(function partDelete2(parameters: { + sessionID: string; + messageID: string; + partID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'messageID' }, + { in: 'path', key: 'partID' }, + { in: 'query', key: 'directory' } + ] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPartDeletePath, + query: zPartDeleteQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPartDeleteResponse.parseAsync(data), + url: '/session/{sessionID}/message/{messageID}/part/{partID}', + ...options, + ...params + }); +}, { + id: 'partDelete', + method: 'delete', + responseSchema: zPartDeleteResponse, + url: '/session/{sessionID}/message/{messageID}/part/{partID}' +}); + +/** + * Update a part in a message + */ +export const partUpdate = Object.assign(function partUpdate2(parameters: { + sessionID: string; + messageID: string; + partID: string; + directory?: string; + part?: Part; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'messageID' }, + { in: 'path', key: 'partID' }, + { in: 'query', key: 'directory' }, + { key: 'part', map: 'body' } + ] }]); + return (options?.client ?? client).patch({ + requestValidator: async (data) => await z.object({ + body: zPartUpdateBody.optional(), + path: zPartUpdatePath, + query: zPartUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPartUpdateResponse.parseAsync(data), + url: '/session/{sessionID}/message/{messageID}/part/{partID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'partUpdate', + method: 'patch', + responseSchema: zPartUpdateResponse, + url: '/session/{sessionID}/message/{messageID}/part/{partID}' +}); + +/** + * Send async message + * + * Create and send a new message to a session asynchronously, starting the session if needed and returning immediately. + */ +export const sessionPromptAsync = Object.assign(function sessionPromptAsync2(parameters: { + sessionID: string; + directory?: string; + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; +}, options?: Options) { + 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: 'tools' }, + { in: 'body', key: 'system' }, + { in: 'body', key: 'variant' }, + { in: 'body', key: 'parts' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionPromptAsyncBody.optional(), + path: zSessionPromptAsyncPath, + query: zSessionPromptAsyncQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionPromptAsyncResponse.parseAsync(data), + url: '/session/{sessionID}/prompt_async', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'sessionPromptAsync', + method: 'post', + responseSchema: zSessionPromptAsyncResponse, + url: '/session/{sessionID}/prompt_async' +}); + +/** + * Send command + * + * Send a new command to a session for execution by the AI assistant. + */ +export const sessionCommand = Object.assign(function sessionCommand2(parameters: { + sessionID: string; + directory?: string; + messageID?: string; + agent?: string; + model?: string; + arguments: string; + command: string; + variant?: string; +}, options?: Options) { + 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' }, + { in: 'body', key: 'variant' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionCommandBody.optional(), + path: zSessionCommandPath, + query: zSessionCommandQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionCommandResponse.parseAsync(data), + url: '/session/{sessionID}/command', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'sessionCommand', + method: 'post', + responseSchema: zSessionCommandResponse, + url: '/session/{sessionID}/command' +}); + +/** + * Run shell command + * + * Execute a shell command within the session context and return the AI's response. + */ +export const sessionShell = Object.assign(function sessionShell2(parameters: { + sessionID: string; + directory?: string; + agent: string; + model?: { + providerID: string; + modelID: string; + }; + command: string; +}, options?: Options) { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionShellBody.optional(), + path: zSessionShellPath, + query: zSessionShellQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionShellResponse.parseAsync(data), + url: '/session/{sessionID}/shell', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'sessionShell', + method: 'post', + responseSchema: zSessionShellResponse, + url: '/session/{sessionID}/shell' +}); + +/** + * Revert message + * + * Revert a specific message in a session, undoing its effects and restoring the previous state. + */ +export const sessionRevert = Object.assign(function sessionRevert2(parameters: { + sessionID: string; + directory?: string; + messageID: string; + partID?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'messageID' }, + { in: 'body', key: 'partID' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionRevertBody.optional(), + path: zSessionRevertPath, + query: zSessionRevertQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionRevertResponse.parseAsync(data), + url: '/session/{sessionID}/revert', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'sessionRevert', + method: 'post', + responseSchema: zSessionRevertResponse, + url: '/session/{sessionID}/revert' +}); + +/** + * Restore reverted messages + * + * Restore all previously reverted messages in a session. + */ +export const sessionUnrevert = Object.assign(function sessionUnrevert2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionUnrevertPath, + query: zSessionUnrevertQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionUnrevertResponse.parseAsync(data), + url: '/session/{sessionID}/unrevert', + ...options, + ...params + }); +}, { + id: 'sessionUnrevert', + method: 'post', + responseSchema: zSessionUnrevertResponse, + url: '/session/{sessionID}/unrevert' +}); + +/** + * Respond to permission + * + * Approve or deny a permission request from the AI assistant. + * + * @deprecated + */ +export const permissionRespond = Object.assign(function permissionRespond2(parameters: { + sessionID: string; + permissionID: string; + directory?: string; + response: 'once' | 'always' | 'reject'; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'permissionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'response' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zPermissionRespondBody.optional(), + path: zPermissionRespondPath, + query: zPermissionRespondQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPermissionRespondResponse.parseAsync(data), + url: '/session/{sessionID}/permissions/{permissionID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'permissionRespond', + method: 'post', + responseSchema: zPermissionRespondResponse, + url: '/session/{sessionID}/permissions/{permissionID}' +}); + +/** + * Respond to permission request + * + * Approve or deny a permission request from the AI assistant. + */ +export const permissionReply = Object.assign(function permissionReply2(parameters: { + requestID: string; + directory?: string; + reply: 'once' | 'always' | 'reject'; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'requestID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'reply' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zPermissionReplyBody.optional(), + path: zPermissionReplyPath, + query: zPermissionReplyQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPermissionReplyResponse.parseAsync(data), + url: '/permission/{requestID}/reply', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'permissionReply', + method: 'post', + responseSchema: zPermissionReplyResponse, + url: '/permission/{requestID}/reply' +}); + +/** + * List pending permissions + * + * Get all pending permission requests across all sessions. + */ +export const permissionList = Object.assign(function permissionList2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zPermissionListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPermissionListResponse.parseAsync(data), + url: '/permission', + ...options, + ...params + }); +}, { + id: 'permissionList', + method: 'get', + responseSchema: zPermissionListResponse, + url: '/permission' +}); + +/** + * List commands + * + * Get a list of all available commands in the OpenCode system. + */ +export const commandList = Object.assign(function commandList2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zCommandListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zCommandListResponse.parseAsync(data), + url: '/command', + ...options, + ...params + }); +}, { + id: 'commandList', + method: 'get', + responseSchema: zCommandListResponse, + url: '/command' +}); + +/** + * List config providers + * + * Get a list of all configured AI providers and their default models. + */ +export const configProviders = Object.assign(function configProviders2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zConfigProvidersQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zConfigProvidersResponse.parseAsync(data), + url: '/config/providers', + ...options, + ...params + }); +}, { + id: 'configProviders', + method: 'get', + responseSchema: zConfigProvidersResponse, + url: '/config/providers' +}); + +/** + * List providers + * + * Get a list of all available AI providers, including both available and connected ones. + */ +export const providerList = Object.assign(function providerList2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProviderListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderListResponse.parseAsync(data), + url: '/provider', + ...options, + ...params + }); +}, { + id: 'providerList', + method: 'get', + responseSchema: zProviderListResponse, + url: '/provider' +}); + +/** + * Get provider auth methods + * + * Retrieve available authentication methods for all AI providers. + */ +export const providerAuth = Object.assign(function providerAuth2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProviderAuthQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderAuthResponse.parseAsync(data), + url: '/provider/auth', + ...options, + ...params + }); +}, { + id: 'providerAuth', + method: 'get', + responseSchema: zProviderAuthResponse, + url: '/provider/auth' +}); + +/** + * OAuth authorize + * + * Initiate OAuth authorization for a specific AI provider to get an authorization URL. + */ +export const providerOauthAuthorize = Object.assign(function providerOauthAuthorize2(parameters: { + providerID: string; + directory?: string; + method: number; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'providerID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'method' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zProviderOauthAuthorizeBody.optional(), + path: zProviderOauthAuthorizePath, + query: zProviderOauthAuthorizeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderOauthAuthorizeResponse.parseAsync(data), + url: '/provider/{providerID}/oauth/authorize', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'providerOauthAuthorize', + method: 'post', + responseSchema: zProviderOauthAuthorizeResponse, + url: '/provider/{providerID}/oauth/authorize' +}); + +/** + * OAuth callback + * + * Handle the OAuth callback from a provider after user authorization. + */ +export const providerOauthCallback = Object.assign(function providerOauthCallback2(parameters: { + providerID: string; + directory?: string; + method: number; + code?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'providerID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'method' }, + { in: 'body', key: 'code' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zProviderOauthCallbackBody.optional(), + path: zProviderOauthCallbackPath, + query: zProviderOauthCallbackQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderOauthCallbackResponse.parseAsync(data), + url: '/provider/{providerID}/oauth/callback', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'providerOauthCallback', + method: 'post', + responseSchema: zProviderOauthCallbackResponse, + url: '/provider/{providerID}/oauth/callback' +}); + +/** + * Find text + * + * Search for text patterns across files in the project using ripgrep. + */ +export const findText = Object.assign(function findText2(parameters: { + directory?: string; + pattern: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'pattern' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFindTextQuery + }).parseAsync(data), + responseValidator: async (data) => await zFindTextResponse.parseAsync(data), + url: '/find', + ...options, + ...params + }); +}, { + id: 'findText', + method: 'get', + responseSchema: zFindTextResponse, + url: '/find' +}); + +/** + * Find files + * + * Search for files or directories by name or pattern in the project directory. + */ +export const findFiles = Object.assign(function findFiles2(parameters: { + directory?: string; + query: string; + dirs?: 'true' | 'false'; + type?: 'file' | 'directory'; + limit?: number; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'query', key: 'query' }, + { in: 'query', key: 'dirs' }, + { in: 'query', key: 'type' }, + { in: 'query', key: 'limit' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFindFilesQuery + }).parseAsync(data), + responseValidator: async (data) => await zFindFilesResponse.parseAsync(data), + url: '/find/file', + ...options, + ...params + }); +}, { + id: 'findFiles', + method: 'get', + responseSchema: zFindFilesResponse, + url: '/find/file' +}); + +/** + * Find symbols + * + * Search for workspace symbols like functions, classes, and variables using LSP. + */ +export const findSymbols = Object.assign(function findSymbols2(parameters: { + directory?: string; + query: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'query' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFindSymbolsQuery + }).parseAsync(data), + responseValidator: async (data) => await zFindSymbolsResponse.parseAsync(data), + url: '/find/symbol', + ...options, + ...params + }); +}, { + id: 'findSymbols', + method: 'get', + responseSchema: zFindSymbolsResponse, + url: '/find/symbol' +}); + +/** + * List files + * + * List files and directories in a specified path. + */ +export const fileList = Object.assign(function fileList2(parameters: { + directory?: string; + path: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'path' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFileListQuery + }).parseAsync(data), + responseValidator: async (data) => await zFileListResponse.parseAsync(data), + url: '/file', + ...options, + ...params + }); +}, { + id: 'fileList', + method: 'get', + responseSchema: zFileListResponse, + url: '/file' +}); + +/** + * Read file + * + * Read the content of a specified file. + */ +export const fileRead = Object.assign(function fileRead2(parameters: { + directory?: string; + path: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'path' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFileReadQuery + }).parseAsync(data), + responseValidator: async (data) => await zFileReadResponse.parseAsync(data), + url: '/file/content', + ...options, + ...params + }); +}, { + id: 'fileRead', + method: 'get', + responseSchema: zFileReadResponse, + url: '/file/content' +}); + +/** + * Get file status + * + * Get the git status of all files in the project. + */ +export const fileStatus = Object.assign(function fileStatus2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFileStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zFileStatusResponse.parseAsync(data), + url: '/file/status', + ...options, + ...params + }); +}, { + id: 'fileStatus', + method: 'get', + responseSchema: zFileStatusResponse, + url: '/file/status' +}); + +/** + * Write log + * + * Write a log entry to the server logs with specified level and metadata. + */ +export const appLog = Object.assign(function appLog2(parameters: { + directory?: string; + service: string; + level: 'debug' | 'info' | 'error' | 'warn'; + message: string; + extra?: { + [key: string]: unknown; + }; +}, options?: Options) { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zAppLogBody.optional(), + path: z.never().optional(), + query: zAppLogQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zAppLogResponse.parseAsync(data), + url: '/log', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'appLog', + method: 'post', + responseSchema: zAppLogResponse, + url: '/log' +}); + +/** + * List agents + * + * Get a list of all available AI agents in the OpenCode system. + */ +export const appAgents = Object.assign(function appAgents2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zAppAgentsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zAppAgentsResponse.parseAsync(data), + url: '/agent', + ...options, + ...params + }); +}, { + id: 'appAgents', + method: 'get', + responseSchema: zAppAgentsResponse, + url: '/agent' +}); + +/** + * Get MCP status + * + * Get the status of all Model Context Protocol (MCP) servers. + */ +export const mcpStatus = Object.assign(function mcpStatus2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zMcpStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpStatusResponse.parseAsync(data), + url: '/mcp', + ...options, + ...params + }); +}, { + id: 'mcpStatus', + method: 'get', + responseSchema: zMcpStatusResponse, + url: '/mcp' +}); + +/** + * Add MCP server + * + * Dynamically add a new Model Context Protocol (MCP) server to the system. + */ +export const mcpAdd = Object.assign(function mcpAdd2(parameters: { + directory?: string; + name: string; + config: McpLocalConfig | McpRemoteConfig; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'body', key: 'name' }, + { in: 'body', key: 'config' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zMcpAddBody.optional(), + path: z.never().optional(), + query: zMcpAddQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAddResponse.parseAsync(data), + url: '/mcp', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'mcpAdd', + method: 'post', + responseSchema: zMcpAddResponse, + url: '/mcp' +}); + +/** + * Remove MCP OAuth + * + * Remove OAuth credentials for an MCP server + */ +export const mcpAuthRemove = Object.assign(function mcpAuthRemove2(parameters: { + name: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpAuthRemovePath, + query: zMcpAuthRemoveQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthRemoveResponse.parseAsync(data), + url: '/mcp/{name}/auth', + ...options, + ...params + }); +}, { + id: 'mcpAuthRemove', + method: 'delete', + responseSchema: zMcpAuthRemoveResponse, + url: '/mcp/{name}/auth' +}); + +/** + * Start MCP OAuth + * + * Start OAuth authentication flow for a Model Context Protocol (MCP) server. + */ +export const mcpAuthStart = Object.assign(function mcpAuthStart2(parameters: { + name: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpAuthStartPath, + query: zMcpAuthStartQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthStartResponse.parseAsync(data), + url: '/mcp/{name}/auth', + ...options, + ...params + }); +}, { + id: 'mcpAuthStart', + method: 'post', + responseSchema: zMcpAuthStartResponse, + url: '/mcp/{name}/auth' +}); + +/** + * Complete MCP OAuth + * + * Complete OAuth authentication for a Model Context Protocol (MCP) server using the authorization code. + */ +export const mcpAuthCallback = Object.assign(function mcpAuthCallback2(parameters: { + name: string; + directory?: string; + code: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'name' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'code' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zMcpAuthCallbackBody.optional(), + path: zMcpAuthCallbackPath, + query: zMcpAuthCallbackQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthCallbackResponse.parseAsync(data), + url: '/mcp/{name}/auth/callback', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'mcpAuthCallback', + method: 'post', + responseSchema: zMcpAuthCallbackResponse, + url: '/mcp/{name}/auth/callback' +}); + +/** + * Authenticate MCP OAuth + * + * Start OAuth flow and wait for callback (opens browser) + */ +export const mcpAuthAuthenticate = Object.assign(function mcpAuthAuthenticate2(parameters: { + name: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpAuthAuthenticatePath, + query: zMcpAuthAuthenticateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthAuthenticateResponse.parseAsync(data), + url: '/mcp/{name}/auth/authenticate', + ...options, + ...params + }); +}, { + id: 'mcpAuthAuthenticate', + method: 'post', + responseSchema: zMcpAuthAuthenticateResponse, + url: '/mcp/{name}/auth/authenticate' +}); + +/** + * Connect an MCP server + */ +export const mcpConnect = Object.assign(function mcpConnect2(parameters: { + name: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpConnectPath, + query: zMcpConnectQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpConnectResponse.parseAsync(data), + url: '/mcp/{name}/connect', + ...options, + ...params + }); +}, { + id: 'mcpConnect', + method: 'post', + responseSchema: zMcpConnectResponse, + url: '/mcp/{name}/connect' +}); + +/** + * Disconnect an MCP server + */ +export const mcpDisconnect = Object.assign(function mcpDisconnect2(parameters: { + name: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpDisconnectPath, + query: zMcpDisconnectQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpDisconnectResponse.parseAsync(data), + url: '/mcp/{name}/disconnect', + ...options, + ...params + }); +}, { + id: 'mcpDisconnect', + method: 'post', + responseSchema: zMcpDisconnectResponse, + url: '/mcp/{name}/disconnect' +}); + +/** + * Get LSP status + * + * Get LSP server status + */ +export const lspStatus = Object.assign(function lspStatus2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zLspStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zLspStatusResponse.parseAsync(data), + url: '/lsp', + ...options, + ...params + }); +}, { + id: 'lspStatus', + method: 'get', + responseSchema: zLspStatusResponse, + url: '/lsp' +}); + +/** + * Get formatter status + * + * Get formatter status + */ +export const formatterStatus = Object.assign(function formatterStatus2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFormatterStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zFormatterStatusResponse.parseAsync(data), + url: '/formatter', + ...options, + ...params + }); +}, { + id: 'formatterStatus', + method: 'get', + responseSchema: zFormatterStatusResponse, + url: '/formatter' +}); + +/** + * Append TUI prompt + * + * Append prompt to the TUI + */ +export const tuiAppendPrompt = Object.assign(function tuiAppendPrompt2(parameters: { + directory?: string; + text: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'body', key: 'text' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiAppendPromptBody.optional(), + path: z.never().optional(), + query: zTuiAppendPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiAppendPromptResponse.parseAsync(data), + url: '/tui/append-prompt', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'tuiAppendPrompt', + method: 'post', + responseSchema: zTuiAppendPromptResponse, + url: '/tui/append-prompt' +}); + +/** + * Open help dialog + * + * Open the help dialog in the TUI to display user assistance information. + */ +export const tuiOpenHelp = Object.assign(function tuiOpenHelp2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenHelpQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenHelpResponse.parseAsync(data), + url: '/tui/open-help', + ...options, + ...params + }); +}, { + id: 'tuiOpenHelp', + method: 'post', + responseSchema: zTuiOpenHelpResponse, + url: '/tui/open-help' +}); + +/** + * Open sessions dialog + * + * Open the session dialog + */ +export const tuiOpenSessions = Object.assign(function tuiOpenSessions2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenSessionsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenSessionsResponse.parseAsync(data), + url: '/tui/open-sessions', + ...options, + ...params + }); +}, { + id: 'tuiOpenSessions', + method: 'post', + responseSchema: zTuiOpenSessionsResponse, + url: '/tui/open-sessions' +}); + +/** + * Open themes dialog + * + * Open the theme dialog + */ +export const tuiOpenThemes = Object.assign(function tuiOpenThemes2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenThemesQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenThemesResponse.parseAsync(data), + url: '/tui/open-themes', + ...options, + ...params + }); +}, { + id: 'tuiOpenThemes', + method: 'post', + responseSchema: zTuiOpenThemesResponse, + url: '/tui/open-themes' +}); + +/** + * Open models dialog + * + * Open the model dialog + */ +export const tuiOpenModels = Object.assign(function tuiOpenModels2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenModelsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenModelsResponse.parseAsync(data), + url: '/tui/open-models', + ...options, + ...params + }); +}, { + id: 'tuiOpenModels', + method: 'post', + responseSchema: zTuiOpenModelsResponse, + url: '/tui/open-models' +}); + +/** + * Submit TUI prompt + * + * Submit the prompt + */ +export const tuiSubmitPrompt = Object.assign(function tuiSubmitPrompt2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiSubmitPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiSubmitPromptResponse.parseAsync(data), + url: '/tui/submit-prompt', + ...options, + ...params + }); +}, { + id: 'tuiSubmitPrompt', + method: 'post', + responseSchema: zTuiSubmitPromptResponse, + url: '/tui/submit-prompt' +}); + +/** + * Clear TUI prompt + * + * Clear the prompt + */ +export const tuiClearPrompt = Object.assign(function tuiClearPrompt2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiClearPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiClearPromptResponse.parseAsync(data), + url: '/tui/clear-prompt', + ...options, + ...params + }); +}, { + id: 'tuiClearPrompt', + method: 'post', + responseSchema: zTuiClearPromptResponse, + url: '/tui/clear-prompt' +}); + +/** + * Execute TUI command + * + * Execute a TUI command (e.g. agent_cycle) + */ +export const tuiExecuteCommand = Object.assign(function tuiExecuteCommand2(parameters: { + directory?: string; + command: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'body', key: 'command' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiExecuteCommandBody.optional(), + path: z.never().optional(), + query: zTuiExecuteCommandQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiExecuteCommandResponse.parseAsync(data), + url: '/tui/execute-command', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'tuiExecuteCommand', + method: 'post', + responseSchema: zTuiExecuteCommandResponse, + url: '/tui/execute-command' +}); + +/** + * Show TUI toast + * + * Show a toast notification in the TUI + */ +export const tuiShowToast = Object.assign(function tuiShowToast2(parameters: { + directory?: string; + title?: string; + message: string; + variant: 'info' | 'success' | 'warning' | 'error'; + duration?: number; +}, options?: Options) { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiShowToastBody.optional(), + path: z.never().optional(), + query: zTuiShowToastQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiShowToastResponse.parseAsync(data), + url: '/tui/show-toast', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'tuiShowToast', + method: 'post', + responseSchema: zTuiShowToastResponse, + url: '/tui/show-toast' +}); + +/** + * Publish TUI event + * + * Publish a TUI event + */ +export const tuiPublish = Object.assign(function tuiPublish2(parameters?: { + directory?: string; + body?: EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { key: 'body', map: 'body' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiPublishBody.optional(), + path: z.never().optional(), + query: zTuiPublishQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiPublishResponse.parseAsync(data), + url: '/tui/publish', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'tuiPublish', + method: 'post', + responseSchema: zTuiPublishResponse, + url: '/tui/publish' +}); + +/** + * Get next TUI request + * + * Retrieve the next TUI (Terminal User Interface) request from the queue for processing. + */ +export const tuiControlNext = Object.assign(function tuiControlNext2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiControlNextQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiControlNextResponse.parseAsync(data), + url: '/tui/control/next', + ...options, + ...params + }); +}, { + id: 'tuiControlNext', + method: 'get', + responseSchema: zTuiControlNextResponse, + url: '/tui/control/next' +}); + +/** + * Submit TUI response + * + * Submit a response to the TUI request queue to complete a pending request. + */ +export const tuiControlResponse = Object.assign(function tuiControlResponse2(parameters?: { + directory?: string; + body?: unknown; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { key: 'body', map: 'body' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiControlResponseBody.optional(), + path: z.never().optional(), + query: zTuiControlResponseQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiControlResponseResponse.parseAsync(data), + url: '/tui/control/response', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'tuiControlResponse', + method: 'post', + responseSchema: zTuiControlResponseResponse, + url: '/tui/control/response' +}); + +/** + * Set auth credentials + * + * Set authentication credentials + */ +export const authSet = Object.assign(function authSet2(parameters: { + providerID: string; + directory?: string; + auth?: Auth; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'providerID' }, + { in: 'query', key: 'directory' }, + { key: 'auth', map: 'body' } + ] }]); + return (options?.client ?? client).put({ + requestValidator: async (data) => await z.object({ + body: zAuthSetBody.optional(), + path: zAuthSetPath, + query: zAuthSetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zAuthSetResponse.parseAsync(data), + url: '/auth/{providerID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { + id: 'authSet', + method: 'put', + responseSchema: zAuthSetResponse, + url: '/auth/{providerID}' +}); + +/** + * Subscribe to events + * + * Get events + */ +export const eventSubscribe = Object.assign(function eventSubscribe2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).sse.get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zEventSubscribeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zEventSubscribeResponse.parseAsync(data), + url: '/event', + ...options, + ...params + }); +}, { + id: 'eventSubscribe', + method: 'get', + responseSchema: zEventSubscribeResponse, + url: '/event' +}); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/types.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/types.gen.ts new file mode 100644 index 0000000000..ccae410e61 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/types.gen.ts @@ -0,0 +1,4322 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type ClientOptions = { + baseUrl: `${string}://${string}` | (string & {}); +}; + +export type EventInstallationUpdated = { + type: 'installation.updated'; + properties: { + version: string; + }; +}; + +export type EventInstallationUpdateAvailable = { + type: 'installation.update-available'; + properties: { + version: string; + }; +}; + +export type Project = { + id: string; + worktree: string; + vcs?: 'git'; + name?: string; + icon?: { + url?: string; + color?: string; + }; + time: { + created: number; + updated: number; + initialized?: number; + }; +}; + +export type EventProjectUpdated = { + type: 'project.updated'; + properties: Project; +}; + +export type EventServerInstanceDisposed = { + type: 'server.instance.disposed'; + properties: { + directory: 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; + }; + agent: string; + model: { + providerID: string; + modelID: string; + }; + system?: string; + tools?: { + [key: string]: boolean; + }; + variant?: string; +}; + +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; + metadata?: { + [key: string]: 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; + agent: 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; +}; + +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; +}; + +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; + command?: 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 PermissionRequest = { + id: string; + sessionID: string; + permission: string; + patterns: Array; + metadata: { + [key: string]: unknown; + }; + always: Array; + tool?: { + messageID: string; + callID: string; + }; +}; + +export type EventPermissionAsked = { + type: 'permission.asked'; + properties: PermissionRequest; +}; + +export type EventPermissionReplied = { + type: 'permission.replied'; + properties: { + sessionID: string; + requestID: string; + reply: 'once' | 'always' | 'reject'; + }; +}; + +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; + }; +}; + +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 EventMcpToolsChanged = { + type: 'mcp.tools.changed'; + properties: { + server: string; + }; +}; + +export type EventCommandExecuted = { + type: 'command.executed'; + properties: { + name: string; + sessionID: string; + arguments: string; + messageID: string; + }; +}; + +export type PermissionAction = 'allow' | 'deny' | 'ask'; + +export type PermissionRule = { + permission: string; + pattern: string; + action: PermissionAction; +}; + +export type PermissionRuleset = Array; + +export type Session = { + id: string; + projectID: string; + directory: string; + parentID?: string; + summary?: { + additions: number; + deletions: number; + files: number; + diffs?: Array; + }; + share?: { + url: string; + }; + title: string; + version: string; + time: { + created: number; + updated: number; + compacting?: number; + archived?: number; + }; + permission?: PermissionRuleset; + 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; + }; +}; + +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 Pty = { + id: string; + title: string; + command: string; + args: Array; + 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 EventGlobalDisposed = { + type: 'global.disposed'; + properties: { + [key: string]: unknown; + }; +}; + +export type Event = EventInstallationUpdated | EventInstallationUpdateAvailable | EventProjectUpdated | EventServerInstanceDisposed | EventLspClientDiagnostics | EventLspUpdated | EventMessageUpdated | EventMessageRemoved | EventMessagePartUpdated | EventMessagePartRemoved | EventPermissionAsked | EventPermissionReplied | EventSessionStatus | EventSessionIdle | EventSessionCompacted | EventFileEdited | EventTodoUpdated | EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow | EventMcpToolsChanged | EventCommandExecuted | EventSessionCreated | EventSessionUpdated | EventSessionDeleted | EventSessionDiff | EventSessionError | EventFileWatcherUpdated | EventVcsBranchUpdated | EventPtyCreated | EventPtyUpdated | EventPtyExited | EventPtyDeleted | EventServerConnected | EventGlobalDisposed; + +export type GlobalEvent = { + directory: string; + payload: Event; +}; + +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; + /** + * Fork session from message + */ + session_fork?: string; + /** + * Rename session + */ + session_rename?: 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 next message + */ + messages_next?: string; + /** + * Navigate to previous message + */ + messages_previous?: 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; + /** + * Next favorite model + */ + model_cycle_favorite?: string; + /** + * Previous favorite model + */ + model_cycle_favorite_reverse?: string; + /** + * List available commands + */ + command_list?: string; + /** + * List agents + */ + agent_list?: string; + /** + * Next agent + */ + agent_cycle?: string; + /** + * Previous agent + */ + agent_cycle_reverse?: string; + /** + * Cycle model variants + */ + variant_cycle?: string; + /** + * Clear input field + */ + input_clear?: string; + /** + * Paste from clipboard + */ + input_paste?: string; + /** + * Submit input + */ + input_submit?: string; + /** + * Insert newline in input + */ + input_newline?: string; + /** + * Move cursor left in input + */ + input_move_left?: string; + /** + * Move cursor right in input + */ + input_move_right?: string; + /** + * Move cursor up in input + */ + input_move_up?: string; + /** + * Move cursor down in input + */ + input_move_down?: string; + /** + * Select left in input + */ + input_select_left?: string; + /** + * Select right in input + */ + input_select_right?: string; + /** + * Select up in input + */ + input_select_up?: string; + /** + * Select down in input + */ + input_select_down?: string; + /** + * Move to start of line in input + */ + input_line_home?: string; + /** + * Move to end of line in input + */ + input_line_end?: string; + /** + * Select to start of line in input + */ + input_select_line_home?: string; + /** + * Select to end of line in input + */ + input_select_line_end?: string; + /** + * Move to start of visual line in input + */ + input_visual_line_home?: string; + /** + * Move to end of visual line in input + */ + input_visual_line_end?: string; + /** + * Select to start of visual line in input + */ + input_select_visual_line_home?: string; + /** + * Select to end of visual line in input + */ + input_select_visual_line_end?: string; + /** + * Move to start of buffer in input + */ + input_buffer_home?: string; + /** + * Move to end of buffer in input + */ + input_buffer_end?: string; + /** + * Select to start of buffer in input + */ + input_select_buffer_home?: string; + /** + * Select to end of buffer in input + */ + input_select_buffer_end?: string; + /** + * Delete line in input + */ + input_delete_line?: string; + /** + * Delete to end of line in input + */ + input_delete_to_line_end?: string; + /** + * Delete to start of line in input + */ + input_delete_to_line_start?: string; + /** + * Backspace in input + */ + input_backspace?: string; + /** + * Delete character in input + */ + input_delete?: string; + /** + * Undo in input + */ + input_undo?: string; + /** + * Redo in input + */ + input_redo?: string; + /** + * Move word forward in input + */ + input_word_forward?: string; + /** + * Move word backward in input + */ + input_word_backward?: string; + /** + * Select word forward in input + */ + input_select_word_forward?: string; + /** + * Select word backward in input + */ + input_select_word_backward?: string; + /** + * Delete word forward in input + */ + input_delete_word_forward?: string; + /** + * Delete word backward in input + */ + input_delete_word_backward?: 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; + /** + * Go to parent session + */ + session_parent?: string; + /** + * Suspend terminal + */ + terminal_suspend?: string; + /** + * Toggle terminal title + */ + terminal_title_toggle?: string; + /** + * Toggle tips on home screen + */ + tips_toggle?: string; +}; + +/** + * Log level + */ +export type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR'; + +/** + * Server configuration for opencode serve and web commands + */ +export type ServerConfig = { + /** + * Port to listen on + */ + port?: number; + /** + * Hostname to listen on + */ + hostname?: string; + /** + * Enable mDNS service discovery + */ + mdns?: boolean; + /** + * Additional domains to allow for CORS + */ + cors?: Array; +}; + +export type PermissionActionConfig = 'ask' | 'allow' | 'deny'; + +export type PermissionObjectConfig = { + [key: string]: PermissionActionConfig; +}; + +export type PermissionRuleConfig = PermissionActionConfig | PermissionObjectConfig; + +export type PermissionConfig = { + read?: PermissionRuleConfig; + edit?: PermissionRuleConfig; + glob?: PermissionRuleConfig; + grep?: PermissionRuleConfig; + list?: PermissionRuleConfig; + bash?: PermissionRuleConfig; + task?: PermissionRuleConfig; + external_directory?: PermissionRuleConfig; + todowrite?: PermissionActionConfig; + todoread?: PermissionActionConfig; + webfetch?: PermissionActionConfig; + websearch?: PermissionActionConfig; + codesearch?: PermissionActionConfig; + lsp?: PermissionRuleConfig; + doom_loop?: PermissionActionConfig; + [key: string]: PermissionRuleConfig | PermissionActionConfig | undefined; +} | PermissionActionConfig; + +export type AgentConfig = { + model?: string; + temperature?: number; + top_p?: number; + prompt?: string; + /** + * @deprecated Use 'permission' field instead + */ + tools?: { + [key: string]: boolean; + }; + disable?: boolean; + /** + * Description of when to use the agent + */ + description?: string; + mode?: 'subagent' | 'primary' | 'all'; + options?: { + [key: string]: unknown; + }; + /** + * Hex color code for the agent (e.g., #FF5733) + */ + color?: string; + /** + * Maximum number of agentic iterations before forcing text-only response + */ + steps?: number; + /** + * @deprecated Use 'steps' field instead. + */ + maxSteps?: number; + permission?: PermissionConfig; + [key: string]: unknown; +}; + +export type ProviderConfig = { + api?: string; + name?: string; + env?: Array; + id?: string; + npm?: string; + models?: { + [key: string]: { + id?: string; + name?: string; + family?: string; + release_date?: string; + attachment?: boolean; + reasoning?: boolean; + temperature?: boolean; + tool_call?: boolean; + interleaved?: true | { + field: 'reasoning_content' | 'reasoning_details'; + }; + 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; + }; + /** + * Variant-specific configuration + */ + variants?: { + [key: string]: { + /** + * Disable this variant for the model + */ + disabled?: boolean; + [key: string]: unknown; + }; + }; + }; + }; + whitelist?: Array; + blacklist?: Array; + 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; + }; +}; + +export type McpLocalConfig = { + /** + * Type of MCP server connection + */ + type: 'local'; + /** + * Command and arguments to run the MCP server + */ + command: Array; + /** + * Environment variables to set when running the MCP server + */ + environment?: { + [key: string]: string; + }; + /** + * Enable or disable the MCP server on startup + */ + enabled?: boolean; + /** + * 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; + logLevel?: LogLevel; + /** + * 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'; + }; + server?: ServerConfig; + /** + * Command configuration, see https://opencode.ai/docs/commands + */ + command?: { + [key: string]: { + template: string; + description?: string; + agent?: string; + model?: string; + subtask?: boolean; + }; + }; + watcher?: { + ignore?: Array; + }; + plugin?: Array; + 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; + /** + * When set, ONLY these providers will be enabled. All other providers will be ignored + */ + enabled_providers?: Array; + /** + * 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; + /** + * Default agent to use when none is specified. Must be a primary agent. Falls back to 'build' if not set or if the specified agent is invalid. + */ + default_agent?: 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; + title?: AgentConfig; + summary?: AgentConfig; + compaction?: 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; + environment?: { + [key: string]: string; + }; + extensions?: Array; + }; + }; + lsp?: false | { + [key: string]: { + disabled: true; + } | { + command: Array; + extensions?: Array; + disabled?: boolean; + env?: { + [key: string]: string; + }; + initialization?: { + [key: string]: unknown; + }; + }; + }; + /** + * Additional instruction files or patterns to include + */ + instructions?: Array; + layout?: LayoutConfig; + permission?: PermissionConfig; + tools?: { + [key: string]: boolean; + }; + enterprise?: { + /** + * Enterprise URL + */ + url?: string; + }; + compaction?: { + /** + * Enable automatic compaction when context is full (default: true) + */ + auto?: boolean; + /** + * Enable pruning of old tool outputs (default: true) + */ + prune?: boolean; + }; + experimental?: { + hook?: { + file_edited?: { + [key: string]: Array<{ + command: Array; + environment?: { + [key: string]: string; + }; + }>; + }; + session_completed?: Array<{ + command: Array; + 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; + /** + * Continue the agent loop when a tool call is denied + */ + continue_loop_on_deny?: boolean; + /** + * Timeout in milliseconds for model context protocol (MCP) requests + */ + mcp_timeout?: number; + }; +}; + +export type ToolIds = Array; + +export type ToolListItem = { + id: string; + description: string; + parameters: unknown; +}; + +export type ToolList = Array; + +export type Path = { + home: string; + 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; + command?: string; +}; + +export type Command = { + name: string; + description?: string; + agent?: string; + model?: string; + mcp?: boolean; + template: string; + subtask?: boolean; + hints: Array; +}; + +export type Model = { + id: string; + providerID: string; + api: { + id: string; + url: string; + npm: string; + }; + name: string; + family?: 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; + }; + interleaved: boolean | { + field: 'reasoning_content' | 'reasoning_details'; + }; + }; + 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; + }; + release_date: string; + variants?: { + [key: string]: { + [key: string]: unknown; + }; + }; +}; + +export type Provider = { + id: string; + name: string; + source: 'env' | 'config' | 'custom' | 'api'; + env: Array; + 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; + }>; + 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'; + native?: boolean; + hidden?: boolean; + topP?: number; + temperature?: number; + color?: string; + permission: PermissionRuleset; + model?: { + modelID: string; + providerID: string; + }; + prompt?: string; + options: { + [key: string]: unknown; + }; + steps?: 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; + 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 GlobalHealthData = { + body?: never; + path?: never; + query?: never; + url: '/global/health'; +}; + +export type GlobalHealthResponses = { + /** + * Health information + */ + 200: { + healthy: true; + version: string; + }; +}; + +export type GlobalHealthResponse = GlobalHealthResponses[keyof GlobalHealthResponses]; + +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 GlobalDisposeData = { + body?: never; + path?: never; + query?: never; + url: '/global/dispose'; +}; + +export type GlobalDisposeResponses = { + /** + * Global disposed + */ + 200: boolean; +}; + +export type GlobalDisposeResponse = GlobalDisposeResponses[keyof GlobalDisposeResponses]; + +export type ProjectListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/project'; +}; + +export type ProjectListResponses = { + /** + * List of projects + */ + 200: Array; +}; + +export type ProjectListResponse = ProjectListResponses[keyof ProjectListResponses]; + +export type ProjectCurrentData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/project/current'; +}; + +export type ProjectCurrentResponses = { + /** + * Current project information + */ + 200: Project; +}; + +export type ProjectCurrentResponse = ProjectCurrentResponses[keyof ProjectCurrentResponses]; + +export type ProjectUpdateData = { + body?: { + name?: string; + icon?: { + url?: string; + color?: string; + }; + }; + path: { + projectID: string; + }; + query?: { + directory?: string; + }; + url: '/project/{projectID}'; +}; + +export type ProjectUpdateErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type ProjectUpdateError = ProjectUpdateErrors[keyof ProjectUpdateErrors]; + +export type ProjectUpdateResponses = { + /** + * Updated project information + */ + 200: Project; +}; + +export type ProjectUpdateResponse = ProjectUpdateResponses[keyof ProjectUpdateResponses]; + +export type PtyListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/pty'; +}; + +export type PtyListResponses = { + /** + * List of sessions + */ + 200: Array; +}; + +export type PtyListResponse = PtyListResponses[keyof PtyListResponses]; + +export type PtyCreateData = { + body?: { + command?: string; + args?: Array; + 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; +}; + +export type SessionListResponse = SessionListResponses[keyof SessionListResponses]; + +export type SessionCreateData = { + body?: { + parentID?: string; + title?: string; + permission?: PermissionRuleset; + }; + 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; + time?: { + archived?: number; + }; + }; + 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; +}; + +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; +}; + +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; +}; + +export type SessionDiffResponse = SessionDiffResponses[keyof SessionDiffResponses]; + +export type SessionSummarizeData = { + body?: { + providerID: string; + modelID: string; + auto?: boolean; + }; + 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; + }>; +}; + +export type SessionMessagesResponse = SessionMessagesResponses[keyof SessionMessagesResponses]; + +export type SessionPromptData = { + body?: { + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + /** + * @deprecated tools and permissions have been merged, you can set permissions on the session itself now + */ + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; + }; + 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; + }; +}; + +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; + }; +}; + +export type SessionMessageResponse = SessionMessageResponses[keyof SessionMessageResponses]; + +export type PartDeleteData = { + body?: never; + path: { + /** + * Session ID + */ + sessionID: string; + /** + * Message ID + */ + messageID: string; + /** + * Part ID + */ + partID: string; + }; + query?: { + directory?: string; + }; + url: '/session/{sessionID}/message/{messageID}/part/{partID}'; +}; + +export type PartDeleteErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type PartDeleteError = PartDeleteErrors[keyof PartDeleteErrors]; + +export type PartDeleteResponses = { + /** + * Successfully deleted part + */ + 200: boolean; +}; + +export type PartDeleteResponse = PartDeleteResponses[keyof PartDeleteResponses]; + +export type PartUpdateData = { + body?: Part; + path: { + /** + * Session ID + */ + sessionID: string; + /** + * Message ID + */ + messageID: string; + /** + * Part ID + */ + partID: string; + }; + query?: { + directory?: string; + }; + url: '/session/{sessionID}/message/{messageID}/part/{partID}'; +}; + +export type PartUpdateErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type PartUpdateError = PartUpdateErrors[keyof PartUpdateErrors]; + +export type PartUpdateResponses = { + /** + * Successfully updated part + */ + 200: Part; +}; + +export type PartUpdateResponse = PartUpdateResponses[keyof PartUpdateResponses]; + +export type SessionPromptAsyncData = { + body?: { + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + /** + * @deprecated tools and permissions have been merged, you can set permissions on the session itself now + */ + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; + }; + 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; + variant?: 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; + }; +}; + +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 PermissionReplyData = { + body?: { + reply: 'once' | 'always' | 'reject'; + }; + path: { + requestID: string; + }; + query?: { + directory?: string; + }; + url: '/permission/{requestID}/reply'; +}; + +export type PermissionReplyErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type PermissionReplyError = PermissionReplyErrors[keyof PermissionReplyErrors]; + +export type PermissionReplyResponses = { + /** + * Permission processed successfully + */ + 200: boolean; +}; + +export type PermissionReplyResponse = PermissionReplyResponses[keyof PermissionReplyResponses]; + +export type PermissionListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/permission'; +}; + +export type PermissionListResponses = { + /** + * List of pending permissions + */ + 200: Array; +}; + +export type PermissionListResponse = PermissionListResponses[keyof PermissionListResponses]; + +export type CommandListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/command'; +}; + +export type CommandListResponses = { + /** + * List of commands + */ + 200: Array; +}; + +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; + 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; + id: string; + npm?: string; + models: { + [key: string]: { + id: string; + name: string; + family?: string; + release_date: string; + attachment: boolean; + reasoning: boolean; + temperature: boolean; + tool_call: boolean; + interleaved?: true | { + field: 'reasoning_content' | 'reasoning_details'; + }; + 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; + }; + variants?: { + [key: string]: { + [key: string]: unknown; + }; + }; + }; + }; + }>; + default: { + [key: string]: string; + }; + connected: Array; + }; +}; + +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; + }; +}; + +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'; + type?: 'file' | 'directory'; + limit?: number; + }; + url: '/find/file'; +}; + +export type FindFilesResponses = { + /** + * File paths + */ + 200: Array; +}; + +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; +}; + +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; +}; + +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; +}; + +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; +}; + +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 McpConnectData = { + body?: never; + path: { + name: string; + }; + query?: { + directory?: string; + }; + url: '/mcp/{name}/connect'; +}; + +export type McpConnectResponses = { + /** + * MCP server connected successfully + */ + 200: boolean; +}; + +export type McpConnectResponse = McpConnectResponses[keyof McpConnectResponses]; + +export type McpDisconnectData = { + body?: never; + path: { + name: string; + }; + query?: { + directory?: string; + }; + url: '/mcp/{name}/disconnect'; +}; + +export type McpDisconnectResponses = { + /** + * MCP server disconnected successfully + */ + 200: boolean; +}; + +export type McpDisconnectResponse = McpDisconnectResponses[keyof McpDisconnectResponses]; + +export type LspStatusData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/lsp'; +}; + +export type LspStatusResponses = { + /** + * LSP server status + */ + 200: Array; +}; + +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; +}; + +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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/zod.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/zod.gen.ts new file mode 100644 index 0000000000..3d21c8726b --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-flat/zod.gen.ts @@ -0,0 +1,2749 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import * as z from 'zod'; + +export const zEventInstallationUpdated = z.object({ + type: z.literal('installation.updated'), + properties: z.object({ + version: z.string() + }) +}); + +export const zEventInstallationUpdateAvailable = z.object({ + type: z.literal('installation.update-available'), + properties: z.object({ + version: z.string() + }) +}); + +export const zProject = z.object({ + id: z.string(), + worktree: z.string(), + vcs: z.literal('git').optional(), + name: z.string().optional(), + icon: z.object({ + url: z.string().optional(), + color: z.string().optional() + }).optional(), + time: z.object({ + created: z.number(), + updated: z.number(), + initialized: z.number().optional() + }) +}); + +export const zEventProjectUpdated = z.object({ + type: z.literal('project.updated'), + properties: zProject +}); + +export const zEventServerInstanceDisposed = z.object({ + type: z.literal('server.instance.disposed'), + properties: z.object({ + directory: z.string() + }) +}); + +export const zEventLspClientDiagnostics = z.object({ + type: z.literal('lsp.client.diagnostics'), + properties: z.object({ + serverID: z.string(), + path: z.string() + }) +}); + +export const zEventLspUpdated = z.object({ + type: z.literal('lsp.updated'), + properties: z.record(z.string(), z.unknown()) +}); + +export const zFileDiff = z.object({ + file: z.string(), + before: z.string(), + after: z.string(), + additions: z.number(), + deletions: z.number() +}); + +export const zUserMessage = z.object({ + id: z.string(), + sessionID: z.string(), + role: z.literal('user'), + time: z.object({ + created: z.number() + }), + summary: z.object({ + title: z.string().optional(), + body: z.string().optional(), + diffs: z.array(zFileDiff) + }).optional(), + agent: z.string(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }), + system: z.string().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + variant: z.string().optional() +}); + +export const zProviderAuthError = z.object({ + name: z.literal('ProviderAuthError'), + data: z.object({ + providerID: z.string(), + message: z.string() + }) +}); + +export const zUnknownError = z.object({ + name: z.literal('UnknownError'), + data: z.object({ + message: z.string() + }) +}); + +export const zMessageOutputLengthError = z.object({ + name: z.literal('MessageOutputLengthError'), + data: z.record(z.string(), z.unknown()) +}); + +export const zMessageAbortedError = z.object({ + name: z.literal('MessageAbortedError'), + data: z.object({ + message: z.string() + }) +}); + +export const zApiError = z.object({ + name: z.literal('APIError'), + data: z.object({ + message: z.string(), + statusCode: z.number().optional(), + isRetryable: z.boolean(), + responseHeaders: z.record(z.string(), z.string()).optional(), + responseBody: z.string().optional(), + metadata: z.record(z.string(), z.string()).optional() + }) +}); + +export const zAssistantMessage = z.object({ + id: z.string(), + sessionID: z.string(), + role: z.literal('assistant'), + time: z.object({ + created: z.number(), + completed: z.number().optional() + }), + error: z.union([ + zProviderAuthError, + zUnknownError, + zMessageOutputLengthError, + zMessageAbortedError, + zApiError + ]).optional(), + parentID: z.string(), + modelID: z.string(), + providerID: z.string(), + mode: z.string(), + agent: z.string(), + path: z.object({ + cwd: z.string(), + root: z.string() + }), + summary: z.boolean().optional(), + cost: z.number(), + tokens: z.object({ + input: z.number(), + output: z.number(), + reasoning: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }) + }), + finish: z.string().optional() +}); + +export const zMessage = z.union([ + zUserMessage, + zAssistantMessage +]); + +export const zEventMessageUpdated = z.object({ + type: z.literal('message.updated'), + properties: z.object({ + info: zMessage + }) +}); + +export const zEventMessageRemoved = z.object({ + type: z.literal('message.removed'), + properties: z.object({ + sessionID: z.string(), + messageID: z.string() + }) +}); + +export const zTextPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('text'), + text: z.string(), + synthetic: z.boolean().optional(), + ignored: z.boolean().optional(), + time: z.object({ + start: z.number(), + end: z.number().optional() + }).optional(), + metadata: z.record(z.string(), z.unknown()).optional() +}); + +export const zReasoningPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('reasoning'), + text: z.string(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number(), + end: z.number().optional() + }) +}); + +export const zFilePartSourceText = z.object({ + value: z.string(), + start: z.int().gte(-9007199254740991).lte(9007199254740991), + end: z.int().gte(-9007199254740991).lte(9007199254740991) +}); + +export const zFileSource = z.object({ + text: zFilePartSourceText, + type: z.literal('file'), + path: z.string() +}); + +export const zRange = z.object({ + start: z.object({ + line: z.number(), + character: z.number() + }), + end: z.object({ + line: z.number(), + character: z.number() + }) +}); + +export const zSymbolSource = z.object({ + text: zFilePartSourceText, + type: z.literal('symbol'), + path: z.string(), + range: zRange, + name: z.string(), + kind: z.int().gte(-9007199254740991).lte(9007199254740991) +}); + +export const zFilePartSource = z.union([ + zFileSource, + zSymbolSource +]); + +export const zFilePart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('file'), + mime: z.string(), + filename: z.string().optional(), + url: z.string(), + source: zFilePartSource.optional() +}); + +export const zToolStatePending = z.object({ + status: z.literal('pending'), + input: z.record(z.string(), z.unknown()), + raw: z.string() +}); + +export const zToolStateRunning = z.object({ + status: z.literal('running'), + input: z.record(z.string(), z.unknown()), + title: z.string().optional(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number() + }) +}); + +export const zToolStateCompleted = z.object({ + status: z.literal('completed'), + input: z.record(z.string(), z.unknown()), + output: z.string(), + title: z.string(), + metadata: z.record(z.string(), z.unknown()), + time: z.object({ + start: z.number(), + end: z.number(), + compacted: z.number().optional() + }), + attachments: z.array(zFilePart).optional() +}); + +export const zToolStateError = z.object({ + status: z.literal('error'), + input: z.record(z.string(), z.unknown()), + error: z.string(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number(), + end: z.number() + }) +}); + +export const zToolState = z.union([ + zToolStatePending, + zToolStateRunning, + zToolStateCompleted, + zToolStateError +]); + +export const zToolPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('tool'), + callID: z.string(), + tool: z.string(), + state: zToolState, + metadata: z.record(z.string(), z.unknown()).optional() +}); + +export const zStepStartPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('step-start'), + snapshot: z.string().optional() +}); + +export const zStepFinishPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('step-finish'), + reason: z.string(), + snapshot: z.string().optional(), + cost: z.number(), + tokens: z.object({ + input: z.number(), + output: z.number(), + reasoning: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }) + }) +}); + +export const zSnapshotPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('snapshot'), + snapshot: z.string() +}); + +export const zPatchPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('patch'), + hash: z.string(), + files: z.array(z.string()) +}); + +export const zAgentPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('agent'), + name: z.string(), + source: z.object({ + value: z.string(), + start: z.int().gte(-9007199254740991).lte(9007199254740991), + end: z.int().gte(-9007199254740991).lte(9007199254740991) + }).optional() +}); + +export const zRetryPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('retry'), + attempt: z.number(), + error: zApiError, + time: z.object({ + created: z.number() + }) +}); + +export const zCompactionPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('compaction'), + auto: z.boolean() +}); + +export const zPart = z.union([ + zTextPart, + z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('subtask'), + prompt: z.string(), + description: z.string(), + agent: z.string(), + command: z.string().optional() + }), + zReasoningPart, + zFilePart, + zToolPart, + zStepStartPart, + zStepFinishPart, + zSnapshotPart, + zPatchPart, + zAgentPart, + zRetryPart, + zCompactionPart +]); + +export const zEventMessagePartUpdated = z.object({ + type: z.literal('message.part.updated'), + properties: z.object({ + part: zPart, + delta: z.string().optional() + }) +}); + +export const zEventMessagePartRemoved = z.object({ + type: z.literal('message.part.removed'), + properties: z.object({ + sessionID: z.string(), + messageID: z.string(), + partID: z.string() + }) +}); + +export const zPermissionRequest = z.object({ + id: z.string().regex(/^per.*/), + sessionID: z.string().regex(/^ses.*/), + permission: z.string(), + patterns: z.array(z.string()), + metadata: z.record(z.string(), z.unknown()), + always: z.array(z.string()), + tool: z.object({ + messageID: z.string(), + callID: z.string() + }).optional() +}); + +export const zEventPermissionAsked = z.object({ + type: z.literal('permission.asked'), + properties: zPermissionRequest +}); + +export const zEventPermissionReplied = z.object({ + type: z.literal('permission.replied'), + properties: z.object({ + sessionID: z.string(), + requestID: z.string(), + reply: z.enum([ + 'once', + 'always', + 'reject' + ]) + }) +}); + +export const zSessionStatus = z.union([ + z.object({ + type: z.literal('idle') + }), + z.object({ + type: z.literal('retry'), + attempt: z.number(), + message: z.string(), + next: z.number() + }), + z.object({ + type: z.literal('busy') + }) +]); + +export const zEventSessionStatus = z.object({ + type: z.literal('session.status'), + properties: z.object({ + sessionID: z.string(), + status: zSessionStatus + }) +}); + +export const zEventSessionIdle = z.object({ + type: z.literal('session.idle'), + properties: z.object({ + sessionID: z.string() + }) +}); + +export const zEventSessionCompacted = z.object({ + type: z.literal('session.compacted'), + properties: z.object({ + sessionID: z.string() + }) +}); + +export const zEventFileEdited = z.object({ + type: z.literal('file.edited'), + properties: z.object({ + file: z.string() + }) +}); + +export const zTodo = z.object({ + content: z.string(), + status: z.string(), + priority: z.string(), + id: z.string() +}); + +export const zEventTodoUpdated = z.object({ + type: z.literal('todo.updated'), + properties: z.object({ + sessionID: z.string(), + todos: z.array(zTodo) + }) +}); + +export const zEventTuiPromptAppend = z.object({ + type: z.literal('tui.prompt.append'), + properties: z.object({ + text: z.string() + }) +}); + +export const zEventTuiCommandExecute = z.object({ + type: z.literal('tui.command.execute'), + properties: z.object({ + command: z.union([ + z.enum([ + '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' + ]), + z.string() + ]) + }) +}); + +export const zEventTuiToastShow = z.object({ + type: z.literal('tui.toast.show'), + properties: z.object({ + title: z.string().optional(), + message: z.string(), + variant: z.enum([ + 'info', + 'success', + 'warning', + 'error' + ]), + duration: z.number().optional().default(5000) + }) +}); + +export const zEventMcpToolsChanged = z.object({ + type: z.literal('mcp.tools.changed'), + properties: z.object({ + server: z.string() + }) +}); + +export const zEventCommandExecuted = z.object({ + type: z.literal('command.executed'), + properties: z.object({ + name: z.string(), + sessionID: z.string().regex(/^ses.*/), + arguments: z.string(), + messageID: z.string().regex(/^msg.*/) + }) +}); + +export const zPermissionAction = z.enum([ + 'allow', + 'deny', + 'ask' +]); + +export const zPermissionRule = z.object({ + permission: z.string(), + pattern: z.string(), + action: zPermissionAction +}); + +export const zPermissionRuleset = z.array(zPermissionRule); + +export const zSession = z.object({ + id: z.string().regex(/^ses.*/), + projectID: z.string(), + directory: z.string(), + parentID: z.string().regex(/^ses.*/).optional(), + summary: z.object({ + additions: z.number(), + deletions: z.number(), + files: z.number(), + diffs: z.array(zFileDiff).optional() + }).optional(), + share: z.object({ + url: z.string() + }).optional(), + title: z.string(), + version: z.string(), + time: z.object({ + created: z.number(), + updated: z.number(), + compacting: z.number().optional(), + archived: z.number().optional() + }), + permission: zPermissionRuleset.optional(), + revert: z.object({ + messageID: z.string(), + partID: z.string().optional(), + snapshot: z.string().optional(), + diff: z.string().optional() + }).optional() +}); + +export const zEventSessionCreated = z.object({ + type: z.literal('session.created'), + properties: z.object({ + info: zSession + }) +}); + +export const zEventSessionUpdated = z.object({ + type: z.literal('session.updated'), + properties: z.object({ + info: zSession + }) +}); + +export const zEventSessionDeleted = z.object({ + type: z.literal('session.deleted'), + properties: z.object({ + info: zSession + }) +}); + +export const zEventSessionDiff = z.object({ + type: z.literal('session.diff'), + properties: z.object({ + sessionID: z.string(), + diff: z.array(zFileDiff) + }) +}); + +export const zEventSessionError = z.object({ + type: z.literal('session.error'), + properties: z.object({ + sessionID: z.string().optional(), + error: z.union([ + zProviderAuthError, + zUnknownError, + zMessageOutputLengthError, + zMessageAbortedError, + zApiError + ]).optional() + }) +}); + +export const zEventFileWatcherUpdated = z.object({ + type: z.literal('file.watcher.updated'), + properties: z.object({ + file: z.string(), + event: z.union([ + z.literal('add'), + z.literal('change'), + z.literal('unlink') + ]) + }) +}); + +export const zEventVcsBranchUpdated = z.object({ + type: z.literal('vcs.branch.updated'), + properties: z.object({ + branch: z.string().optional() + }) +}); + +export const zPty = z.object({ + id: z.string().regex(/^pty.*/), + title: z.string(), + command: z.string(), + args: z.array(z.string()), + cwd: z.string(), + status: z.enum(['running', 'exited']), + pid: z.number() +}); + +export const zEventPtyCreated = z.object({ + type: z.literal('pty.created'), + properties: z.object({ + info: zPty + }) +}); + +export const zEventPtyUpdated = z.object({ + type: z.literal('pty.updated'), + properties: z.object({ + info: zPty + }) +}); + +export const zEventPtyExited = z.object({ + type: z.literal('pty.exited'), + properties: z.object({ + id: z.string().regex(/^pty.*/), + exitCode: z.number() + }) +}); + +export const zEventPtyDeleted = z.object({ + type: z.literal('pty.deleted'), + properties: z.object({ + id: z.string().regex(/^pty.*/) + }) +}); + +export const zEventServerConnected = z.object({ + type: z.literal('server.connected'), + properties: z.record(z.string(), z.unknown()) +}); + +export const zEventGlobalDisposed = z.object({ + type: z.literal('global.disposed'), + properties: z.record(z.string(), z.unknown()) +}); + +export const zEvent = z.union([ + zEventInstallationUpdated, + zEventInstallationUpdateAvailable, + zEventProjectUpdated, + zEventServerInstanceDisposed, + zEventLspClientDiagnostics, + zEventLspUpdated, + zEventMessageUpdated, + zEventMessageRemoved, + zEventMessagePartUpdated, + zEventMessagePartRemoved, + zEventPermissionAsked, + zEventPermissionReplied, + zEventSessionStatus, + zEventSessionIdle, + zEventSessionCompacted, + zEventFileEdited, + zEventTodoUpdated, + zEventTuiPromptAppend, + zEventTuiCommandExecute, + zEventTuiToastShow, + zEventMcpToolsChanged, + zEventCommandExecuted, + zEventSessionCreated, + zEventSessionUpdated, + zEventSessionDeleted, + zEventSessionDiff, + zEventSessionError, + zEventFileWatcherUpdated, + zEventVcsBranchUpdated, + zEventPtyCreated, + zEventPtyUpdated, + zEventPtyExited, + zEventPtyDeleted, + zEventServerConnected, + zEventGlobalDisposed +]); + +export const zGlobalEvent = z.object({ + directory: z.string(), + payload: zEvent +}); + +export const zBadRequestError = z.object({ + data: z.unknown(), + errors: z.array(z.record(z.string(), z.unknown())), + success: z.literal(false) +}); + +export const zNotFoundError = z.object({ + name: z.literal('NotFoundError'), + data: z.object({ + message: z.string() + }) +}); + +/** + * Custom keybind configurations + */ +export const zKeybindsConfig = z.object({ + leader: z.string().optional().default('ctrl+x'), + app_exit: z.string().optional().default('ctrl+c,ctrl+d,q'), + editor_open: z.string().optional().default('e'), + theme_list: z.string().optional().default('t'), + sidebar_toggle: z.string().optional().default('b'), + scrollbar_toggle: z.string().optional().default('none'), + username_toggle: z.string().optional().default('none'), + status_view: z.string().optional().default('s'), + session_export: z.string().optional().default('x'), + session_new: z.string().optional().default('n'), + session_list: z.string().optional().default('l'), + session_timeline: z.string().optional().default('g'), + session_fork: z.string().optional().default('none'), + session_rename: z.string().optional().default('none'), + session_share: z.string().optional().default('none'), + session_unshare: z.string().optional().default('none'), + session_interrupt: z.string().optional().default('escape'), + session_compact: z.string().optional().default('c'), + messages_page_up: z.string().optional().default('pageup'), + messages_page_down: z.string().optional().default('pagedown'), + messages_half_page_up: z.string().optional().default('ctrl+alt+u'), + messages_half_page_down: z.string().optional().default('ctrl+alt+d'), + messages_first: z.string().optional().default('ctrl+g,home'), + messages_last: z.string().optional().default('ctrl+alt+g,end'), + messages_next: z.string().optional().default('none'), + messages_previous: z.string().optional().default('none'), + messages_last_user: z.string().optional().default('none'), + messages_copy: z.string().optional().default('y'), + messages_undo: z.string().optional().default('u'), + messages_redo: z.string().optional().default('r'), + messages_toggle_conceal: z.string().optional().default('h'), + tool_details: z.string().optional().default('none'), + model_list: z.string().optional().default('m'), + model_cycle_recent: z.string().optional().default('f2'), + model_cycle_recent_reverse: z.string().optional().default('shift+f2'), + model_cycle_favorite: z.string().optional().default('none'), + model_cycle_favorite_reverse: z.string().optional().default('none'), + command_list: z.string().optional().default('ctrl+p'), + agent_list: z.string().optional().default('a'), + agent_cycle: z.string().optional().default('tab'), + agent_cycle_reverse: z.string().optional().default('shift+tab'), + variant_cycle: z.string().optional().default('ctrl+t'), + input_clear: z.string().optional().default('ctrl+c'), + input_paste: z.string().optional().default('ctrl+v'), + input_submit: z.string().optional().default('return'), + input_newline: z.string().optional().default('shift+return,ctrl+return,alt+return,ctrl+j'), + input_move_left: z.string().optional().default('left,ctrl+b'), + input_move_right: z.string().optional().default('right,ctrl+f'), + input_move_up: z.string().optional().default('up'), + input_move_down: z.string().optional().default('down'), + input_select_left: z.string().optional().default('shift+left'), + input_select_right: z.string().optional().default('shift+right'), + input_select_up: z.string().optional().default('shift+up'), + input_select_down: z.string().optional().default('shift+down'), + input_line_home: z.string().optional().default('ctrl+a'), + input_line_end: z.string().optional().default('ctrl+e'), + input_select_line_home: z.string().optional().default('ctrl+shift+a'), + input_select_line_end: z.string().optional().default('ctrl+shift+e'), + input_visual_line_home: z.string().optional().default('alt+a'), + input_visual_line_end: z.string().optional().default('alt+e'), + input_select_visual_line_home: z.string().optional().default('alt+shift+a'), + input_select_visual_line_end: z.string().optional().default('alt+shift+e'), + input_buffer_home: z.string().optional().default('home'), + input_buffer_end: z.string().optional().default('end'), + input_select_buffer_home: z.string().optional().default('shift+home'), + input_select_buffer_end: z.string().optional().default('shift+end'), + input_delete_line: z.string().optional().default('ctrl+shift+d'), + input_delete_to_line_end: z.string().optional().default('ctrl+k'), + input_delete_to_line_start: z.string().optional().default('ctrl+u'), + input_backspace: z.string().optional().default('backspace,shift+backspace'), + input_delete: z.string().optional().default('ctrl+d,delete,shift+delete'), + input_undo: z.string().optional().default('ctrl+-,super+z'), + input_redo: z.string().optional().default('ctrl+.,super+shift+z'), + input_word_forward: z.string().optional().default('alt+f,alt+right,ctrl+right'), + input_word_backward: z.string().optional().default('alt+b,alt+left,ctrl+left'), + input_select_word_forward: z.string().optional().default('alt+shift+f,alt+shift+right'), + input_select_word_backward: z.string().optional().default('alt+shift+b,alt+shift+left'), + input_delete_word_forward: z.string().optional().default('alt+d,alt+delete,ctrl+delete'), + input_delete_word_backward: z.string().optional().default('ctrl+w,ctrl+backspace,alt+backspace'), + history_previous: z.string().optional().default('up'), + history_next: z.string().optional().default('down'), + session_child_cycle: z.string().optional().default('right'), + session_child_cycle_reverse: z.string().optional().default('left'), + session_parent: z.string().optional().default('up'), + terminal_suspend: z.string().optional().default('ctrl+z'), + terminal_title_toggle: z.string().optional().default('none'), + tips_toggle: z.string().optional().default('h') +}); + +/** + * Log level + */ +export const zLogLevel = z.enum([ + 'DEBUG', + 'INFO', + 'WARN', + 'ERROR' +]); + +/** + * Server configuration for opencode serve and web commands + */ +export const zServerConfig = z.object({ + port: z.int().gt(0).lte(9007199254740991).optional(), + hostname: z.string().optional(), + mdns: z.boolean().optional(), + cors: z.array(z.string()).optional() +}); + +export const zPermissionActionConfig = z.enum([ + 'ask', + 'allow', + 'deny' +]); + +export const zPermissionObjectConfig = z.record(z.string(), zPermissionActionConfig); + +export const zPermissionRuleConfig = z.union([ + zPermissionActionConfig, + zPermissionObjectConfig +]); + +export const zPermissionConfig = z.union([ + z.object({ + read: zPermissionRuleConfig.optional(), + edit: zPermissionRuleConfig.optional(), + glob: zPermissionRuleConfig.optional(), + grep: zPermissionRuleConfig.optional(), + list: zPermissionRuleConfig.optional(), + bash: zPermissionRuleConfig.optional(), + task: zPermissionRuleConfig.optional(), + external_directory: zPermissionRuleConfig.optional(), + todowrite: zPermissionActionConfig.optional(), + todoread: zPermissionActionConfig.optional(), + webfetch: zPermissionActionConfig.optional(), + websearch: zPermissionActionConfig.optional(), + codesearch: zPermissionActionConfig.optional(), + lsp: zPermissionRuleConfig.optional(), + doom_loop: zPermissionActionConfig.optional() + }), + zPermissionActionConfig +]); + +export const zAgentConfig = z.object({ + model: z.string().optional(), + temperature: z.number().optional(), + top_p: z.number().optional(), + prompt: z.string().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + disable: z.boolean().optional(), + description: z.string().optional(), + mode: z.enum([ + 'subagent', + 'primary', + 'all' + ]).optional(), + options: z.record(z.string(), z.unknown()).optional(), + color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional(), + steps: z.int().gt(0).lte(9007199254740991).optional(), + maxSteps: z.int().gt(0).lte(9007199254740991).optional(), + permission: zPermissionConfig.optional() +}); + +export const zProviderConfig = z.object({ + api: z.string().optional(), + name: z.string().optional(), + env: z.array(z.string()).optional(), + id: z.string().optional(), + npm: z.string().optional(), + models: z.record(z.string(), z.object({ + id: z.string().optional(), + name: z.string().optional(), + family: z.string().optional(), + release_date: z.string().optional(), + attachment: z.boolean().optional(), + reasoning: z.boolean().optional(), + temperature: z.boolean().optional(), + tool_call: z.boolean().optional(), + interleaved: z.union([ + z.literal(true), + z.object({ + field: z.enum(['reasoning_content', 'reasoning_details']) + }) + ]).optional(), + cost: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional(), + context_over_200k: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional() + }).optional() + }).optional(), + limit: z.object({ + context: z.number(), + output: z.number() + }).optional(), + modalities: z.object({ + input: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])), + output: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])) + }).optional(), + experimental: z.boolean().optional(), + status: z.enum([ + 'alpha', + 'beta', + 'deprecated' + ]).optional(), + options: z.record(z.string(), z.unknown()).optional(), + headers: z.record(z.string(), z.string()).optional(), + provider: z.object({ + npm: z.string() + }).optional(), + variants: z.record(z.string(), z.object({ + disabled: z.boolean().optional() + })).optional() + })).optional(), + whitelist: z.array(z.string()).optional(), + blacklist: z.array(z.string()).optional(), + options: z.object({ + apiKey: z.string().optional(), + baseURL: z.string().optional(), + enterpriseUrl: z.string().optional(), + setCacheKey: z.boolean().optional(), + timeout: z.union([ + z.int().gt(0).lte(9007199254740991), + z.literal(false) + ]).optional() + }).optional() +}); + +export const zMcpLocalConfig = z.object({ + type: z.literal('local'), + command: z.array(z.string()), + environment: z.record(z.string(), z.string()).optional(), + enabled: z.boolean().optional(), + timeout: z.int().gt(0).lte(9007199254740991).optional() +}); + +export const zMcpOAuthConfig = z.object({ + clientId: z.string().optional(), + clientSecret: z.string().optional(), + scope: z.string().optional() +}); + +export const zMcpRemoteConfig = z.object({ + type: z.literal('remote'), + url: z.string(), + enabled: z.boolean().optional(), + headers: z.record(z.string(), z.string()).optional(), + oauth: z.union([ + zMcpOAuthConfig, + z.literal(false) + ]).optional(), + timeout: z.int().gt(0).lte(9007199254740991).optional() +}); + +/** + * @deprecated Always uses stretch layout. + */ +export const zLayoutConfig = z.enum(['auto', 'stretch']); + +export const zConfig = z.object({ + $schema: z.string().optional(), + theme: z.string().optional(), + keybinds: zKeybindsConfig.optional(), + logLevel: zLogLevel.optional(), + tui: z.object({ + scroll_speed: z.number().gte(0.001).optional(), + scroll_acceleration: z.object({ + enabled: z.boolean() + }).optional(), + diff_style: z.enum(['auto', 'stacked']).optional() + }).optional(), + server: zServerConfig.optional(), + command: z.record(z.string(), z.object({ + template: z.string(), + description: z.string().optional(), + agent: z.string().optional(), + model: z.string().optional(), + subtask: z.boolean().optional() + })).optional(), + watcher: z.object({ + ignore: z.array(z.string()).optional() + }).optional(), + plugin: z.array(z.string()).optional(), + snapshot: z.boolean().optional(), + share: z.enum([ + 'manual', + 'auto', + 'disabled' + ]).optional(), + autoshare: z.boolean().optional(), + autoupdate: z.union([ + z.boolean(), + z.literal('notify') + ]).optional(), + disabled_providers: z.array(z.string()).optional(), + enabled_providers: z.array(z.string()).optional(), + model: z.string().optional(), + small_model: z.string().optional(), + default_agent: z.string().optional(), + username: z.string().optional(), + mode: z.object({ + build: zAgentConfig.optional(), + plan: zAgentConfig.optional() + }).optional(), + agent: z.object({ + plan: zAgentConfig.optional(), + build: zAgentConfig.optional(), + general: zAgentConfig.optional(), + explore: zAgentConfig.optional(), + title: zAgentConfig.optional(), + summary: zAgentConfig.optional(), + compaction: zAgentConfig.optional() + }).optional(), + provider: z.record(z.string(), zProviderConfig).optional(), + mcp: z.record(z.string(), z.union([ + zMcpLocalConfig, + zMcpRemoteConfig + ])).optional(), + formatter: z.union([ + z.literal(false), + z.record(z.string(), z.object({ + disabled: z.boolean().optional(), + command: z.array(z.string()).optional(), + environment: z.record(z.string(), z.string()).optional(), + extensions: z.array(z.string()).optional() + })) + ]).optional(), + lsp: z.union([ + z.literal(false), + z.record(z.string(), z.union([ + z.object({ + disabled: z.literal(true) + }), + z.object({ + command: z.array(z.string()), + extensions: z.array(z.string()).optional(), + disabled: z.boolean().optional(), + env: z.record(z.string(), z.string()).optional(), + initialization: z.record(z.string(), z.unknown()).optional() + }) + ])) + ]).optional(), + instructions: z.array(z.string()).optional(), + layout: zLayoutConfig.optional(), + permission: zPermissionConfig.optional(), + tools: z.record(z.string(), z.boolean()).optional(), + enterprise: z.object({ + url: z.string().optional() + }).optional(), + compaction: z.object({ + auto: z.boolean().optional(), + prune: z.boolean().optional() + }).optional(), + experimental: z.object({ + hook: z.object({ + file_edited: z.record(z.string(), z.array(z.object({ + command: z.array(z.string()), + environment: z.record(z.string(), z.string()).optional() + }))).optional(), + session_completed: z.array(z.object({ + command: z.array(z.string()), + environment: z.record(z.string(), z.string()).optional() + })).optional() + }).optional(), + chatMaxRetries: z.number().optional(), + disable_paste_summary: z.boolean().optional(), + batch_tool: z.boolean().optional(), + openTelemetry: z.boolean().optional(), + primary_tools: z.array(z.string()).optional(), + continue_loop_on_deny: z.boolean().optional(), + mcp_timeout: z.int().gt(0).lte(9007199254740991).optional() + }).optional() +}); + +export const zToolIds = z.array(z.string()); + +export const zToolListItem = z.object({ + id: z.string(), + description: z.string(), + parameters: z.unknown() +}); + +export const zToolList = z.array(zToolListItem); + +export const zPath = z.object({ + home: z.string(), + state: z.string(), + config: z.string(), + worktree: z.string(), + directory: z.string() +}); + +export const zVcsInfo = z.object({ + branch: z.string() +}); + +export const zTextPartInput = z.object({ + id: z.string().optional(), + type: z.literal('text'), + text: z.string(), + synthetic: z.boolean().optional(), + ignored: z.boolean().optional(), + time: z.object({ + start: z.number(), + end: z.number().optional() + }).optional(), + metadata: z.record(z.string(), z.unknown()).optional() +}); + +export const zFilePartInput = z.object({ + id: z.string().optional(), + type: z.literal('file'), + mime: z.string(), + filename: z.string().optional(), + url: z.string(), + source: zFilePartSource.optional() +}); + +export const zAgentPartInput = z.object({ + id: z.string().optional(), + type: z.literal('agent'), + name: z.string(), + source: z.object({ + value: z.string(), + start: z.int().gte(-9007199254740991).lte(9007199254740991), + end: z.int().gte(-9007199254740991).lte(9007199254740991) + }).optional() +}); + +export const zSubtaskPartInput = z.object({ + id: z.string().optional(), + type: z.literal('subtask'), + prompt: z.string(), + description: z.string(), + agent: z.string(), + command: z.string().optional() +}); + +export const zCommand = z.object({ + name: z.string(), + description: z.string().optional(), + agent: z.string().optional(), + model: z.string().optional(), + mcp: z.boolean().optional(), + template: z.string(), + subtask: z.boolean().optional(), + hints: z.array(z.string()) +}); + +export const zModel = z.object({ + id: z.string(), + providerID: z.string(), + api: z.object({ + id: z.string(), + url: z.string(), + npm: z.string() + }), + name: z.string(), + family: z.string().optional(), + capabilities: z.object({ + temperature: z.boolean(), + reasoning: z.boolean(), + attachment: z.boolean(), + toolcall: z.boolean(), + input: z.object({ + text: z.boolean(), + audio: z.boolean(), + image: z.boolean(), + video: z.boolean(), + pdf: z.boolean() + }), + output: z.object({ + text: z.boolean(), + audio: z.boolean(), + image: z.boolean(), + video: z.boolean(), + pdf: z.boolean() + }), + interleaved: z.union([ + z.boolean(), + z.object({ + field: z.enum(['reasoning_content', 'reasoning_details']) + }) + ]) + }), + cost: z.object({ + input: z.number(), + output: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }), + experimentalOver200K: z.object({ + input: z.number(), + output: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }) + }).optional() + }), + limit: z.object({ + context: z.number(), + output: z.number() + }), + status: z.enum([ + 'alpha', + 'beta', + 'deprecated', + 'active' + ]), + options: z.record(z.string(), z.unknown()), + headers: z.record(z.string(), z.string()), + release_date: z.string(), + variants: z.record(z.string(), z.record(z.string(), z.unknown())).optional() +}); + +export const zProvider = z.object({ + id: z.string(), + name: z.string(), + source: z.enum([ + 'env', + 'config', + 'custom', + 'api' + ]), + env: z.array(z.string()), + key: z.string().optional(), + options: z.record(z.string(), z.unknown()), + models: z.record(z.string(), zModel) +}); + +export const zProviderAuthMethod = z.object({ + type: z.union([ + z.literal('oauth'), + z.literal('api') + ]), + label: z.string() +}); + +export const zProviderAuthAuthorization = z.object({ + url: z.string(), + method: z.union([ + z.literal('auto'), + z.literal('code') + ]), + instructions: z.string() +}); + +export const zSymbol = z.object({ + name: z.string(), + kind: z.number(), + location: z.object({ + uri: z.string(), + range: zRange + }) +}); + +export const zFileNode = z.object({ + name: z.string(), + path: z.string(), + absolute: z.string(), + type: z.enum(['file', 'directory']), + ignored: z.boolean() +}); + +export const zFileContent = z.object({ + type: z.literal('text'), + content: z.string(), + diff: z.string().optional(), + patch: z.object({ + oldFileName: z.string(), + newFileName: z.string(), + oldHeader: z.string().optional(), + newHeader: z.string().optional(), + hunks: z.array(z.object({ + oldStart: z.number(), + oldLines: z.number(), + newStart: z.number(), + newLines: z.number(), + lines: z.array(z.string()) + })), + index: z.string().optional() + }).optional(), + encoding: z.literal('base64').optional(), + mimeType: z.string().optional() +}); + +export const zFile = z.object({ + path: z.string(), + added: z.int().gte(-9007199254740991).lte(9007199254740991), + removed: z.int().gte(-9007199254740991).lte(9007199254740991), + status: z.enum([ + 'added', + 'deleted', + 'modified' + ]) +}); + +export const zAgent = z.object({ + name: z.string(), + description: z.string().optional(), + mode: z.enum([ + 'subagent', + 'primary', + 'all' + ]), + native: z.boolean().optional(), + hidden: z.boolean().optional(), + topP: z.number().optional(), + temperature: z.number().optional(), + color: z.string().optional(), + permission: zPermissionRuleset, + model: z.object({ + modelID: z.string(), + providerID: z.string() + }).optional(), + prompt: z.string().optional(), + options: z.record(z.string(), z.unknown()), + steps: z.int().gt(0).lte(9007199254740991).optional() +}); + +export const zMcpStatusConnected = z.object({ + status: z.literal('connected') +}); + +export const zMcpStatusDisabled = z.object({ + status: z.literal('disabled') +}); + +export const zMcpStatusFailed = z.object({ + status: z.literal('failed'), + error: z.string() +}); + +export const zMcpStatusNeedsAuth = z.object({ + status: z.literal('needs_auth') +}); + +export const zMcpStatusNeedsClientRegistration = z.object({ + status: z.literal('needs_client_registration'), + error: z.string() +}); + +export const zMcpStatus = z.union([ + zMcpStatusConnected, + zMcpStatusDisabled, + zMcpStatusFailed, + zMcpStatusNeedsAuth, + zMcpStatusNeedsClientRegistration +]); + +export const zLspStatus = z.object({ + id: z.string(), + name: z.string(), + root: z.string(), + status: z.union([ + z.literal('connected'), + z.literal('error') + ]) +}); + +export const zFormatterStatus = z.object({ + name: z.string(), + extensions: z.array(z.string()), + enabled: z.boolean() +}); + +export const zOAuth = z.object({ + type: z.literal('oauth'), + refresh: z.string(), + access: z.string(), + expires: z.number(), + enterpriseUrl: z.string().optional() +}); + +export const zApiAuth = z.object({ + type: z.literal('api'), + key: z.string() +}); + +export const zWellKnownAuth = z.object({ + type: z.literal('wellknown'), + key: z.string(), + token: z.string() +}); + +export const zAuth = z.union([ + zOAuth, + zApiAuth, + zWellKnownAuth +]); + +/** + * Health information + */ +export const zGlobalHealthResponse = z.object({ + healthy: z.literal(true), + version: z.string() +}); + +/** + * Event stream + */ +export const zGlobalEventResponse = zGlobalEvent; + +/** + * Global disposed + */ +export const zGlobalDisposeResponse = z.boolean(); + +export const zProjectListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of projects + */ +export const zProjectListResponse = z.array(zProject); + +export const zProjectCurrentQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Current project information + */ +export const zProjectCurrentResponse = zProject; + +export const zProjectUpdateBody = z.object({ + name: z.string().optional(), + icon: z.object({ + url: z.string().optional(), + color: z.string().optional() + }).optional() +}); + +export const zProjectUpdatePath = z.object({ + projectID: z.string() +}); + +export const zProjectUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated project information + */ +export const zProjectUpdateResponse = zProject; + +export const zPtyListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of sessions + */ +export const zPtyListResponse = z.array(zPty); + +export const zPtyCreateBody = z.object({ + command: z.string().optional(), + args: z.array(z.string()).optional(), + cwd: z.string().optional(), + title: z.string().optional(), + env: z.record(z.string(), z.string()).optional() +}); + +export const zPtyCreateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created session + */ +export const zPtyCreateResponse = zPty; + +export const zPtyRemovePath = z.object({ + ptyID: z.string() +}); + +export const zPtyRemoveQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Session removed + */ +export const zPtyRemoveResponse = z.boolean(); + +export const zPtyGetPath = z.object({ + ptyID: z.string() +}); + +export const zPtyGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Session info + */ +export const zPtyGetResponse = zPty; + +export const zPtyUpdateBody = z.object({ + title: z.string().optional(), + size: z.object({ + rows: z.number(), + cols: z.number() + }).optional() +}); + +export const zPtyUpdatePath = z.object({ + ptyID: z.string() +}); + +export const zPtyUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated session + */ +export const zPtyUpdateResponse = zPty; + +export const zPtyConnectPath = z.object({ + ptyID: z.string() +}); + +export const zPtyConnectQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Connected session + */ +export const zPtyConnectResponse = z.boolean(); + +export const zConfigGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Get config info + */ +export const zConfigGetResponse = zConfig; + +export const zConfigUpdateBody = zConfig; + +export const zConfigUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully updated config + */ +export const zConfigUpdateResponse = zConfig; + +export const zToolIdsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Tool IDs + */ +export const zToolIdsResponse = zToolIds; + +export const zToolListQuery = z.object({ + directory: z.string().optional(), + provider: z.string(), + model: z.string() +}); + +/** + * Tools + */ +export const zToolListResponse = zToolList; + +export const zInstanceDisposeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Instance disposed + */ +export const zInstanceDisposeResponse = z.boolean(); + +export const zPathGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Path + */ +export const zPathGetResponse = zPath; + +export const zVcsGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * VCS info + */ +export const zVcsGetResponse = zVcsInfo; + +export const zSessionListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of sessions + */ +export const zSessionListResponse = z.array(zSession); + +export const zSessionCreateBody = z.object({ + parentID: z.string().regex(/^ses.*/).optional(), + title: z.string().optional(), + permission: zPermissionRuleset.optional() +}); + +export const zSessionCreateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully created session + */ +export const zSessionCreateResponse = zSession; + +export const zSessionStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Get session status + */ +export const zSessionStatusResponse = z.record(z.string(), zSessionStatus); + +export const zSessionDeletePath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionDeleteQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully deleted session + */ +export const zSessionDeleteResponse = z.boolean(); + +export const zSessionGetPath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Get session + */ +export const zSessionGetResponse = zSession; + +export const zSessionUpdateBody = z.object({ + title: z.string().optional(), + time: z.object({ + archived: z.number().optional() + }).optional() +}); + +export const zSessionUpdatePath = z.object({ + sessionID: z.string() +}); + +export const zSessionUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully updated session + */ +export const zSessionUpdateResponse = zSession; + +export const zSessionChildrenPath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionChildrenQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of children + */ +export const zSessionChildrenResponse = z.array(zSession); + +export const zSessionTodoPath = z.object({ + sessionID: z.string() +}); + +export const zSessionTodoQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Todo list + */ +export const zSessionTodoResponse = z.array(zTodo); + +export const zSessionInitBody = z.object({ + modelID: z.string(), + providerID: z.string(), + messageID: z.string().regex(/^msg.*/) +}); + +export const zSessionInitPath = z.object({ + sessionID: z.string() +}); + +export const zSessionInitQuery = z.object({ + directory: z.string().optional() +}); + +/** + * 200 + */ +export const zSessionInitResponse = z.boolean(); + +export const zSessionForkBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional() +}); + +export const zSessionForkPath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionForkQuery = z.object({ + directory: z.string().optional() +}); + +/** + * 200 + */ +export const zSessionForkResponse = zSession; + +export const zSessionAbortPath = z.object({ + sessionID: z.string() +}); + +export const zSessionAbortQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Aborted session + */ +export const zSessionAbortResponse = z.boolean(); + +export const zSessionUnsharePath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionUnshareQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully unshared session + */ +export const zSessionUnshareResponse = zSession; + +export const zSessionSharePath = z.object({ + sessionID: z.string() +}); + +export const zSessionShareQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully shared session + */ +export const zSessionShareResponse = zSession; + +export const zSessionDiffPath = z.object({ + sessionID: z.string() +}); + +export const zSessionDiffQuery = z.object({ + directory: z.string().optional(), + messageID: z.string().regex(/^msg.*/).optional() +}); + +/** + * List of diffs + */ +export const zSessionDiffResponse = z.array(zFileDiff); + +export const zSessionSummarizeBody = z.object({ + providerID: z.string(), + modelID: z.string(), + auto: z.boolean().optional().default(false) +}); + +export const zSessionSummarizePath = z.object({ + sessionID: z.string() +}); + +export const zSessionSummarizeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Summarized session + */ +export const zSessionSummarizeResponse = z.boolean(); + +export const zSessionMessagesPath = z.object({ + sessionID: z.string() +}); + +export const zSessionMessagesQuery = z.object({ + directory: z.string().optional(), + limit: z.number().optional() +}); + +/** + * List of messages + */ +export const zSessionMessagesResponse = z.array(z.object({ + info: zMessage, + parts: z.array(zPart) +})); + +export const zSessionPromptBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }).optional(), + agent: z.string().optional(), + noReply: z.boolean().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + system: z.string().optional(), + variant: z.string().optional(), + parts: z.array(z.union([ + zTextPartInput, + zFilePartInput, + zAgentPartInput, + zSubtaskPartInput + ])) +}); + +export const zSessionPromptPath = z.object({ + sessionID: z.string() +}); + +export const zSessionPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created message + */ +export const zSessionPromptResponse = z.object({ + info: zAssistantMessage, + parts: z.array(zPart) +}); + +export const zSessionMessagePath = z.object({ + sessionID: z.string(), + messageID: z.string() +}); + +export const zSessionMessageQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Message + */ +export const zSessionMessageResponse = z.object({ + info: zMessage, + parts: z.array(zPart) +}); + +export const zPartDeletePath = z.object({ + sessionID: z.string(), + messageID: z.string(), + partID: z.string() +}); + +export const zPartDeleteQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully deleted part + */ +export const zPartDeleteResponse = z.boolean(); + +export const zPartUpdateBody = zPart; + +export const zPartUpdatePath = z.object({ + sessionID: z.string(), + messageID: z.string(), + partID: z.string() +}); + +export const zPartUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully updated part + */ +export const zPartUpdateResponse = zPart; + +export const zSessionPromptAsyncBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }).optional(), + agent: z.string().optional(), + noReply: z.boolean().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + system: z.string().optional(), + variant: z.string().optional(), + parts: z.array(z.union([ + zTextPartInput, + zFilePartInput, + zAgentPartInput, + zSubtaskPartInput + ])) +}); + +export const zSessionPromptAsyncPath = z.object({ + sessionID: z.string() +}); + +export const zSessionPromptAsyncQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt accepted + */ +export const zSessionPromptAsyncResponse = z.void(); + +export const zSessionCommandBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional(), + agent: z.string().optional(), + model: z.string().optional(), + arguments: z.string(), + command: z.string(), + variant: z.string().optional() +}); + +export const zSessionCommandPath = z.object({ + sessionID: z.string() +}); + +export const zSessionCommandQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created message + */ +export const zSessionCommandResponse = z.object({ + info: zAssistantMessage, + parts: z.array(zPart) +}); + +export const zSessionShellBody = z.object({ + agent: z.string(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }).optional(), + command: z.string() +}); + +export const zSessionShellPath = z.object({ + sessionID: z.string() +}); + +export const zSessionShellQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created message + */ +export const zSessionShellResponse = zAssistantMessage; + +export const zSessionRevertBody = z.object({ + messageID: z.string().regex(/^msg.*/), + partID: z.string().regex(/^prt.*/).optional() +}); + +export const zSessionRevertPath = z.object({ + sessionID: z.string() +}); + +export const zSessionRevertQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated session + */ +export const zSessionRevertResponse = zSession; + +export const zSessionUnrevertPath = z.object({ + sessionID: z.string() +}); + +export const zSessionUnrevertQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated session + */ +export const zSessionUnrevertResponse = zSession; + +export const zPermissionRespondBody = z.object({ + response: z.enum([ + 'once', + 'always', + 'reject' + ]) +}); + +export const zPermissionRespondPath = z.object({ + sessionID: z.string(), + permissionID: z.string() +}); + +export const zPermissionRespondQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Permission processed successfully + */ +export const zPermissionRespondResponse = z.boolean(); + +export const zPermissionReplyBody = z.object({ + reply: z.enum([ + 'once', + 'always', + 'reject' + ]) +}); + +export const zPermissionReplyPath = z.object({ + requestID: z.string() +}); + +export const zPermissionReplyQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Permission processed successfully + */ +export const zPermissionReplyResponse = z.boolean(); + +export const zPermissionListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of pending permissions + */ +export const zPermissionListResponse = z.array(zPermissionRequest); + +export const zCommandListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of commands + */ +export const zCommandListResponse = z.array(zCommand); + +export const zConfigProvidersQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of providers + */ +export const zConfigProvidersResponse = z.object({ + providers: z.array(zProvider), + default: z.record(z.string(), z.string()) +}); + +export const zProviderListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of providers + */ +export const zProviderListResponse = z.object({ + all: z.array(z.object({ + api: z.string().optional(), + name: z.string(), + env: z.array(z.string()), + id: z.string(), + npm: z.string().optional(), + models: z.record(z.string(), z.object({ + id: z.string(), + name: z.string(), + family: z.string().optional(), + release_date: z.string(), + attachment: z.boolean(), + reasoning: z.boolean(), + temperature: z.boolean(), + tool_call: z.boolean(), + interleaved: z.union([ + z.literal(true), + z.object({ + field: z.enum(['reasoning_content', 'reasoning_details']) + }) + ]).optional(), + cost: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional(), + context_over_200k: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional() + }).optional() + }).optional(), + limit: z.object({ + context: z.number(), + output: z.number() + }), + modalities: z.object({ + input: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])), + output: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])) + }).optional(), + experimental: z.boolean().optional(), + status: z.enum([ + 'alpha', + 'beta', + 'deprecated' + ]).optional(), + options: z.record(z.string(), z.unknown()), + headers: z.record(z.string(), z.string()).optional(), + provider: z.object({ + npm: z.string() + }).optional(), + variants: z.record(z.string(), z.record(z.string(), z.unknown())).optional() + })) + })), + default: z.record(z.string(), z.string()), + connected: z.array(z.string()) +}); + +export const zProviderAuthQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Provider auth methods + */ +export const zProviderAuthResponse = z.record(z.string(), z.array(zProviderAuthMethod)); + +export const zProviderOauthAuthorizeBody = z.object({ + method: z.number() +}); + +export const zProviderOauthAuthorizePath = z.object({ + providerID: z.string() +}); + +export const zProviderOauthAuthorizeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Authorization URL and method + */ +export const zProviderOauthAuthorizeResponse = zProviderAuthAuthorization; + +export const zProviderOauthCallbackBody = z.object({ + method: z.number(), + code: z.string().optional() +}); + +export const zProviderOauthCallbackPath = z.object({ + providerID: z.string() +}); + +export const zProviderOauthCallbackQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth callback processed successfully + */ +export const zProviderOauthCallbackResponse = z.boolean(); + +export const zFindTextQuery = z.object({ + directory: z.string().optional(), + pattern: z.string() +}); + +/** + * Matches + */ +export const zFindTextResponse = z.array(z.object({ + path: z.object({ + text: z.string() + }), + lines: z.object({ + text: z.string() + }), + line_number: z.number(), + absolute_offset: z.number(), + submatches: z.array(z.object({ + match: z.object({ + text: z.string() + }), + start: z.number(), + end: z.number() + })) +})); + +export const zFindFilesQuery = z.object({ + directory: z.string().optional(), + query: z.string(), + dirs: z.enum(['true', 'false']).optional(), + type: z.enum(['file', 'directory']).optional(), + limit: z.int().gte(1).lte(200).optional() +}); + +/** + * File paths + */ +export const zFindFilesResponse = z.array(z.string()); + +export const zFindSymbolsQuery = z.object({ + directory: z.string().optional(), + query: z.string() +}); + +/** + * Symbols + */ +export const zFindSymbolsResponse = z.array(zSymbol); + +export const zFileListQuery = z.object({ + directory: z.string().optional(), + path: z.string() +}); + +/** + * Files and directories + */ +export const zFileListResponse = z.array(zFileNode); + +export const zFileReadQuery = z.object({ + directory: z.string().optional(), + path: z.string() +}); + +/** + * File content + */ +export const zFileReadResponse = zFileContent; + +export const zFileStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * File status + */ +export const zFileStatusResponse = z.array(zFile); + +export const zAppLogBody = z.object({ + service: z.string(), + level: z.enum([ + 'debug', + 'info', + 'error', + 'warn' + ]), + message: z.string(), + extra: z.record(z.string(), z.unknown()).optional() +}); + +export const zAppLogQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Log entry written successfully + */ +export const zAppLogResponse = z.boolean(); + +export const zAppAgentsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of agents + */ +export const zAppAgentsResponse = z.array(zAgent); + +export const zMcpStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server status + */ +export const zMcpStatusResponse = z.record(z.string(), zMcpStatus); + +export const zMcpAddBody = z.object({ + name: z.string(), + config: z.union([ + zMcpLocalConfig, + zMcpRemoteConfig + ]) +}); + +export const zMcpAddQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server added successfully + */ +export const zMcpAddResponse = z.record(z.string(), zMcpStatus); + +export const zMcpAuthRemovePath = z.object({ + name: z.string() +}); + +export const zMcpAuthRemoveQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth credentials removed + */ +export const zMcpAuthRemoveResponse = z.object({ + success: z.literal(true) +}); + +export const zMcpAuthStartPath = z.object({ + name: z.string() +}); + +export const zMcpAuthStartQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth flow started + */ +export const zMcpAuthStartResponse = z.object({ + authorizationUrl: z.string() +}); + +export const zMcpAuthCallbackBody = z.object({ + code: z.string() +}); + +export const zMcpAuthCallbackPath = z.object({ + name: z.string() +}); + +export const zMcpAuthCallbackQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth authentication completed + */ +export const zMcpAuthCallbackResponse = zMcpStatus; + +export const zMcpAuthAuthenticatePath = z.object({ + name: z.string() +}); + +export const zMcpAuthAuthenticateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth authentication completed + */ +export const zMcpAuthAuthenticateResponse = zMcpStatus; + +export const zMcpConnectPath = z.object({ + name: z.string() +}); + +export const zMcpConnectQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server connected successfully + */ +export const zMcpConnectResponse = z.boolean(); + +export const zMcpDisconnectPath = z.object({ + name: z.string() +}); + +export const zMcpDisconnectQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server disconnected successfully + */ +export const zMcpDisconnectResponse = z.boolean(); + +export const zLspStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * LSP server status + */ +export const zLspStatusResponse = z.array(zLspStatus); + +export const zFormatterStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Formatter status + */ +export const zFormatterStatusResponse = z.array(zFormatterStatus); + +export const zTuiAppendPromptBody = z.object({ + text: z.string() +}); + +export const zTuiAppendPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt processed successfully + */ +export const zTuiAppendPromptResponse = z.boolean(); + +export const zTuiOpenHelpQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Help dialog opened successfully + */ +export const zTuiOpenHelpResponse = z.boolean(); + +export const zTuiOpenSessionsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Session dialog opened successfully + */ +export const zTuiOpenSessionsResponse = z.boolean(); + +export const zTuiOpenThemesQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Theme dialog opened successfully + */ +export const zTuiOpenThemesResponse = z.boolean(); + +export const zTuiOpenModelsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Model dialog opened successfully + */ +export const zTuiOpenModelsResponse = z.boolean(); + +export const zTuiSubmitPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt submitted successfully + */ +export const zTuiSubmitPromptResponse = z.boolean(); + +export const zTuiClearPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt cleared successfully + */ +export const zTuiClearPromptResponse = z.boolean(); + +export const zTuiExecuteCommandBody = z.object({ + command: z.string() +}); + +export const zTuiExecuteCommandQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Command executed successfully + */ +export const zTuiExecuteCommandResponse = z.boolean(); + +export const zTuiShowToastBody = z.object({ + title: z.string().optional(), + message: z.string(), + variant: z.enum([ + 'info', + 'success', + 'warning', + 'error' + ]), + duration: z.number().optional().default(5000) +}); + +export const zTuiShowToastQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Toast notification shown successfully + */ +export const zTuiShowToastResponse = z.boolean(); + +export const zTuiPublishBody = z.union([ + zEventTuiPromptAppend, + zEventTuiCommandExecute, + zEventTuiToastShow +]); + +export const zTuiPublishQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Event published successfully + */ +export const zTuiPublishResponse = z.boolean(); + +export const zTuiControlNextQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Next TUI request + */ +export const zTuiControlNextResponse = z.object({ + path: z.string(), + body: z.unknown() +}); + +export const zTuiControlResponseBody = z.unknown(); + +export const zTuiControlResponseQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Response submitted successfully + */ +export const zTuiControlResponseResponse = z.boolean(); + +export const zAuthSetBody = zAuth; + +export const zAuthSetPath = z.object({ + providerID: z.string() +}); + +export const zAuthSetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully set authentication credentials + */ +export const zAuthSetResponse = z.boolean(); + +export const zEventSubscribeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Event stream + */ +export const zEventSubscribeResponse = zEvent; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client.gen.ts new file mode 100644 index 0000000000..cab3c70195 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client.gen.ts @@ -0,0 +1,16 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { type ClientOptions, type Config, createClient, createConfig } from './client'; +import type { ClientOptions as ClientOptions2 } from './types.gen'; + +/** + * 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 = (override?: Config) => Config & T>; + +export const client = createClient(createConfig()); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client/client.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client/client.gen.ts new file mode 100644 index 0000000000..fc3f037f16 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client/client.gen.ts @@ -0,0 +1,277 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { createSseClient } from '../core/serverSentEvents.gen'; +import type { HttpMethod } from '../core/types.gen'; +import { getValidRequestBody } from '../core/utils.gen'; +import type { Client, Config, RequestOptions, ResolvedRequestOptions } from './types.gen'; +import { + buildUrl, + createConfig, + createInterceptors, + getParseAs, + mergeConfigs, + mergeHeaders, + setAuthParams, +} from './utils.gen'; + +type ReqInit = Omit & { + body?: any; + headers: ReturnType; +}; + +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(); + + const beforeRequest = async < + TData = unknown, + TResponseStyle extends 'data' | 'fields' = 'fields', + ThrowOnError extends boolean = boolean, + Url extends string = string, + >( + options: RequestOptions, + ) => { + const opts = { + ..._config, + ...options, + fetch: options.fetch ?? _config.fetch ?? globalThis.fetch, + headers: mergeHeaders(_config.headers, options.headers), + serializedBody: undefined as string | undefined, + }; + + if (opts.security) { + await setAuthParams(opts); + } + + if (opts.requestValidator) { + await opts.requestValidator(opts); + } + + if (opts.body !== undefined && opts.bodySerializer) { + opts.serializedBody = opts.bodySerializer(opts.body) as string | undefined; + } + + // 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 resolvedOpts = opts as typeof opts & + ResolvedRequestOptions; + const url = buildUrl(resolvedOpts); + + return { opts: resolvedOpts, url }; + }; + + const request: Client['request'] = async (options) => { + const throwOnError = options.throwOnError ?? _config.throwOnError; + const responseStyle = options.responseStyle ?? _config.responseStyle; + + let request: Request | undefined; + let response: Response | undefined; + + try { + const { opts, url } = await beforeRequest(options); + const requestInit: ReqInit = { + redirect: 'follow', + ...opts, + body: getValidRequestBody(opts), + }; + + 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!; + + response = await _fetch(request); + + for (const fn of interceptors.response.fns) { + if (fn) { + response = await fn(response, request, opts); + } + } + + const result = { + request, + response, + }; + + if (response.ok) { + 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 'text': + data = await response[parseAs](); + break; + case 'json': { + // Some servers return 200 with no Content-Length and empty body. + // response.json() would throw; read as text and parse if non-empty. + const text = await response.text(); + data = text ? JSON.parse(text) : {}; + 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 + } + + throw jsonError ?? textError; + } catch (error) { + let finalError = error; + + for (const fn of interceptors.error.fns) { + if (fn) { + finalError = await fn(finalError, response, request, options as ResolvedRequestOptions); + } + } + + finalError = finalError || {}; + + if (throwOnError) { + throw finalError; + } + + // TODO: we probably want to return error and improve types + return responseStyle === 'data' + ? undefined + : { + error: finalError, + request, + response, + }; + } + }; + + const makeMethodFn = (method: Uppercase) => (options: RequestOptions) => + request({ ...options, method }); + + const makeSseFn = (method: Uppercase) => async (options: RequestOptions) => { + const { opts, url } = await beforeRequest(options); + return createSseClient({ + ...opts, + body: opts.body as BodyInit | null | undefined, + 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; + }, + serializedBody: getValidRequestBody(opts) as BodyInit | null | undefined, + url, + }); + }; + + const _buildUrl: Client['buildUrl'] = (options) => buildUrl({ ..._config, ...options }); + + return { + buildUrl: _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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client/index.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client/index.ts new file mode 100644 index 0000000000..b295edeca0 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client/index.ts @@ -0,0 +1,25 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type { Auth } from '../core/auth.gen'; +export type { QuerySerializerOptions } from '../core/bodySerializer.gen'; +export { + formDataBodySerializer, + jsonBodySerializer, + urlSearchParamsBodySerializer, +} from '../core/bodySerializer.gen'; +export { buildClientParams } from '../core/params.gen'; +export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen'; +export { createClient } from './client.gen'; +export type { + Client, + ClientOptions, + Config, + CreateClientConfig, + Options, + RequestOptions, + RequestResult, + ResolvedRequestOptions, + ResponseStyle, + TDataShape, +} from './types.gen'; +export { createConfig, mergeHeaders } from './utils.gen'; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client/types.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client/types.gen.ts new file mode 100644 index 0000000000..193646cddf --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client/types.gen.ts @@ -0,0 +1,218 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth } from '../core/auth.gen'; +import type { + ServerSentEventsOptions, + ServerSentEventsResult, +} from '../core/serverSentEvents.gen'; +import type { Client as CoreClient, Config as CoreConfig } from '../core/types.gen'; +import type { Middleware } from './utils.gen'; + +export type ResponseStyle = 'data' | 'fields'; + +export interface Config + extends Omit, 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, + | 'onRequest' + | '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; + query?: Record; + /** + * Security mechanism(s) to use for the request. + */ + security?: ReadonlyArray; + url: Url; +} + +export interface ResolvedRequestOptions< + TResponseStyle extends ResponseStyle = 'fields', + ThrowOnError extends boolean = boolean, + Url extends string = string, +> extends RequestOptions { + headers: Headers; + 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 + ? TData[keyof TData] + : TData + : { + data: TData extends Record ? TData[keyof TData] : TData; + request: Request; + response: Response; + } + > + : Promise< + TResponseStyle extends 'data' + ? (TData extends Record ? TData[keyof TData] : TData) | undefined + : ( + | { + data: TData extends Record ? TData[keyof TData] : TData; + error: undefined; + } + | { + data: undefined; + error: TError extends Record ? TError[keyof TError] : TError; + } + ) & { + /** request may be undefined, because error may be from building the request object itself */ + request?: Request; + /** response may be undefined, because error may be from building the request object itself or from a network error */ + 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, 'method'>, +) => RequestResult; + +type SseFn = < + TData = unknown, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = 'fields', +>( + options: Omit, 'method'>, +) => Promise>; + +type RequestFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = 'fields', +>( + options: Omit, 'method'> & + Pick>, 'method'>, +) => RequestResult; + +type BuildUrlFn = < + TData extends { + body?: unknown; + path?: Record; + query?: Record; + url: string; + }, +>( + options: TData & Options, +) => string; + +export type Client = CoreClient & { + interceptors: Middleware; +}; + +/** + * 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 = ( + override?: Config, +) => Config & T>; + +export interface TDataShape { + body?: unknown; + headers?: unknown; + path?: unknown; + query?: unknown; + url: string; +} + +type OmitKeys = Pick>; + +export type Options< + TData extends TDataShape = TDataShape, + ThrowOnError extends boolean = boolean, + TResponse = unknown, + TResponseStyle extends ResponseStyle = 'fields', +> = OmitKeys< + RequestOptions, + 'body' | 'path' | 'query' | 'url' +> & + ([TData] extends [never] ? unknown : Omit); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client/utils.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client/utils.gen.ts new file mode 100644 index 0000000000..7800fe4b9d --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/client/utils.gen.ts @@ -0,0 +1,316 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { getAuthToken } from '../core/auth.gen'; +import type { QuerySerializerOptions } from '../core/bodySerializer.gen'; +import { jsonBodySerializer } from '../core/bodySerializer.gen'; +import { + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from '../core/pathSerializer.gen'; +import { getUrl } from '../core/utils.gen'; +import type { Client, ClientOptions, Config, RequestOptions } from './types.gen'; + +export const createQuerySerializer = ({ + 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, + ...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 => { + 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 & { + 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 async function setAuthParams( + options: Pick & { + headers: Headers; + }, +): Promise { + for (const auth of options.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['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 = ( + error: Err, + /** response may be undefined due to a network error where no response object is produced */ + response: Res | undefined, + /** request may be undefined, because error may be from building the request object itself */ + request: Req | undefined, + options: Options, +) => Err | Promise; + +type ReqInterceptor = (request: Req, options: Options) => Req | Promise; + +type ResInterceptor = ( + response: Res, + request: Req, + options: Options, +) => Res | Promise; + +class Interceptors { + fns: Array = []; + + 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 { + error: Interceptors>; + request: Interceptors>; + response: Interceptors>; +} + +export const createInterceptors = (): Middleware< + Req, + Res, + Err, + Options +> => ({ + error: new Interceptors>(), + request: new Interceptors>(), + response: new Interceptors>(), +}); + +const defaultQuerySerializer = createQuerySerializer({ + allowReserved: false, + array: { + explode: true, + style: 'form', + }, + object: { + explode: true, + style: 'deepObject', + }, +}); + +const defaultHeaders = { + 'Content-Type': 'application/json', +}; + +export const createConfig = ( + override: Config & T> = {}, +): Config & T> => ({ + ...jsonBodySerializer, + headers: defaultHeaders, + parseAs: 'auto', + querySerializer: defaultQuerySerializer, + ...override, +}); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/auth.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/auth.gen.ts new file mode 100644 index 0000000000..3ebf994788 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/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, +): Promise => { + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/bodySerializer.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/bodySerializer.gen.ts new file mode 100644 index 0000000000..67daca60f8 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/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'; + +export type QuerySerializer = (query: Record) => string; + +export type BodySerializer = (body: unknown) => unknown; + +type QuerySerializerOptionsObject = { + allowReserved?: boolean; + array?: Partial>; + object?: Partial>; +}; + +export type QuerySerializerOptions = QuerySerializerOptionsObject & { + /** + * Per-parameter serialization overrides. When provided, these settings + * override the global array/object settings for specific parameter names. + */ + parameters?: Record; +}; + +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: (body: unknown): FormData => { + const data = new FormData(); + + Object.entries(body as Record).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: (body: unknown): string => + JSON.stringify(body, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)), +}; + +export const urlSearchParamsBodySerializer = { + bodySerializer: (body: unknown): string => { + const data = new URLSearchParams(); + + Object.entries(body as Record).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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/params.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/params.gen.ts new file mode 100644 index 0000000000..6478519bcb --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/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; + /** + * 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; + /** + * 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>; + args?: ReadonlyArray; +} + +export type FieldsConfig = ReadonlyArray; + +const extraPrefixesMap: Record = { + $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; + path: Record; + query: Record; +} + +const stripEmptySlots = (params: Params) => { + for (const [slot, value] of Object.entries(params)) { + if (value && typeof value === 'object' && !Array.isArray(value) && !Object.keys(value).length) { + delete params[slot as Slot]; + } + } +}; + +export const buildClientParams = (args: ReadonlyArray, fields: FieldsConfig) => { + const params: Params = { + body: Object.create(null), + headers: Object.create(null), + path: Object.create(null), + query: Object.create(null), + }; + + 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)[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)[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)[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)[key] = value; + break; + } + } + } + } + } + } + } + + stripEmptySlots(params); + + return params; +}; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/pathSerializer.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/pathSerializer.gen.ts new file mode 100644 index 0000000000..994b2848c6 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/pathSerializer.gen.ts @@ -0,0 +1,171 @@ +// This file is auto-generated by @hey-api/openapi-ts + +interface SerializeOptions extends SerializePrimitiveOptions, SerializerOptions {} + +interface SerializePrimitiveOptions { + allowReserved?: boolean; + name: string; +} + +export interface SerializerOptions { + /** + * @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 & { + 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 & { + value: Record | 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/queryKeySerializer.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/queryKeySerializer.gen.ts new file mode 100644 index 0000000000..5000df606f --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/queryKeySerializer.gen.ts @@ -0,0 +1,117 @@ +// 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 => { + 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 = {}; + + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/serverSentEvents.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/serverSentEvents.gen.ts new file mode 100644 index 0000000000..ddf3c4d13a --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/serverSentEvents.gen.ts @@ -0,0 +1,242 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Config } from './types.gen'; + +export type ServerSentEventsOptions = Omit & + Pick & { + /** + * 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; + /** + * 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) => 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; + url: string; + }; + +export interface StreamEvent { + data: TData; + event?: string; + id?: string; + retry?: number; +} + +export type ServerSentEventsResult = { + stream: AsyncGenerator< + TData extends Record ? TData[keyof TData] : TData, + TReturn, + TNext + >; +}; + +export function createSseClient({ + onRequest, + onSseError, + onSseEvent, + responseTransformer, + responseValidator, + sseDefaultRetryDelay, + sseMaxRetryAttempts, + sseMaxRetryDelay, + sseSleepFn, + url, + ...options +}: ServerSentEventsOptions): ServerSentEventsResult { + 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 | 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; + buffer = buffer.replace(/\r\n?/g, '\n'); // normalize line endings + + const chunks = buffer.split('\n\n'); + buffer = chunks.pop() ?? ''; + + for (const chunk of chunks) { + const lines = chunk.split('\n'); + const dataLines: Array = []; + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/types.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/types.gen.ts new file mode 100644 index 0000000000..9efe71d4c1 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/types.gen.ts @@ -0,0 +1,104 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth, AuthToken } from './auth.gen'; +import type { BodySerializer, QuerySerializer, QuerySerializerOptions } from './bodySerializer.gen'; + +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; + /** + * 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; + /** + * 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; + /** + * 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; + /** + * 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; +} + +type IsExactlyNeverOrNeverUndefined = [T] extends [never] + ? true + : [T] extends [never | undefined] + ? [undefined] extends [T] + ? false + : true + : false; + +export type OmitNever> = { + [K in keyof T as IsExactlyNeverOrNeverUndefined extends true ? never : K]: T[K]; +}; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/utils.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/utils.gen.ts new file mode 100644 index 0000000000..9a4fec7830 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/core/utils.gen.ts @@ -0,0 +1,140 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { BodySerializer, QuerySerializer } from './bodySerializer.gen'; +import { + type ArraySeparatorStyle, + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from './pathSerializer.gen'; + +export interface PathSerializer { + path: Record; + 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, + 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; + query?: Record; + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/index.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/index.ts new file mode 100644 index 0000000000..c1f98cb47e --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/index.ts @@ -0,0 +1,4 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export { appAgents, appLog, authSet, commandList, configGet, configProviders, configUpdate, eventSubscribe, fileList, fileRead, fileStatus, findFiles, findSymbols, findText, formatterStatus, globalDispose, globalEvent, globalHealth, instanceDispose, lspStatus, mcpAdd, mcpAuthAuthenticate, mcpAuthCallback, mcpAuthRemove, mcpAuthStart, mcpConnect, mcpDisconnect, mcpStatus, type Options, partDelete, partUpdate, pathGet, permissionList, permissionReply, permissionRespond, projectCurrent, projectList, projectUpdate, providerAuth, providerList, providerOauthAuthorize, providerOauthCallback, ptyConnect, ptyCreate, ptyGet, ptyList, ptyRemove, ptyUpdate, sessionAbort, sessionChildren, sessionCommand, sessionCreate, sessionDelete, sessionDiff, sessionFork, sessionGet, sessionInit, sessionList, sessionMessage, sessionMessages, sessionPrompt, sessionPromptAsync, sessionRevert, sessionShare, sessionShell, sessionStatus, sessionSummarize, sessionTodo, sessionUnrevert, sessionUnshare, sessionUpdate, toolIds, toolList, tuiAppendPrompt, tuiClearPrompt, tuiControlNext, tuiControlResponse, tuiExecuteCommand, tuiOpenHelp, tuiOpenModels, tuiOpenSessions, tuiOpenThemes, tuiPublish, tuiShowToast, tuiSubmitPrompt, vcsGet } from './sdk.gen'; +export type { Agent, AgentConfig, AgentPart, AgentPartInput, ApiAuth, ApiError, AppAgentsData, AppAgentsResponse, AppAgentsResponses, AppLogData, AppLogError, AppLogErrors, AppLogResponse, AppLogResponses, AssistantMessage, Auth, AuthSetData, AuthSetError, AuthSetErrors, AuthSetResponse, AuthSetResponses, BadRequestError, ClientOptions, Command, CommandListData, CommandListResponse, CommandListResponses, CompactionPart, Config, ConfigGetData, ConfigGetResponse, ConfigGetResponses, ConfigProvidersData, ConfigProvidersResponse, ConfigProvidersResponses, ConfigUpdateData, ConfigUpdateError, ConfigUpdateErrors, ConfigUpdateResponse, ConfigUpdateResponses, Event, EventCommandExecuted, EventFileEdited, EventFileWatcherUpdated, EventGlobalDisposed, EventInstallationUpdateAvailable, EventInstallationUpdated, EventLspClientDiagnostics, EventLspUpdated, EventMcpToolsChanged, EventMessagePartRemoved, EventMessagePartUpdated, EventMessageRemoved, EventMessageUpdated, EventPermissionAsked, EventPermissionReplied, EventProjectUpdated, EventPtyCreated, EventPtyDeleted, EventPtyExited, EventPtyUpdated, EventServerConnected, EventServerInstanceDisposed, EventSessionCompacted, EventSessionCreated, EventSessionDeleted, EventSessionDiff, EventSessionError, EventSessionIdle, EventSessionStatus, EventSessionUpdated, EventSubscribeData, EventSubscribeResponse, EventSubscribeResponses, EventTodoUpdated, EventTuiCommandExecute, EventTuiPromptAppend, EventTuiToastShow, EventVcsBranchUpdated, File, FileContent, FileDiff, FileListData, FileListResponse, FileListResponses, FileNode, FilePart, FilePartInput, FilePartSource, FilePartSourceText, FileReadData, FileReadResponse, FileReadResponses, FileSource, FileStatusData, FileStatusResponse, FileStatusResponses, FindFilesData, FindFilesResponse, FindFilesResponses, FindSymbolsData, FindSymbolsResponse, FindSymbolsResponses, FindTextData, FindTextResponse, FindTextResponses, FormatterStatus, FormatterStatusData, FormatterStatusResponse, FormatterStatusResponses, GlobalDisposeData, GlobalDisposeResponse, GlobalDisposeResponses, GlobalEvent, GlobalEventData, GlobalEventResponse, GlobalEventResponses, GlobalHealthData, GlobalHealthResponse, GlobalHealthResponses, InstanceDisposeData, InstanceDisposeResponse, InstanceDisposeResponses, KeybindsConfig, LayoutConfig, LogLevel, LspStatus, LspStatusData, LspStatusResponse, LspStatusResponses, McpAddData, McpAddError, McpAddErrors, McpAddResponse, McpAddResponses, McpAuthAuthenticateData, McpAuthAuthenticateError, McpAuthAuthenticateErrors, McpAuthAuthenticateResponse, McpAuthAuthenticateResponses, McpAuthCallbackData, McpAuthCallbackError, McpAuthCallbackErrors, McpAuthCallbackResponse, McpAuthCallbackResponses, McpAuthRemoveData, McpAuthRemoveError, McpAuthRemoveErrors, McpAuthRemoveResponse, McpAuthRemoveResponses, McpAuthStartData, McpAuthStartError, McpAuthStartErrors, McpAuthStartResponse, McpAuthStartResponses, McpConnectData, McpConnectResponse, McpConnectResponses, McpDisconnectData, McpDisconnectResponse, McpDisconnectResponses, McpLocalConfig, McpOAuthConfig, McpRemoteConfig, McpStatus, McpStatusConnected, McpStatusData, McpStatusDisabled, McpStatusFailed, McpStatusNeedsAuth, McpStatusNeedsClientRegistration, McpStatusResponse, McpStatusResponses, Message, MessageAbortedError, MessageOutputLengthError, Model, NotFoundError, OAuth, Part, PartDeleteData, PartDeleteError, PartDeleteErrors, PartDeleteResponse, PartDeleteResponses, PartUpdateData, PartUpdateError, PartUpdateErrors, PartUpdateResponse, PartUpdateResponses, PatchPart, Path, PathGetData, PathGetResponse, PathGetResponses, PermissionAction, PermissionActionConfig, PermissionConfig, PermissionListData, PermissionListResponse, PermissionListResponses, PermissionObjectConfig, PermissionReplyData, PermissionReplyError, PermissionReplyErrors, PermissionReplyResponse, PermissionReplyResponses, PermissionRequest, PermissionRespondData, PermissionRespondError, PermissionRespondErrors, PermissionRespondResponse, PermissionRespondResponses, PermissionRule, PermissionRuleConfig, PermissionRuleset, Project, ProjectCurrentData, ProjectCurrentResponse, ProjectCurrentResponses, ProjectListData, ProjectListResponse, ProjectListResponses, ProjectUpdateData, ProjectUpdateError, ProjectUpdateErrors, ProjectUpdateResponse, ProjectUpdateResponses, Provider, ProviderAuthAuthorization, ProviderAuthData, ProviderAuthError, ProviderAuthMethod, ProviderAuthResponse, ProviderAuthResponses, ProviderConfig, ProviderListData, ProviderListResponse, ProviderListResponses, ProviderOauthAuthorizeData, ProviderOauthAuthorizeError, ProviderOauthAuthorizeErrors, ProviderOauthAuthorizeResponse, ProviderOauthAuthorizeResponses, ProviderOauthCallbackData, ProviderOauthCallbackError, ProviderOauthCallbackErrors, ProviderOauthCallbackResponse, ProviderOauthCallbackResponses, Pty, PtyConnectData, PtyConnectError, PtyConnectErrors, PtyConnectResponse, PtyConnectResponses, PtyCreateData, PtyCreateError, PtyCreateErrors, PtyCreateResponse, PtyCreateResponses, PtyGetData, PtyGetError, PtyGetErrors, PtyGetResponse, PtyGetResponses, PtyListData, PtyListResponse, PtyListResponses, PtyRemoveData, PtyRemoveError, PtyRemoveErrors, PtyRemoveResponse, PtyRemoveResponses, PtyUpdateData, PtyUpdateError, PtyUpdateErrors, PtyUpdateResponse, PtyUpdateResponses, Range, ReasoningPart, RetryPart, ServerConfig, Session, SessionAbortData, SessionAbortError, SessionAbortErrors, SessionAbortResponse, SessionAbortResponses, SessionChildrenData, SessionChildrenError, SessionChildrenErrors, SessionChildrenResponse, SessionChildrenResponses, SessionCommandData, SessionCommandError, SessionCommandErrors, SessionCommandResponse, SessionCommandResponses, SessionCreateData, SessionCreateError, SessionCreateErrors, SessionCreateResponse, SessionCreateResponses, SessionDeleteData, SessionDeleteError, SessionDeleteErrors, SessionDeleteResponse, SessionDeleteResponses, SessionDiffData, SessionDiffError, SessionDiffErrors, SessionDiffResponse, SessionDiffResponses, SessionForkData, SessionForkResponse, SessionForkResponses, SessionGetData, SessionGetError, SessionGetErrors, SessionGetResponse, SessionGetResponses, SessionInitData, SessionInitError, SessionInitErrors, SessionInitResponse, SessionInitResponses, SessionListData, SessionListResponse, SessionListResponses, SessionMessageData, SessionMessageError, SessionMessageErrors, SessionMessageResponse, SessionMessageResponses, SessionMessagesData, SessionMessagesError, SessionMessagesErrors, SessionMessagesResponse, SessionMessagesResponses, SessionPromptAsyncData, SessionPromptAsyncError, SessionPromptAsyncErrors, SessionPromptAsyncResponse, SessionPromptAsyncResponses, SessionPromptData, SessionPromptError, SessionPromptErrors, SessionPromptResponse, SessionPromptResponses, SessionRevertData, SessionRevertError, SessionRevertErrors, SessionRevertResponse, SessionRevertResponses, SessionShareData, SessionShareError, SessionShareErrors, SessionShareResponse, SessionShareResponses, SessionShellData, SessionShellError, SessionShellErrors, SessionShellResponse, SessionShellResponses, SessionStatus, SessionStatusData, SessionStatusError, SessionStatusErrors, SessionStatusResponse, SessionStatusResponses, SessionSummarizeData, SessionSummarizeError, SessionSummarizeErrors, SessionSummarizeResponse, SessionSummarizeResponses, SessionTodoData, SessionTodoError, SessionTodoErrors, SessionTodoResponse, SessionTodoResponses, SessionUnrevertData, SessionUnrevertError, SessionUnrevertErrors, SessionUnrevertResponse, SessionUnrevertResponses, SessionUnshareData, SessionUnshareError, SessionUnshareErrors, SessionUnshareResponse, SessionUnshareResponses, SessionUpdateData, SessionUpdateError, SessionUpdateErrors, SessionUpdateResponse, SessionUpdateResponses, SnapshotPart, StepFinishPart, StepStartPart, SubtaskPartInput, Symbol, SymbolSource, TextPart, TextPartInput, Todo, ToolIds, ToolIdsData, ToolIdsError, ToolIdsErrors, ToolIdsResponse, ToolIdsResponses, ToolList, ToolListData, ToolListError, ToolListErrors, ToolListItem, ToolListResponse, ToolListResponses, ToolPart, ToolState, ToolStateCompleted, ToolStateError, ToolStatePending, ToolStateRunning, TuiAppendPromptData, TuiAppendPromptError, TuiAppendPromptErrors, TuiAppendPromptResponse, TuiAppendPromptResponses, TuiClearPromptData, TuiClearPromptResponse, TuiClearPromptResponses, TuiControlNextData, TuiControlNextResponse, TuiControlNextResponses, TuiControlResponseData, TuiControlResponseResponse, TuiControlResponseResponses, TuiExecuteCommandData, TuiExecuteCommandError, TuiExecuteCommandErrors, TuiExecuteCommandResponse, TuiExecuteCommandResponses, TuiOpenHelpData, TuiOpenHelpResponse, TuiOpenHelpResponses, TuiOpenModelsData, TuiOpenModelsResponse, TuiOpenModelsResponses, TuiOpenSessionsData, TuiOpenSessionsResponse, TuiOpenSessionsResponses, TuiOpenThemesData, TuiOpenThemesResponse, TuiOpenThemesResponses, TuiPublishData, TuiPublishError, TuiPublishErrors, TuiPublishResponse, TuiPublishResponses, TuiShowToastData, TuiShowToastResponse, TuiShowToastResponses, TuiSubmitPromptData, TuiSubmitPromptResponse, TuiSubmitPromptResponses, UnknownError, UserMessage, VcsGetData, VcsGetResponse, VcsGetResponses, VcsInfo, WellKnownAuth } from './types.gen'; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/sdk.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/sdk.gen.ts new file mode 100644 index 0000000000..67d08d33d1 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/sdk.gen.ts @@ -0,0 +1,2334 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import * as z from 'zod'; + +import { buildClientParams, type Client, type Options as Options2, type TDataShape } from './client'; +import { client } from './client.gen'; +import type { AgentPartInput, AppAgentsResponses, AppLogErrors, AppLogResponses, Auth, AuthSetErrors, AuthSetResponses, CommandListResponses, Config, ConfigGetResponses, ConfigProvidersResponses, ConfigUpdateErrors, ConfigUpdateResponses, EventSubscribeResponse, EventSubscribeResponses, EventTuiCommandExecute, EventTuiPromptAppend, EventTuiToastShow, FileListResponses, FilePartInput, FileReadResponses, FileStatusResponses, FindFilesResponses, FindSymbolsResponses, FindTextResponses, FormatterStatusResponses, GlobalDisposeResponses, GlobalEventResponse, GlobalEventResponses, GlobalHealthResponses, InstanceDisposeResponses, LspStatusResponses, McpAddErrors, McpAddResponses, McpAuthAuthenticateErrors, McpAuthAuthenticateResponses, McpAuthCallbackErrors, McpAuthCallbackResponses, McpAuthRemoveErrors, McpAuthRemoveResponses, McpAuthStartErrors, McpAuthStartResponses, McpConnectResponses, McpDisconnectResponses, McpLocalConfig, McpRemoteConfig, McpStatusResponses, Part, PartDeleteErrors, PartDeleteResponses, PartUpdateErrors, PartUpdateResponses, PathGetResponses, PermissionListResponses, PermissionReplyErrors, PermissionReplyResponses, PermissionRespondErrors, PermissionRespondResponses, PermissionRuleset, ProjectCurrentResponses, ProjectListResponses, ProjectUpdateErrors, ProjectUpdateResponses, 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'; +import { zAppAgentsQuery, zAppAgentsResponse, zAppLogBody, zAppLogQuery, zAppLogResponse, zAuthSetBody, zAuthSetPath, zAuthSetQuery, zAuthSetResponse, zCommandListQuery, zCommandListResponse, zConfigGetQuery, zConfigGetResponse, zConfigProvidersQuery, zConfigProvidersResponse, zConfigUpdateBody, zConfigUpdateQuery, zConfigUpdateResponse, zEventSubscribeQuery, zEventSubscribeResponse, zFileListQuery, zFileListResponse, zFileReadQuery, zFileReadResponse, zFileStatusQuery, zFileStatusResponse, zFindFilesQuery, zFindFilesResponse, zFindSymbolsQuery, zFindSymbolsResponse, zFindTextQuery, zFindTextResponse, zFormatterStatusQuery, zFormatterStatusResponse, zGlobalDisposeResponse, zGlobalEventResponse, zGlobalHealthResponse, zInstanceDisposeQuery, zInstanceDisposeResponse, zLspStatusQuery, zLspStatusResponse, zMcpAddBody, zMcpAddQuery, zMcpAddResponse, zMcpAuthAuthenticatePath, zMcpAuthAuthenticateQuery, zMcpAuthAuthenticateResponse, zMcpAuthCallbackBody, zMcpAuthCallbackPath, zMcpAuthCallbackQuery, zMcpAuthCallbackResponse, zMcpAuthRemovePath, zMcpAuthRemoveQuery, zMcpAuthRemoveResponse, zMcpAuthStartPath, zMcpAuthStartQuery, zMcpAuthStartResponse, zMcpConnectPath, zMcpConnectQuery, zMcpConnectResponse, zMcpDisconnectPath, zMcpDisconnectQuery, zMcpDisconnectResponse, zMcpStatusQuery, zMcpStatusResponse, zPartDeletePath, zPartDeleteQuery, zPartDeleteResponse, zPartUpdateBody, zPartUpdatePath, zPartUpdateQuery, zPartUpdateResponse, zPathGetQuery, zPathGetResponse, zPermissionListQuery, zPermissionListResponse, zPermissionReplyBody, zPermissionReplyPath, zPermissionReplyQuery, zPermissionReplyResponse, zPermissionRespondBody, zPermissionRespondPath, zPermissionRespondQuery, zPermissionRespondResponse, zProjectCurrentQuery, zProjectCurrentResponse, zProjectListQuery, zProjectListResponse, zProjectUpdateBody, zProjectUpdatePath, zProjectUpdateQuery, zProjectUpdateResponse, zProviderAuthQuery, zProviderAuthResponse, zProviderListQuery, zProviderListResponse, zProviderOauthAuthorizeBody, zProviderOauthAuthorizePath, zProviderOauthAuthorizeQuery, zProviderOauthAuthorizeResponse, zProviderOauthCallbackBody, zProviderOauthCallbackPath, zProviderOauthCallbackQuery, zProviderOauthCallbackResponse, zPtyConnectPath, zPtyConnectQuery, zPtyConnectResponse, zPtyCreateBody, zPtyCreateQuery, zPtyCreateResponse, zPtyGetPath, zPtyGetQuery, zPtyGetResponse, zPtyListQuery, zPtyListResponse, zPtyRemovePath, zPtyRemoveQuery, zPtyRemoveResponse, zPtyUpdateBody, zPtyUpdatePath, zPtyUpdateQuery, zPtyUpdateResponse, zSessionAbortPath, zSessionAbortQuery, zSessionAbortResponse, zSessionChildrenPath, zSessionChildrenQuery, zSessionChildrenResponse, zSessionCommandBody, zSessionCommandPath, zSessionCommandQuery, zSessionCommandResponse, zSessionCreateBody, zSessionCreateQuery, zSessionCreateResponse, zSessionDeletePath, zSessionDeleteQuery, zSessionDeleteResponse, zSessionDiffPath, zSessionDiffQuery, zSessionDiffResponse, zSessionForkBody, zSessionForkPath, zSessionForkQuery, zSessionForkResponse, zSessionGetPath, zSessionGetQuery, zSessionGetResponse, zSessionInitBody, zSessionInitPath, zSessionInitQuery, zSessionInitResponse, zSessionListQuery, zSessionListResponse, zSessionMessagePath, zSessionMessageQuery, zSessionMessageResponse, zSessionMessagesPath, zSessionMessagesQuery, zSessionMessagesResponse, zSessionPromptAsyncBody, zSessionPromptAsyncPath, zSessionPromptAsyncQuery, zSessionPromptAsyncResponse, zSessionPromptBody, zSessionPromptPath, zSessionPromptQuery, zSessionPromptResponse, zSessionRevertBody, zSessionRevertPath, zSessionRevertQuery, zSessionRevertResponse, zSessionSharePath, zSessionShareQuery, zSessionShareResponse, zSessionShellBody, zSessionShellPath, zSessionShellQuery, zSessionShellResponse, zSessionStatusQuery, zSessionStatusResponse, zSessionSummarizeBody, zSessionSummarizePath, zSessionSummarizeQuery, zSessionSummarizeResponse, zSessionTodoPath, zSessionTodoQuery, zSessionTodoResponse, zSessionUnrevertPath, zSessionUnrevertQuery, zSessionUnrevertResponse, zSessionUnsharePath, zSessionUnshareQuery, zSessionUnshareResponse, zSessionUpdateBody, zSessionUpdatePath, zSessionUpdateQuery, zSessionUpdateResponse, zToolIdsQuery, zToolIdsResponse, zToolListQuery, zToolListResponse, zTuiAppendPromptBody, zTuiAppendPromptQuery, zTuiAppendPromptResponse, zTuiClearPromptQuery, zTuiClearPromptResponse, zTuiControlNextQuery, zTuiControlNextResponse, zTuiControlResponseBody, zTuiControlResponseQuery, zTuiControlResponseResponse, zTuiExecuteCommandBody, zTuiExecuteCommandQuery, zTuiExecuteCommandResponse, zTuiOpenHelpQuery, zTuiOpenHelpResponse, zTuiOpenModelsQuery, zTuiOpenModelsResponse, zTuiOpenSessionsQuery, zTuiOpenSessionsResponse, zTuiOpenThemesQuery, zTuiOpenThemesResponse, zTuiPublishBody, zTuiPublishQuery, zTuiPublishResponse, zTuiShowToastBody, zTuiShowToastQuery, zTuiShowToastResponse, zTuiSubmitPromptQuery, zTuiSubmitPromptResponse, zVcsGetQuery, zVcsGetResponse } from './zod.gen'; + +export type Options = Options2 & { + /** + * 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; +}; + +/** + * Get health + * + * Get health information about the OpenCode server. + */ +export const globalHealth = Object.assign(function globalHealth2(options?: Options) { + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: z.never().optional() + }).parseAsync(data), + responseValidator: async (data) => await zGlobalHealthResponse.parseAsync(data), + url: '/global/health', + ...options + }); +}, { id: 'globalHealth', url: '/global/health' }); + +/** + * Get global events + * + * Subscribe to global events from the OpenCode system using server-sent events. + */ +export const globalEvent = Object.assign(function globalEvent2(options?: Options) { + return (options?.client ?? client).sse.get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: z.never().optional() + }).parseAsync(data), + responseValidator: async (data) => await zGlobalEventResponse.parseAsync(data), + url: '/global/event', + ...options + }); +}, { id: 'globalEvent', url: '/global/event' }); + +/** + * Dispose instance + * + * Clean up and dispose all OpenCode instances, releasing all resources. + */ +export const globalDispose = Object.assign(function globalDispose2(options?: Options) { + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: z.never().optional() + }).parseAsync(data), + responseValidator: async (data) => await zGlobalDisposeResponse.parseAsync(data), + url: '/global/dispose', + ...options + }); +}, { id: 'globalDispose', url: '/global/dispose' }); + +/** + * List all projects + * + * Get a list of projects that have been opened with OpenCode. + */ +export const projectList = Object.assign(function projectList2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProjectListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProjectListResponse.parseAsync(data), + url: '/project', + ...options, + ...params + }); +}, { id: 'projectList', url: '/project' }); + +/** + * Get current project + * + * Retrieve the currently active project that OpenCode is working with. + */ +export const projectCurrent = Object.assign(function projectCurrent2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProjectCurrentQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProjectCurrentResponse.parseAsync(data), + url: '/project/current', + ...options, + ...params + }); +}, { id: 'projectCurrent', url: '/project/current' }); + +/** + * Update project + * + * Update project properties such as name, icon and color. + */ +export const projectUpdate = Object.assign(function projectUpdate2(parameters: { + projectID: string; + directory?: string; + name?: string; + icon?: { + url?: string; + color?: string; + }; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'projectID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'name' }, + { in: 'body', key: 'icon' } + ] }]); + return (options?.client ?? client).patch({ + requestValidator: async (data) => await z.object({ + body: zProjectUpdateBody.optional(), + path: zProjectUpdatePath, + query: zProjectUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProjectUpdateResponse.parseAsync(data), + url: '/project/{projectID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'projectUpdate', url: '/project/{projectID}' }); + +/** + * List PTY sessions + * + * Get a list of all active pseudo-terminal (PTY) sessions managed by OpenCode. + */ +export const ptyList = Object.assign(function ptyList2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zPtyListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyListResponse.parseAsync(data), + url: '/pty', + ...options, + ...params + }); +}, { id: 'ptyList', url: '/pty' }); + +/** + * Create PTY session + * + * Create a new pseudo-terminal (PTY) session for running shell commands and processes. + */ +export const ptyCreate = Object.assign(function ptyCreate2(parameters?: { + directory?: string; + command?: string; + args?: Array; + cwd?: string; + title?: string; + env?: { + [key: string]: string; + }; +}, options?: Options) { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zPtyCreateBody.optional(), + path: z.never().optional(), + query: zPtyCreateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyCreateResponse.parseAsync(data), + url: '/pty', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'ptyCreate', url: '/pty' }); + +/** + * Remove PTY session + * + * Remove and terminate a specific pseudo-terminal (PTY) session. + */ +export const ptyRemove = Object.assign(function ptyRemove2(parameters: { + ptyID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'ptyID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPtyRemovePath, + query: zPtyRemoveQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyRemoveResponse.parseAsync(data), + url: '/pty/{ptyID}', + ...options, + ...params + }); +}, { id: 'ptyRemove', url: '/pty/{ptyID}' }); + +/** + * Get PTY session + * + * Retrieve detailed information about a specific pseudo-terminal (PTY) session. + */ +export const ptyGet = Object.assign(function ptyGet2(parameters: { + ptyID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'ptyID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPtyGetPath, + query: zPtyGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyGetResponse.parseAsync(data), + url: '/pty/{ptyID}', + ...options, + ...params + }); +}, { id: 'ptyGet', url: '/pty/{ptyID}' }); + +/** + * Update PTY session + * + * Update properties of an existing pseudo-terminal (PTY) session. + */ +export const ptyUpdate = Object.assign(function ptyUpdate2(parameters: { + ptyID: string; + directory?: string; + title?: string; + size?: { + rows: number; + cols: number; + }; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'ptyID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'title' }, + { in: 'body', key: 'size' } + ] }]); + return (options?.client ?? client).put({ + requestValidator: async (data) => await z.object({ + body: zPtyUpdateBody.optional(), + path: zPtyUpdatePath, + query: zPtyUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyUpdateResponse.parseAsync(data), + url: '/pty/{ptyID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'ptyUpdate', url: '/pty/{ptyID}' }); + +/** + * Connect to PTY session + * + * Establish a WebSocket connection to interact with a pseudo-terminal (PTY) session in real-time. + */ +export const ptyConnect = Object.assign(function ptyConnect2(parameters: { + ptyID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'ptyID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPtyConnectPath, + query: zPtyConnectQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyConnectResponse.parseAsync(data), + url: '/pty/{ptyID}/connect', + ...options, + ...params + }); +}, { id: 'ptyConnect', url: '/pty/{ptyID}/connect' }); + +/** + * Get configuration + * + * Retrieve the current OpenCode configuration settings and preferences. + */ +export const configGet = Object.assign(function configGet2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zConfigGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zConfigGetResponse.parseAsync(data), + url: '/config', + ...options, + ...params + }); +}, { id: 'configGet', url: '/config' }); + +/** + * Update configuration + * + * Update OpenCode configuration settings and preferences. + */ +export const configUpdate = Object.assign(function configUpdate2(parameters?: { + directory?: string; + config?: Config; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { key: 'config', map: 'body' }] }]); + return (options?.client ?? client).patch({ + requestValidator: async (data) => await z.object({ + body: zConfigUpdateBody.optional(), + path: z.never().optional(), + query: zConfigUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zConfigUpdateResponse.parseAsync(data), + url: '/config', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'configUpdate', url: '/config' }); + +/** + * List tool IDs + * + * Get a list of all available tool IDs, including both built-in tools and dynamically registered tools. + */ +export const toolIds = Object.assign(function toolIds2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zToolIdsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zToolIdsResponse.parseAsync(data), + url: '/experimental/tool/ids', + ...options, + ...params + }); +}, { id: 'toolIds', url: '/experimental/tool/ids' }); + +/** + * List tools + * + * Get a list of available tools with their JSON schema parameters for a specific provider and model combination. + */ +export const toolList = Object.assign(function toolList2(parameters: { + directory?: string; + provider: string; + model: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'query', key: 'provider' }, + { in: 'query', key: 'model' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zToolListQuery + }).parseAsync(data), + responseValidator: async (data) => await zToolListResponse.parseAsync(data), + url: '/experimental/tool', + ...options, + ...params + }); +}, { id: 'toolList', url: '/experimental/tool' }); + +/** + * Dispose instance + * + * Clean up and dispose the current OpenCode instance, releasing all resources. + */ +export const instanceDispose = Object.assign(function instanceDispose2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zInstanceDisposeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zInstanceDisposeResponse.parseAsync(data), + url: '/instance/dispose', + ...options, + ...params + }); +}, { id: 'instanceDispose', url: '/instance/dispose' }); + +/** + * Get paths + * + * Retrieve the current working directory and related path information for the OpenCode instance. + */ +export const pathGet = Object.assign(function pathGet2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zPathGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPathGetResponse.parseAsync(data), + url: '/path', + ...options, + ...params + }); +}, { id: 'pathGet', url: '/path' }); + +/** + * Get VCS info + * + * Retrieve version control system (VCS) information for the current project, such as git branch. + */ +export const vcsGet = Object.assign(function vcsGet2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zVcsGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zVcsGetResponse.parseAsync(data), + url: '/vcs', + ...options, + ...params + }); +}, { id: 'vcsGet', url: '/vcs' }); + +/** + * List sessions + * + * Get a list of all OpenCode sessions, sorted by most recently updated. + */ +export const sessionList = Object.assign(function sessionList2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zSessionListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionListResponse.parseAsync(data), + url: '/session', + ...options, + ...params + }); +}, { id: 'sessionList', url: '/session' }); + +/** + * Create session + * + * Create a new OpenCode session for interacting with AI assistants and managing conversations. + */ +export const sessionCreate = Object.assign(function sessionCreate2(parameters?: { + directory?: string; + parentID?: string; + title?: string; + permission?: PermissionRuleset; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'body', key: 'parentID' }, + { in: 'body', key: 'title' }, + { in: 'body', key: 'permission' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionCreateBody.optional(), + path: z.never().optional(), + query: zSessionCreateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionCreateResponse.parseAsync(data), + url: '/session', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'sessionCreate', url: '/session' }); + +/** + * Get session status + * + * Retrieve the current status of all sessions, including active, idle, and completed states. + */ +export const sessionStatus = Object.assign(function sessionStatus2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zSessionStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionStatusResponse.parseAsync(data), + url: '/session/status', + ...options, + ...params + }); +}, { id: 'sessionStatus', url: '/session/status' }); + +/** + * Delete session + * + * Delete a session and permanently remove all associated data, including messages and history. + */ +export const sessionDelete = Object.assign(function sessionDelete2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionDeletePath, + query: zSessionDeleteQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionDeleteResponse.parseAsync(data), + url: '/session/{sessionID}', + ...options, + ...params + }); +}, { id: 'sessionDelete', url: '/session/{sessionID}' }); + +/** + * Get session + * + * Retrieve detailed information about a specific OpenCode session. + */ +export const sessionGet = Object.assign(function sessionGet2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionGetPath, + query: zSessionGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionGetResponse.parseAsync(data), + url: '/session/{sessionID}', + ...options, + ...params + }); +}, { + id: 'sessionGet', + tags: ['Session'], + url: '/session/{sessionID}' +}); + +/** + * Update session + * + * Update properties of an existing session, such as title or other metadata. + */ +export const sessionUpdate = Object.assign(function sessionUpdate2(parameters: { + sessionID: string; + directory?: string; + title?: string; + time?: { + archived?: number; + }; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'title' }, + { in: 'body', key: 'time' } + ] }]); + return (options?.client ?? client).patch({ + requestValidator: async (data) => await z.object({ + body: zSessionUpdateBody.optional(), + path: zSessionUpdatePath, + query: zSessionUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionUpdateResponse.parseAsync(data), + url: '/session/{sessionID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'sessionUpdate', url: '/session/{sessionID}' }); + +/** + * Get session children + * + * Retrieve all child sessions that were forked from the specified parent session. + */ +export const sessionChildren = Object.assign(function sessionChildren2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionChildrenPath, + query: zSessionChildrenQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionChildrenResponse.parseAsync(data), + url: '/session/{sessionID}/children', + ...options, + ...params + }); +}, { + id: 'sessionChildren', + tags: ['Session'], + url: '/session/{sessionID}/children' +}); + +/** + * Get session todos + * + * Retrieve the todo list associated with a specific session, showing tasks and action items. + */ +export const sessionTodo = Object.assign(function sessionTodo2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionTodoPath, + query: zSessionTodoQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionTodoResponse.parseAsync(data), + url: '/session/{sessionID}/todo', + ...options, + ...params + }); +}, { id: 'sessionTodo', url: '/session/{sessionID}/todo' }); + +/** + * Initialize session + * + * Analyze the current application and create an AGENTS.md file with project-specific agent configurations. + */ +export const sessionInit = Object.assign(function sessionInit2(parameters: { + sessionID: string; + directory?: string; + modelID: string; + providerID: string; + messageID: string; +}, options?: Options) { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionInitBody.optional(), + path: zSessionInitPath, + query: zSessionInitQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionInitResponse.parseAsync(data), + url: '/session/{sessionID}/init', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'sessionInit', url: '/session/{sessionID}/init' }); + +/** + * Fork session + * + * Create a new session by forking an existing session at a specific message point. + */ +export const sessionFork = Object.assign(function sessionFork2(parameters: { + sessionID: string; + directory?: string; + messageID?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'messageID' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionForkBody.optional(), + path: zSessionForkPath, + query: zSessionForkQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionForkResponse.parseAsync(data), + url: '/session/{sessionID}/fork', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'sessionFork', url: '/session/{sessionID}/fork' }); + +/** + * Abort session + * + * Abort an active session and stop any ongoing AI processing or command execution. + */ +export const sessionAbort = Object.assign(function sessionAbort2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionAbortPath, + query: zSessionAbortQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionAbortResponse.parseAsync(data), + url: '/session/{sessionID}/abort', + ...options, + ...params + }); +}, { id: 'sessionAbort', url: '/session/{sessionID}/abort' }); + +/** + * Unshare session + * + * Remove the shareable link for a session, making it private again. + */ +export const sessionUnshare = Object.assign(function sessionUnshare2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionUnsharePath, + query: zSessionUnshareQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionUnshareResponse.parseAsync(data), + url: '/session/{sessionID}/share', + ...options, + ...params + }); +}, { id: 'sessionUnshare', url: '/session/{sessionID}/share' }); + +/** + * Share session + * + * Create a shareable link for a session, allowing others to view the conversation. + */ +export const sessionShare = Object.assign(function sessionShare2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionSharePath, + query: zSessionShareQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionShareResponse.parseAsync(data), + url: '/session/{sessionID}/share', + ...options, + ...params + }); +}, { id: 'sessionShare', url: '/session/{sessionID}/share' }); + +/** + * Get session diff + * + * Get all file changes (diffs) made during this session. + */ +export const sessionDiff = Object.assign(function sessionDiff2(parameters: { + sessionID: string; + directory?: string; + messageID?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'query', key: 'messageID' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionDiffPath, + query: zSessionDiffQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionDiffResponse.parseAsync(data), + url: '/session/{sessionID}/diff', + ...options, + ...params + }); +}, { id: 'sessionDiff', url: '/session/{sessionID}/diff' }); + +/** + * Summarize session + * + * Generate a concise summary of the session using AI compaction to preserve key information. + */ +export const sessionSummarize = Object.assign(function sessionSummarize2(parameters: { + sessionID: string; + directory?: string; + providerID: string; + modelID: string; + auto?: boolean; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'providerID' }, + { in: 'body', key: 'modelID' }, + { in: 'body', key: 'auto' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionSummarizeBody.optional(), + path: zSessionSummarizePath, + query: zSessionSummarizeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionSummarizeResponse.parseAsync(data), + url: '/session/{sessionID}/summarize', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'sessionSummarize', url: '/session/{sessionID}/summarize' }); + +/** + * Get session messages + * + * Retrieve all messages in a session, including user prompts and AI responses. + */ +export const sessionMessages = Object.assign(function sessionMessages2(parameters: { + sessionID: string; + directory?: string; + limit?: number; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'query', key: 'limit' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionMessagesPath, + query: zSessionMessagesQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionMessagesResponse.parseAsync(data), + url: '/session/{sessionID}/message', + ...options, + ...params + }); +}, { id: 'sessionMessages', url: '/session/{sessionID}/message' }); + +/** + * Send message + * + * Create and send a new message to a session, streaming the AI response. + */ +export const sessionPrompt = Object.assign(function sessionPrompt2(parameters: { + sessionID: string; + directory?: string; + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; +}, options?: Options) { + 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: 'tools' }, + { in: 'body', key: 'system' }, + { in: 'body', key: 'variant' }, + { in: 'body', key: 'parts' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionPromptBody.optional(), + path: zSessionPromptPath, + query: zSessionPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionPromptResponse.parseAsync(data), + url: '/session/{sessionID}/message', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'sessionPrompt', url: '/session/{sessionID}/message' }); + +/** + * Get message + * + * Retrieve a specific message from a session by its message ID. + */ +export const sessionMessage = Object.assign(function sessionMessage2(parameters: { + sessionID: string; + messageID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'messageID' }, + { in: 'query', key: 'directory' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionMessagePath, + query: zSessionMessageQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionMessageResponse.parseAsync(data), + url: '/session/{sessionID}/message/{messageID}', + ...options, + ...params + }); +}, { id: 'sessionMessage', url: '/session/{sessionID}/message/{messageID}' }); + +/** + * Delete a part from a message + */ +export const partDelete = Object.assign(function partDelete2(parameters: { + sessionID: string; + messageID: string; + partID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'messageID' }, + { in: 'path', key: 'partID' }, + { in: 'query', key: 'directory' } + ] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPartDeletePath, + query: zPartDeleteQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPartDeleteResponse.parseAsync(data), + url: '/session/{sessionID}/message/{messageID}/part/{partID}', + ...options, + ...params + }); +}, { id: 'partDelete', url: '/session/{sessionID}/message/{messageID}/part/{partID}' }); + +/** + * Update a part in a message + */ +export const partUpdate = Object.assign(function partUpdate2(parameters: { + sessionID: string; + messageID: string; + partID: string; + directory?: string; + part?: Part; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'messageID' }, + { in: 'path', key: 'partID' }, + { in: 'query', key: 'directory' }, + { key: 'part', map: 'body' } + ] }]); + return (options?.client ?? client).patch({ + requestValidator: async (data) => await z.object({ + body: zPartUpdateBody.optional(), + path: zPartUpdatePath, + query: zPartUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPartUpdateResponse.parseAsync(data), + url: '/session/{sessionID}/message/{messageID}/part/{partID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'partUpdate', url: '/session/{sessionID}/message/{messageID}/part/{partID}' }); + +/** + * Send async message + * + * Create and send a new message to a session asynchronously, starting the session if needed and returning immediately. + */ +export const sessionPromptAsync = Object.assign(function sessionPromptAsync2(parameters: { + sessionID: string; + directory?: string; + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; +}, options?: Options) { + 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: 'tools' }, + { in: 'body', key: 'system' }, + { in: 'body', key: 'variant' }, + { in: 'body', key: 'parts' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionPromptAsyncBody.optional(), + path: zSessionPromptAsyncPath, + query: zSessionPromptAsyncQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionPromptAsyncResponse.parseAsync(data), + url: '/session/{sessionID}/prompt_async', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'sessionPromptAsync', url: '/session/{sessionID}/prompt_async' }); + +/** + * Send command + * + * Send a new command to a session for execution by the AI assistant. + */ +export const sessionCommand = Object.assign(function sessionCommand2(parameters: { + sessionID: string; + directory?: string; + messageID?: string; + agent?: string; + model?: string; + arguments: string; + command: string; + variant?: string; +}, options?: Options) { + 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' }, + { in: 'body', key: 'variant' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionCommandBody.optional(), + path: zSessionCommandPath, + query: zSessionCommandQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionCommandResponse.parseAsync(data), + url: '/session/{sessionID}/command', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'sessionCommand', url: '/session/{sessionID}/command' }); + +/** + * Run shell command + * + * Execute a shell command within the session context and return the AI's response. + */ +export const sessionShell = Object.assign(function sessionShell2(parameters: { + sessionID: string; + directory?: string; + agent: string; + model?: { + providerID: string; + modelID: string; + }; + command: string; +}, options?: Options) { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionShellBody.optional(), + path: zSessionShellPath, + query: zSessionShellQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionShellResponse.parseAsync(data), + url: '/session/{sessionID}/shell', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'sessionShell', url: '/session/{sessionID}/shell' }); + +/** + * Revert message + * + * Revert a specific message in a session, undoing its effects and restoring the previous state. + */ +export const sessionRevert = Object.assign(function sessionRevert2(parameters: { + sessionID: string; + directory?: string; + messageID: string; + partID?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'messageID' }, + { in: 'body', key: 'partID' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionRevertBody.optional(), + path: zSessionRevertPath, + query: zSessionRevertQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionRevertResponse.parseAsync(data), + url: '/session/{sessionID}/revert', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'sessionRevert', url: '/session/{sessionID}/revert' }); + +/** + * Restore reverted messages + * + * Restore all previously reverted messages in a session. + */ +export const sessionUnrevert = Object.assign(function sessionUnrevert2(parameters: { + sessionID: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionUnrevertPath, + query: zSessionUnrevertQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionUnrevertResponse.parseAsync(data), + url: '/session/{sessionID}/unrevert', + ...options, + ...params + }); +}, { id: 'sessionUnrevert', url: '/session/{sessionID}/unrevert' }); + +/** + * Respond to permission + * + * Approve or deny a permission request from the AI assistant. + * + * @deprecated + */ +export const permissionRespond = Object.assign(function permissionRespond2(parameters: { + sessionID: string; + permissionID: string; + directory?: string; + response: 'once' | 'always' | 'reject'; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'permissionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'response' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zPermissionRespondBody.optional(), + path: zPermissionRespondPath, + query: zPermissionRespondQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPermissionRespondResponse.parseAsync(data), + url: '/session/{sessionID}/permissions/{permissionID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'permissionRespond', url: '/session/{sessionID}/permissions/{permissionID}' }); + +/** + * Respond to permission request + * + * Approve or deny a permission request from the AI assistant. + */ +export const permissionReply = Object.assign(function permissionReply2(parameters: { + requestID: string; + directory?: string; + reply: 'once' | 'always' | 'reject'; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'requestID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'reply' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zPermissionReplyBody.optional(), + path: zPermissionReplyPath, + query: zPermissionReplyQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPermissionReplyResponse.parseAsync(data), + url: '/permission/{requestID}/reply', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'permissionReply', url: '/permission/{requestID}/reply' }); + +/** + * List pending permissions + * + * Get all pending permission requests across all sessions. + */ +export const permissionList = Object.assign(function permissionList2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zPermissionListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPermissionListResponse.parseAsync(data), + url: '/permission', + ...options, + ...params + }); +}, { id: 'permissionList', url: '/permission' }); + +/** + * List commands + * + * Get a list of all available commands in the OpenCode system. + */ +export const commandList = Object.assign(function commandList2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zCommandListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zCommandListResponse.parseAsync(data), + url: '/command', + ...options, + ...params + }); +}, { id: 'commandList', url: '/command' }); + +/** + * List config providers + * + * Get a list of all configured AI providers and their default models. + */ +export const configProviders = Object.assign(function configProviders2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zConfigProvidersQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zConfigProvidersResponse.parseAsync(data), + url: '/config/providers', + ...options, + ...params + }); +}, { id: 'configProviders', url: '/config/providers' }); + +/** + * List providers + * + * Get a list of all available AI providers, including both available and connected ones. + */ +export const providerList = Object.assign(function providerList2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProviderListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderListResponse.parseAsync(data), + url: '/provider', + ...options, + ...params + }); +}, { id: 'providerList', url: '/provider' }); + +/** + * Get provider auth methods + * + * Retrieve available authentication methods for all AI providers. + */ +export const providerAuth = Object.assign(function providerAuth2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProviderAuthQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderAuthResponse.parseAsync(data), + url: '/provider/auth', + ...options, + ...params + }); +}, { id: 'providerAuth', url: '/provider/auth' }); + +/** + * OAuth authorize + * + * Initiate OAuth authorization for a specific AI provider to get an authorization URL. + */ +export const providerOauthAuthorize = Object.assign(function providerOauthAuthorize2(parameters: { + providerID: string; + directory?: string; + method: number; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'providerID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'method' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zProviderOauthAuthorizeBody.optional(), + path: zProviderOauthAuthorizePath, + query: zProviderOauthAuthorizeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderOauthAuthorizeResponse.parseAsync(data), + url: '/provider/{providerID}/oauth/authorize', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'providerOauthAuthorize', url: '/provider/{providerID}/oauth/authorize' }); + +/** + * OAuth callback + * + * Handle the OAuth callback from a provider after user authorization. + */ +export const providerOauthCallback = Object.assign(function providerOauthCallback2(parameters: { + providerID: string; + directory?: string; + method: number; + code?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'providerID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'method' }, + { in: 'body', key: 'code' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zProviderOauthCallbackBody.optional(), + path: zProviderOauthCallbackPath, + query: zProviderOauthCallbackQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderOauthCallbackResponse.parseAsync(data), + url: '/provider/{providerID}/oauth/callback', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'providerOauthCallback', url: '/provider/{providerID}/oauth/callback' }); + +/** + * Find text + * + * Search for text patterns across files in the project using ripgrep. + */ +export const findText = Object.assign(function findText2(parameters: { + directory?: string; + pattern: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'pattern' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFindTextQuery + }).parseAsync(data), + responseValidator: async (data) => await zFindTextResponse.parseAsync(data), + url: '/find', + ...options, + ...params + }); +}, { id: 'findText', url: '/find' }); + +/** + * Find files + * + * Search for files or directories by name or pattern in the project directory. + */ +export const findFiles = Object.assign(function findFiles2(parameters: { + directory?: string; + query: string; + dirs?: 'true' | 'false'; + type?: 'file' | 'directory'; + limit?: number; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'query', key: 'query' }, + { in: 'query', key: 'dirs' }, + { in: 'query', key: 'type' }, + { in: 'query', key: 'limit' } + ] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFindFilesQuery + }).parseAsync(data), + responseValidator: async (data) => await zFindFilesResponse.parseAsync(data), + url: '/find/file', + ...options, + ...params + }); +}, { id: 'findFiles', url: '/find/file' }); + +/** + * Find symbols + * + * Search for workspace symbols like functions, classes, and variables using LSP. + */ +export const findSymbols = Object.assign(function findSymbols2(parameters: { + directory?: string; + query: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'query' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFindSymbolsQuery + }).parseAsync(data), + responseValidator: async (data) => await zFindSymbolsResponse.parseAsync(data), + url: '/find/symbol', + ...options, + ...params + }); +}, { id: 'findSymbols', url: '/find/symbol' }); + +/** + * List files + * + * List files and directories in a specified path. + */ +export const fileList = Object.assign(function fileList2(parameters: { + directory?: string; + path: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'path' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFileListQuery + }).parseAsync(data), + responseValidator: async (data) => await zFileListResponse.parseAsync(data), + url: '/file', + ...options, + ...params + }); +}, { id: 'fileList', url: '/file' }); + +/** + * Read file + * + * Read the content of a specified file. + */ +export const fileRead = Object.assign(function fileRead2(parameters: { + directory?: string; + path: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'path' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFileReadQuery + }).parseAsync(data), + responseValidator: async (data) => await zFileReadResponse.parseAsync(data), + url: '/file/content', + ...options, + ...params + }); +}, { id: 'fileRead', url: '/file/content' }); + +/** + * Get file status + * + * Get the git status of all files in the project. + */ +export const fileStatus = Object.assign(function fileStatus2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFileStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zFileStatusResponse.parseAsync(data), + url: '/file/status', + ...options, + ...params + }); +}, { id: 'fileStatus', url: '/file/status' }); + +/** + * Write log + * + * Write a log entry to the server logs with specified level and metadata. + */ +export const appLog = Object.assign(function appLog2(parameters: { + directory?: string; + service: string; + level: 'debug' | 'info' | 'error' | 'warn'; + message: string; + extra?: { + [key: string]: unknown; + }; +}, options?: Options) { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zAppLogBody.optional(), + path: z.never().optional(), + query: zAppLogQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zAppLogResponse.parseAsync(data), + url: '/log', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'appLog', url: '/log' }); + +/** + * List agents + * + * Get a list of all available AI agents in the OpenCode system. + */ +export const appAgents = Object.assign(function appAgents2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zAppAgentsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zAppAgentsResponse.parseAsync(data), + url: '/agent', + ...options, + ...params + }); +}, { id: 'appAgents', url: '/agent' }); + +/** + * Get MCP status + * + * Get the status of all Model Context Protocol (MCP) servers. + */ +export const mcpStatus = Object.assign(function mcpStatus2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zMcpStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpStatusResponse.parseAsync(data), + url: '/mcp', + ...options, + ...params + }); +}, { id: 'mcpStatus', url: '/mcp' }); + +/** + * Add MCP server + * + * Dynamically add a new Model Context Protocol (MCP) server to the system. + */ +export const mcpAdd = Object.assign(function mcpAdd2(parameters: { + directory?: string; + name: string; + config: McpLocalConfig | McpRemoteConfig; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'body', key: 'name' }, + { in: 'body', key: 'config' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zMcpAddBody.optional(), + path: z.never().optional(), + query: zMcpAddQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAddResponse.parseAsync(data), + url: '/mcp', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'mcpAdd', url: '/mcp' }); + +/** + * Remove MCP OAuth + * + * Remove OAuth credentials for an MCP server + */ +export const mcpAuthRemove = Object.assign(function mcpAuthRemove2(parameters: { + name: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpAuthRemovePath, + query: zMcpAuthRemoveQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthRemoveResponse.parseAsync(data), + url: '/mcp/{name}/auth', + ...options, + ...params + }); +}, { id: 'mcpAuthRemove', url: '/mcp/{name}/auth' }); + +/** + * Start MCP OAuth + * + * Start OAuth authentication flow for a Model Context Protocol (MCP) server. + */ +export const mcpAuthStart = Object.assign(function mcpAuthStart2(parameters: { + name: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpAuthStartPath, + query: zMcpAuthStartQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthStartResponse.parseAsync(data), + url: '/mcp/{name}/auth', + ...options, + ...params + }); +}, { id: 'mcpAuthStart', url: '/mcp/{name}/auth' }); + +/** + * Complete MCP OAuth + * + * Complete OAuth authentication for a Model Context Protocol (MCP) server using the authorization code. + */ +export const mcpAuthCallback = Object.assign(function mcpAuthCallback2(parameters: { + name: string; + directory?: string; + code: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'name' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'code' } + ] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zMcpAuthCallbackBody.optional(), + path: zMcpAuthCallbackPath, + query: zMcpAuthCallbackQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthCallbackResponse.parseAsync(data), + url: '/mcp/{name}/auth/callback', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'mcpAuthCallback', url: '/mcp/{name}/auth/callback' }); + +/** + * Authenticate MCP OAuth + * + * Start OAuth flow and wait for callback (opens browser) + */ +export const mcpAuthAuthenticate = Object.assign(function mcpAuthAuthenticate2(parameters: { + name: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpAuthAuthenticatePath, + query: zMcpAuthAuthenticateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthAuthenticateResponse.parseAsync(data), + url: '/mcp/{name}/auth/authenticate', + ...options, + ...params + }); +}, { id: 'mcpAuthAuthenticate', url: '/mcp/{name}/auth/authenticate' }); + +/** + * Connect an MCP server + */ +export const mcpConnect = Object.assign(function mcpConnect2(parameters: { + name: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpConnectPath, + query: zMcpConnectQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpConnectResponse.parseAsync(data), + url: '/mcp/{name}/connect', + ...options, + ...params + }); +}, { id: 'mcpConnect', url: '/mcp/{name}/connect' }); + +/** + * Disconnect an MCP server + */ +export const mcpDisconnect = Object.assign(function mcpDisconnect2(parameters: { + name: string; + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpDisconnectPath, + query: zMcpDisconnectQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpDisconnectResponse.parseAsync(data), + url: '/mcp/{name}/disconnect', + ...options, + ...params + }); +}, { id: 'mcpDisconnect', url: '/mcp/{name}/disconnect' }); + +/** + * Get LSP status + * + * Get LSP server status + */ +export const lspStatus = Object.assign(function lspStatus2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zLspStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zLspStatusResponse.parseAsync(data), + url: '/lsp', + ...options, + ...params + }); +}, { id: 'lspStatus', url: '/lsp' }); + +/** + * Get formatter status + * + * Get formatter status + */ +export const formatterStatus = Object.assign(function formatterStatus2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFormatterStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zFormatterStatusResponse.parseAsync(data), + url: '/formatter', + ...options, + ...params + }); +}, { id: 'formatterStatus', url: '/formatter' }); + +/** + * Append TUI prompt + * + * Append prompt to the TUI + */ +export const tuiAppendPrompt = Object.assign(function tuiAppendPrompt2(parameters: { + directory?: string; + text: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'body', key: 'text' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiAppendPromptBody.optional(), + path: z.never().optional(), + query: zTuiAppendPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiAppendPromptResponse.parseAsync(data), + url: '/tui/append-prompt', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'tuiAppendPrompt', url: '/tui/append-prompt' }); + +/** + * Open help dialog + * + * Open the help dialog in the TUI to display user assistance information. + */ +export const tuiOpenHelp = Object.assign(function tuiOpenHelp2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenHelpQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenHelpResponse.parseAsync(data), + url: '/tui/open-help', + ...options, + ...params + }); +}, { id: 'tuiOpenHelp', url: '/tui/open-help' }); + +/** + * Open sessions dialog + * + * Open the session dialog + */ +export const tuiOpenSessions = Object.assign(function tuiOpenSessions2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenSessionsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenSessionsResponse.parseAsync(data), + url: '/tui/open-sessions', + ...options, + ...params + }); +}, { id: 'tuiOpenSessions', url: '/tui/open-sessions' }); + +/** + * Open themes dialog + * + * Open the theme dialog + */ +export const tuiOpenThemes = Object.assign(function tuiOpenThemes2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenThemesQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenThemesResponse.parseAsync(data), + url: '/tui/open-themes', + ...options, + ...params + }); +}, { id: 'tuiOpenThemes', url: '/tui/open-themes' }); + +/** + * Open models dialog + * + * Open the model dialog + */ +export const tuiOpenModels = Object.assign(function tuiOpenModels2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenModelsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenModelsResponse.parseAsync(data), + url: '/tui/open-models', + ...options, + ...params + }); +}, { id: 'tuiOpenModels', url: '/tui/open-models' }); + +/** + * Submit TUI prompt + * + * Submit the prompt + */ +export const tuiSubmitPrompt = Object.assign(function tuiSubmitPrompt2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiSubmitPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiSubmitPromptResponse.parseAsync(data), + url: '/tui/submit-prompt', + ...options, + ...params + }); +}, { id: 'tuiSubmitPrompt', url: '/tui/submit-prompt' }); + +/** + * Clear TUI prompt + * + * Clear the prompt + */ +export const tuiClearPrompt = Object.assign(function tuiClearPrompt2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiClearPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiClearPromptResponse.parseAsync(data), + url: '/tui/clear-prompt', + ...options, + ...params + }); +}, { id: 'tuiClearPrompt', url: '/tui/clear-prompt' }); + +/** + * Execute TUI command + * + * Execute a TUI command (e.g. agent_cycle) + */ +export const tuiExecuteCommand = Object.assign(function tuiExecuteCommand2(parameters: { + directory?: string; + command: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'body', key: 'command' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiExecuteCommandBody.optional(), + path: z.never().optional(), + query: zTuiExecuteCommandQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiExecuteCommandResponse.parseAsync(data), + url: '/tui/execute-command', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'tuiExecuteCommand', url: '/tui/execute-command' }); + +/** + * Show TUI toast + * + * Show a toast notification in the TUI + */ +export const tuiShowToast = Object.assign(function tuiShowToast2(parameters: { + directory?: string; + title?: string; + message: string; + variant: 'info' | 'success' | 'warning' | 'error'; + duration?: number; +}, options?: Options) { + 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 ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiShowToastBody.optional(), + path: z.never().optional(), + query: zTuiShowToastQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiShowToastResponse.parseAsync(data), + url: '/tui/show-toast', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'tuiShowToast', url: '/tui/show-toast' }); + +/** + * Publish TUI event + * + * Publish a TUI event + */ +export const tuiPublish = Object.assign(function tuiPublish2(parameters?: { + directory?: string; + body?: EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { key: 'body', map: 'body' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiPublishBody.optional(), + path: z.never().optional(), + query: zTuiPublishQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiPublishResponse.parseAsync(data), + url: '/tui/publish', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'tuiPublish', url: '/tui/publish' }); + +/** + * Get next TUI request + * + * Retrieve the next TUI (Terminal User Interface) request from the queue for processing. + */ +export const tuiControlNext = Object.assign(function tuiControlNext2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiControlNextQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiControlNextResponse.parseAsync(data), + url: '/tui/control/next', + ...options, + ...params + }); +}, { id: 'tuiControlNext', url: '/tui/control/next' }); + +/** + * Submit TUI response + * + * Submit a response to the TUI request queue to complete a pending request. + */ +export const tuiControlResponse = Object.assign(function tuiControlResponse2(parameters?: { + directory?: string; + body?: unknown; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { key: 'body', map: 'body' }] }]); + return (options?.client ?? client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiControlResponseBody.optional(), + path: z.never().optional(), + query: zTuiControlResponseQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiControlResponseResponse.parseAsync(data), + url: '/tui/control/response', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'tuiControlResponse', url: '/tui/control/response' }); + +/** + * Set auth credentials + * + * Set authentication credentials + */ +export const authSet = Object.assign(function authSet2(parameters: { + providerID: string; + directory?: string; + auth?: Auth; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'providerID' }, + { in: 'query', key: 'directory' }, + { key: 'auth', map: 'body' } + ] }]); + return (options?.client ?? client).put({ + requestValidator: async (data) => await z.object({ + body: zAuthSetBody.optional(), + path: zAuthSetPath, + query: zAuthSetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zAuthSetResponse.parseAsync(data), + url: '/auth/{providerID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); +}, { id: 'authSet', url: '/auth/{providerID}' }); + +/** + * Subscribe to events + * + * Get events + */ +export const eventSubscribe = Object.assign(function eventSubscribe2(parameters?: { + directory?: string; +}, options?: Options) { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? client).sse.get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zEventSubscribeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zEventSubscribeResponse.parseAsync(data), + url: '/event', + ...options, + ...params + }); +}, { id: 'eventSubscribe', url: '/event' }); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/types.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/types.gen.ts new file mode 100644 index 0000000000..ccae410e61 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/types.gen.ts @@ -0,0 +1,4322 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type ClientOptions = { + baseUrl: `${string}://${string}` | (string & {}); +}; + +export type EventInstallationUpdated = { + type: 'installation.updated'; + properties: { + version: string; + }; +}; + +export type EventInstallationUpdateAvailable = { + type: 'installation.update-available'; + properties: { + version: string; + }; +}; + +export type Project = { + id: string; + worktree: string; + vcs?: 'git'; + name?: string; + icon?: { + url?: string; + color?: string; + }; + time: { + created: number; + updated: number; + initialized?: number; + }; +}; + +export type EventProjectUpdated = { + type: 'project.updated'; + properties: Project; +}; + +export type EventServerInstanceDisposed = { + type: 'server.instance.disposed'; + properties: { + directory: 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; + }; + agent: string; + model: { + providerID: string; + modelID: string; + }; + system?: string; + tools?: { + [key: string]: boolean; + }; + variant?: string; +}; + +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; + metadata?: { + [key: string]: 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; + agent: 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; +}; + +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; +}; + +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; + command?: 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 PermissionRequest = { + id: string; + sessionID: string; + permission: string; + patterns: Array; + metadata: { + [key: string]: unknown; + }; + always: Array; + tool?: { + messageID: string; + callID: string; + }; +}; + +export type EventPermissionAsked = { + type: 'permission.asked'; + properties: PermissionRequest; +}; + +export type EventPermissionReplied = { + type: 'permission.replied'; + properties: { + sessionID: string; + requestID: string; + reply: 'once' | 'always' | 'reject'; + }; +}; + +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; + }; +}; + +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 EventMcpToolsChanged = { + type: 'mcp.tools.changed'; + properties: { + server: string; + }; +}; + +export type EventCommandExecuted = { + type: 'command.executed'; + properties: { + name: string; + sessionID: string; + arguments: string; + messageID: string; + }; +}; + +export type PermissionAction = 'allow' | 'deny' | 'ask'; + +export type PermissionRule = { + permission: string; + pattern: string; + action: PermissionAction; +}; + +export type PermissionRuleset = Array; + +export type Session = { + id: string; + projectID: string; + directory: string; + parentID?: string; + summary?: { + additions: number; + deletions: number; + files: number; + diffs?: Array; + }; + share?: { + url: string; + }; + title: string; + version: string; + time: { + created: number; + updated: number; + compacting?: number; + archived?: number; + }; + permission?: PermissionRuleset; + 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; + }; +}; + +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 Pty = { + id: string; + title: string; + command: string; + args: Array; + 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 EventGlobalDisposed = { + type: 'global.disposed'; + properties: { + [key: string]: unknown; + }; +}; + +export type Event = EventInstallationUpdated | EventInstallationUpdateAvailable | EventProjectUpdated | EventServerInstanceDisposed | EventLspClientDiagnostics | EventLspUpdated | EventMessageUpdated | EventMessageRemoved | EventMessagePartUpdated | EventMessagePartRemoved | EventPermissionAsked | EventPermissionReplied | EventSessionStatus | EventSessionIdle | EventSessionCompacted | EventFileEdited | EventTodoUpdated | EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow | EventMcpToolsChanged | EventCommandExecuted | EventSessionCreated | EventSessionUpdated | EventSessionDeleted | EventSessionDiff | EventSessionError | EventFileWatcherUpdated | EventVcsBranchUpdated | EventPtyCreated | EventPtyUpdated | EventPtyExited | EventPtyDeleted | EventServerConnected | EventGlobalDisposed; + +export type GlobalEvent = { + directory: string; + payload: Event; +}; + +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; + /** + * Fork session from message + */ + session_fork?: string; + /** + * Rename session + */ + session_rename?: 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 next message + */ + messages_next?: string; + /** + * Navigate to previous message + */ + messages_previous?: 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; + /** + * Next favorite model + */ + model_cycle_favorite?: string; + /** + * Previous favorite model + */ + model_cycle_favorite_reverse?: string; + /** + * List available commands + */ + command_list?: string; + /** + * List agents + */ + agent_list?: string; + /** + * Next agent + */ + agent_cycle?: string; + /** + * Previous agent + */ + agent_cycle_reverse?: string; + /** + * Cycle model variants + */ + variant_cycle?: string; + /** + * Clear input field + */ + input_clear?: string; + /** + * Paste from clipboard + */ + input_paste?: string; + /** + * Submit input + */ + input_submit?: string; + /** + * Insert newline in input + */ + input_newline?: string; + /** + * Move cursor left in input + */ + input_move_left?: string; + /** + * Move cursor right in input + */ + input_move_right?: string; + /** + * Move cursor up in input + */ + input_move_up?: string; + /** + * Move cursor down in input + */ + input_move_down?: string; + /** + * Select left in input + */ + input_select_left?: string; + /** + * Select right in input + */ + input_select_right?: string; + /** + * Select up in input + */ + input_select_up?: string; + /** + * Select down in input + */ + input_select_down?: string; + /** + * Move to start of line in input + */ + input_line_home?: string; + /** + * Move to end of line in input + */ + input_line_end?: string; + /** + * Select to start of line in input + */ + input_select_line_home?: string; + /** + * Select to end of line in input + */ + input_select_line_end?: string; + /** + * Move to start of visual line in input + */ + input_visual_line_home?: string; + /** + * Move to end of visual line in input + */ + input_visual_line_end?: string; + /** + * Select to start of visual line in input + */ + input_select_visual_line_home?: string; + /** + * Select to end of visual line in input + */ + input_select_visual_line_end?: string; + /** + * Move to start of buffer in input + */ + input_buffer_home?: string; + /** + * Move to end of buffer in input + */ + input_buffer_end?: string; + /** + * Select to start of buffer in input + */ + input_select_buffer_home?: string; + /** + * Select to end of buffer in input + */ + input_select_buffer_end?: string; + /** + * Delete line in input + */ + input_delete_line?: string; + /** + * Delete to end of line in input + */ + input_delete_to_line_end?: string; + /** + * Delete to start of line in input + */ + input_delete_to_line_start?: string; + /** + * Backspace in input + */ + input_backspace?: string; + /** + * Delete character in input + */ + input_delete?: string; + /** + * Undo in input + */ + input_undo?: string; + /** + * Redo in input + */ + input_redo?: string; + /** + * Move word forward in input + */ + input_word_forward?: string; + /** + * Move word backward in input + */ + input_word_backward?: string; + /** + * Select word forward in input + */ + input_select_word_forward?: string; + /** + * Select word backward in input + */ + input_select_word_backward?: string; + /** + * Delete word forward in input + */ + input_delete_word_forward?: string; + /** + * Delete word backward in input + */ + input_delete_word_backward?: 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; + /** + * Go to parent session + */ + session_parent?: string; + /** + * Suspend terminal + */ + terminal_suspend?: string; + /** + * Toggle terminal title + */ + terminal_title_toggle?: string; + /** + * Toggle tips on home screen + */ + tips_toggle?: string; +}; + +/** + * Log level + */ +export type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR'; + +/** + * Server configuration for opencode serve and web commands + */ +export type ServerConfig = { + /** + * Port to listen on + */ + port?: number; + /** + * Hostname to listen on + */ + hostname?: string; + /** + * Enable mDNS service discovery + */ + mdns?: boolean; + /** + * Additional domains to allow for CORS + */ + cors?: Array; +}; + +export type PermissionActionConfig = 'ask' | 'allow' | 'deny'; + +export type PermissionObjectConfig = { + [key: string]: PermissionActionConfig; +}; + +export type PermissionRuleConfig = PermissionActionConfig | PermissionObjectConfig; + +export type PermissionConfig = { + read?: PermissionRuleConfig; + edit?: PermissionRuleConfig; + glob?: PermissionRuleConfig; + grep?: PermissionRuleConfig; + list?: PermissionRuleConfig; + bash?: PermissionRuleConfig; + task?: PermissionRuleConfig; + external_directory?: PermissionRuleConfig; + todowrite?: PermissionActionConfig; + todoread?: PermissionActionConfig; + webfetch?: PermissionActionConfig; + websearch?: PermissionActionConfig; + codesearch?: PermissionActionConfig; + lsp?: PermissionRuleConfig; + doom_loop?: PermissionActionConfig; + [key: string]: PermissionRuleConfig | PermissionActionConfig | undefined; +} | PermissionActionConfig; + +export type AgentConfig = { + model?: string; + temperature?: number; + top_p?: number; + prompt?: string; + /** + * @deprecated Use 'permission' field instead + */ + tools?: { + [key: string]: boolean; + }; + disable?: boolean; + /** + * Description of when to use the agent + */ + description?: string; + mode?: 'subagent' | 'primary' | 'all'; + options?: { + [key: string]: unknown; + }; + /** + * Hex color code for the agent (e.g., #FF5733) + */ + color?: string; + /** + * Maximum number of agentic iterations before forcing text-only response + */ + steps?: number; + /** + * @deprecated Use 'steps' field instead. + */ + maxSteps?: number; + permission?: PermissionConfig; + [key: string]: unknown; +}; + +export type ProviderConfig = { + api?: string; + name?: string; + env?: Array; + id?: string; + npm?: string; + models?: { + [key: string]: { + id?: string; + name?: string; + family?: string; + release_date?: string; + attachment?: boolean; + reasoning?: boolean; + temperature?: boolean; + tool_call?: boolean; + interleaved?: true | { + field: 'reasoning_content' | 'reasoning_details'; + }; + 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; + }; + /** + * Variant-specific configuration + */ + variants?: { + [key: string]: { + /** + * Disable this variant for the model + */ + disabled?: boolean; + [key: string]: unknown; + }; + }; + }; + }; + whitelist?: Array; + blacklist?: Array; + 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; + }; +}; + +export type McpLocalConfig = { + /** + * Type of MCP server connection + */ + type: 'local'; + /** + * Command and arguments to run the MCP server + */ + command: Array; + /** + * Environment variables to set when running the MCP server + */ + environment?: { + [key: string]: string; + }; + /** + * Enable or disable the MCP server on startup + */ + enabled?: boolean; + /** + * 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; + logLevel?: LogLevel; + /** + * 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'; + }; + server?: ServerConfig; + /** + * Command configuration, see https://opencode.ai/docs/commands + */ + command?: { + [key: string]: { + template: string; + description?: string; + agent?: string; + model?: string; + subtask?: boolean; + }; + }; + watcher?: { + ignore?: Array; + }; + plugin?: Array; + 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; + /** + * When set, ONLY these providers will be enabled. All other providers will be ignored + */ + enabled_providers?: Array; + /** + * 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; + /** + * Default agent to use when none is specified. Must be a primary agent. Falls back to 'build' if not set or if the specified agent is invalid. + */ + default_agent?: 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; + title?: AgentConfig; + summary?: AgentConfig; + compaction?: 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; + environment?: { + [key: string]: string; + }; + extensions?: Array; + }; + }; + lsp?: false | { + [key: string]: { + disabled: true; + } | { + command: Array; + extensions?: Array; + disabled?: boolean; + env?: { + [key: string]: string; + }; + initialization?: { + [key: string]: unknown; + }; + }; + }; + /** + * Additional instruction files or patterns to include + */ + instructions?: Array; + layout?: LayoutConfig; + permission?: PermissionConfig; + tools?: { + [key: string]: boolean; + }; + enterprise?: { + /** + * Enterprise URL + */ + url?: string; + }; + compaction?: { + /** + * Enable automatic compaction when context is full (default: true) + */ + auto?: boolean; + /** + * Enable pruning of old tool outputs (default: true) + */ + prune?: boolean; + }; + experimental?: { + hook?: { + file_edited?: { + [key: string]: Array<{ + command: Array; + environment?: { + [key: string]: string; + }; + }>; + }; + session_completed?: Array<{ + command: Array; + 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; + /** + * Continue the agent loop when a tool call is denied + */ + continue_loop_on_deny?: boolean; + /** + * Timeout in milliseconds for model context protocol (MCP) requests + */ + mcp_timeout?: number; + }; +}; + +export type ToolIds = Array; + +export type ToolListItem = { + id: string; + description: string; + parameters: unknown; +}; + +export type ToolList = Array; + +export type Path = { + home: string; + 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; + command?: string; +}; + +export type Command = { + name: string; + description?: string; + agent?: string; + model?: string; + mcp?: boolean; + template: string; + subtask?: boolean; + hints: Array; +}; + +export type Model = { + id: string; + providerID: string; + api: { + id: string; + url: string; + npm: string; + }; + name: string; + family?: 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; + }; + interleaved: boolean | { + field: 'reasoning_content' | 'reasoning_details'; + }; + }; + 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; + }; + release_date: string; + variants?: { + [key: string]: { + [key: string]: unknown; + }; + }; +}; + +export type Provider = { + id: string; + name: string; + source: 'env' | 'config' | 'custom' | 'api'; + env: Array; + 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; + }>; + 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'; + native?: boolean; + hidden?: boolean; + topP?: number; + temperature?: number; + color?: string; + permission: PermissionRuleset; + model?: { + modelID: string; + providerID: string; + }; + prompt?: string; + options: { + [key: string]: unknown; + }; + steps?: 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; + 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 GlobalHealthData = { + body?: never; + path?: never; + query?: never; + url: '/global/health'; +}; + +export type GlobalHealthResponses = { + /** + * Health information + */ + 200: { + healthy: true; + version: string; + }; +}; + +export type GlobalHealthResponse = GlobalHealthResponses[keyof GlobalHealthResponses]; + +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 GlobalDisposeData = { + body?: never; + path?: never; + query?: never; + url: '/global/dispose'; +}; + +export type GlobalDisposeResponses = { + /** + * Global disposed + */ + 200: boolean; +}; + +export type GlobalDisposeResponse = GlobalDisposeResponses[keyof GlobalDisposeResponses]; + +export type ProjectListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/project'; +}; + +export type ProjectListResponses = { + /** + * List of projects + */ + 200: Array; +}; + +export type ProjectListResponse = ProjectListResponses[keyof ProjectListResponses]; + +export type ProjectCurrentData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/project/current'; +}; + +export type ProjectCurrentResponses = { + /** + * Current project information + */ + 200: Project; +}; + +export type ProjectCurrentResponse = ProjectCurrentResponses[keyof ProjectCurrentResponses]; + +export type ProjectUpdateData = { + body?: { + name?: string; + icon?: { + url?: string; + color?: string; + }; + }; + path: { + projectID: string; + }; + query?: { + directory?: string; + }; + url: '/project/{projectID}'; +}; + +export type ProjectUpdateErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type ProjectUpdateError = ProjectUpdateErrors[keyof ProjectUpdateErrors]; + +export type ProjectUpdateResponses = { + /** + * Updated project information + */ + 200: Project; +}; + +export type ProjectUpdateResponse = ProjectUpdateResponses[keyof ProjectUpdateResponses]; + +export type PtyListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/pty'; +}; + +export type PtyListResponses = { + /** + * List of sessions + */ + 200: Array; +}; + +export type PtyListResponse = PtyListResponses[keyof PtyListResponses]; + +export type PtyCreateData = { + body?: { + command?: string; + args?: Array; + 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; +}; + +export type SessionListResponse = SessionListResponses[keyof SessionListResponses]; + +export type SessionCreateData = { + body?: { + parentID?: string; + title?: string; + permission?: PermissionRuleset; + }; + 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; + time?: { + archived?: number; + }; + }; + 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; +}; + +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; +}; + +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; +}; + +export type SessionDiffResponse = SessionDiffResponses[keyof SessionDiffResponses]; + +export type SessionSummarizeData = { + body?: { + providerID: string; + modelID: string; + auto?: boolean; + }; + 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; + }>; +}; + +export type SessionMessagesResponse = SessionMessagesResponses[keyof SessionMessagesResponses]; + +export type SessionPromptData = { + body?: { + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + /** + * @deprecated tools and permissions have been merged, you can set permissions on the session itself now + */ + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; + }; + 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; + }; +}; + +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; + }; +}; + +export type SessionMessageResponse = SessionMessageResponses[keyof SessionMessageResponses]; + +export type PartDeleteData = { + body?: never; + path: { + /** + * Session ID + */ + sessionID: string; + /** + * Message ID + */ + messageID: string; + /** + * Part ID + */ + partID: string; + }; + query?: { + directory?: string; + }; + url: '/session/{sessionID}/message/{messageID}/part/{partID}'; +}; + +export type PartDeleteErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type PartDeleteError = PartDeleteErrors[keyof PartDeleteErrors]; + +export type PartDeleteResponses = { + /** + * Successfully deleted part + */ + 200: boolean; +}; + +export type PartDeleteResponse = PartDeleteResponses[keyof PartDeleteResponses]; + +export type PartUpdateData = { + body?: Part; + path: { + /** + * Session ID + */ + sessionID: string; + /** + * Message ID + */ + messageID: string; + /** + * Part ID + */ + partID: string; + }; + query?: { + directory?: string; + }; + url: '/session/{sessionID}/message/{messageID}/part/{partID}'; +}; + +export type PartUpdateErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type PartUpdateError = PartUpdateErrors[keyof PartUpdateErrors]; + +export type PartUpdateResponses = { + /** + * Successfully updated part + */ + 200: Part; +}; + +export type PartUpdateResponse = PartUpdateResponses[keyof PartUpdateResponses]; + +export type SessionPromptAsyncData = { + body?: { + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + /** + * @deprecated tools and permissions have been merged, you can set permissions on the session itself now + */ + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; + }; + 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; + variant?: 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; + }; +}; + +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 PermissionReplyData = { + body?: { + reply: 'once' | 'always' | 'reject'; + }; + path: { + requestID: string; + }; + query?: { + directory?: string; + }; + url: '/permission/{requestID}/reply'; +}; + +export type PermissionReplyErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type PermissionReplyError = PermissionReplyErrors[keyof PermissionReplyErrors]; + +export type PermissionReplyResponses = { + /** + * Permission processed successfully + */ + 200: boolean; +}; + +export type PermissionReplyResponse = PermissionReplyResponses[keyof PermissionReplyResponses]; + +export type PermissionListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/permission'; +}; + +export type PermissionListResponses = { + /** + * List of pending permissions + */ + 200: Array; +}; + +export type PermissionListResponse = PermissionListResponses[keyof PermissionListResponses]; + +export type CommandListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/command'; +}; + +export type CommandListResponses = { + /** + * List of commands + */ + 200: Array; +}; + +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; + 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; + id: string; + npm?: string; + models: { + [key: string]: { + id: string; + name: string; + family?: string; + release_date: string; + attachment: boolean; + reasoning: boolean; + temperature: boolean; + tool_call: boolean; + interleaved?: true | { + field: 'reasoning_content' | 'reasoning_details'; + }; + 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; + }; + variants?: { + [key: string]: { + [key: string]: unknown; + }; + }; + }; + }; + }>; + default: { + [key: string]: string; + }; + connected: Array; + }; +}; + +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; + }; +}; + +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'; + type?: 'file' | 'directory'; + limit?: number; + }; + url: '/find/file'; +}; + +export type FindFilesResponses = { + /** + * File paths + */ + 200: Array; +}; + +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; +}; + +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; +}; + +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; +}; + +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; +}; + +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 McpConnectData = { + body?: never; + path: { + name: string; + }; + query?: { + directory?: string; + }; + url: '/mcp/{name}/connect'; +}; + +export type McpConnectResponses = { + /** + * MCP server connected successfully + */ + 200: boolean; +}; + +export type McpConnectResponse = McpConnectResponses[keyof McpConnectResponses]; + +export type McpDisconnectData = { + body?: never; + path: { + name: string; + }; + query?: { + directory?: string; + }; + url: '/mcp/{name}/disconnect'; +}; + +export type McpDisconnectResponses = { + /** + * MCP server disconnected successfully + */ + 200: boolean; +}; + +export type McpDisconnectResponse = McpDisconnectResponses[keyof McpDisconnectResponses]; + +export type LspStatusData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/lsp'; +}; + +export type LspStatusResponses = { + /** + * LSP server status + */ + 200: Array; +}; + +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; +}; + +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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/zod.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/zod.gen.ts new file mode 100644 index 0000000000..3d21c8726b --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-partial/zod.gen.ts @@ -0,0 +1,2749 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import * as z from 'zod'; + +export const zEventInstallationUpdated = z.object({ + type: z.literal('installation.updated'), + properties: z.object({ + version: z.string() + }) +}); + +export const zEventInstallationUpdateAvailable = z.object({ + type: z.literal('installation.update-available'), + properties: z.object({ + version: z.string() + }) +}); + +export const zProject = z.object({ + id: z.string(), + worktree: z.string(), + vcs: z.literal('git').optional(), + name: z.string().optional(), + icon: z.object({ + url: z.string().optional(), + color: z.string().optional() + }).optional(), + time: z.object({ + created: z.number(), + updated: z.number(), + initialized: z.number().optional() + }) +}); + +export const zEventProjectUpdated = z.object({ + type: z.literal('project.updated'), + properties: zProject +}); + +export const zEventServerInstanceDisposed = z.object({ + type: z.literal('server.instance.disposed'), + properties: z.object({ + directory: z.string() + }) +}); + +export const zEventLspClientDiagnostics = z.object({ + type: z.literal('lsp.client.diagnostics'), + properties: z.object({ + serverID: z.string(), + path: z.string() + }) +}); + +export const zEventLspUpdated = z.object({ + type: z.literal('lsp.updated'), + properties: z.record(z.string(), z.unknown()) +}); + +export const zFileDiff = z.object({ + file: z.string(), + before: z.string(), + after: z.string(), + additions: z.number(), + deletions: z.number() +}); + +export const zUserMessage = z.object({ + id: z.string(), + sessionID: z.string(), + role: z.literal('user'), + time: z.object({ + created: z.number() + }), + summary: z.object({ + title: z.string().optional(), + body: z.string().optional(), + diffs: z.array(zFileDiff) + }).optional(), + agent: z.string(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }), + system: z.string().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + variant: z.string().optional() +}); + +export const zProviderAuthError = z.object({ + name: z.literal('ProviderAuthError'), + data: z.object({ + providerID: z.string(), + message: z.string() + }) +}); + +export const zUnknownError = z.object({ + name: z.literal('UnknownError'), + data: z.object({ + message: z.string() + }) +}); + +export const zMessageOutputLengthError = z.object({ + name: z.literal('MessageOutputLengthError'), + data: z.record(z.string(), z.unknown()) +}); + +export const zMessageAbortedError = z.object({ + name: z.literal('MessageAbortedError'), + data: z.object({ + message: z.string() + }) +}); + +export const zApiError = z.object({ + name: z.literal('APIError'), + data: z.object({ + message: z.string(), + statusCode: z.number().optional(), + isRetryable: z.boolean(), + responseHeaders: z.record(z.string(), z.string()).optional(), + responseBody: z.string().optional(), + metadata: z.record(z.string(), z.string()).optional() + }) +}); + +export const zAssistantMessage = z.object({ + id: z.string(), + sessionID: z.string(), + role: z.literal('assistant'), + time: z.object({ + created: z.number(), + completed: z.number().optional() + }), + error: z.union([ + zProviderAuthError, + zUnknownError, + zMessageOutputLengthError, + zMessageAbortedError, + zApiError + ]).optional(), + parentID: z.string(), + modelID: z.string(), + providerID: z.string(), + mode: z.string(), + agent: z.string(), + path: z.object({ + cwd: z.string(), + root: z.string() + }), + summary: z.boolean().optional(), + cost: z.number(), + tokens: z.object({ + input: z.number(), + output: z.number(), + reasoning: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }) + }), + finish: z.string().optional() +}); + +export const zMessage = z.union([ + zUserMessage, + zAssistantMessage +]); + +export const zEventMessageUpdated = z.object({ + type: z.literal('message.updated'), + properties: z.object({ + info: zMessage + }) +}); + +export const zEventMessageRemoved = z.object({ + type: z.literal('message.removed'), + properties: z.object({ + sessionID: z.string(), + messageID: z.string() + }) +}); + +export const zTextPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('text'), + text: z.string(), + synthetic: z.boolean().optional(), + ignored: z.boolean().optional(), + time: z.object({ + start: z.number(), + end: z.number().optional() + }).optional(), + metadata: z.record(z.string(), z.unknown()).optional() +}); + +export const zReasoningPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('reasoning'), + text: z.string(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number(), + end: z.number().optional() + }) +}); + +export const zFilePartSourceText = z.object({ + value: z.string(), + start: z.int().gte(-9007199254740991).lte(9007199254740991), + end: z.int().gte(-9007199254740991).lte(9007199254740991) +}); + +export const zFileSource = z.object({ + text: zFilePartSourceText, + type: z.literal('file'), + path: z.string() +}); + +export const zRange = z.object({ + start: z.object({ + line: z.number(), + character: z.number() + }), + end: z.object({ + line: z.number(), + character: z.number() + }) +}); + +export const zSymbolSource = z.object({ + text: zFilePartSourceText, + type: z.literal('symbol'), + path: z.string(), + range: zRange, + name: z.string(), + kind: z.int().gte(-9007199254740991).lte(9007199254740991) +}); + +export const zFilePartSource = z.union([ + zFileSource, + zSymbolSource +]); + +export const zFilePart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('file'), + mime: z.string(), + filename: z.string().optional(), + url: z.string(), + source: zFilePartSource.optional() +}); + +export const zToolStatePending = z.object({ + status: z.literal('pending'), + input: z.record(z.string(), z.unknown()), + raw: z.string() +}); + +export const zToolStateRunning = z.object({ + status: z.literal('running'), + input: z.record(z.string(), z.unknown()), + title: z.string().optional(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number() + }) +}); + +export const zToolStateCompleted = z.object({ + status: z.literal('completed'), + input: z.record(z.string(), z.unknown()), + output: z.string(), + title: z.string(), + metadata: z.record(z.string(), z.unknown()), + time: z.object({ + start: z.number(), + end: z.number(), + compacted: z.number().optional() + }), + attachments: z.array(zFilePart).optional() +}); + +export const zToolStateError = z.object({ + status: z.literal('error'), + input: z.record(z.string(), z.unknown()), + error: z.string(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number(), + end: z.number() + }) +}); + +export const zToolState = z.union([ + zToolStatePending, + zToolStateRunning, + zToolStateCompleted, + zToolStateError +]); + +export const zToolPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('tool'), + callID: z.string(), + tool: z.string(), + state: zToolState, + metadata: z.record(z.string(), z.unknown()).optional() +}); + +export const zStepStartPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('step-start'), + snapshot: z.string().optional() +}); + +export const zStepFinishPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('step-finish'), + reason: z.string(), + snapshot: z.string().optional(), + cost: z.number(), + tokens: z.object({ + input: z.number(), + output: z.number(), + reasoning: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }) + }) +}); + +export const zSnapshotPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('snapshot'), + snapshot: z.string() +}); + +export const zPatchPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('patch'), + hash: z.string(), + files: z.array(z.string()) +}); + +export const zAgentPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('agent'), + name: z.string(), + source: z.object({ + value: z.string(), + start: z.int().gte(-9007199254740991).lte(9007199254740991), + end: z.int().gte(-9007199254740991).lte(9007199254740991) + }).optional() +}); + +export const zRetryPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('retry'), + attempt: z.number(), + error: zApiError, + time: z.object({ + created: z.number() + }) +}); + +export const zCompactionPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('compaction'), + auto: z.boolean() +}); + +export const zPart = z.union([ + zTextPart, + z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('subtask'), + prompt: z.string(), + description: z.string(), + agent: z.string(), + command: z.string().optional() + }), + zReasoningPart, + zFilePart, + zToolPart, + zStepStartPart, + zStepFinishPart, + zSnapshotPart, + zPatchPart, + zAgentPart, + zRetryPart, + zCompactionPart +]); + +export const zEventMessagePartUpdated = z.object({ + type: z.literal('message.part.updated'), + properties: z.object({ + part: zPart, + delta: z.string().optional() + }) +}); + +export const zEventMessagePartRemoved = z.object({ + type: z.literal('message.part.removed'), + properties: z.object({ + sessionID: z.string(), + messageID: z.string(), + partID: z.string() + }) +}); + +export const zPermissionRequest = z.object({ + id: z.string().regex(/^per.*/), + sessionID: z.string().regex(/^ses.*/), + permission: z.string(), + patterns: z.array(z.string()), + metadata: z.record(z.string(), z.unknown()), + always: z.array(z.string()), + tool: z.object({ + messageID: z.string(), + callID: z.string() + }).optional() +}); + +export const zEventPermissionAsked = z.object({ + type: z.literal('permission.asked'), + properties: zPermissionRequest +}); + +export const zEventPermissionReplied = z.object({ + type: z.literal('permission.replied'), + properties: z.object({ + sessionID: z.string(), + requestID: z.string(), + reply: z.enum([ + 'once', + 'always', + 'reject' + ]) + }) +}); + +export const zSessionStatus = z.union([ + z.object({ + type: z.literal('idle') + }), + z.object({ + type: z.literal('retry'), + attempt: z.number(), + message: z.string(), + next: z.number() + }), + z.object({ + type: z.literal('busy') + }) +]); + +export const zEventSessionStatus = z.object({ + type: z.literal('session.status'), + properties: z.object({ + sessionID: z.string(), + status: zSessionStatus + }) +}); + +export const zEventSessionIdle = z.object({ + type: z.literal('session.idle'), + properties: z.object({ + sessionID: z.string() + }) +}); + +export const zEventSessionCompacted = z.object({ + type: z.literal('session.compacted'), + properties: z.object({ + sessionID: z.string() + }) +}); + +export const zEventFileEdited = z.object({ + type: z.literal('file.edited'), + properties: z.object({ + file: z.string() + }) +}); + +export const zTodo = z.object({ + content: z.string(), + status: z.string(), + priority: z.string(), + id: z.string() +}); + +export const zEventTodoUpdated = z.object({ + type: z.literal('todo.updated'), + properties: z.object({ + sessionID: z.string(), + todos: z.array(zTodo) + }) +}); + +export const zEventTuiPromptAppend = z.object({ + type: z.literal('tui.prompt.append'), + properties: z.object({ + text: z.string() + }) +}); + +export const zEventTuiCommandExecute = z.object({ + type: z.literal('tui.command.execute'), + properties: z.object({ + command: z.union([ + z.enum([ + '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' + ]), + z.string() + ]) + }) +}); + +export const zEventTuiToastShow = z.object({ + type: z.literal('tui.toast.show'), + properties: z.object({ + title: z.string().optional(), + message: z.string(), + variant: z.enum([ + 'info', + 'success', + 'warning', + 'error' + ]), + duration: z.number().optional().default(5000) + }) +}); + +export const zEventMcpToolsChanged = z.object({ + type: z.literal('mcp.tools.changed'), + properties: z.object({ + server: z.string() + }) +}); + +export const zEventCommandExecuted = z.object({ + type: z.literal('command.executed'), + properties: z.object({ + name: z.string(), + sessionID: z.string().regex(/^ses.*/), + arguments: z.string(), + messageID: z.string().regex(/^msg.*/) + }) +}); + +export const zPermissionAction = z.enum([ + 'allow', + 'deny', + 'ask' +]); + +export const zPermissionRule = z.object({ + permission: z.string(), + pattern: z.string(), + action: zPermissionAction +}); + +export const zPermissionRuleset = z.array(zPermissionRule); + +export const zSession = z.object({ + id: z.string().regex(/^ses.*/), + projectID: z.string(), + directory: z.string(), + parentID: z.string().regex(/^ses.*/).optional(), + summary: z.object({ + additions: z.number(), + deletions: z.number(), + files: z.number(), + diffs: z.array(zFileDiff).optional() + }).optional(), + share: z.object({ + url: z.string() + }).optional(), + title: z.string(), + version: z.string(), + time: z.object({ + created: z.number(), + updated: z.number(), + compacting: z.number().optional(), + archived: z.number().optional() + }), + permission: zPermissionRuleset.optional(), + revert: z.object({ + messageID: z.string(), + partID: z.string().optional(), + snapshot: z.string().optional(), + diff: z.string().optional() + }).optional() +}); + +export const zEventSessionCreated = z.object({ + type: z.literal('session.created'), + properties: z.object({ + info: zSession + }) +}); + +export const zEventSessionUpdated = z.object({ + type: z.literal('session.updated'), + properties: z.object({ + info: zSession + }) +}); + +export const zEventSessionDeleted = z.object({ + type: z.literal('session.deleted'), + properties: z.object({ + info: zSession + }) +}); + +export const zEventSessionDiff = z.object({ + type: z.literal('session.diff'), + properties: z.object({ + sessionID: z.string(), + diff: z.array(zFileDiff) + }) +}); + +export const zEventSessionError = z.object({ + type: z.literal('session.error'), + properties: z.object({ + sessionID: z.string().optional(), + error: z.union([ + zProviderAuthError, + zUnknownError, + zMessageOutputLengthError, + zMessageAbortedError, + zApiError + ]).optional() + }) +}); + +export const zEventFileWatcherUpdated = z.object({ + type: z.literal('file.watcher.updated'), + properties: z.object({ + file: z.string(), + event: z.union([ + z.literal('add'), + z.literal('change'), + z.literal('unlink') + ]) + }) +}); + +export const zEventVcsBranchUpdated = z.object({ + type: z.literal('vcs.branch.updated'), + properties: z.object({ + branch: z.string().optional() + }) +}); + +export const zPty = z.object({ + id: z.string().regex(/^pty.*/), + title: z.string(), + command: z.string(), + args: z.array(z.string()), + cwd: z.string(), + status: z.enum(['running', 'exited']), + pid: z.number() +}); + +export const zEventPtyCreated = z.object({ + type: z.literal('pty.created'), + properties: z.object({ + info: zPty + }) +}); + +export const zEventPtyUpdated = z.object({ + type: z.literal('pty.updated'), + properties: z.object({ + info: zPty + }) +}); + +export const zEventPtyExited = z.object({ + type: z.literal('pty.exited'), + properties: z.object({ + id: z.string().regex(/^pty.*/), + exitCode: z.number() + }) +}); + +export const zEventPtyDeleted = z.object({ + type: z.literal('pty.deleted'), + properties: z.object({ + id: z.string().regex(/^pty.*/) + }) +}); + +export const zEventServerConnected = z.object({ + type: z.literal('server.connected'), + properties: z.record(z.string(), z.unknown()) +}); + +export const zEventGlobalDisposed = z.object({ + type: z.literal('global.disposed'), + properties: z.record(z.string(), z.unknown()) +}); + +export const zEvent = z.union([ + zEventInstallationUpdated, + zEventInstallationUpdateAvailable, + zEventProjectUpdated, + zEventServerInstanceDisposed, + zEventLspClientDiagnostics, + zEventLspUpdated, + zEventMessageUpdated, + zEventMessageRemoved, + zEventMessagePartUpdated, + zEventMessagePartRemoved, + zEventPermissionAsked, + zEventPermissionReplied, + zEventSessionStatus, + zEventSessionIdle, + zEventSessionCompacted, + zEventFileEdited, + zEventTodoUpdated, + zEventTuiPromptAppend, + zEventTuiCommandExecute, + zEventTuiToastShow, + zEventMcpToolsChanged, + zEventCommandExecuted, + zEventSessionCreated, + zEventSessionUpdated, + zEventSessionDeleted, + zEventSessionDiff, + zEventSessionError, + zEventFileWatcherUpdated, + zEventVcsBranchUpdated, + zEventPtyCreated, + zEventPtyUpdated, + zEventPtyExited, + zEventPtyDeleted, + zEventServerConnected, + zEventGlobalDisposed +]); + +export const zGlobalEvent = z.object({ + directory: z.string(), + payload: zEvent +}); + +export const zBadRequestError = z.object({ + data: z.unknown(), + errors: z.array(z.record(z.string(), z.unknown())), + success: z.literal(false) +}); + +export const zNotFoundError = z.object({ + name: z.literal('NotFoundError'), + data: z.object({ + message: z.string() + }) +}); + +/** + * Custom keybind configurations + */ +export const zKeybindsConfig = z.object({ + leader: z.string().optional().default('ctrl+x'), + app_exit: z.string().optional().default('ctrl+c,ctrl+d,q'), + editor_open: z.string().optional().default('e'), + theme_list: z.string().optional().default('t'), + sidebar_toggle: z.string().optional().default('b'), + scrollbar_toggle: z.string().optional().default('none'), + username_toggle: z.string().optional().default('none'), + status_view: z.string().optional().default('s'), + session_export: z.string().optional().default('x'), + session_new: z.string().optional().default('n'), + session_list: z.string().optional().default('l'), + session_timeline: z.string().optional().default('g'), + session_fork: z.string().optional().default('none'), + session_rename: z.string().optional().default('none'), + session_share: z.string().optional().default('none'), + session_unshare: z.string().optional().default('none'), + session_interrupt: z.string().optional().default('escape'), + session_compact: z.string().optional().default('c'), + messages_page_up: z.string().optional().default('pageup'), + messages_page_down: z.string().optional().default('pagedown'), + messages_half_page_up: z.string().optional().default('ctrl+alt+u'), + messages_half_page_down: z.string().optional().default('ctrl+alt+d'), + messages_first: z.string().optional().default('ctrl+g,home'), + messages_last: z.string().optional().default('ctrl+alt+g,end'), + messages_next: z.string().optional().default('none'), + messages_previous: z.string().optional().default('none'), + messages_last_user: z.string().optional().default('none'), + messages_copy: z.string().optional().default('y'), + messages_undo: z.string().optional().default('u'), + messages_redo: z.string().optional().default('r'), + messages_toggle_conceal: z.string().optional().default('h'), + tool_details: z.string().optional().default('none'), + model_list: z.string().optional().default('m'), + model_cycle_recent: z.string().optional().default('f2'), + model_cycle_recent_reverse: z.string().optional().default('shift+f2'), + model_cycle_favorite: z.string().optional().default('none'), + model_cycle_favorite_reverse: z.string().optional().default('none'), + command_list: z.string().optional().default('ctrl+p'), + agent_list: z.string().optional().default('a'), + agent_cycle: z.string().optional().default('tab'), + agent_cycle_reverse: z.string().optional().default('shift+tab'), + variant_cycle: z.string().optional().default('ctrl+t'), + input_clear: z.string().optional().default('ctrl+c'), + input_paste: z.string().optional().default('ctrl+v'), + input_submit: z.string().optional().default('return'), + input_newline: z.string().optional().default('shift+return,ctrl+return,alt+return,ctrl+j'), + input_move_left: z.string().optional().default('left,ctrl+b'), + input_move_right: z.string().optional().default('right,ctrl+f'), + input_move_up: z.string().optional().default('up'), + input_move_down: z.string().optional().default('down'), + input_select_left: z.string().optional().default('shift+left'), + input_select_right: z.string().optional().default('shift+right'), + input_select_up: z.string().optional().default('shift+up'), + input_select_down: z.string().optional().default('shift+down'), + input_line_home: z.string().optional().default('ctrl+a'), + input_line_end: z.string().optional().default('ctrl+e'), + input_select_line_home: z.string().optional().default('ctrl+shift+a'), + input_select_line_end: z.string().optional().default('ctrl+shift+e'), + input_visual_line_home: z.string().optional().default('alt+a'), + input_visual_line_end: z.string().optional().default('alt+e'), + input_select_visual_line_home: z.string().optional().default('alt+shift+a'), + input_select_visual_line_end: z.string().optional().default('alt+shift+e'), + input_buffer_home: z.string().optional().default('home'), + input_buffer_end: z.string().optional().default('end'), + input_select_buffer_home: z.string().optional().default('shift+home'), + input_select_buffer_end: z.string().optional().default('shift+end'), + input_delete_line: z.string().optional().default('ctrl+shift+d'), + input_delete_to_line_end: z.string().optional().default('ctrl+k'), + input_delete_to_line_start: z.string().optional().default('ctrl+u'), + input_backspace: z.string().optional().default('backspace,shift+backspace'), + input_delete: z.string().optional().default('ctrl+d,delete,shift+delete'), + input_undo: z.string().optional().default('ctrl+-,super+z'), + input_redo: z.string().optional().default('ctrl+.,super+shift+z'), + input_word_forward: z.string().optional().default('alt+f,alt+right,ctrl+right'), + input_word_backward: z.string().optional().default('alt+b,alt+left,ctrl+left'), + input_select_word_forward: z.string().optional().default('alt+shift+f,alt+shift+right'), + input_select_word_backward: z.string().optional().default('alt+shift+b,alt+shift+left'), + input_delete_word_forward: z.string().optional().default('alt+d,alt+delete,ctrl+delete'), + input_delete_word_backward: z.string().optional().default('ctrl+w,ctrl+backspace,alt+backspace'), + history_previous: z.string().optional().default('up'), + history_next: z.string().optional().default('down'), + session_child_cycle: z.string().optional().default('right'), + session_child_cycle_reverse: z.string().optional().default('left'), + session_parent: z.string().optional().default('up'), + terminal_suspend: z.string().optional().default('ctrl+z'), + terminal_title_toggle: z.string().optional().default('none'), + tips_toggle: z.string().optional().default('h') +}); + +/** + * Log level + */ +export const zLogLevel = z.enum([ + 'DEBUG', + 'INFO', + 'WARN', + 'ERROR' +]); + +/** + * Server configuration for opencode serve and web commands + */ +export const zServerConfig = z.object({ + port: z.int().gt(0).lte(9007199254740991).optional(), + hostname: z.string().optional(), + mdns: z.boolean().optional(), + cors: z.array(z.string()).optional() +}); + +export const zPermissionActionConfig = z.enum([ + 'ask', + 'allow', + 'deny' +]); + +export const zPermissionObjectConfig = z.record(z.string(), zPermissionActionConfig); + +export const zPermissionRuleConfig = z.union([ + zPermissionActionConfig, + zPermissionObjectConfig +]); + +export const zPermissionConfig = z.union([ + z.object({ + read: zPermissionRuleConfig.optional(), + edit: zPermissionRuleConfig.optional(), + glob: zPermissionRuleConfig.optional(), + grep: zPermissionRuleConfig.optional(), + list: zPermissionRuleConfig.optional(), + bash: zPermissionRuleConfig.optional(), + task: zPermissionRuleConfig.optional(), + external_directory: zPermissionRuleConfig.optional(), + todowrite: zPermissionActionConfig.optional(), + todoread: zPermissionActionConfig.optional(), + webfetch: zPermissionActionConfig.optional(), + websearch: zPermissionActionConfig.optional(), + codesearch: zPermissionActionConfig.optional(), + lsp: zPermissionRuleConfig.optional(), + doom_loop: zPermissionActionConfig.optional() + }), + zPermissionActionConfig +]); + +export const zAgentConfig = z.object({ + model: z.string().optional(), + temperature: z.number().optional(), + top_p: z.number().optional(), + prompt: z.string().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + disable: z.boolean().optional(), + description: z.string().optional(), + mode: z.enum([ + 'subagent', + 'primary', + 'all' + ]).optional(), + options: z.record(z.string(), z.unknown()).optional(), + color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional(), + steps: z.int().gt(0).lte(9007199254740991).optional(), + maxSteps: z.int().gt(0).lte(9007199254740991).optional(), + permission: zPermissionConfig.optional() +}); + +export const zProviderConfig = z.object({ + api: z.string().optional(), + name: z.string().optional(), + env: z.array(z.string()).optional(), + id: z.string().optional(), + npm: z.string().optional(), + models: z.record(z.string(), z.object({ + id: z.string().optional(), + name: z.string().optional(), + family: z.string().optional(), + release_date: z.string().optional(), + attachment: z.boolean().optional(), + reasoning: z.boolean().optional(), + temperature: z.boolean().optional(), + tool_call: z.boolean().optional(), + interleaved: z.union([ + z.literal(true), + z.object({ + field: z.enum(['reasoning_content', 'reasoning_details']) + }) + ]).optional(), + cost: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional(), + context_over_200k: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional() + }).optional() + }).optional(), + limit: z.object({ + context: z.number(), + output: z.number() + }).optional(), + modalities: z.object({ + input: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])), + output: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])) + }).optional(), + experimental: z.boolean().optional(), + status: z.enum([ + 'alpha', + 'beta', + 'deprecated' + ]).optional(), + options: z.record(z.string(), z.unknown()).optional(), + headers: z.record(z.string(), z.string()).optional(), + provider: z.object({ + npm: z.string() + }).optional(), + variants: z.record(z.string(), z.object({ + disabled: z.boolean().optional() + })).optional() + })).optional(), + whitelist: z.array(z.string()).optional(), + blacklist: z.array(z.string()).optional(), + options: z.object({ + apiKey: z.string().optional(), + baseURL: z.string().optional(), + enterpriseUrl: z.string().optional(), + setCacheKey: z.boolean().optional(), + timeout: z.union([ + z.int().gt(0).lte(9007199254740991), + z.literal(false) + ]).optional() + }).optional() +}); + +export const zMcpLocalConfig = z.object({ + type: z.literal('local'), + command: z.array(z.string()), + environment: z.record(z.string(), z.string()).optional(), + enabled: z.boolean().optional(), + timeout: z.int().gt(0).lte(9007199254740991).optional() +}); + +export const zMcpOAuthConfig = z.object({ + clientId: z.string().optional(), + clientSecret: z.string().optional(), + scope: z.string().optional() +}); + +export const zMcpRemoteConfig = z.object({ + type: z.literal('remote'), + url: z.string(), + enabled: z.boolean().optional(), + headers: z.record(z.string(), z.string()).optional(), + oauth: z.union([ + zMcpOAuthConfig, + z.literal(false) + ]).optional(), + timeout: z.int().gt(0).lte(9007199254740991).optional() +}); + +/** + * @deprecated Always uses stretch layout. + */ +export const zLayoutConfig = z.enum(['auto', 'stretch']); + +export const zConfig = z.object({ + $schema: z.string().optional(), + theme: z.string().optional(), + keybinds: zKeybindsConfig.optional(), + logLevel: zLogLevel.optional(), + tui: z.object({ + scroll_speed: z.number().gte(0.001).optional(), + scroll_acceleration: z.object({ + enabled: z.boolean() + }).optional(), + diff_style: z.enum(['auto', 'stacked']).optional() + }).optional(), + server: zServerConfig.optional(), + command: z.record(z.string(), z.object({ + template: z.string(), + description: z.string().optional(), + agent: z.string().optional(), + model: z.string().optional(), + subtask: z.boolean().optional() + })).optional(), + watcher: z.object({ + ignore: z.array(z.string()).optional() + }).optional(), + plugin: z.array(z.string()).optional(), + snapshot: z.boolean().optional(), + share: z.enum([ + 'manual', + 'auto', + 'disabled' + ]).optional(), + autoshare: z.boolean().optional(), + autoupdate: z.union([ + z.boolean(), + z.literal('notify') + ]).optional(), + disabled_providers: z.array(z.string()).optional(), + enabled_providers: z.array(z.string()).optional(), + model: z.string().optional(), + small_model: z.string().optional(), + default_agent: z.string().optional(), + username: z.string().optional(), + mode: z.object({ + build: zAgentConfig.optional(), + plan: zAgentConfig.optional() + }).optional(), + agent: z.object({ + plan: zAgentConfig.optional(), + build: zAgentConfig.optional(), + general: zAgentConfig.optional(), + explore: zAgentConfig.optional(), + title: zAgentConfig.optional(), + summary: zAgentConfig.optional(), + compaction: zAgentConfig.optional() + }).optional(), + provider: z.record(z.string(), zProviderConfig).optional(), + mcp: z.record(z.string(), z.union([ + zMcpLocalConfig, + zMcpRemoteConfig + ])).optional(), + formatter: z.union([ + z.literal(false), + z.record(z.string(), z.object({ + disabled: z.boolean().optional(), + command: z.array(z.string()).optional(), + environment: z.record(z.string(), z.string()).optional(), + extensions: z.array(z.string()).optional() + })) + ]).optional(), + lsp: z.union([ + z.literal(false), + z.record(z.string(), z.union([ + z.object({ + disabled: z.literal(true) + }), + z.object({ + command: z.array(z.string()), + extensions: z.array(z.string()).optional(), + disabled: z.boolean().optional(), + env: z.record(z.string(), z.string()).optional(), + initialization: z.record(z.string(), z.unknown()).optional() + }) + ])) + ]).optional(), + instructions: z.array(z.string()).optional(), + layout: zLayoutConfig.optional(), + permission: zPermissionConfig.optional(), + tools: z.record(z.string(), z.boolean()).optional(), + enterprise: z.object({ + url: z.string().optional() + }).optional(), + compaction: z.object({ + auto: z.boolean().optional(), + prune: z.boolean().optional() + }).optional(), + experimental: z.object({ + hook: z.object({ + file_edited: z.record(z.string(), z.array(z.object({ + command: z.array(z.string()), + environment: z.record(z.string(), z.string()).optional() + }))).optional(), + session_completed: z.array(z.object({ + command: z.array(z.string()), + environment: z.record(z.string(), z.string()).optional() + })).optional() + }).optional(), + chatMaxRetries: z.number().optional(), + disable_paste_summary: z.boolean().optional(), + batch_tool: z.boolean().optional(), + openTelemetry: z.boolean().optional(), + primary_tools: z.array(z.string()).optional(), + continue_loop_on_deny: z.boolean().optional(), + mcp_timeout: z.int().gt(0).lte(9007199254740991).optional() + }).optional() +}); + +export const zToolIds = z.array(z.string()); + +export const zToolListItem = z.object({ + id: z.string(), + description: z.string(), + parameters: z.unknown() +}); + +export const zToolList = z.array(zToolListItem); + +export const zPath = z.object({ + home: z.string(), + state: z.string(), + config: z.string(), + worktree: z.string(), + directory: z.string() +}); + +export const zVcsInfo = z.object({ + branch: z.string() +}); + +export const zTextPartInput = z.object({ + id: z.string().optional(), + type: z.literal('text'), + text: z.string(), + synthetic: z.boolean().optional(), + ignored: z.boolean().optional(), + time: z.object({ + start: z.number(), + end: z.number().optional() + }).optional(), + metadata: z.record(z.string(), z.unknown()).optional() +}); + +export const zFilePartInput = z.object({ + id: z.string().optional(), + type: z.literal('file'), + mime: z.string(), + filename: z.string().optional(), + url: z.string(), + source: zFilePartSource.optional() +}); + +export const zAgentPartInput = z.object({ + id: z.string().optional(), + type: z.literal('agent'), + name: z.string(), + source: z.object({ + value: z.string(), + start: z.int().gte(-9007199254740991).lte(9007199254740991), + end: z.int().gte(-9007199254740991).lte(9007199254740991) + }).optional() +}); + +export const zSubtaskPartInput = z.object({ + id: z.string().optional(), + type: z.literal('subtask'), + prompt: z.string(), + description: z.string(), + agent: z.string(), + command: z.string().optional() +}); + +export const zCommand = z.object({ + name: z.string(), + description: z.string().optional(), + agent: z.string().optional(), + model: z.string().optional(), + mcp: z.boolean().optional(), + template: z.string(), + subtask: z.boolean().optional(), + hints: z.array(z.string()) +}); + +export const zModel = z.object({ + id: z.string(), + providerID: z.string(), + api: z.object({ + id: z.string(), + url: z.string(), + npm: z.string() + }), + name: z.string(), + family: z.string().optional(), + capabilities: z.object({ + temperature: z.boolean(), + reasoning: z.boolean(), + attachment: z.boolean(), + toolcall: z.boolean(), + input: z.object({ + text: z.boolean(), + audio: z.boolean(), + image: z.boolean(), + video: z.boolean(), + pdf: z.boolean() + }), + output: z.object({ + text: z.boolean(), + audio: z.boolean(), + image: z.boolean(), + video: z.boolean(), + pdf: z.boolean() + }), + interleaved: z.union([ + z.boolean(), + z.object({ + field: z.enum(['reasoning_content', 'reasoning_details']) + }) + ]) + }), + cost: z.object({ + input: z.number(), + output: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }), + experimentalOver200K: z.object({ + input: z.number(), + output: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }) + }).optional() + }), + limit: z.object({ + context: z.number(), + output: z.number() + }), + status: z.enum([ + 'alpha', + 'beta', + 'deprecated', + 'active' + ]), + options: z.record(z.string(), z.unknown()), + headers: z.record(z.string(), z.string()), + release_date: z.string(), + variants: z.record(z.string(), z.record(z.string(), z.unknown())).optional() +}); + +export const zProvider = z.object({ + id: z.string(), + name: z.string(), + source: z.enum([ + 'env', + 'config', + 'custom', + 'api' + ]), + env: z.array(z.string()), + key: z.string().optional(), + options: z.record(z.string(), z.unknown()), + models: z.record(z.string(), zModel) +}); + +export const zProviderAuthMethod = z.object({ + type: z.union([ + z.literal('oauth'), + z.literal('api') + ]), + label: z.string() +}); + +export const zProviderAuthAuthorization = z.object({ + url: z.string(), + method: z.union([ + z.literal('auto'), + z.literal('code') + ]), + instructions: z.string() +}); + +export const zSymbol = z.object({ + name: z.string(), + kind: z.number(), + location: z.object({ + uri: z.string(), + range: zRange + }) +}); + +export const zFileNode = z.object({ + name: z.string(), + path: z.string(), + absolute: z.string(), + type: z.enum(['file', 'directory']), + ignored: z.boolean() +}); + +export const zFileContent = z.object({ + type: z.literal('text'), + content: z.string(), + diff: z.string().optional(), + patch: z.object({ + oldFileName: z.string(), + newFileName: z.string(), + oldHeader: z.string().optional(), + newHeader: z.string().optional(), + hunks: z.array(z.object({ + oldStart: z.number(), + oldLines: z.number(), + newStart: z.number(), + newLines: z.number(), + lines: z.array(z.string()) + })), + index: z.string().optional() + }).optional(), + encoding: z.literal('base64').optional(), + mimeType: z.string().optional() +}); + +export const zFile = z.object({ + path: z.string(), + added: z.int().gte(-9007199254740991).lte(9007199254740991), + removed: z.int().gte(-9007199254740991).lte(9007199254740991), + status: z.enum([ + 'added', + 'deleted', + 'modified' + ]) +}); + +export const zAgent = z.object({ + name: z.string(), + description: z.string().optional(), + mode: z.enum([ + 'subagent', + 'primary', + 'all' + ]), + native: z.boolean().optional(), + hidden: z.boolean().optional(), + topP: z.number().optional(), + temperature: z.number().optional(), + color: z.string().optional(), + permission: zPermissionRuleset, + model: z.object({ + modelID: z.string(), + providerID: z.string() + }).optional(), + prompt: z.string().optional(), + options: z.record(z.string(), z.unknown()), + steps: z.int().gt(0).lte(9007199254740991).optional() +}); + +export const zMcpStatusConnected = z.object({ + status: z.literal('connected') +}); + +export const zMcpStatusDisabled = z.object({ + status: z.literal('disabled') +}); + +export const zMcpStatusFailed = z.object({ + status: z.literal('failed'), + error: z.string() +}); + +export const zMcpStatusNeedsAuth = z.object({ + status: z.literal('needs_auth') +}); + +export const zMcpStatusNeedsClientRegistration = z.object({ + status: z.literal('needs_client_registration'), + error: z.string() +}); + +export const zMcpStatus = z.union([ + zMcpStatusConnected, + zMcpStatusDisabled, + zMcpStatusFailed, + zMcpStatusNeedsAuth, + zMcpStatusNeedsClientRegistration +]); + +export const zLspStatus = z.object({ + id: z.string(), + name: z.string(), + root: z.string(), + status: z.union([ + z.literal('connected'), + z.literal('error') + ]) +}); + +export const zFormatterStatus = z.object({ + name: z.string(), + extensions: z.array(z.string()), + enabled: z.boolean() +}); + +export const zOAuth = z.object({ + type: z.literal('oauth'), + refresh: z.string(), + access: z.string(), + expires: z.number(), + enterpriseUrl: z.string().optional() +}); + +export const zApiAuth = z.object({ + type: z.literal('api'), + key: z.string() +}); + +export const zWellKnownAuth = z.object({ + type: z.literal('wellknown'), + key: z.string(), + token: z.string() +}); + +export const zAuth = z.union([ + zOAuth, + zApiAuth, + zWellKnownAuth +]); + +/** + * Health information + */ +export const zGlobalHealthResponse = z.object({ + healthy: z.literal(true), + version: z.string() +}); + +/** + * Event stream + */ +export const zGlobalEventResponse = zGlobalEvent; + +/** + * Global disposed + */ +export const zGlobalDisposeResponse = z.boolean(); + +export const zProjectListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of projects + */ +export const zProjectListResponse = z.array(zProject); + +export const zProjectCurrentQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Current project information + */ +export const zProjectCurrentResponse = zProject; + +export const zProjectUpdateBody = z.object({ + name: z.string().optional(), + icon: z.object({ + url: z.string().optional(), + color: z.string().optional() + }).optional() +}); + +export const zProjectUpdatePath = z.object({ + projectID: z.string() +}); + +export const zProjectUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated project information + */ +export const zProjectUpdateResponse = zProject; + +export const zPtyListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of sessions + */ +export const zPtyListResponse = z.array(zPty); + +export const zPtyCreateBody = z.object({ + command: z.string().optional(), + args: z.array(z.string()).optional(), + cwd: z.string().optional(), + title: z.string().optional(), + env: z.record(z.string(), z.string()).optional() +}); + +export const zPtyCreateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created session + */ +export const zPtyCreateResponse = zPty; + +export const zPtyRemovePath = z.object({ + ptyID: z.string() +}); + +export const zPtyRemoveQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Session removed + */ +export const zPtyRemoveResponse = z.boolean(); + +export const zPtyGetPath = z.object({ + ptyID: z.string() +}); + +export const zPtyGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Session info + */ +export const zPtyGetResponse = zPty; + +export const zPtyUpdateBody = z.object({ + title: z.string().optional(), + size: z.object({ + rows: z.number(), + cols: z.number() + }).optional() +}); + +export const zPtyUpdatePath = z.object({ + ptyID: z.string() +}); + +export const zPtyUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated session + */ +export const zPtyUpdateResponse = zPty; + +export const zPtyConnectPath = z.object({ + ptyID: z.string() +}); + +export const zPtyConnectQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Connected session + */ +export const zPtyConnectResponse = z.boolean(); + +export const zConfigGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Get config info + */ +export const zConfigGetResponse = zConfig; + +export const zConfigUpdateBody = zConfig; + +export const zConfigUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully updated config + */ +export const zConfigUpdateResponse = zConfig; + +export const zToolIdsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Tool IDs + */ +export const zToolIdsResponse = zToolIds; + +export const zToolListQuery = z.object({ + directory: z.string().optional(), + provider: z.string(), + model: z.string() +}); + +/** + * Tools + */ +export const zToolListResponse = zToolList; + +export const zInstanceDisposeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Instance disposed + */ +export const zInstanceDisposeResponse = z.boolean(); + +export const zPathGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Path + */ +export const zPathGetResponse = zPath; + +export const zVcsGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * VCS info + */ +export const zVcsGetResponse = zVcsInfo; + +export const zSessionListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of sessions + */ +export const zSessionListResponse = z.array(zSession); + +export const zSessionCreateBody = z.object({ + parentID: z.string().regex(/^ses.*/).optional(), + title: z.string().optional(), + permission: zPermissionRuleset.optional() +}); + +export const zSessionCreateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully created session + */ +export const zSessionCreateResponse = zSession; + +export const zSessionStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Get session status + */ +export const zSessionStatusResponse = z.record(z.string(), zSessionStatus); + +export const zSessionDeletePath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionDeleteQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully deleted session + */ +export const zSessionDeleteResponse = z.boolean(); + +export const zSessionGetPath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Get session + */ +export const zSessionGetResponse = zSession; + +export const zSessionUpdateBody = z.object({ + title: z.string().optional(), + time: z.object({ + archived: z.number().optional() + }).optional() +}); + +export const zSessionUpdatePath = z.object({ + sessionID: z.string() +}); + +export const zSessionUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully updated session + */ +export const zSessionUpdateResponse = zSession; + +export const zSessionChildrenPath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionChildrenQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of children + */ +export const zSessionChildrenResponse = z.array(zSession); + +export const zSessionTodoPath = z.object({ + sessionID: z.string() +}); + +export const zSessionTodoQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Todo list + */ +export const zSessionTodoResponse = z.array(zTodo); + +export const zSessionInitBody = z.object({ + modelID: z.string(), + providerID: z.string(), + messageID: z.string().regex(/^msg.*/) +}); + +export const zSessionInitPath = z.object({ + sessionID: z.string() +}); + +export const zSessionInitQuery = z.object({ + directory: z.string().optional() +}); + +/** + * 200 + */ +export const zSessionInitResponse = z.boolean(); + +export const zSessionForkBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional() +}); + +export const zSessionForkPath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionForkQuery = z.object({ + directory: z.string().optional() +}); + +/** + * 200 + */ +export const zSessionForkResponse = zSession; + +export const zSessionAbortPath = z.object({ + sessionID: z.string() +}); + +export const zSessionAbortQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Aborted session + */ +export const zSessionAbortResponse = z.boolean(); + +export const zSessionUnsharePath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionUnshareQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully unshared session + */ +export const zSessionUnshareResponse = zSession; + +export const zSessionSharePath = z.object({ + sessionID: z.string() +}); + +export const zSessionShareQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully shared session + */ +export const zSessionShareResponse = zSession; + +export const zSessionDiffPath = z.object({ + sessionID: z.string() +}); + +export const zSessionDiffQuery = z.object({ + directory: z.string().optional(), + messageID: z.string().regex(/^msg.*/).optional() +}); + +/** + * List of diffs + */ +export const zSessionDiffResponse = z.array(zFileDiff); + +export const zSessionSummarizeBody = z.object({ + providerID: z.string(), + modelID: z.string(), + auto: z.boolean().optional().default(false) +}); + +export const zSessionSummarizePath = z.object({ + sessionID: z.string() +}); + +export const zSessionSummarizeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Summarized session + */ +export const zSessionSummarizeResponse = z.boolean(); + +export const zSessionMessagesPath = z.object({ + sessionID: z.string() +}); + +export const zSessionMessagesQuery = z.object({ + directory: z.string().optional(), + limit: z.number().optional() +}); + +/** + * List of messages + */ +export const zSessionMessagesResponse = z.array(z.object({ + info: zMessage, + parts: z.array(zPart) +})); + +export const zSessionPromptBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }).optional(), + agent: z.string().optional(), + noReply: z.boolean().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + system: z.string().optional(), + variant: z.string().optional(), + parts: z.array(z.union([ + zTextPartInput, + zFilePartInput, + zAgentPartInput, + zSubtaskPartInput + ])) +}); + +export const zSessionPromptPath = z.object({ + sessionID: z.string() +}); + +export const zSessionPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created message + */ +export const zSessionPromptResponse = z.object({ + info: zAssistantMessage, + parts: z.array(zPart) +}); + +export const zSessionMessagePath = z.object({ + sessionID: z.string(), + messageID: z.string() +}); + +export const zSessionMessageQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Message + */ +export const zSessionMessageResponse = z.object({ + info: zMessage, + parts: z.array(zPart) +}); + +export const zPartDeletePath = z.object({ + sessionID: z.string(), + messageID: z.string(), + partID: z.string() +}); + +export const zPartDeleteQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully deleted part + */ +export const zPartDeleteResponse = z.boolean(); + +export const zPartUpdateBody = zPart; + +export const zPartUpdatePath = z.object({ + sessionID: z.string(), + messageID: z.string(), + partID: z.string() +}); + +export const zPartUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully updated part + */ +export const zPartUpdateResponse = zPart; + +export const zSessionPromptAsyncBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }).optional(), + agent: z.string().optional(), + noReply: z.boolean().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + system: z.string().optional(), + variant: z.string().optional(), + parts: z.array(z.union([ + zTextPartInput, + zFilePartInput, + zAgentPartInput, + zSubtaskPartInput + ])) +}); + +export const zSessionPromptAsyncPath = z.object({ + sessionID: z.string() +}); + +export const zSessionPromptAsyncQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt accepted + */ +export const zSessionPromptAsyncResponse = z.void(); + +export const zSessionCommandBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional(), + agent: z.string().optional(), + model: z.string().optional(), + arguments: z.string(), + command: z.string(), + variant: z.string().optional() +}); + +export const zSessionCommandPath = z.object({ + sessionID: z.string() +}); + +export const zSessionCommandQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created message + */ +export const zSessionCommandResponse = z.object({ + info: zAssistantMessage, + parts: z.array(zPart) +}); + +export const zSessionShellBody = z.object({ + agent: z.string(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }).optional(), + command: z.string() +}); + +export const zSessionShellPath = z.object({ + sessionID: z.string() +}); + +export const zSessionShellQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created message + */ +export const zSessionShellResponse = zAssistantMessage; + +export const zSessionRevertBody = z.object({ + messageID: z.string().regex(/^msg.*/), + partID: z.string().regex(/^prt.*/).optional() +}); + +export const zSessionRevertPath = z.object({ + sessionID: z.string() +}); + +export const zSessionRevertQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated session + */ +export const zSessionRevertResponse = zSession; + +export const zSessionUnrevertPath = z.object({ + sessionID: z.string() +}); + +export const zSessionUnrevertQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated session + */ +export const zSessionUnrevertResponse = zSession; + +export const zPermissionRespondBody = z.object({ + response: z.enum([ + 'once', + 'always', + 'reject' + ]) +}); + +export const zPermissionRespondPath = z.object({ + sessionID: z.string(), + permissionID: z.string() +}); + +export const zPermissionRespondQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Permission processed successfully + */ +export const zPermissionRespondResponse = z.boolean(); + +export const zPermissionReplyBody = z.object({ + reply: z.enum([ + 'once', + 'always', + 'reject' + ]) +}); + +export const zPermissionReplyPath = z.object({ + requestID: z.string() +}); + +export const zPermissionReplyQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Permission processed successfully + */ +export const zPermissionReplyResponse = z.boolean(); + +export const zPermissionListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of pending permissions + */ +export const zPermissionListResponse = z.array(zPermissionRequest); + +export const zCommandListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of commands + */ +export const zCommandListResponse = z.array(zCommand); + +export const zConfigProvidersQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of providers + */ +export const zConfigProvidersResponse = z.object({ + providers: z.array(zProvider), + default: z.record(z.string(), z.string()) +}); + +export const zProviderListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of providers + */ +export const zProviderListResponse = z.object({ + all: z.array(z.object({ + api: z.string().optional(), + name: z.string(), + env: z.array(z.string()), + id: z.string(), + npm: z.string().optional(), + models: z.record(z.string(), z.object({ + id: z.string(), + name: z.string(), + family: z.string().optional(), + release_date: z.string(), + attachment: z.boolean(), + reasoning: z.boolean(), + temperature: z.boolean(), + tool_call: z.boolean(), + interleaved: z.union([ + z.literal(true), + z.object({ + field: z.enum(['reasoning_content', 'reasoning_details']) + }) + ]).optional(), + cost: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional(), + context_over_200k: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional() + }).optional() + }).optional(), + limit: z.object({ + context: z.number(), + output: z.number() + }), + modalities: z.object({ + input: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])), + output: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])) + }).optional(), + experimental: z.boolean().optional(), + status: z.enum([ + 'alpha', + 'beta', + 'deprecated' + ]).optional(), + options: z.record(z.string(), z.unknown()), + headers: z.record(z.string(), z.string()).optional(), + provider: z.object({ + npm: z.string() + }).optional(), + variants: z.record(z.string(), z.record(z.string(), z.unknown())).optional() + })) + })), + default: z.record(z.string(), z.string()), + connected: z.array(z.string()) +}); + +export const zProviderAuthQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Provider auth methods + */ +export const zProviderAuthResponse = z.record(z.string(), z.array(zProviderAuthMethod)); + +export const zProviderOauthAuthorizeBody = z.object({ + method: z.number() +}); + +export const zProviderOauthAuthorizePath = z.object({ + providerID: z.string() +}); + +export const zProviderOauthAuthorizeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Authorization URL and method + */ +export const zProviderOauthAuthorizeResponse = zProviderAuthAuthorization; + +export const zProviderOauthCallbackBody = z.object({ + method: z.number(), + code: z.string().optional() +}); + +export const zProviderOauthCallbackPath = z.object({ + providerID: z.string() +}); + +export const zProviderOauthCallbackQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth callback processed successfully + */ +export const zProviderOauthCallbackResponse = z.boolean(); + +export const zFindTextQuery = z.object({ + directory: z.string().optional(), + pattern: z.string() +}); + +/** + * Matches + */ +export const zFindTextResponse = z.array(z.object({ + path: z.object({ + text: z.string() + }), + lines: z.object({ + text: z.string() + }), + line_number: z.number(), + absolute_offset: z.number(), + submatches: z.array(z.object({ + match: z.object({ + text: z.string() + }), + start: z.number(), + end: z.number() + })) +})); + +export const zFindFilesQuery = z.object({ + directory: z.string().optional(), + query: z.string(), + dirs: z.enum(['true', 'false']).optional(), + type: z.enum(['file', 'directory']).optional(), + limit: z.int().gte(1).lte(200).optional() +}); + +/** + * File paths + */ +export const zFindFilesResponse = z.array(z.string()); + +export const zFindSymbolsQuery = z.object({ + directory: z.string().optional(), + query: z.string() +}); + +/** + * Symbols + */ +export const zFindSymbolsResponse = z.array(zSymbol); + +export const zFileListQuery = z.object({ + directory: z.string().optional(), + path: z.string() +}); + +/** + * Files and directories + */ +export const zFileListResponse = z.array(zFileNode); + +export const zFileReadQuery = z.object({ + directory: z.string().optional(), + path: z.string() +}); + +/** + * File content + */ +export const zFileReadResponse = zFileContent; + +export const zFileStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * File status + */ +export const zFileStatusResponse = z.array(zFile); + +export const zAppLogBody = z.object({ + service: z.string(), + level: z.enum([ + 'debug', + 'info', + 'error', + 'warn' + ]), + message: z.string(), + extra: z.record(z.string(), z.unknown()).optional() +}); + +export const zAppLogQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Log entry written successfully + */ +export const zAppLogResponse = z.boolean(); + +export const zAppAgentsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of agents + */ +export const zAppAgentsResponse = z.array(zAgent); + +export const zMcpStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server status + */ +export const zMcpStatusResponse = z.record(z.string(), zMcpStatus); + +export const zMcpAddBody = z.object({ + name: z.string(), + config: z.union([ + zMcpLocalConfig, + zMcpRemoteConfig + ]) +}); + +export const zMcpAddQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server added successfully + */ +export const zMcpAddResponse = z.record(z.string(), zMcpStatus); + +export const zMcpAuthRemovePath = z.object({ + name: z.string() +}); + +export const zMcpAuthRemoveQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth credentials removed + */ +export const zMcpAuthRemoveResponse = z.object({ + success: z.literal(true) +}); + +export const zMcpAuthStartPath = z.object({ + name: z.string() +}); + +export const zMcpAuthStartQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth flow started + */ +export const zMcpAuthStartResponse = z.object({ + authorizationUrl: z.string() +}); + +export const zMcpAuthCallbackBody = z.object({ + code: z.string() +}); + +export const zMcpAuthCallbackPath = z.object({ + name: z.string() +}); + +export const zMcpAuthCallbackQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth authentication completed + */ +export const zMcpAuthCallbackResponse = zMcpStatus; + +export const zMcpAuthAuthenticatePath = z.object({ + name: z.string() +}); + +export const zMcpAuthAuthenticateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth authentication completed + */ +export const zMcpAuthAuthenticateResponse = zMcpStatus; + +export const zMcpConnectPath = z.object({ + name: z.string() +}); + +export const zMcpConnectQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server connected successfully + */ +export const zMcpConnectResponse = z.boolean(); + +export const zMcpDisconnectPath = z.object({ + name: z.string() +}); + +export const zMcpDisconnectQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server disconnected successfully + */ +export const zMcpDisconnectResponse = z.boolean(); + +export const zLspStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * LSP server status + */ +export const zLspStatusResponse = z.array(zLspStatus); + +export const zFormatterStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Formatter status + */ +export const zFormatterStatusResponse = z.array(zFormatterStatus); + +export const zTuiAppendPromptBody = z.object({ + text: z.string() +}); + +export const zTuiAppendPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt processed successfully + */ +export const zTuiAppendPromptResponse = z.boolean(); + +export const zTuiOpenHelpQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Help dialog opened successfully + */ +export const zTuiOpenHelpResponse = z.boolean(); + +export const zTuiOpenSessionsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Session dialog opened successfully + */ +export const zTuiOpenSessionsResponse = z.boolean(); + +export const zTuiOpenThemesQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Theme dialog opened successfully + */ +export const zTuiOpenThemesResponse = z.boolean(); + +export const zTuiOpenModelsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Model dialog opened successfully + */ +export const zTuiOpenModelsResponse = z.boolean(); + +export const zTuiSubmitPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt submitted successfully + */ +export const zTuiSubmitPromptResponse = z.boolean(); + +export const zTuiClearPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt cleared successfully + */ +export const zTuiClearPromptResponse = z.boolean(); + +export const zTuiExecuteCommandBody = z.object({ + command: z.string() +}); + +export const zTuiExecuteCommandQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Command executed successfully + */ +export const zTuiExecuteCommandResponse = z.boolean(); + +export const zTuiShowToastBody = z.object({ + title: z.string().optional(), + message: z.string(), + variant: z.enum([ + 'info', + 'success', + 'warning', + 'error' + ]), + duration: z.number().optional().default(5000) +}); + +export const zTuiShowToastQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Toast notification shown successfully + */ +export const zTuiShowToastResponse = z.boolean(); + +export const zTuiPublishBody = z.union([ + zEventTuiPromptAppend, + zEventTuiCommandExecute, + zEventTuiToastShow +]); + +export const zTuiPublishQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Event published successfully + */ +export const zTuiPublishResponse = z.boolean(); + +export const zTuiControlNextQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Next TUI request + */ +export const zTuiControlNextResponse = z.object({ + path: z.string(), + body: z.unknown() +}); + +export const zTuiControlResponseBody = z.unknown(); + +export const zTuiControlResponseQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Response submitted successfully + */ +export const zTuiControlResponseResponse = z.boolean(); + +export const zAuthSetBody = zAuth; + +export const zAuthSetPath = z.object({ + providerID: z.string() +}); + +export const zAuthSetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully set authentication credentials + */ +export const zAuthSetResponse = z.boolean(); + +export const zEventSubscribeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Event stream + */ +export const zEventSubscribeResponse = zEvent; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client.gen.ts new file mode 100644 index 0000000000..cab3c70195 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client.gen.ts @@ -0,0 +1,16 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { type ClientOptions, type Config, createClient, createConfig } from './client'; +import type { ClientOptions as ClientOptions2 } from './types.gen'; + +/** + * 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 = (override?: Config) => Config & T>; + +export const client = createClient(createConfig()); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client/client.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client/client.gen.ts new file mode 100644 index 0000000000..fc3f037f16 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client/client.gen.ts @@ -0,0 +1,277 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { createSseClient } from '../core/serverSentEvents.gen'; +import type { HttpMethod } from '../core/types.gen'; +import { getValidRequestBody } from '../core/utils.gen'; +import type { Client, Config, RequestOptions, ResolvedRequestOptions } from './types.gen'; +import { + buildUrl, + createConfig, + createInterceptors, + getParseAs, + mergeConfigs, + mergeHeaders, + setAuthParams, +} from './utils.gen'; + +type ReqInit = Omit & { + body?: any; + headers: ReturnType; +}; + +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(); + + const beforeRequest = async < + TData = unknown, + TResponseStyle extends 'data' | 'fields' = 'fields', + ThrowOnError extends boolean = boolean, + Url extends string = string, + >( + options: RequestOptions, + ) => { + const opts = { + ..._config, + ...options, + fetch: options.fetch ?? _config.fetch ?? globalThis.fetch, + headers: mergeHeaders(_config.headers, options.headers), + serializedBody: undefined as string | undefined, + }; + + if (opts.security) { + await setAuthParams(opts); + } + + if (opts.requestValidator) { + await opts.requestValidator(opts); + } + + if (opts.body !== undefined && opts.bodySerializer) { + opts.serializedBody = opts.bodySerializer(opts.body) as string | undefined; + } + + // 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 resolvedOpts = opts as typeof opts & + ResolvedRequestOptions; + const url = buildUrl(resolvedOpts); + + return { opts: resolvedOpts, url }; + }; + + const request: Client['request'] = async (options) => { + const throwOnError = options.throwOnError ?? _config.throwOnError; + const responseStyle = options.responseStyle ?? _config.responseStyle; + + let request: Request | undefined; + let response: Response | undefined; + + try { + const { opts, url } = await beforeRequest(options); + const requestInit: ReqInit = { + redirect: 'follow', + ...opts, + body: getValidRequestBody(opts), + }; + + 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!; + + response = await _fetch(request); + + for (const fn of interceptors.response.fns) { + if (fn) { + response = await fn(response, request, opts); + } + } + + const result = { + request, + response, + }; + + if (response.ok) { + 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 'text': + data = await response[parseAs](); + break; + case 'json': { + // Some servers return 200 with no Content-Length and empty body. + // response.json() would throw; read as text and parse if non-empty. + const text = await response.text(); + data = text ? JSON.parse(text) : {}; + 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 + } + + throw jsonError ?? textError; + } catch (error) { + let finalError = error; + + for (const fn of interceptors.error.fns) { + if (fn) { + finalError = await fn(finalError, response, request, options as ResolvedRequestOptions); + } + } + + finalError = finalError || {}; + + if (throwOnError) { + throw finalError; + } + + // TODO: we probably want to return error and improve types + return responseStyle === 'data' + ? undefined + : { + error: finalError, + request, + response, + }; + } + }; + + const makeMethodFn = (method: Uppercase) => (options: RequestOptions) => + request({ ...options, method }); + + const makeSseFn = (method: Uppercase) => async (options: RequestOptions) => { + const { opts, url } = await beforeRequest(options); + return createSseClient({ + ...opts, + body: opts.body as BodyInit | null | undefined, + 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; + }, + serializedBody: getValidRequestBody(opts) as BodyInit | null | undefined, + url, + }); + }; + + const _buildUrl: Client['buildUrl'] = (options) => buildUrl({ ..._config, ...options }); + + return { + buildUrl: _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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client/index.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client/index.ts new file mode 100644 index 0000000000..b295edeca0 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client/index.ts @@ -0,0 +1,25 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type { Auth } from '../core/auth.gen'; +export type { QuerySerializerOptions } from '../core/bodySerializer.gen'; +export { + formDataBodySerializer, + jsonBodySerializer, + urlSearchParamsBodySerializer, +} from '../core/bodySerializer.gen'; +export { buildClientParams } from '../core/params.gen'; +export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen'; +export { createClient } from './client.gen'; +export type { + Client, + ClientOptions, + Config, + CreateClientConfig, + Options, + RequestOptions, + RequestResult, + ResolvedRequestOptions, + ResponseStyle, + TDataShape, +} from './types.gen'; +export { createConfig, mergeHeaders } from './utils.gen'; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client/types.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client/types.gen.ts new file mode 100644 index 0000000000..193646cddf --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client/types.gen.ts @@ -0,0 +1,218 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth } from '../core/auth.gen'; +import type { + ServerSentEventsOptions, + ServerSentEventsResult, +} from '../core/serverSentEvents.gen'; +import type { Client as CoreClient, Config as CoreConfig } from '../core/types.gen'; +import type { Middleware } from './utils.gen'; + +export type ResponseStyle = 'data' | 'fields'; + +export interface Config + extends Omit, 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, + | 'onRequest' + | '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; + query?: Record; + /** + * Security mechanism(s) to use for the request. + */ + security?: ReadonlyArray; + url: Url; +} + +export interface ResolvedRequestOptions< + TResponseStyle extends ResponseStyle = 'fields', + ThrowOnError extends boolean = boolean, + Url extends string = string, +> extends RequestOptions { + headers: Headers; + 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 + ? TData[keyof TData] + : TData + : { + data: TData extends Record ? TData[keyof TData] : TData; + request: Request; + response: Response; + } + > + : Promise< + TResponseStyle extends 'data' + ? (TData extends Record ? TData[keyof TData] : TData) | undefined + : ( + | { + data: TData extends Record ? TData[keyof TData] : TData; + error: undefined; + } + | { + data: undefined; + error: TError extends Record ? TError[keyof TError] : TError; + } + ) & { + /** request may be undefined, because error may be from building the request object itself */ + request?: Request; + /** response may be undefined, because error may be from building the request object itself or from a network error */ + 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, 'method'>, +) => RequestResult; + +type SseFn = < + TData = unknown, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = 'fields', +>( + options: Omit, 'method'>, +) => Promise>; + +type RequestFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = 'fields', +>( + options: Omit, 'method'> & + Pick>, 'method'>, +) => RequestResult; + +type BuildUrlFn = < + TData extends { + body?: unknown; + path?: Record; + query?: Record; + url: string; + }, +>( + options: TData & Options, +) => string; + +export type Client = CoreClient & { + interceptors: Middleware; +}; + +/** + * 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 = ( + override?: Config, +) => Config & T>; + +export interface TDataShape { + body?: unknown; + headers?: unknown; + path?: unknown; + query?: unknown; + url: string; +} + +type OmitKeys = Pick>; + +export type Options< + TData extends TDataShape = TDataShape, + ThrowOnError extends boolean = boolean, + TResponse = unknown, + TResponseStyle extends ResponseStyle = 'fields', +> = OmitKeys< + RequestOptions, + 'body' | 'path' | 'query' | 'url' +> & + ([TData] extends [never] ? unknown : Omit); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client/utils.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client/utils.gen.ts new file mode 100644 index 0000000000..7800fe4b9d --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/client/utils.gen.ts @@ -0,0 +1,316 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { getAuthToken } from '../core/auth.gen'; +import type { QuerySerializerOptions } from '../core/bodySerializer.gen'; +import { jsonBodySerializer } from '../core/bodySerializer.gen'; +import { + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from '../core/pathSerializer.gen'; +import { getUrl } from '../core/utils.gen'; +import type { Client, ClientOptions, Config, RequestOptions } from './types.gen'; + +export const createQuerySerializer = ({ + 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, + ...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 => { + 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 & { + 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 async function setAuthParams( + options: Pick & { + headers: Headers; + }, +): Promise { + for (const auth of options.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['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 = ( + error: Err, + /** response may be undefined due to a network error where no response object is produced */ + response: Res | undefined, + /** request may be undefined, because error may be from building the request object itself */ + request: Req | undefined, + options: Options, +) => Err | Promise; + +type ReqInterceptor = (request: Req, options: Options) => Req | Promise; + +type ResInterceptor = ( + response: Res, + request: Req, + options: Options, +) => Res | Promise; + +class Interceptors { + fns: Array = []; + + 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 { + error: Interceptors>; + request: Interceptors>; + response: Interceptors>; +} + +export const createInterceptors = (): Middleware< + Req, + Res, + Err, + Options +> => ({ + error: new Interceptors>(), + request: new Interceptors>(), + response: new Interceptors>(), +}); + +const defaultQuerySerializer = createQuerySerializer({ + allowReserved: false, + array: { + explode: true, + style: 'form', + }, + object: { + explode: true, + style: 'deepObject', + }, +}); + +const defaultHeaders = { + 'Content-Type': 'application/json', +}; + +export const createConfig = ( + override: Config & T> = {}, +): Config & T> => ({ + ...jsonBodySerializer, + headers: defaultHeaders, + parseAs: 'auto', + querySerializer: defaultQuerySerializer, + ...override, +}); diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/auth.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/auth.gen.ts new file mode 100644 index 0000000000..3ebf994788 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/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, +): Promise => { + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/bodySerializer.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/bodySerializer.gen.ts new file mode 100644 index 0000000000..67daca60f8 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/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'; + +export type QuerySerializer = (query: Record) => string; + +export type BodySerializer = (body: unknown) => unknown; + +type QuerySerializerOptionsObject = { + allowReserved?: boolean; + array?: Partial>; + object?: Partial>; +}; + +export type QuerySerializerOptions = QuerySerializerOptionsObject & { + /** + * Per-parameter serialization overrides. When provided, these settings + * override the global array/object settings for specific parameter names. + */ + parameters?: Record; +}; + +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: (body: unknown): FormData => { + const data = new FormData(); + + Object.entries(body as Record).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: (body: unknown): string => + JSON.stringify(body, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)), +}; + +export const urlSearchParamsBodySerializer = { + bodySerializer: (body: unknown): string => { + const data = new URLSearchParams(); + + Object.entries(body as Record).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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/params.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/params.gen.ts new file mode 100644 index 0000000000..6478519bcb --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/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; + /** + * 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; + /** + * 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>; + args?: ReadonlyArray; +} + +export type FieldsConfig = ReadonlyArray; + +const extraPrefixesMap: Record = { + $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; + path: Record; + query: Record; +} + +const stripEmptySlots = (params: Params) => { + for (const [slot, value] of Object.entries(params)) { + if (value && typeof value === 'object' && !Array.isArray(value) && !Object.keys(value).length) { + delete params[slot as Slot]; + } + } +}; + +export const buildClientParams = (args: ReadonlyArray, fields: FieldsConfig) => { + const params: Params = { + body: Object.create(null), + headers: Object.create(null), + path: Object.create(null), + query: Object.create(null), + }; + + 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)[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)[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)[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)[key] = value; + break; + } + } + } + } + } + } + } + + stripEmptySlots(params); + + return params; +}; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/pathSerializer.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/pathSerializer.gen.ts new file mode 100644 index 0000000000..994b2848c6 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/pathSerializer.gen.ts @@ -0,0 +1,171 @@ +// This file is auto-generated by @hey-api/openapi-ts + +interface SerializeOptions extends SerializePrimitiveOptions, SerializerOptions {} + +interface SerializePrimitiveOptions { + allowReserved?: boolean; + name: string; +} + +export interface SerializerOptions { + /** + * @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 & { + 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 & { + value: Record | 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/queryKeySerializer.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/queryKeySerializer.gen.ts new file mode 100644 index 0000000000..5000df606f --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/queryKeySerializer.gen.ts @@ -0,0 +1,117 @@ +// 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 => { + 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 = {}; + + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/serverSentEvents.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/serverSentEvents.gen.ts new file mode 100644 index 0000000000..ddf3c4d13a --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/serverSentEvents.gen.ts @@ -0,0 +1,242 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Config } from './types.gen'; + +export type ServerSentEventsOptions = Omit & + Pick & { + /** + * 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; + /** + * 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) => 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; + url: string; + }; + +export interface StreamEvent { + data: TData; + event?: string; + id?: string; + retry?: number; +} + +export type ServerSentEventsResult = { + stream: AsyncGenerator< + TData extends Record ? TData[keyof TData] : TData, + TReturn, + TNext + >; +}; + +export function createSseClient({ + onRequest, + onSseError, + onSseEvent, + responseTransformer, + responseValidator, + sseDefaultRetryDelay, + sseMaxRetryAttempts, + sseMaxRetryDelay, + sseSleepFn, + url, + ...options +}: ServerSentEventsOptions): ServerSentEventsResult { + 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 | 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; + buffer = buffer.replace(/\r\n?/g, '\n'); // normalize line endings + + const chunks = buffer.split('\n\n'); + buffer = chunks.pop() ?? ''; + + for (const chunk of chunks) { + const lines = chunk.split('\n'); + const dataLines: Array = []; + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/types.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/types.gen.ts new file mode 100644 index 0000000000..9efe71d4c1 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/types.gen.ts @@ -0,0 +1,104 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth, AuthToken } from './auth.gen'; +import type { BodySerializer, QuerySerializer, QuerySerializerOptions } from './bodySerializer.gen'; + +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; + /** + * 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; + /** + * 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; + /** + * 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; + /** + * 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; +} + +type IsExactlyNeverOrNeverUndefined = [T] extends [never] + ? true + : [T] extends [never | undefined] + ? [undefined] extends [T] + ? false + : true + : false; + +export type OmitNever> = { + [K in keyof T as IsExactlyNeverOrNeverUndefined extends true ? never : K]: T[K]; +}; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/utils.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/utils.gen.ts new file mode 100644 index 0000000000..9a4fec7830 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/core/utils.gen.ts @@ -0,0 +1,140 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { BodySerializer, QuerySerializer } from './bodySerializer.gen'; +import { + type ArraySeparatorStyle, + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from './pathSerializer.gen'; + +export interface PathSerializer { + path: Record; + 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, + 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; + query?: Record; + 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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/index.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/index.ts new file mode 100644 index 0000000000..1126121160 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/index.ts @@ -0,0 +1,4 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export { App, Auth as Auth2, Auth2 as Auth22, Command as Command2, Config as Config2, Control, Event_, File_, Find, Formatter, Global, Instance, Lsp, Mcp, Oauth, OpenCode, type Options, Part as Part2, Path as Path2, Permission, Project as Project2, Provider as Provider2, Pty as Pty2, Session as Session2, Tool, Tui, Vcs } from './sdk.gen'; +export type { Agent, AgentConfig, AgentPart, AgentPartInput, ApiAuth, ApiError, AppAgentsData, AppAgentsResponse, AppAgentsResponses, AppLogData, AppLogError, AppLogErrors, AppLogResponse, AppLogResponses, AssistantMessage, Auth, AuthSetData, AuthSetError, AuthSetErrors, AuthSetResponse, AuthSetResponses, BadRequestError, ClientOptions, Command, CommandListData, CommandListResponse, CommandListResponses, CompactionPart, Config, ConfigGetData, ConfigGetResponse, ConfigGetResponses, ConfigProvidersData, ConfigProvidersResponse, ConfigProvidersResponses, ConfigUpdateData, ConfigUpdateError, ConfigUpdateErrors, ConfigUpdateResponse, ConfigUpdateResponses, Event, EventCommandExecuted, EventFileEdited, EventFileWatcherUpdated, EventGlobalDisposed, EventInstallationUpdateAvailable, EventInstallationUpdated, EventLspClientDiagnostics, EventLspUpdated, EventMcpToolsChanged, EventMessagePartRemoved, EventMessagePartUpdated, EventMessageRemoved, EventMessageUpdated, EventPermissionAsked, EventPermissionReplied, EventProjectUpdated, EventPtyCreated, EventPtyDeleted, EventPtyExited, EventPtyUpdated, EventServerConnected, EventServerInstanceDisposed, EventSessionCompacted, EventSessionCreated, EventSessionDeleted, EventSessionDiff, EventSessionError, EventSessionIdle, EventSessionStatus, EventSessionUpdated, EventSubscribeData, EventSubscribeResponse, EventSubscribeResponses, EventTodoUpdated, EventTuiCommandExecute, EventTuiPromptAppend, EventTuiToastShow, EventVcsBranchUpdated, File, FileContent, FileDiff, FileListData, FileListResponse, FileListResponses, FileNode, FilePart, FilePartInput, FilePartSource, FilePartSourceText, FileReadData, FileReadResponse, FileReadResponses, FileSource, FileStatusData, FileStatusResponse, FileStatusResponses, FindFilesData, FindFilesResponse, FindFilesResponses, FindSymbolsData, FindSymbolsResponse, FindSymbolsResponses, FindTextData, FindTextResponse, FindTextResponses, FormatterStatus, FormatterStatusData, FormatterStatusResponse, FormatterStatusResponses, GlobalDisposeData, GlobalDisposeResponse, GlobalDisposeResponses, GlobalEvent, GlobalEventData, GlobalEventResponse, GlobalEventResponses, GlobalHealthData, GlobalHealthResponse, GlobalHealthResponses, InstanceDisposeData, InstanceDisposeResponse, InstanceDisposeResponses, KeybindsConfig, LayoutConfig, LogLevel, LspStatus, LspStatusData, LspStatusResponse, LspStatusResponses, McpAddData, McpAddError, McpAddErrors, McpAddResponse, McpAddResponses, McpAuthAuthenticateData, McpAuthAuthenticateError, McpAuthAuthenticateErrors, McpAuthAuthenticateResponse, McpAuthAuthenticateResponses, McpAuthCallbackData, McpAuthCallbackError, McpAuthCallbackErrors, McpAuthCallbackResponse, McpAuthCallbackResponses, McpAuthRemoveData, McpAuthRemoveError, McpAuthRemoveErrors, McpAuthRemoveResponse, McpAuthRemoveResponses, McpAuthStartData, McpAuthStartError, McpAuthStartErrors, McpAuthStartResponse, McpAuthStartResponses, McpConnectData, McpConnectResponse, McpConnectResponses, McpDisconnectData, McpDisconnectResponse, McpDisconnectResponses, McpLocalConfig, McpOAuthConfig, McpRemoteConfig, McpStatus, McpStatusConnected, McpStatusData, McpStatusDisabled, McpStatusFailed, McpStatusNeedsAuth, McpStatusNeedsClientRegistration, McpStatusResponse, McpStatusResponses, Message, MessageAbortedError, MessageOutputLengthError, Model, NotFoundError, OAuth, Part, PartDeleteData, PartDeleteError, PartDeleteErrors, PartDeleteResponse, PartDeleteResponses, PartUpdateData, PartUpdateError, PartUpdateErrors, PartUpdateResponse, PartUpdateResponses, PatchPart, Path, PathGetData, PathGetResponse, PathGetResponses, PermissionAction, PermissionActionConfig, PermissionConfig, PermissionListData, PermissionListResponse, PermissionListResponses, PermissionObjectConfig, PermissionReplyData, PermissionReplyError, PermissionReplyErrors, PermissionReplyResponse, PermissionReplyResponses, PermissionRequest, PermissionRespondData, PermissionRespondError, PermissionRespondErrors, PermissionRespondResponse, PermissionRespondResponses, PermissionRule, PermissionRuleConfig, PermissionRuleset, Project, ProjectCurrentData, ProjectCurrentResponse, ProjectCurrentResponses, ProjectListData, ProjectListResponse, ProjectListResponses, ProjectUpdateData, ProjectUpdateError, ProjectUpdateErrors, ProjectUpdateResponse, ProjectUpdateResponses, Provider, ProviderAuthAuthorization, ProviderAuthData, ProviderAuthError, ProviderAuthMethod, ProviderAuthResponse, ProviderAuthResponses, ProviderConfig, ProviderListData, ProviderListResponse, ProviderListResponses, ProviderOauthAuthorizeData, ProviderOauthAuthorizeError, ProviderOauthAuthorizeErrors, ProviderOauthAuthorizeResponse, ProviderOauthAuthorizeResponses, ProviderOauthCallbackData, ProviderOauthCallbackError, ProviderOauthCallbackErrors, ProviderOauthCallbackResponse, ProviderOauthCallbackResponses, Pty, PtyConnectData, PtyConnectError, PtyConnectErrors, PtyConnectResponse, PtyConnectResponses, PtyCreateData, PtyCreateError, PtyCreateErrors, PtyCreateResponse, PtyCreateResponses, PtyGetData, PtyGetError, PtyGetErrors, PtyGetResponse, PtyGetResponses, PtyListData, PtyListResponse, PtyListResponses, PtyRemoveData, PtyRemoveError, PtyRemoveErrors, PtyRemoveResponse, PtyRemoveResponses, PtyUpdateData, PtyUpdateError, PtyUpdateErrors, PtyUpdateResponse, PtyUpdateResponses, Range, ReasoningPart, RetryPart, ServerConfig, Session, SessionAbortData, SessionAbortError, SessionAbortErrors, SessionAbortResponse, SessionAbortResponses, SessionChildrenData, SessionChildrenError, SessionChildrenErrors, SessionChildrenResponse, SessionChildrenResponses, SessionCommandData, SessionCommandError, SessionCommandErrors, SessionCommandResponse, SessionCommandResponses, SessionCreateData, SessionCreateError, SessionCreateErrors, SessionCreateResponse, SessionCreateResponses, SessionDeleteData, SessionDeleteError, SessionDeleteErrors, SessionDeleteResponse, SessionDeleteResponses, SessionDiffData, SessionDiffError, SessionDiffErrors, SessionDiffResponse, SessionDiffResponses, SessionForkData, SessionForkResponse, SessionForkResponses, SessionGetData, SessionGetError, SessionGetErrors, SessionGetResponse, SessionGetResponses, SessionInitData, SessionInitError, SessionInitErrors, SessionInitResponse, SessionInitResponses, SessionListData, SessionListResponse, SessionListResponses, SessionMessageData, SessionMessageError, SessionMessageErrors, SessionMessageResponse, SessionMessageResponses, SessionMessagesData, SessionMessagesError, SessionMessagesErrors, SessionMessagesResponse, SessionMessagesResponses, SessionPromptAsyncData, SessionPromptAsyncError, SessionPromptAsyncErrors, SessionPromptAsyncResponse, SessionPromptAsyncResponses, SessionPromptData, SessionPromptError, SessionPromptErrors, SessionPromptResponse, SessionPromptResponses, SessionRevertData, SessionRevertError, SessionRevertErrors, SessionRevertResponse, SessionRevertResponses, SessionShareData, SessionShareError, SessionShareErrors, SessionShareResponse, SessionShareResponses, SessionShellData, SessionShellError, SessionShellErrors, SessionShellResponse, SessionShellResponses, SessionStatus, SessionStatusData, SessionStatusError, SessionStatusErrors, SessionStatusResponse, SessionStatusResponses, SessionSummarizeData, SessionSummarizeError, SessionSummarizeErrors, SessionSummarizeResponse, SessionSummarizeResponses, SessionTodoData, SessionTodoError, SessionTodoErrors, SessionTodoResponse, SessionTodoResponses, SessionUnrevertData, SessionUnrevertError, SessionUnrevertErrors, SessionUnrevertResponse, SessionUnrevertResponses, SessionUnshareData, SessionUnshareError, SessionUnshareErrors, SessionUnshareResponse, SessionUnshareResponses, SessionUpdateData, SessionUpdateError, SessionUpdateErrors, SessionUpdateResponse, SessionUpdateResponses, SnapshotPart, StepFinishPart, StepStartPart, SubtaskPartInput, Symbol, SymbolSource, TextPart, TextPartInput, Todo, ToolIds, ToolIdsData, ToolIdsError, ToolIdsErrors, ToolIdsResponse, ToolIdsResponses, ToolList, ToolListData, ToolListError, ToolListErrors, ToolListItem, ToolListResponse, ToolListResponses, ToolPart, ToolState, ToolStateCompleted, ToolStateError, ToolStatePending, ToolStateRunning, TuiAppendPromptData, TuiAppendPromptError, TuiAppendPromptErrors, TuiAppendPromptResponse, TuiAppendPromptResponses, TuiClearPromptData, TuiClearPromptResponse, TuiClearPromptResponses, TuiControlNextData, TuiControlNextResponse, TuiControlNextResponses, TuiControlResponseData, TuiControlResponseResponse, TuiControlResponseResponses, TuiExecuteCommandData, TuiExecuteCommandError, TuiExecuteCommandErrors, TuiExecuteCommandResponse, TuiExecuteCommandResponses, TuiOpenHelpData, TuiOpenHelpResponse, TuiOpenHelpResponses, TuiOpenModelsData, TuiOpenModelsResponse, TuiOpenModelsResponses, TuiOpenSessionsData, TuiOpenSessionsResponse, TuiOpenSessionsResponses, TuiOpenThemesData, TuiOpenThemesResponse, TuiOpenThemesResponses, TuiPublishData, TuiPublishError, TuiPublishErrors, TuiPublishResponse, TuiPublishResponses, TuiShowToastData, TuiShowToastResponse, TuiShowToastResponses, TuiSubmitPromptData, TuiSubmitPromptResponse, TuiSubmitPromptResponses, UnknownError, UserMessage, VcsGetData, VcsGetResponse, VcsGetResponses, VcsInfo, WellKnownAuth } from './types.gen'; diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/sdk.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/sdk.gen.ts new file mode 100644 index 0000000000..82ee28ea85 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/sdk.gen.ts @@ -0,0 +1,2962 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import * as z from 'zod'; + +import { buildClientParams, type Client, type Options as Options2, type TDataShape } from './client'; +import { client } from './client.gen'; +import type { AgentPartInput, AppAgentsResponses, AppLogErrors, AppLogResponses, Auth as Auth3, AuthSetErrors, AuthSetResponses, CommandListResponses, Config as Config2, ConfigGetResponses, ConfigProvidersResponses, ConfigUpdateErrors, ConfigUpdateResponses, EventSubscribeResponse, EventSubscribeResponses, EventTuiCommandExecute, EventTuiPromptAppend, EventTuiToastShow, FileListResponses, FilePartInput, FileReadResponses, FileStatusResponses, FindFilesResponses, FindSymbolsResponses, FindTextResponses, FormatterStatusResponses, GlobalDisposeResponses, GlobalEventResponse, GlobalEventResponses, GlobalHealthResponses, InstanceDisposeResponses, LspStatusResponses, McpAddErrors, McpAddResponses, McpAuthAuthenticateErrors, McpAuthAuthenticateResponses, McpAuthCallbackErrors, McpAuthCallbackResponses, McpAuthRemoveErrors, McpAuthRemoveResponses, McpAuthStartErrors, McpAuthStartResponses, McpConnectResponses, McpDisconnectResponses, McpLocalConfig, McpRemoteConfig, McpStatusResponses, Part as Part2, PartDeleteErrors, PartDeleteResponses, PartUpdateErrors, PartUpdateResponses, PathGetResponses, PermissionListResponses, PermissionReplyErrors, PermissionReplyResponses, PermissionRespondErrors, PermissionRespondResponses, PermissionRuleset, ProjectCurrentResponses, ProjectListResponses, ProjectUpdateErrors, ProjectUpdateResponses, 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'; +import { zAppAgentsQuery, zAppAgentsResponse, zAppLogBody, zAppLogQuery, zAppLogResponse, zAuthSetBody, zAuthSetPath, zAuthSetQuery, zAuthSetResponse, zCommandListQuery, zCommandListResponse, zConfigGetQuery, zConfigGetResponse, zConfigProvidersQuery, zConfigProvidersResponse, zConfigUpdateBody, zConfigUpdateQuery, zConfigUpdateResponse, zEventSubscribeQuery, zEventSubscribeResponse, zFileListQuery, zFileListResponse, zFileReadQuery, zFileReadResponse, zFileStatusQuery, zFileStatusResponse, zFindFilesQuery, zFindFilesResponse, zFindSymbolsQuery, zFindSymbolsResponse, zFindTextQuery, zFindTextResponse, zFormatterStatusQuery, zFormatterStatusResponse, zGlobalDisposeResponse, zGlobalEventResponse, zGlobalHealthResponse, zInstanceDisposeQuery, zInstanceDisposeResponse, zLspStatusQuery, zLspStatusResponse, zMcpAddBody, zMcpAddQuery, zMcpAddResponse, zMcpAuthAuthenticatePath, zMcpAuthAuthenticateQuery, zMcpAuthAuthenticateResponse, zMcpAuthCallbackBody, zMcpAuthCallbackPath, zMcpAuthCallbackQuery, zMcpAuthCallbackResponse, zMcpAuthRemovePath, zMcpAuthRemoveQuery, zMcpAuthRemoveResponse, zMcpAuthStartPath, zMcpAuthStartQuery, zMcpAuthStartResponse, zMcpConnectPath, zMcpConnectQuery, zMcpConnectResponse, zMcpDisconnectPath, zMcpDisconnectQuery, zMcpDisconnectResponse, zMcpStatusQuery, zMcpStatusResponse, zPartDeletePath, zPartDeleteQuery, zPartDeleteResponse, zPartUpdateBody, zPartUpdatePath, zPartUpdateQuery, zPartUpdateResponse, zPathGetQuery, zPathGetResponse, zPermissionListQuery, zPermissionListResponse, zPermissionReplyBody, zPermissionReplyPath, zPermissionReplyQuery, zPermissionReplyResponse, zPermissionRespondBody, zPermissionRespondPath, zPermissionRespondQuery, zPermissionRespondResponse, zProjectCurrentQuery, zProjectCurrentResponse, zProjectListQuery, zProjectListResponse, zProjectUpdateBody, zProjectUpdatePath, zProjectUpdateQuery, zProjectUpdateResponse, zProviderAuthQuery, zProviderAuthResponse, zProviderListQuery, zProviderListResponse, zProviderOauthAuthorizeBody, zProviderOauthAuthorizePath, zProviderOauthAuthorizeQuery, zProviderOauthAuthorizeResponse, zProviderOauthCallbackBody, zProviderOauthCallbackPath, zProviderOauthCallbackQuery, zProviderOauthCallbackResponse, zPtyConnectPath, zPtyConnectQuery, zPtyConnectResponse, zPtyCreateBody, zPtyCreateQuery, zPtyCreateResponse, zPtyGetPath, zPtyGetQuery, zPtyGetResponse, zPtyListQuery, zPtyListResponse, zPtyRemovePath, zPtyRemoveQuery, zPtyRemoveResponse, zPtyUpdateBody, zPtyUpdatePath, zPtyUpdateQuery, zPtyUpdateResponse, zSessionAbortPath, zSessionAbortQuery, zSessionAbortResponse, zSessionChildrenPath, zSessionChildrenQuery, zSessionChildrenResponse, zSessionCommandBody, zSessionCommandPath, zSessionCommandQuery, zSessionCommandResponse, zSessionCreateBody, zSessionCreateQuery, zSessionCreateResponse, zSessionDeletePath, zSessionDeleteQuery, zSessionDeleteResponse, zSessionDiffPath, zSessionDiffQuery, zSessionDiffResponse, zSessionForkBody, zSessionForkPath, zSessionForkQuery, zSessionForkResponse, zSessionGetPath, zSessionGetQuery, zSessionGetResponse, zSessionInitBody, zSessionInitPath, zSessionInitQuery, zSessionInitResponse, zSessionListQuery, zSessionListResponse, zSessionMessagePath, zSessionMessageQuery, zSessionMessageResponse, zSessionMessagesPath, zSessionMessagesQuery, zSessionMessagesResponse, zSessionPromptAsyncBody, zSessionPromptAsyncPath, zSessionPromptAsyncQuery, zSessionPromptAsyncResponse, zSessionPromptBody, zSessionPromptPath, zSessionPromptQuery, zSessionPromptResponse, zSessionRevertBody, zSessionRevertPath, zSessionRevertQuery, zSessionRevertResponse, zSessionSharePath, zSessionShareQuery, zSessionShareResponse, zSessionShellBody, zSessionShellPath, zSessionShellQuery, zSessionShellResponse, zSessionStatusQuery, zSessionStatusResponse, zSessionSummarizeBody, zSessionSummarizePath, zSessionSummarizeQuery, zSessionSummarizeResponse, zSessionTodoPath, zSessionTodoQuery, zSessionTodoResponse, zSessionUnrevertPath, zSessionUnrevertQuery, zSessionUnrevertResponse, zSessionUnsharePath, zSessionUnshareQuery, zSessionUnshareResponse, zSessionUpdateBody, zSessionUpdatePath, zSessionUpdateQuery, zSessionUpdateResponse, zToolIdsQuery, zToolIdsResponse, zToolListQuery, zToolListResponse, zTuiAppendPromptBody, zTuiAppendPromptQuery, zTuiAppendPromptResponse, zTuiClearPromptQuery, zTuiClearPromptResponse, zTuiControlNextQuery, zTuiControlNextResponse, zTuiControlResponseBody, zTuiControlResponseQuery, zTuiControlResponseResponse, zTuiExecuteCommandBody, zTuiExecuteCommandQuery, zTuiExecuteCommandResponse, zTuiOpenHelpQuery, zTuiOpenHelpResponse, zTuiOpenModelsQuery, zTuiOpenModelsResponse, zTuiOpenSessionsQuery, zTuiOpenSessionsResponse, zTuiOpenThemesQuery, zTuiOpenThemesResponse, zTuiPublishBody, zTuiPublishQuery, zTuiPublishResponse, zTuiShowToastBody, zTuiShowToastQuery, zTuiShowToastResponse, zTuiSubmitPromptQuery, zTuiSubmitPromptResponse, zVcsGetQuery, zVcsGetResponse } from './zod.gen'; + +export type Options = Options2 & { + /** + * You can provide a client instance returned by `createClient()` instead of + * individual options. This might be also useful if you want to implement a + * custom client. + */ + client?: Client; + /** + * You can pass arbitrary values through the `meta` object. This can be + * used to access values that aren't defined as part of the SDK function. + */ + meta?: Record; +}; + +class HeyApiClient { + protected client: Client; + + constructor(args?: { + client?: Client; + }) { + this.client = args?.client ?? client; + } +} + +class HeyApiRegistry { + private readonly defaultKey = 'default'; + + private readonly instances: Map = 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 OpenCode()" 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 health + * + * Get health information about the OpenCode server. + */ + public health = Object.assign((options?: Options) => (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: z.never().optional() + }).parseAsync(data), + responseValidator: async (data) => await zGlobalHealthResponse.parseAsync(data), + url: '/global/health', + ...options + }), { + id: 'globalHealth', + method: 'get', + responseSchema: zGlobalHealthResponse, + url: '/global/health' + }); + + /** + * Get global events + * + * Subscribe to global events from the OpenCode system using server-sent events. + */ + public event = Object.assign((options?: Options) => (options?.client ?? this.client).sse.get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: z.never().optional() + }).parseAsync(data), + responseValidator: async (data) => await zGlobalEventResponse.parseAsync(data), + url: '/global/event', + ...options + }), { + id: 'globalEvent', + method: 'get', + responseSchema: zGlobalEventResponse, + url: '/global/event' + }); + + /** + * Dispose instance + * + * Clean up and dispose all OpenCode instances, releasing all resources. + */ + public dispose = Object.assign((options?: Options) => (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: z.never().optional() + }).parseAsync(data), + responseValidator: async (data) => await zGlobalDisposeResponse.parseAsync(data), + url: '/global/dispose', + ...options + }), { + id: 'globalDispose', + method: 'post', + responseSchema: zGlobalDisposeResponse, + url: '/global/dispose' + }); +} + +export class Project extends HeyApiClient { + /** + * List all projects + * + * Get a list of projects that have been opened with OpenCode. + */ + public list = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProjectListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProjectListResponse.parseAsync(data), + url: '/project', + ...options, + ...params + }); + }, { + id: 'projectList', + method: 'get', + responseSchema: zProjectListResponse, + url: '/project' + }); + + /** + * Get current project + * + * Retrieve the currently active project that OpenCode is working with. + */ + public current = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProjectCurrentQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProjectCurrentResponse.parseAsync(data), + url: '/project/current', + ...options, + ...params + }); + }, { + id: 'projectCurrent', + method: 'get', + responseSchema: zProjectCurrentResponse, + url: '/project/current' + }); + + /** + * Update project + * + * Update project properties such as name, icon and color. + */ + public update = Object.assign((parameters: { + projectID: string; + directory?: string; + name?: string; + icon?: { + url?: string; + color?: string; + }; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'projectID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'name' }, + { in: 'body', key: 'icon' } + ] }]); + return (options?.client ?? this.client).patch({ + requestValidator: async (data) => await z.object({ + body: zProjectUpdateBody.optional(), + path: zProjectUpdatePath, + query: zProjectUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProjectUpdateResponse.parseAsync(data), + url: '/project/{projectID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'projectUpdate', + method: 'patch', + responseSchema: zProjectUpdateResponse, + url: '/project/{projectID}' + }); +} + +export class Pty extends HeyApiClient { + /** + * List PTY sessions + * + * Get a list of all active pseudo-terminal (PTY) sessions managed by OpenCode. + */ + public list = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zPtyListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyListResponse.parseAsync(data), + url: '/pty', + ...options, + ...params + }); + }, { + id: 'ptyList', + method: 'get', + responseSchema: zPtyListResponse, + url: '/pty' + }); + + /** + * Create PTY session + * + * Create a new pseudo-terminal (PTY) session for running shell commands and processes. + */ + public create = Object.assign((parameters?: { + directory?: string; + command?: string; + args?: Array; + cwd?: string; + title?: string; + env?: { + [key: string]: string; + }; + }, options?: Options) => { + 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({ + requestValidator: async (data) => await z.object({ + body: zPtyCreateBody.optional(), + path: z.never().optional(), + query: zPtyCreateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyCreateResponse.parseAsync(data), + url: '/pty', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'ptyCreate', + method: 'post', + responseSchema: zPtyCreateResponse, + url: '/pty' + }); + + /** + * Remove PTY session + * + * Remove and terminate a specific pseudo-terminal (PTY) session. + */ + public remove = Object.assign((parameters: { + ptyID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'ptyID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPtyRemovePath, + query: zPtyRemoveQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyRemoveResponse.parseAsync(data), + url: '/pty/{ptyID}', + ...options, + ...params + }); + }, { + id: 'ptyRemove', + method: 'delete', + responseSchema: zPtyRemoveResponse, + url: '/pty/{ptyID}' + }); + + /** + * Get PTY session + * + * Retrieve detailed information about a specific pseudo-terminal (PTY) session. + */ + public get = Object.assign((parameters: { + ptyID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'ptyID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPtyGetPath, + query: zPtyGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyGetResponse.parseAsync(data), + url: '/pty/{ptyID}', + ...options, + ...params + }); + }, { + id: 'ptyGet', + method: 'get', + responseSchema: zPtyGetResponse, + url: '/pty/{ptyID}' + }); + + /** + * Update PTY session + * + * Update properties of an existing pseudo-terminal (PTY) session. + */ + public update = Object.assign((parameters: { + ptyID: string; + directory?: string; + title?: string; + size?: { + rows: number; + cols: number; + }; + }, options?: Options) => { + 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({ + requestValidator: async (data) => await z.object({ + body: zPtyUpdateBody.optional(), + path: zPtyUpdatePath, + query: zPtyUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyUpdateResponse.parseAsync(data), + url: '/pty/{ptyID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'ptyUpdate', + method: 'put', + responseSchema: zPtyUpdateResponse, + url: '/pty/{ptyID}' + }); + + /** + * Connect to PTY session + * + * Establish a WebSocket connection to interact with a pseudo-terminal (PTY) session in real-time. + */ + public connect = Object.assign((parameters: { + ptyID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'ptyID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPtyConnectPath, + query: zPtyConnectQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPtyConnectResponse.parseAsync(data), + url: '/pty/{ptyID}/connect', + ...options, + ...params + }); + }, { + id: 'ptyConnect', + method: 'get', + responseSchema: zPtyConnectResponse, + url: '/pty/{ptyID}/connect' + }); +} + +export class Config extends HeyApiClient { + /** + * Get configuration + * + * Retrieve the current OpenCode configuration settings and preferences. + */ + public get = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zConfigGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zConfigGetResponse.parseAsync(data), + url: '/config', + ...options, + ...params + }); + }, { + id: 'configGet', + method: 'get', + responseSchema: zConfigGetResponse, + url: '/config' + }); + + /** + * Update configuration + * + * Update OpenCode configuration settings and preferences. + */ + public update = Object.assign((parameters?: { + directory?: string; + config?: Config2; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { key: 'config', map: 'body' }] }]); + return (options?.client ?? this.client).patch({ + requestValidator: async (data) => await z.object({ + body: zConfigUpdateBody.optional(), + path: z.never().optional(), + query: zConfigUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zConfigUpdateResponse.parseAsync(data), + url: '/config', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'configUpdate', + method: 'patch', + responseSchema: zConfigUpdateResponse, + url: '/config' + }); + + /** + * List config providers + * + * Get a list of all configured AI providers and their default models. + */ + public providers = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zConfigProvidersQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zConfigProvidersResponse.parseAsync(data), + url: '/config/providers', + ...options, + ...params + }); + }, { + id: 'configProviders', + method: 'get', + responseSchema: zConfigProvidersResponse, + url: '/config/providers' + }); +} + +export class Tool extends HeyApiClient { + /** + * List tool IDs + * + * Get a list of all available tool IDs, including both built-in tools and dynamically registered tools. + */ + public ids = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zToolIdsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zToolIdsResponse.parseAsync(data), + url: '/experimental/tool/ids', + ...options, + ...params + }); + }, { + id: 'toolIds', + method: 'get', + responseSchema: zToolIdsResponse, + url: '/experimental/tool/ids' + }); + + /** + * List tools + * + * Get a list of available tools with their JSON schema parameters for a specific provider and model combination. + */ + public list = Object.assign((parameters: { + directory?: string; + provider: string; + model: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'query', key: 'provider' }, + { in: 'query', key: 'model' } + ] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zToolListQuery + }).parseAsync(data), + responseValidator: async (data) => await zToolListResponse.parseAsync(data), + url: '/experimental/tool', + ...options, + ...params + }); + }, { + id: 'toolList', + method: 'get', + responseSchema: zToolListResponse, + url: '/experimental/tool' + }); +} + +export class Instance extends HeyApiClient { + /** + * Dispose instance + * + * Clean up and dispose the current OpenCode instance, releasing all resources. + */ + public dispose = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zInstanceDisposeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zInstanceDisposeResponse.parseAsync(data), + url: '/instance/dispose', + ...options, + ...params + }); + }, { + id: 'instanceDispose', + method: 'post', + responseSchema: zInstanceDisposeResponse, + url: '/instance/dispose' + }); +} + +export class Path extends HeyApiClient { + /** + * Get paths + * + * Retrieve the current working directory and related path information for the OpenCode instance. + */ + public get = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zPathGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPathGetResponse.parseAsync(data), + url: '/path', + ...options, + ...params + }); + }, { + id: 'pathGet', + method: 'get', + responseSchema: zPathGetResponse, + url: '/path' + }); +} + +export class Vcs extends HeyApiClient { + /** + * Get VCS info + * + * Retrieve version control system (VCS) information for the current project, such as git branch. + */ + public get = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zVcsGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zVcsGetResponse.parseAsync(data), + url: '/vcs', + ...options, + ...params + }); + }, { + id: 'vcsGet', + method: 'get', + responseSchema: zVcsGetResponse, + url: '/vcs' + }); +} + +export class Session extends HeyApiClient { + /** + * List sessions + * + * Get a list of all OpenCode sessions, sorted by most recently updated. + */ + public list = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zSessionListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionListResponse.parseAsync(data), + url: '/session', + ...options, + ...params + }); + }, { + id: 'sessionList', + method: 'get', + responseSchema: zSessionListResponse, + url: '/session' + }); + + /** + * Create session + * + * Create a new OpenCode session for interacting with AI assistants and managing conversations. + */ + public create = Object.assign((parameters?: { + directory?: string; + parentID?: string; + title?: string; + permission?: PermissionRuleset; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'body', key: 'parentID' }, + { in: 'body', key: 'title' }, + { in: 'body', key: 'permission' } + ] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionCreateBody.optional(), + path: z.never().optional(), + query: zSessionCreateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionCreateResponse.parseAsync(data), + url: '/session', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionCreate', + method: 'post', + responseSchema: zSessionCreateResponse, + url: '/session' + }); + + /** + * Get session status + * + * Retrieve the current status of all sessions, including active, idle, and completed states. + */ + public status = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zSessionStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionStatusResponse.parseAsync(data), + url: '/session/status', + ...options, + ...params + }); + }, { + id: 'sessionStatus', + method: 'get', + responseSchema: zSessionStatusResponse, + url: '/session/status' + }); + + /** + * Delete session + * + * Delete a session and permanently remove all associated data, including messages and history. + */ + public delete = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionDeletePath, + query: zSessionDeleteQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionDeleteResponse.parseAsync(data), + url: '/session/{sessionID}', + ...options, + ...params + }); + }, { + id: 'sessionDelete', + method: 'delete', + responseSchema: zSessionDeleteResponse, + url: '/session/{sessionID}' + }); + + /** + * Get session + * + * Retrieve detailed information about a specific OpenCode session. + */ + public get = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionGetPath, + query: zSessionGetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionGetResponse.parseAsync(data), + url: '/session/{sessionID}', + ...options, + ...params + }); + }, { + id: 'sessionGet', + method: 'get', + responseSchema: zSessionGetResponse, + tags: ['Session'], + url: '/session/{sessionID}' + }); + + /** + * Update session + * + * Update properties of an existing session, such as title or other metadata. + */ + public update = Object.assign((parameters: { + sessionID: string; + directory?: string; + title?: string; + time?: { + archived?: number; + }; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'title' }, + { in: 'body', key: 'time' } + ] }]); + return (options?.client ?? this.client).patch({ + requestValidator: async (data) => await z.object({ + body: zSessionUpdateBody.optional(), + path: zSessionUpdatePath, + query: zSessionUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionUpdateResponse.parseAsync(data), + url: '/session/{sessionID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionUpdate', + method: 'patch', + responseSchema: zSessionUpdateResponse, + url: '/session/{sessionID}' + }); + + /** + * Get session children + * + * Retrieve all child sessions that were forked from the specified parent session. + */ + public children = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionChildrenPath, + query: zSessionChildrenQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionChildrenResponse.parseAsync(data), + url: '/session/{sessionID}/children', + ...options, + ...params + }); + }, { + id: 'sessionChildren', + method: 'get', + responseSchema: zSessionChildrenResponse, + tags: ['Session'], + url: '/session/{sessionID}/children' + }); + + /** + * Get session todos + * + * Retrieve the todo list associated with a specific session, showing tasks and action items. + */ + public todo = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionTodoPath, + query: zSessionTodoQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionTodoResponse.parseAsync(data), + url: '/session/{sessionID}/todo', + ...options, + ...params + }); + }, { + id: 'sessionTodo', + method: 'get', + responseSchema: zSessionTodoResponse, + url: '/session/{sessionID}/todo' + }); + + /** + * Initialize session + * + * Analyze the current application and create an AGENTS.md file with project-specific agent configurations. + */ + public init = Object.assign((parameters: { + sessionID: string; + directory?: string; + modelID: string; + providerID: string; + messageID: string; + }, options?: Options) => { + 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({ + requestValidator: async (data) => await z.object({ + body: zSessionInitBody.optional(), + path: zSessionInitPath, + query: zSessionInitQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionInitResponse.parseAsync(data), + url: '/session/{sessionID}/init', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionInit', + method: 'post', + responseSchema: zSessionInitResponse, + url: '/session/{sessionID}/init' + }); + + /** + * Fork session + * + * Create a new session by forking an existing session at a specific message point. + */ + public fork = Object.assign((parameters: { + sessionID: string; + directory?: string; + messageID?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'messageID' } + ] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionForkBody.optional(), + path: zSessionForkPath, + query: zSessionForkQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionForkResponse.parseAsync(data), + url: '/session/{sessionID}/fork', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionFork', + method: 'post', + responseSchema: zSessionForkResponse, + url: '/session/{sessionID}/fork' + }); + + /** + * Abort session + * + * Abort an active session and stop any ongoing AI processing or command execution. + */ + public abort = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionAbortPath, + query: zSessionAbortQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionAbortResponse.parseAsync(data), + url: '/session/{sessionID}/abort', + ...options, + ...params + }); + }, { + id: 'sessionAbort', + method: 'post', + responseSchema: zSessionAbortResponse, + url: '/session/{sessionID}/abort' + }); + + /** + * Unshare session + * + * Remove the shareable link for a session, making it private again. + */ + public unshare = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionUnsharePath, + query: zSessionUnshareQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionUnshareResponse.parseAsync(data), + url: '/session/{sessionID}/share', + ...options, + ...params + }); + }, { + id: 'sessionUnshare', + method: 'delete', + responseSchema: zSessionUnshareResponse, + url: '/session/{sessionID}/share' + }); + + /** + * Share session + * + * Create a shareable link for a session, allowing others to view the conversation. + */ + public share = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionSharePath, + query: zSessionShareQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionShareResponse.parseAsync(data), + url: '/session/{sessionID}/share', + ...options, + ...params + }); + }, { + id: 'sessionShare', + method: 'post', + responseSchema: zSessionShareResponse, + url: '/session/{sessionID}/share' + }); + + /** + * Get session diff + * + * Get all file changes (diffs) made during this session. + */ + public diff = Object.assign((parameters: { + sessionID: string; + directory?: string; + messageID?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'query', key: 'messageID' } + ] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionDiffPath, + query: zSessionDiffQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionDiffResponse.parseAsync(data), + url: '/session/{sessionID}/diff', + ...options, + ...params + }); + }, { + id: 'sessionDiff', + method: 'get', + responseSchema: zSessionDiffResponse, + url: '/session/{sessionID}/diff' + }); + + /** + * Summarize session + * + * Generate a concise summary of the session using AI compaction to preserve key information. + */ + public summarize = Object.assign((parameters: { + sessionID: string; + directory?: string; + providerID: string; + modelID: string; + auto?: boolean; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'providerID' }, + { in: 'body', key: 'modelID' }, + { in: 'body', key: 'auto' } + ] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionSummarizeBody.optional(), + path: zSessionSummarizePath, + query: zSessionSummarizeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionSummarizeResponse.parseAsync(data), + url: '/session/{sessionID}/summarize', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionSummarize', + method: 'post', + responseSchema: zSessionSummarizeResponse, + url: '/session/{sessionID}/summarize' + }); + + /** + * Get session messages + * + * Retrieve all messages in a session, including user prompts and AI responses. + */ + public messages = Object.assign((parameters: { + sessionID: string; + directory?: string; + limit?: number; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'query', key: 'directory' }, + { in: 'query', key: 'limit' } + ] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionMessagesPath, + query: zSessionMessagesQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionMessagesResponse.parseAsync(data), + url: '/session/{sessionID}/message', + ...options, + ...params + }); + }, { + id: 'sessionMessages', + method: 'get', + responseSchema: zSessionMessagesResponse, + url: '/session/{sessionID}/message' + }); + + /** + * Send message + * + * Create and send a new message to a session, streaming the AI response. + */ + public prompt = Object.assign((parameters: { + sessionID: string; + directory?: string; + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; + }, options?: Options) => { + 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: 'tools' }, + { in: 'body', key: 'system' }, + { in: 'body', key: 'variant' }, + { in: 'body', key: 'parts' } + ] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionPromptBody.optional(), + path: zSessionPromptPath, + query: zSessionPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionPromptResponse.parseAsync(data), + url: '/session/{sessionID}/message', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionPrompt', + method: 'post', + responseSchema: zSessionPromptResponse, + url: '/session/{sessionID}/message' + }); + + /** + * Get message + * + * Retrieve a specific message from a session by its message ID. + */ + public message = Object.assign((parameters: { + sessionID: string; + messageID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'messageID' }, + { in: 'query', key: 'directory' } + ] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionMessagePath, + query: zSessionMessageQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionMessageResponse.parseAsync(data), + url: '/session/{sessionID}/message/{messageID}', + ...options, + ...params + }); + }, { + id: 'sessionMessage', + method: 'get', + responseSchema: zSessionMessageResponse, + url: '/session/{sessionID}/message/{messageID}' + }); + + /** + * Send async message + * + * Create and send a new message to a session asynchronously, starting the session if needed and returning immediately. + */ + public promptAsync = Object.assign((parameters: { + sessionID: string; + directory?: string; + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; + }, options?: Options) => { + 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: 'tools' }, + { in: 'body', key: 'system' }, + { in: 'body', key: 'variant' }, + { in: 'body', key: 'parts' } + ] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionPromptAsyncBody.optional(), + path: zSessionPromptAsyncPath, + query: zSessionPromptAsyncQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionPromptAsyncResponse.parseAsync(data), + url: '/session/{sessionID}/prompt_async', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionPromptAsync', + method: 'post', + responseSchema: zSessionPromptAsyncResponse, + url: '/session/{sessionID}/prompt_async' + }); + + /** + * Send command + * + * Send a new command to a session for execution by the AI assistant. + */ + public command = Object.assign((parameters: { + sessionID: string; + directory?: string; + messageID?: string; + agent?: string; + model?: string; + arguments: string; + command: string; + variant?: string; + }, options?: Options) => { + 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' }, + { in: 'body', key: 'variant' } + ] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: zSessionCommandBody.optional(), + path: zSessionCommandPath, + query: zSessionCommandQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionCommandResponse.parseAsync(data), + url: '/session/{sessionID}/command', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionCommand', + method: 'post', + responseSchema: zSessionCommandResponse, + url: '/session/{sessionID}/command' + }); + + /** + * Run shell command + * + * Execute a shell command within the session context and return the AI's response. + */ + public shell = Object.assign((parameters: { + sessionID: string; + directory?: string; + agent: string; + model?: { + providerID: string; + modelID: string; + }; + command: string; + }, options?: Options) => { + 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({ + requestValidator: async (data) => await z.object({ + body: zSessionShellBody.optional(), + path: zSessionShellPath, + query: zSessionShellQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionShellResponse.parseAsync(data), + url: '/session/{sessionID}/shell', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionShell', + method: 'post', + responseSchema: zSessionShellResponse, + url: '/session/{sessionID}/shell' + }); + + /** + * Revert message + * + * Revert a specific message in a session, undoing its effects and restoring the previous state. + */ + public revert = Object.assign((parameters: { + sessionID: string; + directory?: string; + messageID: string; + partID?: string; + }, options?: Options) => { + 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({ + requestValidator: async (data) => await z.object({ + body: zSessionRevertBody.optional(), + path: zSessionRevertPath, + query: zSessionRevertQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionRevertResponse.parseAsync(data), + url: '/session/{sessionID}/revert', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'sessionRevert', + method: 'post', + responseSchema: zSessionRevertResponse, + url: '/session/{sessionID}/revert' + }); + + /** + * Restore reverted messages + * + * Restore all previously reverted messages in a session. + */ + public unrevert = Object.assign((parameters: { + sessionID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'sessionID' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zSessionUnrevertPath, + query: zSessionUnrevertQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zSessionUnrevertResponse.parseAsync(data), + url: '/session/{sessionID}/unrevert', + ...options, + ...params + }); + }, { + id: 'sessionUnrevert', + method: 'post', + responseSchema: zSessionUnrevertResponse, + url: '/session/{sessionID}/unrevert' + }); +} + +export class Part extends HeyApiClient { + /** + * Delete a part from a message + */ + public delete = Object.assign((parameters: { + sessionID: string; + messageID: string; + partID: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'messageID' }, + { in: 'path', key: 'partID' }, + { in: 'query', key: 'directory' } + ] }]); + return (options?.client ?? this.client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zPartDeletePath, + query: zPartDeleteQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPartDeleteResponse.parseAsync(data), + url: '/session/{sessionID}/message/{messageID}/part/{partID}', + ...options, + ...params + }); + }, { + id: 'partDelete', + method: 'delete', + responseSchema: zPartDeleteResponse, + url: '/session/{sessionID}/message/{messageID}/part/{partID}' + }); + + /** + * Update a part in a message + */ + public update = Object.assign((parameters: { + sessionID: string; + messageID: string; + partID: string; + directory?: string; + part?: Part2; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'sessionID' }, + { in: 'path', key: 'messageID' }, + { in: 'path', key: 'partID' }, + { in: 'query', key: 'directory' }, + { key: 'part', map: 'body' } + ] }]); + return (options?.client ?? this.client).patch({ + requestValidator: async (data) => await z.object({ + body: zPartUpdateBody.optional(), + path: zPartUpdatePath, + query: zPartUpdateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPartUpdateResponse.parseAsync(data), + url: '/session/{sessionID}/message/{messageID}/part/{partID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'partUpdate', + method: 'patch', + responseSchema: zPartUpdateResponse, + url: '/session/{sessionID}/message/{messageID}/part/{partID}' + }); +} + +export class Permission extends HeyApiClient { + /** + * Respond to permission + * + * Approve or deny a permission request from the AI assistant. + * + * @deprecated + */ + public respond = Object.assign((parameters: { + sessionID: string; + permissionID: string; + directory?: string; + response: 'once' | 'always' | 'reject'; + }, options?: Options) => { + 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({ + requestValidator: async (data) => await z.object({ + body: zPermissionRespondBody.optional(), + path: zPermissionRespondPath, + query: zPermissionRespondQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPermissionRespondResponse.parseAsync(data), + url: '/session/{sessionID}/permissions/{permissionID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'permissionRespond', + method: 'post', + responseSchema: zPermissionRespondResponse, + url: '/session/{sessionID}/permissions/{permissionID}' + }); + + /** + * Respond to permission request + * + * Approve or deny a permission request from the AI assistant. + */ + public reply = Object.assign((parameters: { + requestID: string; + directory?: string; + reply: 'once' | 'always' | 'reject'; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'requestID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'reply' } + ] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: zPermissionReplyBody.optional(), + path: zPermissionReplyPath, + query: zPermissionReplyQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPermissionReplyResponse.parseAsync(data), + url: '/permission/{requestID}/reply', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'permissionReply', + method: 'post', + responseSchema: zPermissionReplyResponse, + url: '/permission/{requestID}/reply' + }); + + /** + * List pending permissions + * + * Get all pending permission requests across all sessions. + */ + public list = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zPermissionListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zPermissionListResponse.parseAsync(data), + url: '/permission', + ...options, + ...params + }); + }, { + id: 'permissionList', + method: 'get', + responseSchema: zPermissionListResponse, + url: '/permission' + }); +} + +export class Command extends HeyApiClient { + /** + * List commands + * + * Get a list of all available commands in the OpenCode system. + */ + public list = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zCommandListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zCommandListResponse.parseAsync(data), + url: '/command', + ...options, + ...params + }); + }, { + id: 'commandList', + method: 'get', + responseSchema: zCommandListResponse, + url: '/command' + }); +} + +export class Oauth extends HeyApiClient { + /** + * OAuth authorize + * + * Initiate OAuth authorization for a specific AI provider to get an authorization URL. + */ + public authorize = Object.assign((parameters: { + providerID: string; + directory?: string; + method: number; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'providerID' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'method' } + ] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: zProviderOauthAuthorizeBody.optional(), + path: zProviderOauthAuthorizePath, + query: zProviderOauthAuthorizeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderOauthAuthorizeResponse.parseAsync(data), + url: '/provider/{providerID}/oauth/authorize', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'providerOauthAuthorize', + method: 'post', + responseSchema: zProviderOauthAuthorizeResponse, + url: '/provider/{providerID}/oauth/authorize' + }); + + /** + * OAuth callback + * + * Handle the OAuth callback from a provider after user authorization. + */ + public callback = Object.assign((parameters: { + providerID: string; + directory?: string; + method: number; + code?: string; + }, options?: Options) => { + 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({ + requestValidator: async (data) => await z.object({ + body: zProviderOauthCallbackBody.optional(), + path: zProviderOauthCallbackPath, + query: zProviderOauthCallbackQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderOauthCallbackResponse.parseAsync(data), + url: '/provider/{providerID}/oauth/callback', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'providerOauthCallback', + method: 'post', + responseSchema: zProviderOauthCallbackResponse, + url: '/provider/{providerID}/oauth/callback' + }); +} + +export class Provider extends HeyApiClient { + /** + * List providers + * + * Get a list of all available AI providers, including both available and connected ones. + */ + public list = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProviderListQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderListResponse.parseAsync(data), + url: '/provider', + ...options, + ...params + }); + }, { + id: 'providerList', + method: 'get', + responseSchema: zProviderListResponse, + url: '/provider' + }); + + /** + * Get provider auth methods + * + * Retrieve available authentication methods for all AI providers. + */ + public auth = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zProviderAuthQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zProviderAuthResponse.parseAsync(data), + url: '/provider/auth', + ...options, + ...params + }); + }, { + id: 'providerAuth', + method: 'get', + responseSchema: zProviderAuthResponse, + url: '/provider/auth' + }); + + private _oauth?: Oauth; + get oauth(): Oauth { + return this._oauth ??= new Oauth({ client: this.client }); + } +} + +export class Find extends HeyApiClient { + /** + * Find text + * + * Search for text patterns across files in the project using ripgrep. + */ + public text = Object.assign((parameters: { + directory?: string; + pattern: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'pattern' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFindTextQuery + }).parseAsync(data), + responseValidator: async (data) => await zFindTextResponse.parseAsync(data), + url: '/find', + ...options, + ...params + }); + }, { + id: 'findText', + method: 'get', + responseSchema: zFindTextResponse, + url: '/find' + }); + + /** + * Find files + * + * Search for files or directories by name or pattern in the project directory. + */ + public files = Object.assign((parameters: { + directory?: string; + query: string; + dirs?: 'true' | 'false'; + type?: 'file' | 'directory'; + limit?: number; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'query', key: 'query' }, + { in: 'query', key: 'dirs' }, + { in: 'query', key: 'type' }, + { in: 'query', key: 'limit' } + ] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFindFilesQuery + }).parseAsync(data), + responseValidator: async (data) => await zFindFilesResponse.parseAsync(data), + url: '/find/file', + ...options, + ...params + }); + }, { + id: 'findFiles', + method: 'get', + responseSchema: zFindFilesResponse, + url: '/find/file' + }); + + /** + * Find symbols + * + * Search for workspace symbols like functions, classes, and variables using LSP. + */ + public symbols = Object.assign((parameters: { + directory?: string; + query: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'query' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFindSymbolsQuery + }).parseAsync(data), + responseValidator: async (data) => await zFindSymbolsResponse.parseAsync(data), + url: '/find/symbol', + ...options, + ...params + }); + }, { + id: 'findSymbols', + method: 'get', + responseSchema: zFindSymbolsResponse, + url: '/find/symbol' + }); +} + +export class File_ extends HeyApiClient { + /** + * List files + * + * List files and directories in a specified path. + */ + public list = Object.assign((parameters: { + directory?: string; + path: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'path' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFileListQuery + }).parseAsync(data), + responseValidator: async (data) => await zFileListResponse.parseAsync(data), + url: '/file', + ...options, + ...params + }); + }, { + id: 'fileList', + method: 'get', + responseSchema: zFileListResponse, + url: '/file' + }); + + /** + * Read file + * + * Read the content of a specified file. + */ + public read = Object.assign((parameters: { + directory?: string; + path: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'query', key: 'path' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFileReadQuery + }).parseAsync(data), + responseValidator: async (data) => await zFileReadResponse.parseAsync(data), + url: '/file/content', + ...options, + ...params + }); + }, { + id: 'fileRead', + method: 'get', + responseSchema: zFileReadResponse, + url: '/file/content' + }); + + /** + * Get file status + * + * Get the git status of all files in the project. + */ + public status = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFileStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zFileStatusResponse.parseAsync(data), + url: '/file/status', + ...options, + ...params + }); + }, { + id: 'fileStatus', + method: 'get', + responseSchema: zFileStatusResponse, + url: '/file/status' + }); +} + +export class App extends HeyApiClient { + /** + * Write log + * + * Write a log entry to the server logs with specified level and metadata. + */ + public log = Object.assign((parameters: { + directory?: string; + service: string; + level: 'debug' | 'info' | 'error' | 'warn'; + message: string; + extra?: { + [key: string]: unknown; + }; + }, options?: Options) => { + 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({ + requestValidator: async (data) => await z.object({ + body: zAppLogBody.optional(), + path: z.never().optional(), + query: zAppLogQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zAppLogResponse.parseAsync(data), + url: '/log', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'appLog', + method: 'post', + responseSchema: zAppLogResponse, + url: '/log' + }); + + /** + * List agents + * + * Get a list of all available AI agents in the OpenCode system. + */ + public agents = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zAppAgentsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zAppAgentsResponse.parseAsync(data), + url: '/agent', + ...options, + ...params + }); + }, { + id: 'appAgents', + method: 'get', + responseSchema: zAppAgentsResponse, + url: '/agent' + }); +} + +export class Auth extends HeyApiClient { + /** + * Remove MCP OAuth + * + * Remove OAuth credentials for an MCP server + */ + public remove = Object.assign((parameters: { + name: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).delete({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpAuthRemovePath, + query: zMcpAuthRemoveQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthRemoveResponse.parseAsync(data), + url: '/mcp/{name}/auth', + ...options, + ...params + }); + }, { + id: 'mcpAuthRemove', + method: 'delete', + responseSchema: zMcpAuthRemoveResponse, + url: '/mcp/{name}/auth' + }); + + /** + * Start MCP OAuth + * + * Start OAuth authentication flow for a Model Context Protocol (MCP) server. + */ + public start = Object.assign((parameters: { + name: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpAuthStartPath, + query: zMcpAuthStartQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthStartResponse.parseAsync(data), + url: '/mcp/{name}/auth', + ...options, + ...params + }); + }, { + id: 'mcpAuthStart', + method: 'post', + responseSchema: zMcpAuthStartResponse, + url: '/mcp/{name}/auth' + }); + + /** + * Complete MCP OAuth + * + * Complete OAuth authentication for a Model Context Protocol (MCP) server using the authorization code. + */ + public callback = Object.assign((parameters: { + name: string; + directory?: string; + code: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'name' }, + { in: 'query', key: 'directory' }, + { in: 'body', key: 'code' } + ] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: zMcpAuthCallbackBody.optional(), + path: zMcpAuthCallbackPath, + query: zMcpAuthCallbackQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthCallbackResponse.parseAsync(data), + url: '/mcp/{name}/auth/callback', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'mcpAuthCallback', + method: 'post', + responseSchema: zMcpAuthCallbackResponse, + url: '/mcp/{name}/auth/callback' + }); + + /** + * Authenticate MCP OAuth + * + * Start OAuth flow and wait for callback (opens browser) + */ + public authenticate = Object.assign((parameters: { + name: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpAuthAuthenticatePath, + query: zMcpAuthAuthenticateQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAuthAuthenticateResponse.parseAsync(data), + url: '/mcp/{name}/auth/authenticate', + ...options, + ...params + }); + }, { + id: 'mcpAuthAuthenticate', + method: 'post', + responseSchema: zMcpAuthAuthenticateResponse, + url: '/mcp/{name}/auth/authenticate' + }); +} + +export class Mcp extends HeyApiClient { + /** + * Get MCP status + * + * Get the status of all Model Context Protocol (MCP) servers. + */ + public status = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zMcpStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpStatusResponse.parseAsync(data), + url: '/mcp', + ...options, + ...params + }); + }, { + id: 'mcpStatus', + method: 'get', + responseSchema: zMcpStatusResponse, + url: '/mcp' + }); + + /** + * Add MCP server + * + * Dynamically add a new Model Context Protocol (MCP) server to the system. + */ + public add = Object.assign((parameters: { + directory?: string; + name: string; + config: McpLocalConfig | McpRemoteConfig; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'query', key: 'directory' }, + { in: 'body', key: 'name' }, + { in: 'body', key: 'config' } + ] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: zMcpAddBody.optional(), + path: z.never().optional(), + query: zMcpAddQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpAddResponse.parseAsync(data), + url: '/mcp', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'mcpAdd', + method: 'post', + responseSchema: zMcpAddResponse, + url: '/mcp' + }); + + /** + * Connect an MCP server + */ + public connect = Object.assign((parameters: { + name: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpConnectPath, + query: zMcpConnectQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpConnectResponse.parseAsync(data), + url: '/mcp/{name}/connect', + ...options, + ...params + }); + }, { + id: 'mcpConnect', + method: 'post', + responseSchema: zMcpConnectResponse, + url: '/mcp/{name}/connect' + }); + + /** + * Disconnect an MCP server + */ + public disconnect = Object.assign((parameters: { + name: string; + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'path', key: 'name' }, { in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: zMcpDisconnectPath, + query: zMcpDisconnectQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zMcpDisconnectResponse.parseAsync(data), + url: '/mcp/{name}/disconnect', + ...options, + ...params + }); + }, { + id: 'mcpDisconnect', + method: 'post', + responseSchema: zMcpDisconnectResponse, + url: '/mcp/{name}/disconnect' + }); + + private _auth?: Auth; + get auth(): Auth { + return this._auth ??= new Auth({ client: this.client }); + } +} + +export class Lsp extends HeyApiClient { + /** + * Get LSP status + * + * Get LSP server status + */ + public status = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zLspStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zLspStatusResponse.parseAsync(data), + url: '/lsp', + ...options, + ...params + }); + }, { + id: 'lspStatus', + method: 'get', + responseSchema: zLspStatusResponse, + url: '/lsp' + }); +} + +export class Formatter extends HeyApiClient { + /** + * Get formatter status + * + * Get formatter status + */ + public status = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zFormatterStatusQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zFormatterStatusResponse.parseAsync(data), + url: '/formatter', + ...options, + ...params + }); + }, { + id: 'formatterStatus', + method: 'get', + responseSchema: zFormatterStatusResponse, + url: '/formatter' + }); +} + +export class Control extends HeyApiClient { + /** + * Get next TUI request + * + * Retrieve the next TUI (Terminal User Interface) request from the queue for processing. + */ + public next = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiControlNextQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiControlNextResponse.parseAsync(data), + url: '/tui/control/next', + ...options, + ...params + }); + }, { + id: 'tuiControlNext', + method: 'get', + responseSchema: zTuiControlNextResponse, + url: '/tui/control/next' + }); + + /** + * Submit TUI response + * + * Submit a response to the TUI request queue to complete a pending request. + */ + public response = Object.assign((parameters?: { + directory?: string; + body?: unknown; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { key: 'body', map: 'body' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiControlResponseBody.optional(), + path: z.never().optional(), + query: zTuiControlResponseQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiControlResponseResponse.parseAsync(data), + url: '/tui/control/response', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'tuiControlResponse', + method: 'post', + responseSchema: zTuiControlResponseResponse, + url: '/tui/control/response' + }); +} + +export class Tui extends HeyApiClient { + /** + * Append TUI prompt + * + * Append prompt to the TUI + */ + public appendPrompt = Object.assign((parameters: { + directory?: string; + text: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'body', key: 'text' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiAppendPromptBody.optional(), + path: z.never().optional(), + query: zTuiAppendPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiAppendPromptResponse.parseAsync(data), + url: '/tui/append-prompt', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'tuiAppendPrompt', + method: 'post', + responseSchema: zTuiAppendPromptResponse, + url: '/tui/append-prompt' + }); + + /** + * Open help dialog + * + * Open the help dialog in the TUI to display user assistance information. + */ + public openHelp = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenHelpQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenHelpResponse.parseAsync(data), + url: '/tui/open-help', + ...options, + ...params + }); + }, { + id: 'tuiOpenHelp', + method: 'post', + responseSchema: zTuiOpenHelpResponse, + url: '/tui/open-help' + }); + + /** + * Open sessions dialog + * + * Open the session dialog + */ + public openSessions = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenSessionsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenSessionsResponse.parseAsync(data), + url: '/tui/open-sessions', + ...options, + ...params + }); + }, { + id: 'tuiOpenSessions', + method: 'post', + responseSchema: zTuiOpenSessionsResponse, + url: '/tui/open-sessions' + }); + + /** + * Open themes dialog + * + * Open the theme dialog + */ + public openThemes = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenThemesQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenThemesResponse.parseAsync(data), + url: '/tui/open-themes', + ...options, + ...params + }); + }, { + id: 'tuiOpenThemes', + method: 'post', + responseSchema: zTuiOpenThemesResponse, + url: '/tui/open-themes' + }); + + /** + * Open models dialog + * + * Open the model dialog + */ + public openModels = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiOpenModelsQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiOpenModelsResponse.parseAsync(data), + url: '/tui/open-models', + ...options, + ...params + }); + }, { + id: 'tuiOpenModels', + method: 'post', + responseSchema: zTuiOpenModelsResponse, + url: '/tui/open-models' + }); + + /** + * Submit TUI prompt + * + * Submit the prompt + */ + public submitPrompt = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiSubmitPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiSubmitPromptResponse.parseAsync(data), + url: '/tui/submit-prompt', + ...options, + ...params + }); + }, { + id: 'tuiSubmitPrompt', + method: 'post', + responseSchema: zTuiSubmitPromptResponse, + url: '/tui/submit-prompt' + }); + + /** + * Clear TUI prompt + * + * Clear the prompt + */ + public clearPrompt = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zTuiClearPromptQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiClearPromptResponse.parseAsync(data), + url: '/tui/clear-prompt', + ...options, + ...params + }); + }, { + id: 'tuiClearPrompt', + method: 'post', + responseSchema: zTuiClearPromptResponse, + url: '/tui/clear-prompt' + }); + + /** + * Execute TUI command + * + * Execute a TUI command (e.g. agent_cycle) + */ + public executeCommand = Object.assign((parameters: { + directory?: string; + command: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { in: 'body', key: 'command' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiExecuteCommandBody.optional(), + path: z.never().optional(), + query: zTuiExecuteCommandQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiExecuteCommandResponse.parseAsync(data), + url: '/tui/execute-command', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'tuiExecuteCommand', + method: 'post', + responseSchema: zTuiExecuteCommandResponse, + url: '/tui/execute-command' + }); + + /** + * Show TUI toast + * + * Show a toast notification in the TUI + */ + public showToast = Object.assign((parameters: { + directory?: string; + title?: string; + message: string; + variant: 'info' | 'success' | 'warning' | 'error'; + duration?: number; + }, options?: Options) => { + 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({ + requestValidator: async (data) => await z.object({ + body: zTuiShowToastBody.optional(), + path: z.never().optional(), + query: zTuiShowToastQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiShowToastResponse.parseAsync(data), + url: '/tui/show-toast', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'tuiShowToast', + method: 'post', + responseSchema: zTuiShowToastResponse, + url: '/tui/show-toast' + }); + + /** + * Publish TUI event + * + * Publish a TUI event + */ + public publish = Object.assign((parameters?: { + directory?: string; + body?: EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }, { key: 'body', map: 'body' }] }]); + return (options?.client ?? this.client).post({ + requestValidator: async (data) => await z.object({ + body: zTuiPublishBody.optional(), + path: z.never().optional(), + query: zTuiPublishQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zTuiPublishResponse.parseAsync(data), + url: '/tui/publish', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'tuiPublish', + method: 'post', + responseSchema: zTuiPublishResponse, + url: '/tui/publish' + }); + + private _control?: Control; + get control(): Control { + return this._control ??= new Control({ client: this.client }); + } +} + +export class Auth2 extends HeyApiClient { + /** + * Set auth credentials + * + * Set authentication credentials + */ + public set = Object.assign((parameters: { + providerID: string; + directory?: string; + auth?: Auth3; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [ + { in: 'path', key: 'providerID' }, + { in: 'query', key: 'directory' }, + { key: 'auth', map: 'body' } + ] }]); + return (options?.client ?? this.client).put({ + requestValidator: async (data) => await z.object({ + body: zAuthSetBody.optional(), + path: zAuthSetPath, + query: zAuthSetQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zAuthSetResponse.parseAsync(data), + url: '/auth/{providerID}', + ...options, + ...params, + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + ...params.headers + } + }); + }, { + id: 'authSet', + method: 'put', + responseSchema: zAuthSetResponse, + url: '/auth/{providerID}' + }); +} + +export class Event_ extends HeyApiClient { + /** + * Subscribe to events + * + * Get events + */ + public subscribe = Object.assign((parameters?: { + directory?: string; + }, options?: Options) => { + const params = buildClientParams([parameters], [{ args: [{ in: 'query', key: 'directory' }] }]); + return (options?.client ?? this.client).sse.get({ + requestValidator: async (data) => await z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: zEventSubscribeQuery.optional() + }).parseAsync(data), + responseValidator: async (data) => await zEventSubscribeResponse.parseAsync(data), + url: '/event', + ...options, + ...params + }); + }, { + id: 'eventSubscribe', + method: 'get', + responseSchema: zEventSubscribeResponse, + url: '/event' + }); +} + +export class OpenCode extends HeyApiClient { + public static readonly __registry = new HeyApiRegistry(); + + constructor(args?: { + client?: Client; + key?: string; + }) { + super(args); + OpenCode.__registry.set(this, args?.key); + } + + private _global?: Global; + get global(): Global { + return this._global ??= new Global({ client: this.client }); + } + + private _project?: Project; + get project(): Project { + return this._project ??= new Project({ client: this.client }); + } + + private _pty?: Pty; + get pty(): Pty { + return this._pty ??= new Pty({ client: this.client }); + } + + private _config?: Config; + get config(): Config { + return this._config ??= new Config({ client: this.client }); + } + + private _tool?: Tool; + get tool(): Tool { + return this._tool ??= new Tool({ client: this.client }); + } + + private _instance?: Instance; + get instance(): Instance { + return this._instance ??= new Instance({ client: this.client }); + } + + private _path?: Path; + get path(): Path { + return this._path ??= new Path({ client: this.client }); + } + + private _vcs?: Vcs; + get vcs(): Vcs { + return this._vcs ??= new Vcs({ client: this.client }); + } + + private _session?: Session; + get session(): Session { + return this._session ??= new Session({ client: this.client }); + } + + private _part?: Part; + get part(): Part { + return this._part ??= new Part({ client: this.client }); + } + + private _permission?: Permission; + get permission(): Permission { + return this._permission ??= new Permission({ client: this.client }); + } + + private _command?: Command; + get command(): Command { + return this._command ??= new Command({ client: this.client }); + } + + private _provider?: Provider; + get provider(): Provider { + return this._provider ??= new Provider({ client: this.client }); + } + + private _find?: Find; + get find(): Find { + return this._find ??= new Find({ client: this.client }); + } + + private _file?: File_; + get file(): File_ { + return this._file ??= new File_({ client: this.client }); + } + + private _app?: App; + get app(): App { + return this._app ??= new App({ client: this.client }); + } + + private _mcp?: Mcp; + get mcp(): Mcp { + return this._mcp ??= new Mcp({ client: this.client }); + } + + private _lsp?: Lsp; + get lsp(): Lsp { + return this._lsp ??= new Lsp({ client: this.client }); + } + + private _formatter?: Formatter; + get formatter(): Formatter { + return this._formatter ??= new Formatter({ client: this.client }); + } + + private _tui?: Tui; + get tui(): Tui { + return this._tui ??= new Tui({ client: this.client }); + } + + private _auth?: Auth2; + get auth(): Auth2 { + return this._auth ??= new Auth2({ client: this.client }); + } + + private _event?: Event_; + get event(): Event_ { + return this._event ??= new Event_({ client: this.client }); + } +} diff --git a/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/types.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/types.gen.ts new file mode 100644 index 0000000000..ccae410e61 --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/types.gen.ts @@ -0,0 +1,4322 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type ClientOptions = { + baseUrl: `${string}://${string}` | (string & {}); +}; + +export type EventInstallationUpdated = { + type: 'installation.updated'; + properties: { + version: string; + }; +}; + +export type EventInstallationUpdateAvailable = { + type: 'installation.update-available'; + properties: { + version: string; + }; +}; + +export type Project = { + id: string; + worktree: string; + vcs?: 'git'; + name?: string; + icon?: { + url?: string; + color?: string; + }; + time: { + created: number; + updated: number; + initialized?: number; + }; +}; + +export type EventProjectUpdated = { + type: 'project.updated'; + properties: Project; +}; + +export type EventServerInstanceDisposed = { + type: 'server.instance.disposed'; + properties: { + directory: 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; + }; + agent: string; + model: { + providerID: string; + modelID: string; + }; + system?: string; + tools?: { + [key: string]: boolean; + }; + variant?: string; +}; + +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; + metadata?: { + [key: string]: 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; + agent: 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; +}; + +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; +}; + +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; + command?: 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 PermissionRequest = { + id: string; + sessionID: string; + permission: string; + patterns: Array; + metadata: { + [key: string]: unknown; + }; + always: Array; + tool?: { + messageID: string; + callID: string; + }; +}; + +export type EventPermissionAsked = { + type: 'permission.asked'; + properties: PermissionRequest; +}; + +export type EventPermissionReplied = { + type: 'permission.replied'; + properties: { + sessionID: string; + requestID: string; + reply: 'once' | 'always' | 'reject'; + }; +}; + +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; + }; +}; + +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 EventMcpToolsChanged = { + type: 'mcp.tools.changed'; + properties: { + server: string; + }; +}; + +export type EventCommandExecuted = { + type: 'command.executed'; + properties: { + name: string; + sessionID: string; + arguments: string; + messageID: string; + }; +}; + +export type PermissionAction = 'allow' | 'deny' | 'ask'; + +export type PermissionRule = { + permission: string; + pattern: string; + action: PermissionAction; +}; + +export type PermissionRuleset = Array; + +export type Session = { + id: string; + projectID: string; + directory: string; + parentID?: string; + summary?: { + additions: number; + deletions: number; + files: number; + diffs?: Array; + }; + share?: { + url: string; + }; + title: string; + version: string; + time: { + created: number; + updated: number; + compacting?: number; + archived?: number; + }; + permission?: PermissionRuleset; + 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; + }; +}; + +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 Pty = { + id: string; + title: string; + command: string; + args: Array; + 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 EventGlobalDisposed = { + type: 'global.disposed'; + properties: { + [key: string]: unknown; + }; +}; + +export type Event = EventInstallationUpdated | EventInstallationUpdateAvailable | EventProjectUpdated | EventServerInstanceDisposed | EventLspClientDiagnostics | EventLspUpdated | EventMessageUpdated | EventMessageRemoved | EventMessagePartUpdated | EventMessagePartRemoved | EventPermissionAsked | EventPermissionReplied | EventSessionStatus | EventSessionIdle | EventSessionCompacted | EventFileEdited | EventTodoUpdated | EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow | EventMcpToolsChanged | EventCommandExecuted | EventSessionCreated | EventSessionUpdated | EventSessionDeleted | EventSessionDiff | EventSessionError | EventFileWatcherUpdated | EventVcsBranchUpdated | EventPtyCreated | EventPtyUpdated | EventPtyExited | EventPtyDeleted | EventServerConnected | EventGlobalDisposed; + +export type GlobalEvent = { + directory: string; + payload: Event; +}; + +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; + /** + * Fork session from message + */ + session_fork?: string; + /** + * Rename session + */ + session_rename?: 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 next message + */ + messages_next?: string; + /** + * Navigate to previous message + */ + messages_previous?: 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; + /** + * Next favorite model + */ + model_cycle_favorite?: string; + /** + * Previous favorite model + */ + model_cycle_favorite_reverse?: string; + /** + * List available commands + */ + command_list?: string; + /** + * List agents + */ + agent_list?: string; + /** + * Next agent + */ + agent_cycle?: string; + /** + * Previous agent + */ + agent_cycle_reverse?: string; + /** + * Cycle model variants + */ + variant_cycle?: string; + /** + * Clear input field + */ + input_clear?: string; + /** + * Paste from clipboard + */ + input_paste?: string; + /** + * Submit input + */ + input_submit?: string; + /** + * Insert newline in input + */ + input_newline?: string; + /** + * Move cursor left in input + */ + input_move_left?: string; + /** + * Move cursor right in input + */ + input_move_right?: string; + /** + * Move cursor up in input + */ + input_move_up?: string; + /** + * Move cursor down in input + */ + input_move_down?: string; + /** + * Select left in input + */ + input_select_left?: string; + /** + * Select right in input + */ + input_select_right?: string; + /** + * Select up in input + */ + input_select_up?: string; + /** + * Select down in input + */ + input_select_down?: string; + /** + * Move to start of line in input + */ + input_line_home?: string; + /** + * Move to end of line in input + */ + input_line_end?: string; + /** + * Select to start of line in input + */ + input_select_line_home?: string; + /** + * Select to end of line in input + */ + input_select_line_end?: string; + /** + * Move to start of visual line in input + */ + input_visual_line_home?: string; + /** + * Move to end of visual line in input + */ + input_visual_line_end?: string; + /** + * Select to start of visual line in input + */ + input_select_visual_line_home?: string; + /** + * Select to end of visual line in input + */ + input_select_visual_line_end?: string; + /** + * Move to start of buffer in input + */ + input_buffer_home?: string; + /** + * Move to end of buffer in input + */ + input_buffer_end?: string; + /** + * Select to start of buffer in input + */ + input_select_buffer_home?: string; + /** + * Select to end of buffer in input + */ + input_select_buffer_end?: string; + /** + * Delete line in input + */ + input_delete_line?: string; + /** + * Delete to end of line in input + */ + input_delete_to_line_end?: string; + /** + * Delete to start of line in input + */ + input_delete_to_line_start?: string; + /** + * Backspace in input + */ + input_backspace?: string; + /** + * Delete character in input + */ + input_delete?: string; + /** + * Undo in input + */ + input_undo?: string; + /** + * Redo in input + */ + input_redo?: string; + /** + * Move word forward in input + */ + input_word_forward?: string; + /** + * Move word backward in input + */ + input_word_backward?: string; + /** + * Select word forward in input + */ + input_select_word_forward?: string; + /** + * Select word backward in input + */ + input_select_word_backward?: string; + /** + * Delete word forward in input + */ + input_delete_word_forward?: string; + /** + * Delete word backward in input + */ + input_delete_word_backward?: 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; + /** + * Go to parent session + */ + session_parent?: string; + /** + * Suspend terminal + */ + terminal_suspend?: string; + /** + * Toggle terminal title + */ + terminal_title_toggle?: string; + /** + * Toggle tips on home screen + */ + tips_toggle?: string; +}; + +/** + * Log level + */ +export type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR'; + +/** + * Server configuration for opencode serve and web commands + */ +export type ServerConfig = { + /** + * Port to listen on + */ + port?: number; + /** + * Hostname to listen on + */ + hostname?: string; + /** + * Enable mDNS service discovery + */ + mdns?: boolean; + /** + * Additional domains to allow for CORS + */ + cors?: Array; +}; + +export type PermissionActionConfig = 'ask' | 'allow' | 'deny'; + +export type PermissionObjectConfig = { + [key: string]: PermissionActionConfig; +}; + +export type PermissionRuleConfig = PermissionActionConfig | PermissionObjectConfig; + +export type PermissionConfig = { + read?: PermissionRuleConfig; + edit?: PermissionRuleConfig; + glob?: PermissionRuleConfig; + grep?: PermissionRuleConfig; + list?: PermissionRuleConfig; + bash?: PermissionRuleConfig; + task?: PermissionRuleConfig; + external_directory?: PermissionRuleConfig; + todowrite?: PermissionActionConfig; + todoread?: PermissionActionConfig; + webfetch?: PermissionActionConfig; + websearch?: PermissionActionConfig; + codesearch?: PermissionActionConfig; + lsp?: PermissionRuleConfig; + doom_loop?: PermissionActionConfig; + [key: string]: PermissionRuleConfig | PermissionActionConfig | undefined; +} | PermissionActionConfig; + +export type AgentConfig = { + model?: string; + temperature?: number; + top_p?: number; + prompt?: string; + /** + * @deprecated Use 'permission' field instead + */ + tools?: { + [key: string]: boolean; + }; + disable?: boolean; + /** + * Description of when to use the agent + */ + description?: string; + mode?: 'subagent' | 'primary' | 'all'; + options?: { + [key: string]: unknown; + }; + /** + * Hex color code for the agent (e.g., #FF5733) + */ + color?: string; + /** + * Maximum number of agentic iterations before forcing text-only response + */ + steps?: number; + /** + * @deprecated Use 'steps' field instead. + */ + maxSteps?: number; + permission?: PermissionConfig; + [key: string]: unknown; +}; + +export type ProviderConfig = { + api?: string; + name?: string; + env?: Array; + id?: string; + npm?: string; + models?: { + [key: string]: { + id?: string; + name?: string; + family?: string; + release_date?: string; + attachment?: boolean; + reasoning?: boolean; + temperature?: boolean; + tool_call?: boolean; + interleaved?: true | { + field: 'reasoning_content' | 'reasoning_details'; + }; + 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; + }; + /** + * Variant-specific configuration + */ + variants?: { + [key: string]: { + /** + * Disable this variant for the model + */ + disabled?: boolean; + [key: string]: unknown; + }; + }; + }; + }; + whitelist?: Array; + blacklist?: Array; + 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; + }; +}; + +export type McpLocalConfig = { + /** + * Type of MCP server connection + */ + type: 'local'; + /** + * Command and arguments to run the MCP server + */ + command: Array; + /** + * Environment variables to set when running the MCP server + */ + environment?: { + [key: string]: string; + }; + /** + * Enable or disable the MCP server on startup + */ + enabled?: boolean; + /** + * 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; + logLevel?: LogLevel; + /** + * 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'; + }; + server?: ServerConfig; + /** + * Command configuration, see https://opencode.ai/docs/commands + */ + command?: { + [key: string]: { + template: string; + description?: string; + agent?: string; + model?: string; + subtask?: boolean; + }; + }; + watcher?: { + ignore?: Array; + }; + plugin?: Array; + 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; + /** + * When set, ONLY these providers will be enabled. All other providers will be ignored + */ + enabled_providers?: Array; + /** + * 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; + /** + * Default agent to use when none is specified. Must be a primary agent. Falls back to 'build' if not set or if the specified agent is invalid. + */ + default_agent?: 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; + title?: AgentConfig; + summary?: AgentConfig; + compaction?: 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; + environment?: { + [key: string]: string; + }; + extensions?: Array; + }; + }; + lsp?: false | { + [key: string]: { + disabled: true; + } | { + command: Array; + extensions?: Array; + disabled?: boolean; + env?: { + [key: string]: string; + }; + initialization?: { + [key: string]: unknown; + }; + }; + }; + /** + * Additional instruction files or patterns to include + */ + instructions?: Array; + layout?: LayoutConfig; + permission?: PermissionConfig; + tools?: { + [key: string]: boolean; + }; + enterprise?: { + /** + * Enterprise URL + */ + url?: string; + }; + compaction?: { + /** + * Enable automatic compaction when context is full (default: true) + */ + auto?: boolean; + /** + * Enable pruning of old tool outputs (default: true) + */ + prune?: boolean; + }; + experimental?: { + hook?: { + file_edited?: { + [key: string]: Array<{ + command: Array; + environment?: { + [key: string]: string; + }; + }>; + }; + session_completed?: Array<{ + command: Array; + 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; + /** + * Continue the agent loop when a tool call is denied + */ + continue_loop_on_deny?: boolean; + /** + * Timeout in milliseconds for model context protocol (MCP) requests + */ + mcp_timeout?: number; + }; +}; + +export type ToolIds = Array; + +export type ToolListItem = { + id: string; + description: string; + parameters: unknown; +}; + +export type ToolList = Array; + +export type Path = { + home: string; + 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; + command?: string; +}; + +export type Command = { + name: string; + description?: string; + agent?: string; + model?: string; + mcp?: boolean; + template: string; + subtask?: boolean; + hints: Array; +}; + +export type Model = { + id: string; + providerID: string; + api: { + id: string; + url: string; + npm: string; + }; + name: string; + family?: 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; + }; + interleaved: boolean | { + field: 'reasoning_content' | 'reasoning_details'; + }; + }; + 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; + }; + release_date: string; + variants?: { + [key: string]: { + [key: string]: unknown; + }; + }; +}; + +export type Provider = { + id: string; + name: string; + source: 'env' | 'config' | 'custom' | 'api'; + env: Array; + 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; + }>; + 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'; + native?: boolean; + hidden?: boolean; + topP?: number; + temperature?: number; + color?: string; + permission: PermissionRuleset; + model?: { + modelID: string; + providerID: string; + }; + prompt?: string; + options: { + [key: string]: unknown; + }; + steps?: 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; + 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 GlobalHealthData = { + body?: never; + path?: never; + query?: never; + url: '/global/health'; +}; + +export type GlobalHealthResponses = { + /** + * Health information + */ + 200: { + healthy: true; + version: string; + }; +}; + +export type GlobalHealthResponse = GlobalHealthResponses[keyof GlobalHealthResponses]; + +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 GlobalDisposeData = { + body?: never; + path?: never; + query?: never; + url: '/global/dispose'; +}; + +export type GlobalDisposeResponses = { + /** + * Global disposed + */ + 200: boolean; +}; + +export type GlobalDisposeResponse = GlobalDisposeResponses[keyof GlobalDisposeResponses]; + +export type ProjectListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/project'; +}; + +export type ProjectListResponses = { + /** + * List of projects + */ + 200: Array; +}; + +export type ProjectListResponse = ProjectListResponses[keyof ProjectListResponses]; + +export type ProjectCurrentData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/project/current'; +}; + +export type ProjectCurrentResponses = { + /** + * Current project information + */ + 200: Project; +}; + +export type ProjectCurrentResponse = ProjectCurrentResponses[keyof ProjectCurrentResponses]; + +export type ProjectUpdateData = { + body?: { + name?: string; + icon?: { + url?: string; + color?: string; + }; + }; + path: { + projectID: string; + }; + query?: { + directory?: string; + }; + url: '/project/{projectID}'; +}; + +export type ProjectUpdateErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type ProjectUpdateError = ProjectUpdateErrors[keyof ProjectUpdateErrors]; + +export type ProjectUpdateResponses = { + /** + * Updated project information + */ + 200: Project; +}; + +export type ProjectUpdateResponse = ProjectUpdateResponses[keyof ProjectUpdateResponses]; + +export type PtyListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/pty'; +}; + +export type PtyListResponses = { + /** + * List of sessions + */ + 200: Array; +}; + +export type PtyListResponse = PtyListResponses[keyof PtyListResponses]; + +export type PtyCreateData = { + body?: { + command?: string; + args?: Array; + 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; +}; + +export type SessionListResponse = SessionListResponses[keyof SessionListResponses]; + +export type SessionCreateData = { + body?: { + parentID?: string; + title?: string; + permission?: PermissionRuleset; + }; + 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; + time?: { + archived?: number; + }; + }; + 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; +}; + +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; +}; + +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; +}; + +export type SessionDiffResponse = SessionDiffResponses[keyof SessionDiffResponses]; + +export type SessionSummarizeData = { + body?: { + providerID: string; + modelID: string; + auto?: boolean; + }; + 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; + }>; +}; + +export type SessionMessagesResponse = SessionMessagesResponses[keyof SessionMessagesResponses]; + +export type SessionPromptData = { + body?: { + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + /** + * @deprecated tools and permissions have been merged, you can set permissions on the session itself now + */ + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; + }; + 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; + }; +}; + +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; + }; +}; + +export type SessionMessageResponse = SessionMessageResponses[keyof SessionMessageResponses]; + +export type PartDeleteData = { + body?: never; + path: { + /** + * Session ID + */ + sessionID: string; + /** + * Message ID + */ + messageID: string; + /** + * Part ID + */ + partID: string; + }; + query?: { + directory?: string; + }; + url: '/session/{sessionID}/message/{messageID}/part/{partID}'; +}; + +export type PartDeleteErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type PartDeleteError = PartDeleteErrors[keyof PartDeleteErrors]; + +export type PartDeleteResponses = { + /** + * Successfully deleted part + */ + 200: boolean; +}; + +export type PartDeleteResponse = PartDeleteResponses[keyof PartDeleteResponses]; + +export type PartUpdateData = { + body?: Part; + path: { + /** + * Session ID + */ + sessionID: string; + /** + * Message ID + */ + messageID: string; + /** + * Part ID + */ + partID: string; + }; + query?: { + directory?: string; + }; + url: '/session/{sessionID}/message/{messageID}/part/{partID}'; +}; + +export type PartUpdateErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type PartUpdateError = PartUpdateErrors[keyof PartUpdateErrors]; + +export type PartUpdateResponses = { + /** + * Successfully updated part + */ + 200: Part; +}; + +export type PartUpdateResponse = PartUpdateResponses[keyof PartUpdateResponses]; + +export type SessionPromptAsyncData = { + body?: { + messageID?: string; + model?: { + providerID: string; + modelID: string; + }; + agent?: string; + noReply?: boolean; + /** + * @deprecated tools and permissions have been merged, you can set permissions on the session itself now + */ + tools?: { + [key: string]: boolean; + }; + system?: string; + variant?: string; + parts: Array; + }; + 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; + variant?: 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; + }; +}; + +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 PermissionReplyData = { + body?: { + reply: 'once' | 'always' | 'reject'; + }; + path: { + requestID: string; + }; + query?: { + directory?: string; + }; + url: '/permission/{requestID}/reply'; +}; + +export type PermissionReplyErrors = { + /** + * Bad request + */ + 400: BadRequestError; + /** + * Not found + */ + 404: NotFoundError; +}; + +export type PermissionReplyError = PermissionReplyErrors[keyof PermissionReplyErrors]; + +export type PermissionReplyResponses = { + /** + * Permission processed successfully + */ + 200: boolean; +}; + +export type PermissionReplyResponse = PermissionReplyResponses[keyof PermissionReplyResponses]; + +export type PermissionListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/permission'; +}; + +export type PermissionListResponses = { + /** + * List of pending permissions + */ + 200: Array; +}; + +export type PermissionListResponse = PermissionListResponses[keyof PermissionListResponses]; + +export type CommandListData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/command'; +}; + +export type CommandListResponses = { + /** + * List of commands + */ + 200: Array; +}; + +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; + 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; + id: string; + npm?: string; + models: { + [key: string]: { + id: string; + name: string; + family?: string; + release_date: string; + attachment: boolean; + reasoning: boolean; + temperature: boolean; + tool_call: boolean; + interleaved?: true | { + field: 'reasoning_content' | 'reasoning_details'; + }; + 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; + }; + variants?: { + [key: string]: { + [key: string]: unknown; + }; + }; + }; + }; + }>; + default: { + [key: string]: string; + }; + connected: Array; + }; +}; + +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; + }; +}; + +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'; + type?: 'file' | 'directory'; + limit?: number; + }; + url: '/find/file'; +}; + +export type FindFilesResponses = { + /** + * File paths + */ + 200: Array; +}; + +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; +}; + +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; +}; + +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; +}; + +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; +}; + +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 McpConnectData = { + body?: never; + path: { + name: string; + }; + query?: { + directory?: string; + }; + url: '/mcp/{name}/connect'; +}; + +export type McpConnectResponses = { + /** + * MCP server connected successfully + */ + 200: boolean; +}; + +export type McpConnectResponse = McpConnectResponses[keyof McpConnectResponses]; + +export type McpDisconnectData = { + body?: never; + path: { + name: string; + }; + query?: { + directory?: string; + }; + url: '/mcp/{name}/disconnect'; +}; + +export type McpDisconnectResponses = { + /** + * MCP server disconnected successfully + */ + 200: boolean; +}; + +export type McpDisconnectResponse = McpDisconnectResponses[keyof McpDisconnectResponses]; + +export type LspStatusData = { + body?: never; + path?: never; + query?: { + directory?: string; + }; + url: '/lsp'; +}; + +export type LspStatusResponses = { + /** + * LSP server status + */ + 200: Array; +}; + +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; +}; + +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/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/zod.gen.ts b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/zod.gen.ts new file mode 100644 index 0000000000..3d21c8726b --- /dev/null +++ b/packages/openapi-ts-tests/sdks/__snapshots__/opencode/metadata-single/zod.gen.ts @@ -0,0 +1,2749 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import * as z from 'zod'; + +export const zEventInstallationUpdated = z.object({ + type: z.literal('installation.updated'), + properties: z.object({ + version: z.string() + }) +}); + +export const zEventInstallationUpdateAvailable = z.object({ + type: z.literal('installation.update-available'), + properties: z.object({ + version: z.string() + }) +}); + +export const zProject = z.object({ + id: z.string(), + worktree: z.string(), + vcs: z.literal('git').optional(), + name: z.string().optional(), + icon: z.object({ + url: z.string().optional(), + color: z.string().optional() + }).optional(), + time: z.object({ + created: z.number(), + updated: z.number(), + initialized: z.number().optional() + }) +}); + +export const zEventProjectUpdated = z.object({ + type: z.literal('project.updated'), + properties: zProject +}); + +export const zEventServerInstanceDisposed = z.object({ + type: z.literal('server.instance.disposed'), + properties: z.object({ + directory: z.string() + }) +}); + +export const zEventLspClientDiagnostics = z.object({ + type: z.literal('lsp.client.diagnostics'), + properties: z.object({ + serverID: z.string(), + path: z.string() + }) +}); + +export const zEventLspUpdated = z.object({ + type: z.literal('lsp.updated'), + properties: z.record(z.string(), z.unknown()) +}); + +export const zFileDiff = z.object({ + file: z.string(), + before: z.string(), + after: z.string(), + additions: z.number(), + deletions: z.number() +}); + +export const zUserMessage = z.object({ + id: z.string(), + sessionID: z.string(), + role: z.literal('user'), + time: z.object({ + created: z.number() + }), + summary: z.object({ + title: z.string().optional(), + body: z.string().optional(), + diffs: z.array(zFileDiff) + }).optional(), + agent: z.string(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }), + system: z.string().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + variant: z.string().optional() +}); + +export const zProviderAuthError = z.object({ + name: z.literal('ProviderAuthError'), + data: z.object({ + providerID: z.string(), + message: z.string() + }) +}); + +export const zUnknownError = z.object({ + name: z.literal('UnknownError'), + data: z.object({ + message: z.string() + }) +}); + +export const zMessageOutputLengthError = z.object({ + name: z.literal('MessageOutputLengthError'), + data: z.record(z.string(), z.unknown()) +}); + +export const zMessageAbortedError = z.object({ + name: z.literal('MessageAbortedError'), + data: z.object({ + message: z.string() + }) +}); + +export const zApiError = z.object({ + name: z.literal('APIError'), + data: z.object({ + message: z.string(), + statusCode: z.number().optional(), + isRetryable: z.boolean(), + responseHeaders: z.record(z.string(), z.string()).optional(), + responseBody: z.string().optional(), + metadata: z.record(z.string(), z.string()).optional() + }) +}); + +export const zAssistantMessage = z.object({ + id: z.string(), + sessionID: z.string(), + role: z.literal('assistant'), + time: z.object({ + created: z.number(), + completed: z.number().optional() + }), + error: z.union([ + zProviderAuthError, + zUnknownError, + zMessageOutputLengthError, + zMessageAbortedError, + zApiError + ]).optional(), + parentID: z.string(), + modelID: z.string(), + providerID: z.string(), + mode: z.string(), + agent: z.string(), + path: z.object({ + cwd: z.string(), + root: z.string() + }), + summary: z.boolean().optional(), + cost: z.number(), + tokens: z.object({ + input: z.number(), + output: z.number(), + reasoning: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }) + }), + finish: z.string().optional() +}); + +export const zMessage = z.union([ + zUserMessage, + zAssistantMessage +]); + +export const zEventMessageUpdated = z.object({ + type: z.literal('message.updated'), + properties: z.object({ + info: zMessage + }) +}); + +export const zEventMessageRemoved = z.object({ + type: z.literal('message.removed'), + properties: z.object({ + sessionID: z.string(), + messageID: z.string() + }) +}); + +export const zTextPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('text'), + text: z.string(), + synthetic: z.boolean().optional(), + ignored: z.boolean().optional(), + time: z.object({ + start: z.number(), + end: z.number().optional() + }).optional(), + metadata: z.record(z.string(), z.unknown()).optional() +}); + +export const zReasoningPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('reasoning'), + text: z.string(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number(), + end: z.number().optional() + }) +}); + +export const zFilePartSourceText = z.object({ + value: z.string(), + start: z.int().gte(-9007199254740991).lte(9007199254740991), + end: z.int().gte(-9007199254740991).lte(9007199254740991) +}); + +export const zFileSource = z.object({ + text: zFilePartSourceText, + type: z.literal('file'), + path: z.string() +}); + +export const zRange = z.object({ + start: z.object({ + line: z.number(), + character: z.number() + }), + end: z.object({ + line: z.number(), + character: z.number() + }) +}); + +export const zSymbolSource = z.object({ + text: zFilePartSourceText, + type: z.literal('symbol'), + path: z.string(), + range: zRange, + name: z.string(), + kind: z.int().gte(-9007199254740991).lte(9007199254740991) +}); + +export const zFilePartSource = z.union([ + zFileSource, + zSymbolSource +]); + +export const zFilePart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('file'), + mime: z.string(), + filename: z.string().optional(), + url: z.string(), + source: zFilePartSource.optional() +}); + +export const zToolStatePending = z.object({ + status: z.literal('pending'), + input: z.record(z.string(), z.unknown()), + raw: z.string() +}); + +export const zToolStateRunning = z.object({ + status: z.literal('running'), + input: z.record(z.string(), z.unknown()), + title: z.string().optional(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number() + }) +}); + +export const zToolStateCompleted = z.object({ + status: z.literal('completed'), + input: z.record(z.string(), z.unknown()), + output: z.string(), + title: z.string(), + metadata: z.record(z.string(), z.unknown()), + time: z.object({ + start: z.number(), + end: z.number(), + compacted: z.number().optional() + }), + attachments: z.array(zFilePart).optional() +}); + +export const zToolStateError = z.object({ + status: z.literal('error'), + input: z.record(z.string(), z.unknown()), + error: z.string(), + metadata: z.record(z.string(), z.unknown()).optional(), + time: z.object({ + start: z.number(), + end: z.number() + }) +}); + +export const zToolState = z.union([ + zToolStatePending, + zToolStateRunning, + zToolStateCompleted, + zToolStateError +]); + +export const zToolPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('tool'), + callID: z.string(), + tool: z.string(), + state: zToolState, + metadata: z.record(z.string(), z.unknown()).optional() +}); + +export const zStepStartPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('step-start'), + snapshot: z.string().optional() +}); + +export const zStepFinishPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('step-finish'), + reason: z.string(), + snapshot: z.string().optional(), + cost: z.number(), + tokens: z.object({ + input: z.number(), + output: z.number(), + reasoning: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }) + }) +}); + +export const zSnapshotPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('snapshot'), + snapshot: z.string() +}); + +export const zPatchPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('patch'), + hash: z.string(), + files: z.array(z.string()) +}); + +export const zAgentPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('agent'), + name: z.string(), + source: z.object({ + value: z.string(), + start: z.int().gte(-9007199254740991).lte(9007199254740991), + end: z.int().gte(-9007199254740991).lte(9007199254740991) + }).optional() +}); + +export const zRetryPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('retry'), + attempt: z.number(), + error: zApiError, + time: z.object({ + created: z.number() + }) +}); + +export const zCompactionPart = z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('compaction'), + auto: z.boolean() +}); + +export const zPart = z.union([ + zTextPart, + z.object({ + id: z.string(), + sessionID: z.string(), + messageID: z.string(), + type: z.literal('subtask'), + prompt: z.string(), + description: z.string(), + agent: z.string(), + command: z.string().optional() + }), + zReasoningPart, + zFilePart, + zToolPart, + zStepStartPart, + zStepFinishPart, + zSnapshotPart, + zPatchPart, + zAgentPart, + zRetryPart, + zCompactionPart +]); + +export const zEventMessagePartUpdated = z.object({ + type: z.literal('message.part.updated'), + properties: z.object({ + part: zPart, + delta: z.string().optional() + }) +}); + +export const zEventMessagePartRemoved = z.object({ + type: z.literal('message.part.removed'), + properties: z.object({ + sessionID: z.string(), + messageID: z.string(), + partID: z.string() + }) +}); + +export const zPermissionRequest = z.object({ + id: z.string().regex(/^per.*/), + sessionID: z.string().regex(/^ses.*/), + permission: z.string(), + patterns: z.array(z.string()), + metadata: z.record(z.string(), z.unknown()), + always: z.array(z.string()), + tool: z.object({ + messageID: z.string(), + callID: z.string() + }).optional() +}); + +export const zEventPermissionAsked = z.object({ + type: z.literal('permission.asked'), + properties: zPermissionRequest +}); + +export const zEventPermissionReplied = z.object({ + type: z.literal('permission.replied'), + properties: z.object({ + sessionID: z.string(), + requestID: z.string(), + reply: z.enum([ + 'once', + 'always', + 'reject' + ]) + }) +}); + +export const zSessionStatus = z.union([ + z.object({ + type: z.literal('idle') + }), + z.object({ + type: z.literal('retry'), + attempt: z.number(), + message: z.string(), + next: z.number() + }), + z.object({ + type: z.literal('busy') + }) +]); + +export const zEventSessionStatus = z.object({ + type: z.literal('session.status'), + properties: z.object({ + sessionID: z.string(), + status: zSessionStatus + }) +}); + +export const zEventSessionIdle = z.object({ + type: z.literal('session.idle'), + properties: z.object({ + sessionID: z.string() + }) +}); + +export const zEventSessionCompacted = z.object({ + type: z.literal('session.compacted'), + properties: z.object({ + sessionID: z.string() + }) +}); + +export const zEventFileEdited = z.object({ + type: z.literal('file.edited'), + properties: z.object({ + file: z.string() + }) +}); + +export const zTodo = z.object({ + content: z.string(), + status: z.string(), + priority: z.string(), + id: z.string() +}); + +export const zEventTodoUpdated = z.object({ + type: z.literal('todo.updated'), + properties: z.object({ + sessionID: z.string(), + todos: z.array(zTodo) + }) +}); + +export const zEventTuiPromptAppend = z.object({ + type: z.literal('tui.prompt.append'), + properties: z.object({ + text: z.string() + }) +}); + +export const zEventTuiCommandExecute = z.object({ + type: z.literal('tui.command.execute'), + properties: z.object({ + command: z.union([ + z.enum([ + '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' + ]), + z.string() + ]) + }) +}); + +export const zEventTuiToastShow = z.object({ + type: z.literal('tui.toast.show'), + properties: z.object({ + title: z.string().optional(), + message: z.string(), + variant: z.enum([ + 'info', + 'success', + 'warning', + 'error' + ]), + duration: z.number().optional().default(5000) + }) +}); + +export const zEventMcpToolsChanged = z.object({ + type: z.literal('mcp.tools.changed'), + properties: z.object({ + server: z.string() + }) +}); + +export const zEventCommandExecuted = z.object({ + type: z.literal('command.executed'), + properties: z.object({ + name: z.string(), + sessionID: z.string().regex(/^ses.*/), + arguments: z.string(), + messageID: z.string().regex(/^msg.*/) + }) +}); + +export const zPermissionAction = z.enum([ + 'allow', + 'deny', + 'ask' +]); + +export const zPermissionRule = z.object({ + permission: z.string(), + pattern: z.string(), + action: zPermissionAction +}); + +export const zPermissionRuleset = z.array(zPermissionRule); + +export const zSession = z.object({ + id: z.string().regex(/^ses.*/), + projectID: z.string(), + directory: z.string(), + parentID: z.string().regex(/^ses.*/).optional(), + summary: z.object({ + additions: z.number(), + deletions: z.number(), + files: z.number(), + diffs: z.array(zFileDiff).optional() + }).optional(), + share: z.object({ + url: z.string() + }).optional(), + title: z.string(), + version: z.string(), + time: z.object({ + created: z.number(), + updated: z.number(), + compacting: z.number().optional(), + archived: z.number().optional() + }), + permission: zPermissionRuleset.optional(), + revert: z.object({ + messageID: z.string(), + partID: z.string().optional(), + snapshot: z.string().optional(), + diff: z.string().optional() + }).optional() +}); + +export const zEventSessionCreated = z.object({ + type: z.literal('session.created'), + properties: z.object({ + info: zSession + }) +}); + +export const zEventSessionUpdated = z.object({ + type: z.literal('session.updated'), + properties: z.object({ + info: zSession + }) +}); + +export const zEventSessionDeleted = z.object({ + type: z.literal('session.deleted'), + properties: z.object({ + info: zSession + }) +}); + +export const zEventSessionDiff = z.object({ + type: z.literal('session.diff'), + properties: z.object({ + sessionID: z.string(), + diff: z.array(zFileDiff) + }) +}); + +export const zEventSessionError = z.object({ + type: z.literal('session.error'), + properties: z.object({ + sessionID: z.string().optional(), + error: z.union([ + zProviderAuthError, + zUnknownError, + zMessageOutputLengthError, + zMessageAbortedError, + zApiError + ]).optional() + }) +}); + +export const zEventFileWatcherUpdated = z.object({ + type: z.literal('file.watcher.updated'), + properties: z.object({ + file: z.string(), + event: z.union([ + z.literal('add'), + z.literal('change'), + z.literal('unlink') + ]) + }) +}); + +export const zEventVcsBranchUpdated = z.object({ + type: z.literal('vcs.branch.updated'), + properties: z.object({ + branch: z.string().optional() + }) +}); + +export const zPty = z.object({ + id: z.string().regex(/^pty.*/), + title: z.string(), + command: z.string(), + args: z.array(z.string()), + cwd: z.string(), + status: z.enum(['running', 'exited']), + pid: z.number() +}); + +export const zEventPtyCreated = z.object({ + type: z.literal('pty.created'), + properties: z.object({ + info: zPty + }) +}); + +export const zEventPtyUpdated = z.object({ + type: z.literal('pty.updated'), + properties: z.object({ + info: zPty + }) +}); + +export const zEventPtyExited = z.object({ + type: z.literal('pty.exited'), + properties: z.object({ + id: z.string().regex(/^pty.*/), + exitCode: z.number() + }) +}); + +export const zEventPtyDeleted = z.object({ + type: z.literal('pty.deleted'), + properties: z.object({ + id: z.string().regex(/^pty.*/) + }) +}); + +export const zEventServerConnected = z.object({ + type: z.literal('server.connected'), + properties: z.record(z.string(), z.unknown()) +}); + +export const zEventGlobalDisposed = z.object({ + type: z.literal('global.disposed'), + properties: z.record(z.string(), z.unknown()) +}); + +export const zEvent = z.union([ + zEventInstallationUpdated, + zEventInstallationUpdateAvailable, + zEventProjectUpdated, + zEventServerInstanceDisposed, + zEventLspClientDiagnostics, + zEventLspUpdated, + zEventMessageUpdated, + zEventMessageRemoved, + zEventMessagePartUpdated, + zEventMessagePartRemoved, + zEventPermissionAsked, + zEventPermissionReplied, + zEventSessionStatus, + zEventSessionIdle, + zEventSessionCompacted, + zEventFileEdited, + zEventTodoUpdated, + zEventTuiPromptAppend, + zEventTuiCommandExecute, + zEventTuiToastShow, + zEventMcpToolsChanged, + zEventCommandExecuted, + zEventSessionCreated, + zEventSessionUpdated, + zEventSessionDeleted, + zEventSessionDiff, + zEventSessionError, + zEventFileWatcherUpdated, + zEventVcsBranchUpdated, + zEventPtyCreated, + zEventPtyUpdated, + zEventPtyExited, + zEventPtyDeleted, + zEventServerConnected, + zEventGlobalDisposed +]); + +export const zGlobalEvent = z.object({ + directory: z.string(), + payload: zEvent +}); + +export const zBadRequestError = z.object({ + data: z.unknown(), + errors: z.array(z.record(z.string(), z.unknown())), + success: z.literal(false) +}); + +export const zNotFoundError = z.object({ + name: z.literal('NotFoundError'), + data: z.object({ + message: z.string() + }) +}); + +/** + * Custom keybind configurations + */ +export const zKeybindsConfig = z.object({ + leader: z.string().optional().default('ctrl+x'), + app_exit: z.string().optional().default('ctrl+c,ctrl+d,q'), + editor_open: z.string().optional().default('e'), + theme_list: z.string().optional().default('t'), + sidebar_toggle: z.string().optional().default('b'), + scrollbar_toggle: z.string().optional().default('none'), + username_toggle: z.string().optional().default('none'), + status_view: z.string().optional().default('s'), + session_export: z.string().optional().default('x'), + session_new: z.string().optional().default('n'), + session_list: z.string().optional().default('l'), + session_timeline: z.string().optional().default('g'), + session_fork: z.string().optional().default('none'), + session_rename: z.string().optional().default('none'), + session_share: z.string().optional().default('none'), + session_unshare: z.string().optional().default('none'), + session_interrupt: z.string().optional().default('escape'), + session_compact: z.string().optional().default('c'), + messages_page_up: z.string().optional().default('pageup'), + messages_page_down: z.string().optional().default('pagedown'), + messages_half_page_up: z.string().optional().default('ctrl+alt+u'), + messages_half_page_down: z.string().optional().default('ctrl+alt+d'), + messages_first: z.string().optional().default('ctrl+g,home'), + messages_last: z.string().optional().default('ctrl+alt+g,end'), + messages_next: z.string().optional().default('none'), + messages_previous: z.string().optional().default('none'), + messages_last_user: z.string().optional().default('none'), + messages_copy: z.string().optional().default('y'), + messages_undo: z.string().optional().default('u'), + messages_redo: z.string().optional().default('r'), + messages_toggle_conceal: z.string().optional().default('h'), + tool_details: z.string().optional().default('none'), + model_list: z.string().optional().default('m'), + model_cycle_recent: z.string().optional().default('f2'), + model_cycle_recent_reverse: z.string().optional().default('shift+f2'), + model_cycle_favorite: z.string().optional().default('none'), + model_cycle_favorite_reverse: z.string().optional().default('none'), + command_list: z.string().optional().default('ctrl+p'), + agent_list: z.string().optional().default('a'), + agent_cycle: z.string().optional().default('tab'), + agent_cycle_reverse: z.string().optional().default('shift+tab'), + variant_cycle: z.string().optional().default('ctrl+t'), + input_clear: z.string().optional().default('ctrl+c'), + input_paste: z.string().optional().default('ctrl+v'), + input_submit: z.string().optional().default('return'), + input_newline: z.string().optional().default('shift+return,ctrl+return,alt+return,ctrl+j'), + input_move_left: z.string().optional().default('left,ctrl+b'), + input_move_right: z.string().optional().default('right,ctrl+f'), + input_move_up: z.string().optional().default('up'), + input_move_down: z.string().optional().default('down'), + input_select_left: z.string().optional().default('shift+left'), + input_select_right: z.string().optional().default('shift+right'), + input_select_up: z.string().optional().default('shift+up'), + input_select_down: z.string().optional().default('shift+down'), + input_line_home: z.string().optional().default('ctrl+a'), + input_line_end: z.string().optional().default('ctrl+e'), + input_select_line_home: z.string().optional().default('ctrl+shift+a'), + input_select_line_end: z.string().optional().default('ctrl+shift+e'), + input_visual_line_home: z.string().optional().default('alt+a'), + input_visual_line_end: z.string().optional().default('alt+e'), + input_select_visual_line_home: z.string().optional().default('alt+shift+a'), + input_select_visual_line_end: z.string().optional().default('alt+shift+e'), + input_buffer_home: z.string().optional().default('home'), + input_buffer_end: z.string().optional().default('end'), + input_select_buffer_home: z.string().optional().default('shift+home'), + input_select_buffer_end: z.string().optional().default('shift+end'), + input_delete_line: z.string().optional().default('ctrl+shift+d'), + input_delete_to_line_end: z.string().optional().default('ctrl+k'), + input_delete_to_line_start: z.string().optional().default('ctrl+u'), + input_backspace: z.string().optional().default('backspace,shift+backspace'), + input_delete: z.string().optional().default('ctrl+d,delete,shift+delete'), + input_undo: z.string().optional().default('ctrl+-,super+z'), + input_redo: z.string().optional().default('ctrl+.,super+shift+z'), + input_word_forward: z.string().optional().default('alt+f,alt+right,ctrl+right'), + input_word_backward: z.string().optional().default('alt+b,alt+left,ctrl+left'), + input_select_word_forward: z.string().optional().default('alt+shift+f,alt+shift+right'), + input_select_word_backward: z.string().optional().default('alt+shift+b,alt+shift+left'), + input_delete_word_forward: z.string().optional().default('alt+d,alt+delete,ctrl+delete'), + input_delete_word_backward: z.string().optional().default('ctrl+w,ctrl+backspace,alt+backspace'), + history_previous: z.string().optional().default('up'), + history_next: z.string().optional().default('down'), + session_child_cycle: z.string().optional().default('right'), + session_child_cycle_reverse: z.string().optional().default('left'), + session_parent: z.string().optional().default('up'), + terminal_suspend: z.string().optional().default('ctrl+z'), + terminal_title_toggle: z.string().optional().default('none'), + tips_toggle: z.string().optional().default('h') +}); + +/** + * Log level + */ +export const zLogLevel = z.enum([ + 'DEBUG', + 'INFO', + 'WARN', + 'ERROR' +]); + +/** + * Server configuration for opencode serve and web commands + */ +export const zServerConfig = z.object({ + port: z.int().gt(0).lte(9007199254740991).optional(), + hostname: z.string().optional(), + mdns: z.boolean().optional(), + cors: z.array(z.string()).optional() +}); + +export const zPermissionActionConfig = z.enum([ + 'ask', + 'allow', + 'deny' +]); + +export const zPermissionObjectConfig = z.record(z.string(), zPermissionActionConfig); + +export const zPermissionRuleConfig = z.union([ + zPermissionActionConfig, + zPermissionObjectConfig +]); + +export const zPermissionConfig = z.union([ + z.object({ + read: zPermissionRuleConfig.optional(), + edit: zPermissionRuleConfig.optional(), + glob: zPermissionRuleConfig.optional(), + grep: zPermissionRuleConfig.optional(), + list: zPermissionRuleConfig.optional(), + bash: zPermissionRuleConfig.optional(), + task: zPermissionRuleConfig.optional(), + external_directory: zPermissionRuleConfig.optional(), + todowrite: zPermissionActionConfig.optional(), + todoread: zPermissionActionConfig.optional(), + webfetch: zPermissionActionConfig.optional(), + websearch: zPermissionActionConfig.optional(), + codesearch: zPermissionActionConfig.optional(), + lsp: zPermissionRuleConfig.optional(), + doom_loop: zPermissionActionConfig.optional() + }), + zPermissionActionConfig +]); + +export const zAgentConfig = z.object({ + model: z.string().optional(), + temperature: z.number().optional(), + top_p: z.number().optional(), + prompt: z.string().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + disable: z.boolean().optional(), + description: z.string().optional(), + mode: z.enum([ + 'subagent', + 'primary', + 'all' + ]).optional(), + options: z.record(z.string(), z.unknown()).optional(), + color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional(), + steps: z.int().gt(0).lte(9007199254740991).optional(), + maxSteps: z.int().gt(0).lte(9007199254740991).optional(), + permission: zPermissionConfig.optional() +}); + +export const zProviderConfig = z.object({ + api: z.string().optional(), + name: z.string().optional(), + env: z.array(z.string()).optional(), + id: z.string().optional(), + npm: z.string().optional(), + models: z.record(z.string(), z.object({ + id: z.string().optional(), + name: z.string().optional(), + family: z.string().optional(), + release_date: z.string().optional(), + attachment: z.boolean().optional(), + reasoning: z.boolean().optional(), + temperature: z.boolean().optional(), + tool_call: z.boolean().optional(), + interleaved: z.union([ + z.literal(true), + z.object({ + field: z.enum(['reasoning_content', 'reasoning_details']) + }) + ]).optional(), + cost: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional(), + context_over_200k: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional() + }).optional() + }).optional(), + limit: z.object({ + context: z.number(), + output: z.number() + }).optional(), + modalities: z.object({ + input: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])), + output: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])) + }).optional(), + experimental: z.boolean().optional(), + status: z.enum([ + 'alpha', + 'beta', + 'deprecated' + ]).optional(), + options: z.record(z.string(), z.unknown()).optional(), + headers: z.record(z.string(), z.string()).optional(), + provider: z.object({ + npm: z.string() + }).optional(), + variants: z.record(z.string(), z.object({ + disabled: z.boolean().optional() + })).optional() + })).optional(), + whitelist: z.array(z.string()).optional(), + blacklist: z.array(z.string()).optional(), + options: z.object({ + apiKey: z.string().optional(), + baseURL: z.string().optional(), + enterpriseUrl: z.string().optional(), + setCacheKey: z.boolean().optional(), + timeout: z.union([ + z.int().gt(0).lte(9007199254740991), + z.literal(false) + ]).optional() + }).optional() +}); + +export const zMcpLocalConfig = z.object({ + type: z.literal('local'), + command: z.array(z.string()), + environment: z.record(z.string(), z.string()).optional(), + enabled: z.boolean().optional(), + timeout: z.int().gt(0).lte(9007199254740991).optional() +}); + +export const zMcpOAuthConfig = z.object({ + clientId: z.string().optional(), + clientSecret: z.string().optional(), + scope: z.string().optional() +}); + +export const zMcpRemoteConfig = z.object({ + type: z.literal('remote'), + url: z.string(), + enabled: z.boolean().optional(), + headers: z.record(z.string(), z.string()).optional(), + oauth: z.union([ + zMcpOAuthConfig, + z.literal(false) + ]).optional(), + timeout: z.int().gt(0).lte(9007199254740991).optional() +}); + +/** + * @deprecated Always uses stretch layout. + */ +export const zLayoutConfig = z.enum(['auto', 'stretch']); + +export const zConfig = z.object({ + $schema: z.string().optional(), + theme: z.string().optional(), + keybinds: zKeybindsConfig.optional(), + logLevel: zLogLevel.optional(), + tui: z.object({ + scroll_speed: z.number().gte(0.001).optional(), + scroll_acceleration: z.object({ + enabled: z.boolean() + }).optional(), + diff_style: z.enum(['auto', 'stacked']).optional() + }).optional(), + server: zServerConfig.optional(), + command: z.record(z.string(), z.object({ + template: z.string(), + description: z.string().optional(), + agent: z.string().optional(), + model: z.string().optional(), + subtask: z.boolean().optional() + })).optional(), + watcher: z.object({ + ignore: z.array(z.string()).optional() + }).optional(), + plugin: z.array(z.string()).optional(), + snapshot: z.boolean().optional(), + share: z.enum([ + 'manual', + 'auto', + 'disabled' + ]).optional(), + autoshare: z.boolean().optional(), + autoupdate: z.union([ + z.boolean(), + z.literal('notify') + ]).optional(), + disabled_providers: z.array(z.string()).optional(), + enabled_providers: z.array(z.string()).optional(), + model: z.string().optional(), + small_model: z.string().optional(), + default_agent: z.string().optional(), + username: z.string().optional(), + mode: z.object({ + build: zAgentConfig.optional(), + plan: zAgentConfig.optional() + }).optional(), + agent: z.object({ + plan: zAgentConfig.optional(), + build: zAgentConfig.optional(), + general: zAgentConfig.optional(), + explore: zAgentConfig.optional(), + title: zAgentConfig.optional(), + summary: zAgentConfig.optional(), + compaction: zAgentConfig.optional() + }).optional(), + provider: z.record(z.string(), zProviderConfig).optional(), + mcp: z.record(z.string(), z.union([ + zMcpLocalConfig, + zMcpRemoteConfig + ])).optional(), + formatter: z.union([ + z.literal(false), + z.record(z.string(), z.object({ + disabled: z.boolean().optional(), + command: z.array(z.string()).optional(), + environment: z.record(z.string(), z.string()).optional(), + extensions: z.array(z.string()).optional() + })) + ]).optional(), + lsp: z.union([ + z.literal(false), + z.record(z.string(), z.union([ + z.object({ + disabled: z.literal(true) + }), + z.object({ + command: z.array(z.string()), + extensions: z.array(z.string()).optional(), + disabled: z.boolean().optional(), + env: z.record(z.string(), z.string()).optional(), + initialization: z.record(z.string(), z.unknown()).optional() + }) + ])) + ]).optional(), + instructions: z.array(z.string()).optional(), + layout: zLayoutConfig.optional(), + permission: zPermissionConfig.optional(), + tools: z.record(z.string(), z.boolean()).optional(), + enterprise: z.object({ + url: z.string().optional() + }).optional(), + compaction: z.object({ + auto: z.boolean().optional(), + prune: z.boolean().optional() + }).optional(), + experimental: z.object({ + hook: z.object({ + file_edited: z.record(z.string(), z.array(z.object({ + command: z.array(z.string()), + environment: z.record(z.string(), z.string()).optional() + }))).optional(), + session_completed: z.array(z.object({ + command: z.array(z.string()), + environment: z.record(z.string(), z.string()).optional() + })).optional() + }).optional(), + chatMaxRetries: z.number().optional(), + disable_paste_summary: z.boolean().optional(), + batch_tool: z.boolean().optional(), + openTelemetry: z.boolean().optional(), + primary_tools: z.array(z.string()).optional(), + continue_loop_on_deny: z.boolean().optional(), + mcp_timeout: z.int().gt(0).lte(9007199254740991).optional() + }).optional() +}); + +export const zToolIds = z.array(z.string()); + +export const zToolListItem = z.object({ + id: z.string(), + description: z.string(), + parameters: z.unknown() +}); + +export const zToolList = z.array(zToolListItem); + +export const zPath = z.object({ + home: z.string(), + state: z.string(), + config: z.string(), + worktree: z.string(), + directory: z.string() +}); + +export const zVcsInfo = z.object({ + branch: z.string() +}); + +export const zTextPartInput = z.object({ + id: z.string().optional(), + type: z.literal('text'), + text: z.string(), + synthetic: z.boolean().optional(), + ignored: z.boolean().optional(), + time: z.object({ + start: z.number(), + end: z.number().optional() + }).optional(), + metadata: z.record(z.string(), z.unknown()).optional() +}); + +export const zFilePartInput = z.object({ + id: z.string().optional(), + type: z.literal('file'), + mime: z.string(), + filename: z.string().optional(), + url: z.string(), + source: zFilePartSource.optional() +}); + +export const zAgentPartInput = z.object({ + id: z.string().optional(), + type: z.literal('agent'), + name: z.string(), + source: z.object({ + value: z.string(), + start: z.int().gte(-9007199254740991).lte(9007199254740991), + end: z.int().gte(-9007199254740991).lte(9007199254740991) + }).optional() +}); + +export const zSubtaskPartInput = z.object({ + id: z.string().optional(), + type: z.literal('subtask'), + prompt: z.string(), + description: z.string(), + agent: z.string(), + command: z.string().optional() +}); + +export const zCommand = z.object({ + name: z.string(), + description: z.string().optional(), + agent: z.string().optional(), + model: z.string().optional(), + mcp: z.boolean().optional(), + template: z.string(), + subtask: z.boolean().optional(), + hints: z.array(z.string()) +}); + +export const zModel = z.object({ + id: z.string(), + providerID: z.string(), + api: z.object({ + id: z.string(), + url: z.string(), + npm: z.string() + }), + name: z.string(), + family: z.string().optional(), + capabilities: z.object({ + temperature: z.boolean(), + reasoning: z.boolean(), + attachment: z.boolean(), + toolcall: z.boolean(), + input: z.object({ + text: z.boolean(), + audio: z.boolean(), + image: z.boolean(), + video: z.boolean(), + pdf: z.boolean() + }), + output: z.object({ + text: z.boolean(), + audio: z.boolean(), + image: z.boolean(), + video: z.boolean(), + pdf: z.boolean() + }), + interleaved: z.union([ + z.boolean(), + z.object({ + field: z.enum(['reasoning_content', 'reasoning_details']) + }) + ]) + }), + cost: z.object({ + input: z.number(), + output: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }), + experimentalOver200K: z.object({ + input: z.number(), + output: z.number(), + cache: z.object({ + read: z.number(), + write: z.number() + }) + }).optional() + }), + limit: z.object({ + context: z.number(), + output: z.number() + }), + status: z.enum([ + 'alpha', + 'beta', + 'deprecated', + 'active' + ]), + options: z.record(z.string(), z.unknown()), + headers: z.record(z.string(), z.string()), + release_date: z.string(), + variants: z.record(z.string(), z.record(z.string(), z.unknown())).optional() +}); + +export const zProvider = z.object({ + id: z.string(), + name: z.string(), + source: z.enum([ + 'env', + 'config', + 'custom', + 'api' + ]), + env: z.array(z.string()), + key: z.string().optional(), + options: z.record(z.string(), z.unknown()), + models: z.record(z.string(), zModel) +}); + +export const zProviderAuthMethod = z.object({ + type: z.union([ + z.literal('oauth'), + z.literal('api') + ]), + label: z.string() +}); + +export const zProviderAuthAuthorization = z.object({ + url: z.string(), + method: z.union([ + z.literal('auto'), + z.literal('code') + ]), + instructions: z.string() +}); + +export const zSymbol = z.object({ + name: z.string(), + kind: z.number(), + location: z.object({ + uri: z.string(), + range: zRange + }) +}); + +export const zFileNode = z.object({ + name: z.string(), + path: z.string(), + absolute: z.string(), + type: z.enum(['file', 'directory']), + ignored: z.boolean() +}); + +export const zFileContent = z.object({ + type: z.literal('text'), + content: z.string(), + diff: z.string().optional(), + patch: z.object({ + oldFileName: z.string(), + newFileName: z.string(), + oldHeader: z.string().optional(), + newHeader: z.string().optional(), + hunks: z.array(z.object({ + oldStart: z.number(), + oldLines: z.number(), + newStart: z.number(), + newLines: z.number(), + lines: z.array(z.string()) + })), + index: z.string().optional() + }).optional(), + encoding: z.literal('base64').optional(), + mimeType: z.string().optional() +}); + +export const zFile = z.object({ + path: z.string(), + added: z.int().gte(-9007199254740991).lte(9007199254740991), + removed: z.int().gte(-9007199254740991).lte(9007199254740991), + status: z.enum([ + 'added', + 'deleted', + 'modified' + ]) +}); + +export const zAgent = z.object({ + name: z.string(), + description: z.string().optional(), + mode: z.enum([ + 'subagent', + 'primary', + 'all' + ]), + native: z.boolean().optional(), + hidden: z.boolean().optional(), + topP: z.number().optional(), + temperature: z.number().optional(), + color: z.string().optional(), + permission: zPermissionRuleset, + model: z.object({ + modelID: z.string(), + providerID: z.string() + }).optional(), + prompt: z.string().optional(), + options: z.record(z.string(), z.unknown()), + steps: z.int().gt(0).lte(9007199254740991).optional() +}); + +export const zMcpStatusConnected = z.object({ + status: z.literal('connected') +}); + +export const zMcpStatusDisabled = z.object({ + status: z.literal('disabled') +}); + +export const zMcpStatusFailed = z.object({ + status: z.literal('failed'), + error: z.string() +}); + +export const zMcpStatusNeedsAuth = z.object({ + status: z.literal('needs_auth') +}); + +export const zMcpStatusNeedsClientRegistration = z.object({ + status: z.literal('needs_client_registration'), + error: z.string() +}); + +export const zMcpStatus = z.union([ + zMcpStatusConnected, + zMcpStatusDisabled, + zMcpStatusFailed, + zMcpStatusNeedsAuth, + zMcpStatusNeedsClientRegistration +]); + +export const zLspStatus = z.object({ + id: z.string(), + name: z.string(), + root: z.string(), + status: z.union([ + z.literal('connected'), + z.literal('error') + ]) +}); + +export const zFormatterStatus = z.object({ + name: z.string(), + extensions: z.array(z.string()), + enabled: z.boolean() +}); + +export const zOAuth = z.object({ + type: z.literal('oauth'), + refresh: z.string(), + access: z.string(), + expires: z.number(), + enterpriseUrl: z.string().optional() +}); + +export const zApiAuth = z.object({ + type: z.literal('api'), + key: z.string() +}); + +export const zWellKnownAuth = z.object({ + type: z.literal('wellknown'), + key: z.string(), + token: z.string() +}); + +export const zAuth = z.union([ + zOAuth, + zApiAuth, + zWellKnownAuth +]); + +/** + * Health information + */ +export const zGlobalHealthResponse = z.object({ + healthy: z.literal(true), + version: z.string() +}); + +/** + * Event stream + */ +export const zGlobalEventResponse = zGlobalEvent; + +/** + * Global disposed + */ +export const zGlobalDisposeResponse = z.boolean(); + +export const zProjectListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of projects + */ +export const zProjectListResponse = z.array(zProject); + +export const zProjectCurrentQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Current project information + */ +export const zProjectCurrentResponse = zProject; + +export const zProjectUpdateBody = z.object({ + name: z.string().optional(), + icon: z.object({ + url: z.string().optional(), + color: z.string().optional() + }).optional() +}); + +export const zProjectUpdatePath = z.object({ + projectID: z.string() +}); + +export const zProjectUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated project information + */ +export const zProjectUpdateResponse = zProject; + +export const zPtyListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of sessions + */ +export const zPtyListResponse = z.array(zPty); + +export const zPtyCreateBody = z.object({ + command: z.string().optional(), + args: z.array(z.string()).optional(), + cwd: z.string().optional(), + title: z.string().optional(), + env: z.record(z.string(), z.string()).optional() +}); + +export const zPtyCreateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created session + */ +export const zPtyCreateResponse = zPty; + +export const zPtyRemovePath = z.object({ + ptyID: z.string() +}); + +export const zPtyRemoveQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Session removed + */ +export const zPtyRemoveResponse = z.boolean(); + +export const zPtyGetPath = z.object({ + ptyID: z.string() +}); + +export const zPtyGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Session info + */ +export const zPtyGetResponse = zPty; + +export const zPtyUpdateBody = z.object({ + title: z.string().optional(), + size: z.object({ + rows: z.number(), + cols: z.number() + }).optional() +}); + +export const zPtyUpdatePath = z.object({ + ptyID: z.string() +}); + +export const zPtyUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated session + */ +export const zPtyUpdateResponse = zPty; + +export const zPtyConnectPath = z.object({ + ptyID: z.string() +}); + +export const zPtyConnectQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Connected session + */ +export const zPtyConnectResponse = z.boolean(); + +export const zConfigGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Get config info + */ +export const zConfigGetResponse = zConfig; + +export const zConfigUpdateBody = zConfig; + +export const zConfigUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully updated config + */ +export const zConfigUpdateResponse = zConfig; + +export const zToolIdsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Tool IDs + */ +export const zToolIdsResponse = zToolIds; + +export const zToolListQuery = z.object({ + directory: z.string().optional(), + provider: z.string(), + model: z.string() +}); + +/** + * Tools + */ +export const zToolListResponse = zToolList; + +export const zInstanceDisposeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Instance disposed + */ +export const zInstanceDisposeResponse = z.boolean(); + +export const zPathGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Path + */ +export const zPathGetResponse = zPath; + +export const zVcsGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * VCS info + */ +export const zVcsGetResponse = zVcsInfo; + +export const zSessionListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of sessions + */ +export const zSessionListResponse = z.array(zSession); + +export const zSessionCreateBody = z.object({ + parentID: z.string().regex(/^ses.*/).optional(), + title: z.string().optional(), + permission: zPermissionRuleset.optional() +}); + +export const zSessionCreateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully created session + */ +export const zSessionCreateResponse = zSession; + +export const zSessionStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Get session status + */ +export const zSessionStatusResponse = z.record(z.string(), zSessionStatus); + +export const zSessionDeletePath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionDeleteQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully deleted session + */ +export const zSessionDeleteResponse = z.boolean(); + +export const zSessionGetPath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionGetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Get session + */ +export const zSessionGetResponse = zSession; + +export const zSessionUpdateBody = z.object({ + title: z.string().optional(), + time: z.object({ + archived: z.number().optional() + }).optional() +}); + +export const zSessionUpdatePath = z.object({ + sessionID: z.string() +}); + +export const zSessionUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully updated session + */ +export const zSessionUpdateResponse = zSession; + +export const zSessionChildrenPath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionChildrenQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of children + */ +export const zSessionChildrenResponse = z.array(zSession); + +export const zSessionTodoPath = z.object({ + sessionID: z.string() +}); + +export const zSessionTodoQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Todo list + */ +export const zSessionTodoResponse = z.array(zTodo); + +export const zSessionInitBody = z.object({ + modelID: z.string(), + providerID: z.string(), + messageID: z.string().regex(/^msg.*/) +}); + +export const zSessionInitPath = z.object({ + sessionID: z.string() +}); + +export const zSessionInitQuery = z.object({ + directory: z.string().optional() +}); + +/** + * 200 + */ +export const zSessionInitResponse = z.boolean(); + +export const zSessionForkBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional() +}); + +export const zSessionForkPath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionForkQuery = z.object({ + directory: z.string().optional() +}); + +/** + * 200 + */ +export const zSessionForkResponse = zSession; + +export const zSessionAbortPath = z.object({ + sessionID: z.string() +}); + +export const zSessionAbortQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Aborted session + */ +export const zSessionAbortResponse = z.boolean(); + +export const zSessionUnsharePath = z.object({ + sessionID: z.string().regex(/^ses.*/) +}); + +export const zSessionUnshareQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully unshared session + */ +export const zSessionUnshareResponse = zSession; + +export const zSessionSharePath = z.object({ + sessionID: z.string() +}); + +export const zSessionShareQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully shared session + */ +export const zSessionShareResponse = zSession; + +export const zSessionDiffPath = z.object({ + sessionID: z.string() +}); + +export const zSessionDiffQuery = z.object({ + directory: z.string().optional(), + messageID: z.string().regex(/^msg.*/).optional() +}); + +/** + * List of diffs + */ +export const zSessionDiffResponse = z.array(zFileDiff); + +export const zSessionSummarizeBody = z.object({ + providerID: z.string(), + modelID: z.string(), + auto: z.boolean().optional().default(false) +}); + +export const zSessionSummarizePath = z.object({ + sessionID: z.string() +}); + +export const zSessionSummarizeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Summarized session + */ +export const zSessionSummarizeResponse = z.boolean(); + +export const zSessionMessagesPath = z.object({ + sessionID: z.string() +}); + +export const zSessionMessagesQuery = z.object({ + directory: z.string().optional(), + limit: z.number().optional() +}); + +/** + * List of messages + */ +export const zSessionMessagesResponse = z.array(z.object({ + info: zMessage, + parts: z.array(zPart) +})); + +export const zSessionPromptBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }).optional(), + agent: z.string().optional(), + noReply: z.boolean().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + system: z.string().optional(), + variant: z.string().optional(), + parts: z.array(z.union([ + zTextPartInput, + zFilePartInput, + zAgentPartInput, + zSubtaskPartInput + ])) +}); + +export const zSessionPromptPath = z.object({ + sessionID: z.string() +}); + +export const zSessionPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created message + */ +export const zSessionPromptResponse = z.object({ + info: zAssistantMessage, + parts: z.array(zPart) +}); + +export const zSessionMessagePath = z.object({ + sessionID: z.string(), + messageID: z.string() +}); + +export const zSessionMessageQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Message + */ +export const zSessionMessageResponse = z.object({ + info: zMessage, + parts: z.array(zPart) +}); + +export const zPartDeletePath = z.object({ + sessionID: z.string(), + messageID: z.string(), + partID: z.string() +}); + +export const zPartDeleteQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully deleted part + */ +export const zPartDeleteResponse = z.boolean(); + +export const zPartUpdateBody = zPart; + +export const zPartUpdatePath = z.object({ + sessionID: z.string(), + messageID: z.string(), + partID: z.string() +}); + +export const zPartUpdateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully updated part + */ +export const zPartUpdateResponse = zPart; + +export const zSessionPromptAsyncBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }).optional(), + agent: z.string().optional(), + noReply: z.boolean().optional(), + tools: z.record(z.string(), z.boolean()).optional(), + system: z.string().optional(), + variant: z.string().optional(), + parts: z.array(z.union([ + zTextPartInput, + zFilePartInput, + zAgentPartInput, + zSubtaskPartInput + ])) +}); + +export const zSessionPromptAsyncPath = z.object({ + sessionID: z.string() +}); + +export const zSessionPromptAsyncQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt accepted + */ +export const zSessionPromptAsyncResponse = z.void(); + +export const zSessionCommandBody = z.object({ + messageID: z.string().regex(/^msg.*/).optional(), + agent: z.string().optional(), + model: z.string().optional(), + arguments: z.string(), + command: z.string(), + variant: z.string().optional() +}); + +export const zSessionCommandPath = z.object({ + sessionID: z.string() +}); + +export const zSessionCommandQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created message + */ +export const zSessionCommandResponse = z.object({ + info: zAssistantMessage, + parts: z.array(zPart) +}); + +export const zSessionShellBody = z.object({ + agent: z.string(), + model: z.object({ + providerID: z.string(), + modelID: z.string() + }).optional(), + command: z.string() +}); + +export const zSessionShellPath = z.object({ + sessionID: z.string() +}); + +export const zSessionShellQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Created message + */ +export const zSessionShellResponse = zAssistantMessage; + +export const zSessionRevertBody = z.object({ + messageID: z.string().regex(/^msg.*/), + partID: z.string().regex(/^prt.*/).optional() +}); + +export const zSessionRevertPath = z.object({ + sessionID: z.string() +}); + +export const zSessionRevertQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated session + */ +export const zSessionRevertResponse = zSession; + +export const zSessionUnrevertPath = z.object({ + sessionID: z.string() +}); + +export const zSessionUnrevertQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Updated session + */ +export const zSessionUnrevertResponse = zSession; + +export const zPermissionRespondBody = z.object({ + response: z.enum([ + 'once', + 'always', + 'reject' + ]) +}); + +export const zPermissionRespondPath = z.object({ + sessionID: z.string(), + permissionID: z.string() +}); + +export const zPermissionRespondQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Permission processed successfully + */ +export const zPermissionRespondResponse = z.boolean(); + +export const zPermissionReplyBody = z.object({ + reply: z.enum([ + 'once', + 'always', + 'reject' + ]) +}); + +export const zPermissionReplyPath = z.object({ + requestID: z.string() +}); + +export const zPermissionReplyQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Permission processed successfully + */ +export const zPermissionReplyResponse = z.boolean(); + +export const zPermissionListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of pending permissions + */ +export const zPermissionListResponse = z.array(zPermissionRequest); + +export const zCommandListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of commands + */ +export const zCommandListResponse = z.array(zCommand); + +export const zConfigProvidersQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of providers + */ +export const zConfigProvidersResponse = z.object({ + providers: z.array(zProvider), + default: z.record(z.string(), z.string()) +}); + +export const zProviderListQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of providers + */ +export const zProviderListResponse = z.object({ + all: z.array(z.object({ + api: z.string().optional(), + name: z.string(), + env: z.array(z.string()), + id: z.string(), + npm: z.string().optional(), + models: z.record(z.string(), z.object({ + id: z.string(), + name: z.string(), + family: z.string().optional(), + release_date: z.string(), + attachment: z.boolean(), + reasoning: z.boolean(), + temperature: z.boolean(), + tool_call: z.boolean(), + interleaved: z.union([ + z.literal(true), + z.object({ + field: z.enum(['reasoning_content', 'reasoning_details']) + }) + ]).optional(), + cost: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional(), + context_over_200k: z.object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional() + }).optional() + }).optional(), + limit: z.object({ + context: z.number(), + output: z.number() + }), + modalities: z.object({ + input: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])), + output: z.array(z.enum([ + 'text', + 'audio', + 'image', + 'video', + 'pdf' + ])) + }).optional(), + experimental: z.boolean().optional(), + status: z.enum([ + 'alpha', + 'beta', + 'deprecated' + ]).optional(), + options: z.record(z.string(), z.unknown()), + headers: z.record(z.string(), z.string()).optional(), + provider: z.object({ + npm: z.string() + }).optional(), + variants: z.record(z.string(), z.record(z.string(), z.unknown())).optional() + })) + })), + default: z.record(z.string(), z.string()), + connected: z.array(z.string()) +}); + +export const zProviderAuthQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Provider auth methods + */ +export const zProviderAuthResponse = z.record(z.string(), z.array(zProviderAuthMethod)); + +export const zProviderOauthAuthorizeBody = z.object({ + method: z.number() +}); + +export const zProviderOauthAuthorizePath = z.object({ + providerID: z.string() +}); + +export const zProviderOauthAuthorizeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Authorization URL and method + */ +export const zProviderOauthAuthorizeResponse = zProviderAuthAuthorization; + +export const zProviderOauthCallbackBody = z.object({ + method: z.number(), + code: z.string().optional() +}); + +export const zProviderOauthCallbackPath = z.object({ + providerID: z.string() +}); + +export const zProviderOauthCallbackQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth callback processed successfully + */ +export const zProviderOauthCallbackResponse = z.boolean(); + +export const zFindTextQuery = z.object({ + directory: z.string().optional(), + pattern: z.string() +}); + +/** + * Matches + */ +export const zFindTextResponse = z.array(z.object({ + path: z.object({ + text: z.string() + }), + lines: z.object({ + text: z.string() + }), + line_number: z.number(), + absolute_offset: z.number(), + submatches: z.array(z.object({ + match: z.object({ + text: z.string() + }), + start: z.number(), + end: z.number() + })) +})); + +export const zFindFilesQuery = z.object({ + directory: z.string().optional(), + query: z.string(), + dirs: z.enum(['true', 'false']).optional(), + type: z.enum(['file', 'directory']).optional(), + limit: z.int().gte(1).lte(200).optional() +}); + +/** + * File paths + */ +export const zFindFilesResponse = z.array(z.string()); + +export const zFindSymbolsQuery = z.object({ + directory: z.string().optional(), + query: z.string() +}); + +/** + * Symbols + */ +export const zFindSymbolsResponse = z.array(zSymbol); + +export const zFileListQuery = z.object({ + directory: z.string().optional(), + path: z.string() +}); + +/** + * Files and directories + */ +export const zFileListResponse = z.array(zFileNode); + +export const zFileReadQuery = z.object({ + directory: z.string().optional(), + path: z.string() +}); + +/** + * File content + */ +export const zFileReadResponse = zFileContent; + +export const zFileStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * File status + */ +export const zFileStatusResponse = z.array(zFile); + +export const zAppLogBody = z.object({ + service: z.string(), + level: z.enum([ + 'debug', + 'info', + 'error', + 'warn' + ]), + message: z.string(), + extra: z.record(z.string(), z.unknown()).optional() +}); + +export const zAppLogQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Log entry written successfully + */ +export const zAppLogResponse = z.boolean(); + +export const zAppAgentsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * List of agents + */ +export const zAppAgentsResponse = z.array(zAgent); + +export const zMcpStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server status + */ +export const zMcpStatusResponse = z.record(z.string(), zMcpStatus); + +export const zMcpAddBody = z.object({ + name: z.string(), + config: z.union([ + zMcpLocalConfig, + zMcpRemoteConfig + ]) +}); + +export const zMcpAddQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server added successfully + */ +export const zMcpAddResponse = z.record(z.string(), zMcpStatus); + +export const zMcpAuthRemovePath = z.object({ + name: z.string() +}); + +export const zMcpAuthRemoveQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth credentials removed + */ +export const zMcpAuthRemoveResponse = z.object({ + success: z.literal(true) +}); + +export const zMcpAuthStartPath = z.object({ + name: z.string() +}); + +export const zMcpAuthStartQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth flow started + */ +export const zMcpAuthStartResponse = z.object({ + authorizationUrl: z.string() +}); + +export const zMcpAuthCallbackBody = z.object({ + code: z.string() +}); + +export const zMcpAuthCallbackPath = z.object({ + name: z.string() +}); + +export const zMcpAuthCallbackQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth authentication completed + */ +export const zMcpAuthCallbackResponse = zMcpStatus; + +export const zMcpAuthAuthenticatePath = z.object({ + name: z.string() +}); + +export const zMcpAuthAuthenticateQuery = z.object({ + directory: z.string().optional() +}); + +/** + * OAuth authentication completed + */ +export const zMcpAuthAuthenticateResponse = zMcpStatus; + +export const zMcpConnectPath = z.object({ + name: z.string() +}); + +export const zMcpConnectQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server connected successfully + */ +export const zMcpConnectResponse = z.boolean(); + +export const zMcpDisconnectPath = z.object({ + name: z.string() +}); + +export const zMcpDisconnectQuery = z.object({ + directory: z.string().optional() +}); + +/** + * MCP server disconnected successfully + */ +export const zMcpDisconnectResponse = z.boolean(); + +export const zLspStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * LSP server status + */ +export const zLspStatusResponse = z.array(zLspStatus); + +export const zFormatterStatusQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Formatter status + */ +export const zFormatterStatusResponse = z.array(zFormatterStatus); + +export const zTuiAppendPromptBody = z.object({ + text: z.string() +}); + +export const zTuiAppendPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt processed successfully + */ +export const zTuiAppendPromptResponse = z.boolean(); + +export const zTuiOpenHelpQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Help dialog opened successfully + */ +export const zTuiOpenHelpResponse = z.boolean(); + +export const zTuiOpenSessionsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Session dialog opened successfully + */ +export const zTuiOpenSessionsResponse = z.boolean(); + +export const zTuiOpenThemesQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Theme dialog opened successfully + */ +export const zTuiOpenThemesResponse = z.boolean(); + +export const zTuiOpenModelsQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Model dialog opened successfully + */ +export const zTuiOpenModelsResponse = z.boolean(); + +export const zTuiSubmitPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt submitted successfully + */ +export const zTuiSubmitPromptResponse = z.boolean(); + +export const zTuiClearPromptQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Prompt cleared successfully + */ +export const zTuiClearPromptResponse = z.boolean(); + +export const zTuiExecuteCommandBody = z.object({ + command: z.string() +}); + +export const zTuiExecuteCommandQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Command executed successfully + */ +export const zTuiExecuteCommandResponse = z.boolean(); + +export const zTuiShowToastBody = z.object({ + title: z.string().optional(), + message: z.string(), + variant: z.enum([ + 'info', + 'success', + 'warning', + 'error' + ]), + duration: z.number().optional().default(5000) +}); + +export const zTuiShowToastQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Toast notification shown successfully + */ +export const zTuiShowToastResponse = z.boolean(); + +export const zTuiPublishBody = z.union([ + zEventTuiPromptAppend, + zEventTuiCommandExecute, + zEventTuiToastShow +]); + +export const zTuiPublishQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Event published successfully + */ +export const zTuiPublishResponse = z.boolean(); + +export const zTuiControlNextQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Next TUI request + */ +export const zTuiControlNextResponse = z.object({ + path: z.string(), + body: z.unknown() +}); + +export const zTuiControlResponseBody = z.unknown(); + +export const zTuiControlResponseQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Response submitted successfully + */ +export const zTuiControlResponseResponse = z.boolean(); + +export const zAuthSetBody = zAuth; + +export const zAuthSetPath = z.object({ + providerID: z.string() +}); + +export const zAuthSetQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Successfully set authentication credentials + */ +export const zAuthSetResponse = z.boolean(); + +export const zEventSubscribeQuery = z.object({ + directory: z.string().optional() +}); + +/** + * Event stream + */ +export const zEventSubscribeResponse = zEvent; diff --git a/packages/openapi-ts-tests/sdks/test/opencode.test.ts b/packages/openapi-ts-tests/sdks/test/opencode.test.ts index 199448a493..8db52e0abb 100644 --- a/packages/openapi-ts-tests/sdks/test/opencode.test.ts +++ b/packages/openapi-ts-tests/sdks/test/opencode.test.ts @@ -59,6 +59,83 @@ describe(`SDK: ${namespace}`, () => { }), description: 'grouped', }, + { + config: createConfig({ + input: specPath, + output: 'metadata-by-tags', + plugins: [ + 'zod', + { + metadata: true, + name: '@hey-api/sdk', + operations: { + strategy: 'byTags', + }, + paramsStructure: 'flat', + validator: true, + }, + ], + }), + description: 'metadata by tags', + }, + { + config: createConfig({ + input: specPath, + output: 'metadata-flat', + plugins: [ + 'zod', + { + metadata: true, + name: '@hey-api/sdk', + paramsStructure: 'flat', + validator: true, + }, + ], + }), + description: 'metadata flat', + }, + { + config: createConfig({ + input: specPath, + output: 'metadata-single', + plugins: [ + 'zod', + { + metadata: true, + name: '@hey-api/sdk', + operations: { + containerName: 'OpenCode', + strategy: 'single', + }, + paramsStructure: 'flat', + validator: true, + }, + ], + }), + description: 'metadata single', + }, + { + config: createConfig({ + input: specPath, + output: 'metadata-partial', + plugins: [ + 'zod', + { + metadata: { + id: true, + method: false, + responseSchema: false, + tags: true, + url: true, + }, + name: '@hey-api/sdk', + paramsStructure: 'flat', + validator: true, + }, + ], + }), + description: 'metadata partial', + }, ]; it.each(scenarios)( diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts index 5713405c74..ab038432d0 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/config.ts @@ -4,12 +4,26 @@ import { definePluginConfig } from '@hey-api/shared'; import { resolveExamples } from './examples'; import { resolveOperations } from './operations'; import { handler } from './plugin'; -import type { HeyApiSdkPlugin } from './types'; +import type { HeyApiSdkPlugin, MetadataConfig } from './types'; const transformerInferWarn = 'You set `transformer: true` but no transformer plugin was found in your plugins. Add a transformer plugin like `@hey-api/transformers` to enable this feature. The transformer option has been disabled.'; const validatorInferWarn = 'You set `validator: true` but no validator plugin was found in your plugins. Add a validator plugin like `zod` to enable this feature. The validator option has been disabled.'; +const enabledMetadata: MetadataConfig = { + id: true, + method: true, + responseSchema: true, + tags: true, + url: true, +}; +const disabledMetadata: MetadataConfig = { + id: false, + method: false, + responseSchema: false, + tags: false, + url: false, +}; export const defaultConfig: HeyApiSdkPlugin['Config'] = { config: { @@ -17,6 +31,9 @@ export const defaultConfig: HeyApiSdkPlugin['Config'] = { client: true, comments: true, includeInEntry: true, + metadata: { + ...disabledMetadata, + }, paramsStructure: 'grouped', responseStyle: 'fields', transformer: false, @@ -103,6 +120,18 @@ export const defaultConfig: HeyApiSdkPlugin['Config'] = { plugin.config.validator.response = false; } + plugin.config.metadata = context.valueToObject({ + defaultValue: disabledMetadata, + mappers: { + boolean: (enabled) => (enabled ? { ...enabledMetadata } : { ...disabledMetadata }), + object: (fields) => ({ + ...enabledMetadata, + ...fields, + }), + }, + value: plugin.config.metadata, + }); + plugin.config.examples = resolveExamples(plugin.config, context); plugin.config.operations = resolveOperations(plugin.config, context); }, diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/metadata.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/metadata.ts new file mode 100644 index 0000000000..af750201e1 --- /dev/null +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/shared/metadata.ts @@ -0,0 +1,64 @@ +import type { IR } from '@hey-api/shared'; +import type ts from 'typescript'; + +import { $, type TsDsl } from '../../../../ts-dsl'; +import type { HeyApiSdkPlugin } from '../types'; + +type MetadataFn = TsDsl; + +function createResponseSchema(args: { + operation: IR.OperationObject; + plugin: HeyApiSdkPlugin['Instance']; +}) { + const { operation, plugin } = args; + if (!plugin.config.validator.response) return; + + const query = { + category: 'schema' as const, + resource: 'operation' as const, + resourceId: operation.id, + role: 'responses' as const, + tool: plugin.config.validator.response, + }; + + if (!plugin.isSymbolRegistered(query)) return; + + return plugin.referenceSymbol(query); +} + +export function createMetadataObject(args: { + operation: IR.OperationObject; + plugin: HeyApiSdkPlugin['Instance']; + tags?: ReadonlyArray; +}) { + const { operation, plugin, tags } = args; + const responseSchema = createResponseSchema({ operation, plugin }); + const metadata = plugin.config.metadata; + + return $.object() + .$if(metadata.id, (o) => o.prop('id', $.literal(operation.id))) + .$if(metadata.method, (o) => o.prop('method', $.literal(operation.method))) + .$if(metadata.responseSchema && responseSchema, (o, v) => o.prop('responseSchema', v)) + .$if(metadata.tags && Boolean(tags?.length) && tags, (o, v) => + o.prop('tags', $.array().elements(...v)), + ) + .$if(metadata.url, (o) => o.prop('url', $.literal(operation.path))); +} + +export function withMetadata(args: { + fn: MetadataFn; + operation: IR.OperationObject; + plugin: HeyApiSdkPlugin['Instance']; + tags?: ReadonlyArray; +}): ReturnType { + const { fn, operation, plugin, tags } = args; + + return $('Object').attr('assign').call( + fn, + createMetadataObject({ + operation, + plugin, + tags, + }), + ); +} diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/types.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/types.ts index fc36d2f087..7d0271203f 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/types.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/types.ts @@ -4,6 +4,16 @@ import type { PluginClientNames, PluginTransformerNames, PluginValidatorNames } import type { ExamplesConfig, UserExamplesConfig } from './examples'; import type { OperationsConfig, UserOperationsConfig } from './operations'; +export type UserMetadataConfig = { + id?: boolean; + method?: boolean; + responseSchema?: boolean; + tags?: boolean; + url?: boolean; +}; + +export type MetadataConfig = Required; + export type UserConfig = Plugin.Name<'@hey-api/sdk'> & Plugin.Hooks & Plugin.UserComments & @@ -28,6 +38,52 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & * @default true */ client?: PluginClientNames | boolean; + /** + * Customize the generated class names. The name variable is obtained from + * your OpenAPI specification tags or `instance` value. + * + * This option has no effect if `sdk.asClass` is `false`. + * + * @deprecated Use `operations: { containerName: "..." }` instead. + */ + classNameBuilder?: NameTransformer; + /** + * How should we structure your SDK? By default, we try to infer the ideal + * structure using `operationId` keywords. If you prefer a flatter structure, + * you can set `classStructure` to `off` to disable this behavior. + * + * @deprecated Use `operations: { nesting: "operationId" }` or `operations: { nesting: "id" }` instead. + * @default 'auto' + */ + classStructure?: 'auto' | 'off'; + /** + * Transform response data before returning. This is useful if you want to + * convert for example ISO strings into Date objects. However, transformation + * adds runtime overhead, so it's not recommended to use unless necessary. + * + * You can customize the transformer output through its plugin. You can also + * set `transformer` to `true` to automatically choose the transformer from your + * defined plugins. + * + * Ensure you have declared the selected library as a dependency to avoid + * errors. + * + * @default false + */ + transformer?: + | PluginTransformerNames + | boolean + | { + /** + * Transform response data before returning. + * + * Can be a transformer plugin name or boolean (true to auto-select, false + * to disable). + * + * @default false + */ + response?: PluginTransformerNames | boolean; + }; /** * Generate code examples for SDK operations and attach them to the * input source (e.g., via `x-codeSamples`). @@ -38,6 +94,40 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & * @default false */ examples?: boolean | UserExamplesConfig; + /** + * Set `instance` to create an instantiable SDK. Using `true` will use the + * default instance name; in practice, you want to define your own by passing + * a string value. + * + * @deprecated Use `operations: { strategy: "single", containerName: "Name", methods: "instance" }` instead. + * @default false + */ + instance?: string | boolean; + /** + * Attach OpenAPI-derived metadata to generated SDK methods. + * + * When enabled, generated methods are wrapped with `Object.assign()` and + * expose static metadata such as operation id, HTTP method, path, tags, + * and validator schemas when available. + * + * @default false + */ + metadata?: boolean | UserMetadataConfig; + /** + * Customise the name of methods within the service. By default, + * `operation.id` is used. + * + * @deprecated Use `operations: { methodName: "..." }` instead. + */ + methodNameBuilder?: NameTransformer; + + /** + * Use operation ID to generate operation names? + * + * @deprecated Use `operations: { nesting: "operationId" }` or `operations: { nesting: "id" }` instead. + * @default true + */ + operationId?: boolean; /** * Define the structure of generated SDK operations. * @@ -71,34 +161,6 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & * @default 'fields' */ responseStyle?: 'data' | 'fields'; - /** - * Transform response data before returning. This is useful if you want to - * convert for example ISO strings into Date objects. However, transformation - * adds runtime overhead, so it's not recommended to use unless necessary. - * - * You can customize the transformer output through its plugin. You can also - * set `transformer` to `true` to automatically choose the transformer from your - * defined plugins. - * - * Ensure you have declared the selected library as a dependency to avoid - * errors. - * - * @default false - */ - transformer?: - | PluginTransformerNames - | boolean - | { - /** - * Transform response data before returning. - * - * Can be a transformer plugin name or boolean (true to auto-select, false - * to disable). - * - * @default false - */ - response?: PluginTransformerNames | boolean; - }; /** * Validate request and/or response data against schema before returning. * This is useful if you want to ensure the request and/or response conforms @@ -140,9 +202,7 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & */ response?: PluginValidatorNames | boolean; }; - // DEPRECATED OPTIONS BELOW - /** * Group operation methods into classes? When enabled, you can select which * classes to export with `sdk.include` and/or transform their names with @@ -157,47 +217,6 @@ export type UserConfig = Plugin.Name<'@hey-api/sdk'> & */ // eslint-disable-next-line typescript-sort-keys/interface asClass?: boolean; - /** - * Customize the generated class names. The name variable is obtained from - * your OpenAPI specification tags or `instance` value. - * - * This option has no effect if `sdk.asClass` is `false`. - * - * @deprecated Use `operations: { containerName: "..." }` instead. - */ - classNameBuilder?: NameTransformer; - /** - * How should we structure your SDK? By default, we try to infer the ideal - * structure using `operationId` keywords. If you prefer a flatter structure, - * you can set `classStructure` to `off` to disable this behavior. - * - * @deprecated Use `operations: { nesting: "operationId" }` or `operations: { nesting: "id" }` instead. - * @default 'auto' - */ - classStructure?: 'auto' | 'off'; - /** - * Set `instance` to create an instantiable SDK. Using `true` will use the - * default instance name; in practice, you want to define your own by passing - * a string value. - * - * @deprecated Use `operations: { strategy: "single", containerName: "Name", methods: "instance" }` instead. - * @default false - */ - instance?: string | boolean; - /** - * Customise the name of methods within the service. By default, - * `operation.id` is used. - * - * @deprecated Use `operations: { methodName: "..." }` instead. - */ - methodNameBuilder?: NameTransformer; - /** - * Use operation ID to generate operation names? - * - * @deprecated Use `operations: { nesting: "operationId" }` or `operations: { nesting: "id" }` instead. - * @default true - */ - operationId?: boolean; /** * Define shape of returned value from service calls * @@ -217,6 +236,8 @@ export type Config = Plugin.Name<'@hey-api/sdk'> & client: PluginClientNames | false; /** Configuration for generating SDK code examples. */ examples: ExamplesConfig; + /** Attach OpenAPI-derived metadata to generated SDK methods. */ + metadata: MetadataConfig; /** Define the structure of generated SDK operations. */ operations: OperationsConfig; /** Define how request parameters are structured in generated SDK methods. */ diff --git a/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/node.ts b/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/node.ts index e93792196e..47017d7111 100644 --- a/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/node.ts +++ b/packages/openapi-ts/src/plugins/@hey-api/sdk/v1/node.ts @@ -17,9 +17,13 @@ import { import { $, ctx } from '../../../../ts-dsl'; import { createClientClass, createRegistryClass } from '../shared/class'; import { nuxtTypeComposable, nuxtTypeDefault } from '../shared/constants'; +import { withMetadata } from '../shared/metadata'; import { operationParameters, operationStatements } from '../shared/operation'; import type { HeyApiSdkPlugin } from '../types'; +type ArrowFunc = Extract, { '~mode': 'arrow' }>; +type ExprFunc = Extract, { '~mode': 'expr' }>; + export interface OperationItem { operation: IR.OperationObject; path: ReadonlyArray; @@ -35,17 +39,19 @@ export function isInstance(plugin: HeyApiSdkPlugin['Instance']): boolean { ); } -function attachComment>(args: { - node: T; - operation: IR.OperationObject; - plugin: HeyApiSdkPlugin['Instance']; -}): T { +function attachComment< + T extends ReturnType, +>(args: { node: T; operation: IR.OperationObject; plugin: HeyApiSdkPlugin['Instance'] }): T { const { node, operation, plugin } = args; return node.$if(plugin.config.comments && createOperationComment(operation), (n, v) => n.doc(v), ) as T; } +function isMetadataEnabled(plugin: HeyApiSdkPlugin['Instance']): boolean { + return Object.values(plugin.config.metadata).some(Boolean); +} + function createShellMeta(node: StructureNode): SymbolMeta { return { category: 'utility', @@ -228,7 +234,7 @@ function enrichRootClass(args: { } function exampleIntent( - node: ReturnType, + node: ReturnType, operation: IR.OperationObject, plugin: HeyApiSdkPlugin['Instance'], ): void { @@ -254,7 +260,7 @@ function exampleIntent( }); } -function implementFn>(args: { +function implementFn | ArrowFunc | ExprFunc>(args: { node: T; operation: IR.OperationObject; plugin: HeyApiSdkPlugin['Instance']; @@ -320,15 +326,26 @@ export function toNode( if (model.virtual) { const nodes: Array> = []; for (const item of model.itemsFrom(source)) { - const { operation } = item.data; + const { operation, tags } = item.data; let node = $.const(createFnSymbol(plugin, item)) .export() .assign( - implementFn({ - node: $.func(), - operation, - plugin, - }), + isMetadataEnabled(plugin) + ? withMetadata({ + fn: implementFn({ + node: $.func(createFnSymbol(plugin, item)).expr() as ExprFunc, + operation, + plugin, + }), + operation, + plugin, + tags, + }) + : implementFn({ + node: $.func(), + operation, + plugin, + }), ); node = attachComment({ node, operation, plugin }); nodes.push(node); @@ -351,26 +368,49 @@ export function toNode( let index = 0; for (const item of model.itemsFrom(source)) { - const { operation } = item.data; + const { operation, tags } = item.data; if (node['~dsl'] === 'VarTsDsl') { // TODO: object } else { if (index > 0 || node.hasBody) node.newline(); - const method = implementFn({ - node: $.method(createFnSymbol(plugin, item), (m) => - attachComment({ - node: m, - operation, - plugin, - }) - .public() - .static(!isAngularClient && !isInstance(plugin)), - ), - operation, - plugin, - }); - node.do(method); - exampleIntent(method, operation, plugin); + if (isMetadataEnabled(plugin)) { + const field = attachComment({ + node: $.field(createFnSymbol(plugin, item), (f) => + f.public().static(!isAngularClient && !isInstance(plugin)), + ).assign( + withMetadata({ + fn: implementFn({ + node: $.func() as ArrowFunc, + operation, + plugin, + }), + operation, + plugin, + tags, + }), + ), + operation, + plugin, + }); + node.do(field); + exampleIntent(field, operation, plugin); + } else { + const method = implementFn({ + node: $.method(createFnSymbol(plugin, item), (m) => + attachComment({ + node: m, + operation, + plugin, + }) + .public() + .static(!isAngularClient && !isInstance(plugin)), + ), + operation, + plugin, + }); + node.do(method); + exampleIntent(method, operation, plugin); + } } index += 1; }