diff --git a/bun.lock b/bun.lock index ae547d8692..6a203012b5 100644 --- a/bun.lock +++ b/bun.lock @@ -126,7 +126,6 @@ "@opencode-ai/schema": "workspace:*", }, "devDependencies": { - "@effect/platform-node": "catalog:", "@opencode-ai/core": "workspace:*", "@opencode-ai/httpapi-codegen": "workspace:*", "@opencode-ai/server": "workspace:*", diff --git a/packages/cli/src/commands/handlers/api.ts b/packages/cli/src/commands/handlers/api.ts index 2ed0adb917..82d273c25d 100644 --- a/packages/cli/src/commands/handlers/api.ts +++ b/packages/cli/src/commands/handlers/api.ts @@ -2,8 +2,9 @@ import { EOL } from "node:os" import { Effect, Option } from "effect" import { Commands } from "../commands" import { Runtime } from "../../framework/runtime" -import { Service } from "../../services/service" -import type { Transport } from "@opencode-ai/client/service" +import { Service } from "@opencode-ai/client/effect" +import { ServiceConfig } from "../../services/service-config" +import type { Transport } from "@opencode-ai/client/effect" const methods = new Set(["delete", "get", "head", "options", "patch", "post", "put"]) @@ -18,7 +19,9 @@ type OpenApi = { export default Runtime.handler( Commands.commands.api, Effect.fn("cli.api")(function* (input) { - const transport = yield* Service.connect() + const options = yield* ServiceConfig.options() + const found = yield* Service.discover(options) + const transport = found ?? (yield* Service.start(options)) const params = Option.getOrElse(input.param, () => ({})) const request = yield* resolveRequest(transport, input.request, params) const headers = new Headers(transport.headers) diff --git a/packages/cli/src/commands/handlers/debug/agents.ts b/packages/cli/src/commands/handlers/debug/agents.ts index fd0e1500c4..ee241bcc1b 100644 --- a/packages/cli/src/commands/handlers/debug/agents.ts +++ b/packages/cli/src/commands/handlers/debug/agents.ts @@ -3,12 +3,15 @@ import * as Effect from "effect/Effect" import { createOpencodeClient } from "@opencode-ai/sdk/v2/client" import { Commands } from "../../commands" import { Runtime } from "../../../framework/runtime" -import { Service } from "../../../services/service" +import { Service } from "@opencode-ai/client/effect" +import { ServiceConfig } from "../../../services/service-config" export default Runtime.handler( Commands.commands.debug.commands.agents, Effect.fn("cli.debug.agents")(function* () { - const transport = yield* Service.connect() + const options = yield* ServiceConfig.options() + const found = yield* Service.discover(options) + const transport = found ?? (yield* Service.start(options)) const client = createOpencodeClient({ baseUrl: transport.url, headers: transport.headers }) const response = yield* Effect.promise(() => client.v2.agent.list({ location: { directory: process.cwd() } })) process.stdout.write( diff --git a/packages/cli/src/commands/handlers/default.ts b/packages/cli/src/commands/handlers/default.ts index c48a383534..98b0c9b3c9 100644 --- a/packages/cli/src/commands/handlers/default.ts +++ b/packages/cli/src/commands/handlers/default.ts @@ -1,12 +1,12 @@ +import { NodeFileSystem } from "@effect/platform-node" import { Commands } from "../commands" import { Runtime } from "../../framework/runtime" -import { Global } from "@opencode-ai/core/global" -import { Effect, FileSystem, Option } from "effect" -import { Service } from "../../services/service" +import { Effect, Option } from "effect" +import { Service } from "@opencode-ai/client/effect" +import type { Transport } from "@opencode-ai/client/effect" +import { ServiceConfig } from "../../services/service-config" import { Standalone } from "../../services/standalone" import { Updater } from "../../services/updater" -import { basicAuth } from "@opencode-ai/client/service" -import type { Transport } from "@opencode-ai/client/service" export default Runtime.handler(Commands, (input) => Effect.gen(function* () { @@ -17,29 +17,34 @@ export default Runtime.handler(Commands, (input) => const server = Option.getOrUndefined(input.server) if (server !== undefined && input.standalone) return yield* Effect.fail(new Error("--server and --standalone cannot be combined")) - const transport = yield* resolveTransport(server, input.standalone) + const transport = yield* Effect.gen(function* () { + if (server !== undefined) { + const password = process.env["OPENCODE_SERVER_PASSWORD"] + return { + url: server, + headers: password ? { authorization: "Basic " + btoa("opencode:" + password) } : undefined, + } satisfies Transport + } + if (input.standalone) return yield* Standalone.transport() + const options = yield* ServiceConfig.options() + const found = yield* Service.discover(options) + return found ?? (yield* Service.start(options)) + }) const { runTui } = yield* Effect.promise(() => import("../../tui")) // The TUI re-runs discover whenever its event stream drops. For an explicit // --server or a standalone child the transport is fixed, so reconnects // retry the same address; for the managed service discovery re-reads the // registration and may start a replacement. - const context = yield* Effect.context() - const discover = - server !== undefined || input.standalone - ? () => Promise.resolve(transport) - : () => Effect.runPromise(Service.connect().pipe(Effect.provide(context))) + const serviceOptions = server === undefined && !input.standalone ? yield* ServiceConfig.options() : undefined + const discover = serviceOptions + ? () => + Effect.runPromise( + Effect.gen(function* () { + const found = yield* Service.discover(serviceOptions) + return found ?? (yield* Service.start(serviceOptions)) + }).pipe(Effect.provide(NodeFileSystem.layer)), + ) + : () => Promise.resolve(transport) yield* runTui(transport, { continue: input.continue, sessionID: Option.getOrUndefined(input.session) }, discover) }), ) - -function resolveTransport(server: string | undefined, standalone: boolean) { - if (server !== undefined) { - const password = process.env["OPENCODE_SERVER_PASSWORD"] - return Effect.succeed({ - url: server, - headers: password ? basicAuth(password) : undefined, - } satisfies Transport) - } - if (standalone) return Standalone.transport() - return Service.connect() -} diff --git a/packages/cli/src/commands/handlers/mcp/auth.ts b/packages/cli/src/commands/handlers/mcp/auth.ts index 96affd21f8..967f24e28f 100644 --- a/packages/cli/src/commands/handlers/mcp/auth.ts +++ b/packages/cli/src/commands/handlers/mcp/auth.ts @@ -8,7 +8,8 @@ import { } from "@opencode-ai/sdk/v2/client" import { Commands } from "../../commands" import { Runtime } from "../../../framework/runtime" -import { Service } from "../../../services/service" +import { Service } from "@opencode-ai/client/effect" +import { ServiceConfig } from "../../../services/service-config" import { resolveIntegration } from "./resolve" const location = { directory: process.cwd() } @@ -16,7 +17,9 @@ const location = { directory: process.cwd() } export default Runtime.handler( Commands.commands.mcp.commands.auth, Effect.fn("cli.mcp.auth")(function* (input) { - const transport = yield* Service.connect() + const options = yield* ServiceConfig.options() + const found = yield* Service.discover(options) + const transport = found ?? (yield* Service.start(options)) const client = createOpencodeClient({ baseUrl: transport.url, headers: transport.headers }) const integration = yield* resolveIntegration(client, input.name, location) diff --git a/packages/cli/src/commands/handlers/mcp/list.ts b/packages/cli/src/commands/handlers/mcp/list.ts index e7e2dd3e38..167509fb70 100644 --- a/packages/cli/src/commands/handlers/mcp/list.ts +++ b/packages/cli/src/commands/handlers/mcp/list.ts @@ -3,12 +3,15 @@ import * as Effect from "effect/Effect" import { createOpencodeClient, type McpServer } from "@opencode-ai/sdk/v2/client" import { Commands } from "../../commands" import { Runtime } from "../../../framework/runtime" -import { Service } from "../../../services/service" +import { Service } from "@opencode-ai/client/effect" +import { ServiceConfig } from "../../../services/service-config" export default Runtime.handler( Commands.commands.mcp.commands.list, Effect.fn("cli.mcp.list")(function* () { - const transport = yield* Service.connect() + const options = yield* ServiceConfig.options() + const found = yield* Service.discover(options) + const transport = found ?? (yield* Service.start(options)) const client = createOpencodeClient({ baseUrl: transport.url, headers: transport.headers }) const response = yield* Effect.promise(() => client.v2.mcp.list({ location: { directory: process.cwd() } })) const servers = (response.data?.data ?? []).toSorted((a, b) => a.name.localeCompare(b.name)) diff --git a/packages/cli/src/commands/handlers/mcp/logout.ts b/packages/cli/src/commands/handlers/mcp/logout.ts index 1fa1e482dc..94a3114cfa 100644 --- a/packages/cli/src/commands/handlers/mcp/logout.ts +++ b/packages/cli/src/commands/handlers/mcp/logout.ts @@ -3,7 +3,8 @@ import { Effect } from "effect" import { createOpencodeClient } from "@opencode-ai/sdk/v2/client" import { Commands } from "../../commands" import { Runtime } from "../../../framework/runtime" -import { Service } from "../../../services/service" +import { Service } from "@opencode-ai/client/effect" +import { ServiceConfig } from "../../../services/service-config" import { resolveIntegration } from "./resolve" const location = { directory: process.cwd() } @@ -11,7 +12,9 @@ const location = { directory: process.cwd() } export default Runtime.handler( Commands.commands.mcp.commands.logout, Effect.fn("cli.mcp.logout")(function* (input) { - const transport = yield* Service.connect() + const options = yield* ServiceConfig.options() + const found = yield* Service.discover(options) + const transport = found ?? (yield* Service.start(options)) const client = createOpencodeClient({ baseUrl: transport.url, headers: transport.headers }) const integration = yield* resolveIntegration(client, input.name, location) diff --git a/packages/cli/src/commands/handlers/serve.ts b/packages/cli/src/commands/handlers/serve.ts index bf406f2a89..80cf6cba9f 100644 --- a/packages/cli/src/commands/handlers/serve.ts +++ b/packages/cli/src/commands/handlers/serve.ts @@ -4,18 +4,20 @@ import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { PermissionSaved } from "@opencode-ai/core/permission/saved" import { Global } from "@opencode-ai/core/global" -import { Context, Layer, Option, Schedule } from "effect" +import { Context, FileSystem, Layer, Option, Schedule, Schema } from "effect" import * as Effect from "effect/Effect" import { HttpRouter, HttpServer } from "effect/unstable/http" import { createServer } from "node:http" import { createRoutes } from "@opencode-ai/server/routes" import { ServerAuth } from "@opencode-ai/server/auth" +import { InstallationVersion } from "@opencode-ai/core/installation/version" import { createOpencodeClient } from "@opencode-ai/sdk/v2/client" import { Commands } from "../commands" import { Runtime } from "../../framework/runtime" -import { Service } from "../../services/service" +import { ServiceConfig } from "../../services/service-config" import { Updater } from "../../services/updater" -import { randomBytes } from "crypto" +import { randomBytes, randomUUID } from "crypto" +import path from "path" export default Runtime.handler( Commands.commands.serve, @@ -25,9 +27,9 @@ export default Runtime.handler( Effect.gen(function* () { const standalonePassword = process.env.OPENCODE_SERVER_PASSWORD if (input.stdio) delete process.env.OPENCODE_SERVER_PASSWORD - const config = input.service ? yield* Service.config() : {} + const config = input.service ? yield* ServiceConfig.read() : {} const password = input.service - ? yield* Service.password() + ? yield* ServiceConfig.password() : standalonePassword || randomBytes(32).toString("base64url") if (!password) return yield* Effect.fail(new Error("Missing server password")) const hostname = Option.getOrUndefined(input.hostname) ?? config.hostname ?? "127.0.0.1" @@ -43,7 +45,7 @@ export default Runtime.handler( headers: ServerAuth.headers({ password }), }).v2.health.get({}), ) - if (input.service) yield* Service.register(address) + if (input.service) yield* register(address) const url = HttpServer.formatAddress(address) console.log(input.stdio ? JSON.stringify({ url }) : `server listening on ${url}`) if (!input.service && !input.stdio && !standalonePassword) console.log(`server password ${password}`) @@ -55,6 +57,56 @@ export default Runtime.handler( }), ) +// Server-side half of the registration protocol. The registration embeds the +// password so the file alone is enough for any client to discover and +// authenticate. The file arbitrates ownership after concurrent starts; it is +// not a startup lock: the atomic rename elects the latest writer, the watcher +// self-evicts losers, and the finalizer id-guard keeps an exiting server from +// deleting its successor's registration. +const RegistrationId = Schema.Struct({ id: Schema.optional(Schema.String) }) +const decodeRegistrationId = Schema.decodeUnknownEffect(Schema.fromJsonString(RegistrationId)) + +const register = Effect.fnUntraced(function* (address: HttpServer.Address) { + const fs = yield* FileSystem.FileSystem + const { file } = yield* ServiceConfig.options() + const id = randomUUID() + const secret = yield* ServiceConfig.password() + const temp = file + "." + id + ".tmp" + yield* fs.makeDirectory(path.dirname(file), { recursive: true }) + yield* fs.writeFileString( + temp, + JSON.stringify({ + id, + version: InstallationVersion, + url: HttpServer.formatAddress(address), + pid: process.pid, + password: secret, + }), + { mode: 0o600 }, + ) + yield* fs.rename(temp, file) + const currentID = fs.readFileString(file).pipe( + Effect.flatMap(decodeRegistrationId), + Effect.map((info) => info.id), + Effect.orElseSucceed(() => undefined), + ) + yield* currentID.pipe( + Effect.flatMap((current) => + current === id + ? Effect.void + : Effect.try({ try: () => process.kill(process.pid, "SIGTERM"), catch: (cause) => cause }).pipe(Effect.ignore), + ), + Effect.repeat(Schedule.spaced("10 seconds")), + Effect.forkScoped, + ) + yield* Effect.addFinalizer(() => + currentID.pipe( + Effect.flatMap((current) => (current === id ? fs.remove(file) : Effect.void)), + Effect.ignore, + ), + ) +}) + function waitForStdinClose() { return Effect.callback((resume) => { const close = () => resume(Effect.void) diff --git a/packages/cli/src/commands/handlers/service/get.ts b/packages/cli/src/commands/handlers/service/get.ts index 545ef7994f..1b85faf6e9 100644 --- a/packages/cli/src/commands/handlers/service/get.ts +++ b/packages/cli/src/commands/handlers/service/get.ts @@ -3,11 +3,11 @@ import { Option } from "effect" import * as Effect from "effect/Effect" import { Commands } from "../../commands" import { Runtime } from "../../../framework/runtime" -import { Service } from "../../../services/service" +import { ServiceConfig } from "../../../services/service-config" export default Runtime.handler( Commands.commands.service.commands.get, Effect.fn("cli.service.get")(function* (input) { - process.stdout.write((yield* Service.get(Option.getOrUndefined(input.key))) + EOL) + process.stdout.write((yield* ServiceConfig.get(Option.getOrUndefined(input.key))) + EOL) }), ) diff --git a/packages/cli/src/commands/handlers/service/restart.ts b/packages/cli/src/commands/handlers/service/restart.ts index 767ff65a5b..c78273ed0f 100644 --- a/packages/cli/src/commands/handlers/service/restart.ts +++ b/packages/cli/src/commands/handlers/service/restart.ts @@ -1,13 +1,16 @@ import { EOL } from "os" import * as Effect from "effect/Effect" +import { Service } from "@opencode-ai/client/effect" import { Commands } from "../../commands" import { Runtime } from "../../../framework/runtime" -import { Service } from "../../../services/service" +import { ServiceConfig } from "../../../services/service-config" export default Runtime.handler( Commands.commands.service.commands.restart, Effect.fn("cli.service.restart")(function* () { - yield* Service.stop() - process.stdout.write((yield* Service.start()).url + EOL) + const options = yield* ServiceConfig.options() + yield* Service.stop(options) + const transport = yield* Service.start(options) + process.stdout.write(transport.url + EOL) }), ) diff --git a/packages/cli/src/commands/handlers/service/set.ts b/packages/cli/src/commands/handlers/service/set.ts index 39c0be6079..6ecde18d41 100644 --- a/packages/cli/src/commands/handlers/service/set.ts +++ b/packages/cli/src/commands/handlers/service/set.ts @@ -1,11 +1,11 @@ import * as Effect from "effect/Effect" import { Commands } from "../../commands" import { Runtime } from "../../../framework/runtime" -import { Service } from "../../../services/service" +import { ServiceConfig } from "../../../services/service-config" export default Runtime.handler( Commands.commands.service.commands.set, Effect.fn("cli.service.set")(function* (input) { - yield* Service.set(input.key, input.value) + yield* ServiceConfig.set(input.key, input.value) }), ) diff --git a/packages/cli/src/commands/handlers/service/start.ts b/packages/cli/src/commands/handlers/service/start.ts index 58807c8fea..a3a7200bf9 100644 --- a/packages/cli/src/commands/handlers/service/start.ts +++ b/packages/cli/src/commands/handlers/service/start.ts @@ -1,12 +1,14 @@ import { EOL } from "os" import * as Effect from "effect/Effect" +import { Service } from "@opencode-ai/client/effect" import { Commands } from "../../commands" import { Runtime } from "../../../framework/runtime" -import { Service } from "../../../services/service" +import { ServiceConfig } from "../../../services/service-config" export default Runtime.handler( Commands.commands.service.commands.start, Effect.fn("cli.service.start")(function* () { - process.stdout.write((yield* Service.start()).url + EOL) + const transport = yield* Service.start(yield* ServiceConfig.options()) + process.stdout.write(transport.url + EOL) }), ) diff --git a/packages/cli/src/commands/handlers/service/status.ts b/packages/cli/src/commands/handlers/service/status.ts index 9fc27505f6..807d7d749d 100644 --- a/packages/cli/src/commands/handlers/service/status.ts +++ b/packages/cli/src/commands/handlers/service/status.ts @@ -1,13 +1,14 @@ import { EOL } from "os" import * as Effect from "effect/Effect" +import { Service } from "@opencode-ai/client/effect" import { Commands } from "../../commands" import { Runtime } from "../../../framework/runtime" -import { Service } from "../../../services/service" +import { ServiceConfig } from "../../../services/service-config" export default Runtime.handler( Commands.commands.service.commands.status, Effect.fn("cli.service.status")(function* () { - const found = yield* Service.discover() + const found = yield* Service.discover(yield* ServiceConfig.options()) process.stdout.write((found ? found.url : "stopped") + EOL) }), ) diff --git a/packages/cli/src/commands/handlers/service/stop.ts b/packages/cli/src/commands/handlers/service/stop.ts index 1336cdbe1a..53ad3615c3 100644 --- a/packages/cli/src/commands/handlers/service/stop.ts +++ b/packages/cli/src/commands/handlers/service/stop.ts @@ -1,11 +1,12 @@ import * as Effect from "effect/Effect" +import { Service } from "@opencode-ai/client/effect" import { Commands } from "../../commands" import { Runtime } from "../../../framework/runtime" -import { Service } from "../../../services/service" +import { ServiceConfig } from "../../../services/service-config" export default Runtime.handler( Commands.commands.service.commands.stop, Effect.fn("cli.service.stop")(function* () { - yield* Service.stop() + yield* Service.stop(yield* ServiceConfig.options()) }), ) diff --git a/packages/cli/src/commands/handlers/service/unset.ts b/packages/cli/src/commands/handlers/service/unset.ts index 83b5c2b172..ef5fdf9330 100644 --- a/packages/cli/src/commands/handlers/service/unset.ts +++ b/packages/cli/src/commands/handlers/service/unset.ts @@ -1,11 +1,11 @@ import * as Effect from "effect/Effect" import { Commands } from "../../commands" import { Runtime } from "../../../framework/runtime" -import { Service } from "../../../services/service" +import { ServiceConfig } from "../../../services/service-config" export default Runtime.handler( Commands.commands.service.commands.unset, Effect.fn("cli.service.unset")(function* (input) { - yield* Service.unset(input.key) + yield* ServiceConfig.unset(input.key) }), ) diff --git a/packages/cli/src/services/service-config.ts b/packages/cli/src/services/service-config.ts new file mode 100644 index 0000000000..356472e359 --- /dev/null +++ b/packages/cli/src/services/service-config.ts @@ -0,0 +1,143 @@ +import { Global } from "@opencode-ai/core/global" +import { InstallationChannel, InstallationVersion } from "@opencode-ai/core/installation/version" +import { Service } from "@opencode-ai/client/effect" +import { Effect, FileSystem, Schema } from "effect" +import { randomBytes } from "crypto" +import path from "path" + +// The CLI's service configuration file, plus the ServiceOptions binding that +// points the client package's service operations at this CLI: which +// registration file (by channel), which version, and how to spawn opencode. + +export const Info = Schema.Struct({ + hostname: Schema.optional(Schema.String), + port: Schema.optional(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(65_535))), + password: Schema.optional(Schema.String), +}) +export type Info = typeof Info.Type + +const keys = ["hostname", "port", "password"] as const +type Key = (typeof keys)[number] + +const decodeInfo = Schema.decodeUnknownEffect(Schema.fromJsonString(Info)) + +function configKey(key: string): Key { + if (keys.includes(key as Key)) return key as Key + throw new Error(`Unknown service config key: ${key}`) +} + +const env = Effect.gen(function* () { + const fs = yield* FileSystem.FileSystem + const global = yield* Global.Service + const filename = InstallationChannel === "local" ? "service-local.json" : "service.json" + return { + fs, + file: path.join(global.state, filename), + configFile: path.join(global.config, filename), + } +}) + +export const options = Effect.fnUntraced(function* () { + const { file } = yield* env + const compiled = path.basename(process.execPath).replace(/\.exe$/, "") !== "bun" + const entrypoint = compiled ? undefined : process.argv[1] + if (!compiled && entrypoint === undefined) return yield* Effect.fail(new Error("Failed to resolve CLI entrypoint")) + return { + file, + version: InstallationVersion, + command: [process.execPath, ...(entrypoint ? [entrypoint] : []), "serve", "--service"], + } +}) + +export const read = Effect.fn("cli.service-config.read")(function* () { + const { fs, configFile } = yield* env + return yield* fs.readFileString(configFile).pipe( + Effect.flatMap(decodeInfo), + Effect.catch(() => Effect.succeed({} as Info)), + ) +}) + +const write = Effect.fn("cli.service-config.write")(function* (value: Info) { + const { fs, configFile } = yield* env + const temp = configFile + ".tmp" + yield* fs.makeDirectory(path.dirname(configFile), { recursive: true }) + yield* fs.writeFileString(temp, JSON.stringify(value, null, 2) + "\n", { mode: 0o600 }) + yield* fs.rename(temp, configFile) +}) + +export const password = Effect.fn("cli.service-config.password")(function* (value?: string) { + const existing = yield* read() + if (value === undefined && existing.password) return existing.password + const next = value ?? randomBytes(32).toString("base64url") + + // Keep one private credential across server restarts so discovered clients + // can reconnect without exposing a password flag or environment variable. + yield* write({ ...existing, password: next }) + return next +}) + +export const get = Effect.fn("cli.service-config.get")(function* (key?: string) { + if (key === undefined) { + const { password: _password, ...safe } = yield* read() + return JSON.stringify(safe, null, 2) + } + switch (configKey(key)) { + case "hostname": { + return (yield* read()).hostname ?? "" + } + case "port": { + const port = (yield* read()).port + return port === undefined ? "" : String(port) + } + case "password": { + return yield* password() + } + } +}) + +export const set = Effect.fn("cli.service-config.set")(function* (key: string, value: string) { + switch (configKey(key)) { + case "hostname": { + yield* Service.stop(yield* options()) + yield* write({ ...(yield* read()), hostname: value }) + return + } + case "port": { + const port = Number(value) + if (!Number.isInteger(port) || port < 1 || port > 65_535) throw new Error("Port must be between 1 and 65535") + yield* Service.stop(yield* options()) + yield* write({ ...(yield* read()), port }) + return + } + case "password": { + yield* Service.stop(yield* options()) + yield* password(value) + return + } + } +}) + +export const unset = Effect.fn("cli.service-config.unset")(function* (key: string) { + switch (configKey(key)) { + case "hostname": { + yield* Service.stop(yield* options()) + const { hostname: _hostname, ...next } = yield* read() + yield* write(next) + return + } + case "port": { + yield* Service.stop(yield* options()) + const { port: _port, ...next } = yield* read() + yield* write(next) + return + } + case "password": { + yield* Service.stop(yield* options()) + const { password: _password, ...next } = yield* read() + yield* write(next) + return + } + } +}) + +export * as ServiceConfig from "./service-config" diff --git a/packages/cli/src/services/service.ts b/packages/cli/src/services/service.ts deleted file mode 100644 index e7801fd134..0000000000 --- a/packages/cli/src/services/service.ts +++ /dev/null @@ -1,203 +0,0 @@ -import { Global } from "@opencode-ai/core/global" -import { InstallationChannel, InstallationVersion } from "@opencode-ai/core/installation/version" -import { ServiceEffect } from "@opencode-ai/client/service/effect" -import { Effect, FileSystem, Schedule, Schema } from "effect" -import { HttpServer } from "effect/unstable/http" -import { randomBytes, randomUUID } from "crypto" -import path from "path" - -// Binds the client package's service operations to this CLI: which -// registration file (by channel), which version, and how to spawn opencode. -// Also owns the service config file and the server-side registration write. - -const ServiceConfig = Schema.Struct({ - hostname: Schema.optional(Schema.String), - port: Schema.optional(Schema.Int.check(Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(65_535))), - password: Schema.optional(Schema.String), -}) -export type ServiceConfig = typeof ServiceConfig.Type - -const serviceConfigKeys = ["hostname", "port", "password"] as const -type ServiceConfigKey = (typeof serviceConfigKeys)[number] - -const decodeServiceConfig = Schema.decodeUnknownEffect(Schema.fromJsonString(ServiceConfig)) - -function serviceConfigKey(key: string): ServiceConfigKey { - if (serviceConfigKeys.includes(key as ServiceConfigKey)) return key as ServiceConfigKey - throw new Error(`Unknown service config key: ${key}`) -} - -const env = Effect.gen(function* () { - const fs = yield* FileSystem.FileSystem - const global = yield* Global.Service - const filename = InstallationChannel === "local" ? "service-local.json" : "service.json" - return { - fs, - stateDir: global.state, - file: path.join(global.state, filename), - configFile: path.join(global.config, filename), - } -}) - -const options = Effect.fnUntraced(function* () { - const { file } = yield* env - const compiled = path.basename(process.execPath).replace(/\.exe$/, "") !== "bun" - const entrypoint = compiled ? undefined : process.argv[1] - if (!compiled && entrypoint === undefined) return yield* Effect.fail(new Error("Failed to resolve CLI entrypoint")) - return { - file, - version: InstallationVersion, - command: [process.execPath, ...(entrypoint ? [entrypoint] : []), "serve", "--service"], - } -}) - -export const discover = Effect.fn("cli.service.discover")(function* () { - const found = yield* ServiceEffect.discover(yield* options()) - return found?.transport -}) - -export const start = Effect.fn("cli.service.start")(function* () { - return yield* ServiceEffect.start(yield* options()) -}) - -export const connect = Effect.fn("cli.service.connect")(function* () { - return yield* ServiceEffect.connect(yield* options()) -}) - -export const stop = Effect.fn("cli.service.stop")(function* () { - return yield* ServiceEffect.stop(yield* options()) -}) - -export const config = Effect.fn("cli.service.config")(function* () { - const { fs, configFile } = yield* env - return yield* fs.readFileString(configFile).pipe( - Effect.flatMap(decodeServiceConfig), - Effect.catch(() => Effect.succeed({} as ServiceConfig)), - ) -}) - -const writeConfig = Effect.fn("cli.service.writeConfig")(function* (value: ServiceConfig) { - const { fs, configFile } = yield* env - const temp = configFile + ".tmp" - yield* fs.makeDirectory(path.dirname(configFile), { recursive: true }) - yield* fs.writeFileString(temp, JSON.stringify(value, null, 2) + "\n", { mode: 0o600 }) - yield* fs.rename(temp, configFile) -}) - -export const password = Effect.fn("cli.service.password")(function* (value?: string) { - const existing = yield* config() - if (value === undefined && existing.password) return existing.password - const next = value ?? randomBytes(32).toString("base64url") - - // Keep one private credential across server restarts so discovered clients - // can reconnect without exposing a password flag or environment variable. - yield* writeConfig({ ...existing, password: next }) - return next -}) - -export const get = Effect.fn("cli.service.get")(function* (key?: string) { - if (key === undefined) { - const { password: _password, ...safe } = yield* config() - return JSON.stringify(safe, null, 2) - } - switch (serviceConfigKey(key)) { - case "hostname": { - return (yield* config()).hostname ?? "" - } - case "port": { - const port = (yield* config()).port - return port === undefined ? "" : String(port) - } - case "password": { - return yield* password() - } - } -}) - -export const set = Effect.fn("cli.service.set")(function* (key: string, value: string) { - switch (serviceConfigKey(key)) { - case "hostname": { - yield* stop() - yield* writeConfig({ ...(yield* config()), hostname: value }) - return - } - case "port": { - const port = Number(value) - if (!Number.isInteger(port) || port < 1 || port > 65_535) throw new Error("Port must be between 1 and 65535") - yield* stop() - yield* writeConfig({ ...(yield* config()), port }) - return - } - case "password": { - yield* stop() - yield* password(value) - return - } - } -}) - -export const unset = Effect.fn("cli.service.unset")(function* (key: string) { - switch (serviceConfigKey(key)) { - case "hostname": { - yield* stop() - const { hostname: _hostname, ...next } = yield* config() - yield* writeConfig(next) - return - } - case "port": { - yield* stop() - const { port: _port, ...next } = yield* config() - yield* writeConfig(next) - return - } - case "password": { - yield* stop() - const { password: _password, ...next } = yield* config() - yield* writeConfig(next) - return - } - } -}) - -// Server-side half of the registration protocol, run by `serve --service` at -// boot. The registration embeds the password so the file alone is enough for -// any client to discover and authenticate. service.json arbitrates ownership -// after concurrent starts; it is not a startup lock: the atomic rename elects -// the latest writer, the watcher self-evicts losers, and the finalizer -// id-guard keeps an exiting server from deleting its successor's registration. -export const register = Effect.fn("cli.service.register")(function* (address: HttpServer.Address) { - const { fs, stateDir, file } = yield* env - const id = randomUUID() - const secret = yield* password() - const temp = file + "." + id + ".tmp" - yield* fs.makeDirectory(stateDir, { recursive: true }) - yield* fs.writeFileString( - temp, - JSON.stringify({ - id, - version: InstallationVersion, - url: HttpServer.formatAddress(address), - pid: process.pid, - password: secret, - }), - { mode: 0o600 }, - ) - yield* fs.rename(temp, file) - yield* ServiceEffect.readRegistration(file).pipe( - Effect.flatMap((info) => - info?.id === id - ? Effect.void - : Effect.try({ try: () => process.kill(process.pid, "SIGTERM"), catch: (cause) => cause }).pipe(Effect.ignore), - ), - Effect.repeat(Schedule.spaced("10 seconds")), - Effect.forkScoped, - ) - yield* Effect.addFinalizer(() => - ServiceEffect.readRegistration(file).pipe( - Effect.flatMap((info) => (info?.id === id ? fs.remove(file) : Effect.void)), - Effect.ignore, - ), - ) -}) - -export * as Service from "./service" diff --git a/packages/cli/src/tui.ts b/packages/cli/src/tui.ts index 234f69d729..577a7be493 100644 --- a/packages/cli/src/tui.ts +++ b/packages/cli/src/tui.ts @@ -4,8 +4,8 @@ import { Effect } from "effect" import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { Global } from "@opencode-ai/core/global" import { loadBuiltinPlugins } from "@opencode-ai/tui/builtins" -import { OpenCode } from "@opencode-ai/client" -import type { Transport } from "@opencode-ai/client/service" +import { OpenCode } from "@opencode-ai/client/promise" +import type { Transport } from "@opencode-ai/client/effect" import { createOpencodeClient } from "@opencode-ai/sdk/v2/client" import type { Args } from "@opencode-ai/tui/context/args" diff --git a/packages/cli/test/service.test.ts b/packages/cli/test/service.test.ts index 6a4330ac76..68073851c1 100644 --- a/packages/cli/test/service.test.ts +++ b/packages/cli/test/service.test.ts @@ -5,13 +5,13 @@ import { Effect } from "effect" import fs from "node:fs/promises" import os from "node:os" import path from "node:path" -import { Service } from "../src/services/service" +import { ServiceConfig } from "../src/services/service-config" test("local channel stores service config with the local service filename", async () => { const root = await fs.mkdtemp(path.join(os.tmpdir(), "opencode-service-")) try { await Effect.runPromise( - Service.set("hostname", "127.0.0.2").pipe( + ServiceConfig.set("hostname", "127.0.0.2").pipe( Effect.provide(Global.layerWith({ config: path.join(root, "config"), state: path.join(root, "state") })), Effect.provide(NodeFileSystem.layer), ), diff --git a/packages/client/package.json b/packages/client/package.json index 0b93fa532a..0027e19739 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -5,14 +5,12 @@ "type": "module", "license": "MIT", "exports": { - ".": "./src/index.ts", - "./effect": "./src/effect.ts", - "./service": "./src/service/index.ts", - "./service/effect": "./src/service/effect.ts" + "./promise": "./src/promise/index.ts", + "./effect": "./src/effect/index.ts" }, "scripts": { "generate": "bun run script/build.ts", - "check:generated": "bun run generate && git diff --exit-code -- src/generated src/generated-effect", + "check:generated": "bun run generate && git diff --exit-code -- src/promise/generated src/effect/generated", "test": "bun test --timeout 5000", "typecheck": "tsgo --noEmit" }, @@ -29,7 +27,6 @@ } }, "devDependencies": { - "@effect/platform-node": "catalog:", "@opencode-ai/core": "workspace:*", "@opencode-ai/httpapi-codegen": "workspace:*", "@opencode-ai/server": "workspace:*", diff --git a/packages/client/script/build.ts b/packages/client/script/build.ts index 10c3a23d0d..2ba1dbc9c2 100644 --- a/packages/client/script/build.ts +++ b/packages/client/script/build.ts @@ -25,11 +25,11 @@ await Effect.runPromise( }, }, }), - fileURLToPath(new URL("../src/generated", import.meta.url)), + fileURLToPath(new URL("../src/promise/generated", import.meta.url)), ), write( - emitEffectImported(effectContract, { module: "../contract", api: "ClientApi" }), - fileURLToPath(new URL("../src/generated-effect", import.meta.url)), + emitEffectImported(effectContract, { module: "../../contract", api: "ClientApi" }), + fileURLToPath(new URL("../src/effect/generated", import.meta.url)), ), write( emitEffectShape(effectContract, { module: "@opencode-ai/protocol/client", api: "ClientApi" }), diff --git a/packages/client/src/generated-effect/.httpapi-codegen.json b/packages/client/src/effect/generated/.httpapi-codegen.json similarity index 100% rename from packages/client/src/generated-effect/.httpapi-codegen.json rename to packages/client/src/effect/generated/.httpapi-codegen.json diff --git a/packages/client/src/generated-effect/client-error.ts b/packages/client/src/effect/generated/client-error.ts similarity index 100% rename from packages/client/src/generated-effect/client-error.ts rename to packages/client/src/effect/generated/client-error.ts diff --git a/packages/client/src/generated-effect/client.ts b/packages/client/src/effect/generated/client.ts similarity index 99% rename from packages/client/src/generated-effect/client.ts rename to packages/client/src/effect/generated/client.ts index 2aa2c6cb3e..6cce70214c 100644 --- a/packages/client/src/generated-effect/client.ts +++ b/packages/client/src/effect/generated/client.ts @@ -3,7 +3,7 @@ import { Effect, Stream, Schema } from "effect" import { Sse } from "effect/unstable/encoding" import { HttpClientError } from "effect/unstable/http" import { HttpApiClient } from "effect/unstable/httpapi" -import { ClientApi } from "../contract" +import { ClientApi } from "../../contract" import { ClientError } from "./client-error" type RawClient = HttpApiClient.ForApi diff --git a/packages/client/src/generated-effect/index.ts b/packages/client/src/effect/generated/index.ts similarity index 100% rename from packages/client/src/generated-effect/index.ts rename to packages/client/src/effect/generated/index.ts diff --git a/packages/client/src/effect.ts b/packages/client/src/effect/index.ts similarity index 92% rename from packages/client/src/effect.ts rename to packages/client/src/effect/index.ts index ee8652c700..38bae4d753 100644 --- a/packages/client/src/effect.ts +++ b/packages/client/src/effect/index.ts @@ -1,6 +1,8 @@ // TODO: Keep additional network capabilities inside Schema and Protocol as the client grows; /effect must never import // Core or Server. Preserve these datatype exports so internal model reorganizations do not require caller migrations. -export * from "./generated-effect/index" +export * from "./generated/index" +export { Service } from "./service.js" +export type { Transport, ServiceOptions } from "./service.js" export { Agent } from "@opencode-ai/schema/agent" export { Command } from "@opencode-ai/schema/command" export { Credential } from "@opencode-ai/schema/credential" diff --git a/packages/client/src/effect/service.ts b/packages/client/src/effect/service.ts new file mode 100644 index 0000000000..93cbdd03fc --- /dev/null +++ b/packages/client/src/effect/service.ts @@ -0,0 +1,165 @@ +import { Effect, FileSystem, Option, Schedule, Schema } from "effect" +import { spawn } from "node:child_process" +import { homedir } from "node:os" +import { join } from "node:path" + +// Find, start, and stop the local opencode background service. +// +// The service daemon advertises itself through a registration file in the +// user's state directory: url, pid, version, and the private password, with +// 0600 permissions. That file is the complete discovery contract — reading it +// is all a client needs to connect. The daemon's own configuration (port, +// persisted password) is CLI-owned and never read here. + +export type Transport = { + readonly url: string + readonly headers?: RequestInit["headers"] +} + +export type ServiceOptions = { + // Absolute path to the service registration file. Defaults to + // opencode/service.json in the XDG state directory. + readonly file?: string + // When set, discovery only returns a server reporting this exact version, + // and start() replaces a healthy server whose version differs. + readonly version?: string + // Argv used to spawn the service. Defaults to ["opencode", "serve", + // "--service"] resolved from PATH. + readonly command?: ReadonlyArray +} + +// Read-only lookup: registration file plus health check and version gate. +// Never spawns; escalation to start() is the caller's policy. +export const discover = Effect.fn("service.discover")(function* (options: ServiceOptions = {}) { + const registration = yield* read(options.file) + if (registration === undefined) return undefined + if (options.version !== undefined && registration.version !== options.version) return undefined + const found = yield* probe(registration) + return found?.transport +}) + +// Idempotent ensure-running: reuses a healthy compatible server, replaces a +// version-mismatched one, and otherwise spawns the service command detached. +export const start = Effect.fn("service.start")(function* (options: ServiceOptions = {}) { + const compatible = yield* discover(options) + if (compatible !== undefined) return compatible + const mismatched = yield* find(options) + if (mismatched !== undefined) yield* kill(mismatched.registration, options).pipe(Effect.ignore) + + const [command, ...args] = options.command ?? ["opencode", "serve", "--service"] + if (command === undefined) return yield* Effect.fail(new Error("Missing service command")) + yield* Effect.try({ + try: () => { + spawn(command, args, { detached: true, stdio: "ignore" }).unref() + }, + catch: (cause) => new Error("Failed to start server", { cause }), + }) + + return yield* discover(options).pipe( + Effect.flatMap((found) => + found === undefined ? Effect.fail(new Error("Server is not ready")) : Effect.succeed(found), + ), + Effect.retry(poll), + Effect.mapError(() => new Error("Failed to start server")), + ) +}) + +export const stop = Effect.fn("service.stop")(function* (options: ServiceOptions = {}) { + const fs = yield* FileSystem.FileSystem + const existing = yield* find(options) + if (existing !== undefined) yield* kill(existing.registration, options) + yield* fs.remove(options.file ?? fallback()).pipe(Effect.ignore) +}) + +function fallback() { + const state = process.env["XDG_STATE_HOME"] ?? join(homedir(), ".local", "state") + return join(state, "opencode", "service.json") +} + +function auth(password: string): RequestInit["headers"] { + return { authorization: "Basic " + btoa("opencode:" + password) } +} + +const Registration = Schema.Struct({ + id: Schema.optional(Schema.String), + version: Schema.optional(Schema.String), + url: Schema.String, + pid: Schema.Int.check(Schema.isGreaterThan(0)), + password: Schema.optional(Schema.String), +}) +type Registration = typeof Registration.Type + +const decode = Schema.decodeUnknownEffect(Schema.fromJsonString(Registration)) + +// A missing or corrupt file means no valid registration; callers treat both +// the same (the registering server self-evicts, clients rediscover). +const read = Effect.fnUntraced(function* (file?: string) { + const fs = yield* FileSystem.FileSystem + const text = yield* fs.readFileString(file ?? fallback()).pipe(Effect.option) + if (Option.isNone(text)) return undefined + return yield* decode(text.value).pipe(Effect.option, Effect.map(Option.getOrUndefined)) +}) + +type LocalService = { + readonly registration: Registration + readonly transport: Transport +} + +const probe = Effect.fnUntraced(function* (registration: Registration) { + const headers = registration.password === undefined ? undefined : auth(registration.password) + const healthy = yield* Effect.tryPromise(() => + fetch(new URL("/api/health", registration.url), { + headers, + signal: AbortSignal.timeout(2_000), + }), + ).pipe( + Effect.map((response) => response.ok), + Effect.orElseSucceed(() => false), + ) + if (!healthy) return undefined + return { registration, transport: { url: registration.url, headers } } satisfies LocalService +}) + +// Health-checked lookup without the version gate: lifecycle operations must be +// able to see (and replace or stop) a server from a different version. +const find = Effect.fnUntraced(function* (options: ServiceOptions) { + const registration = yield* read(options.file) + if (registration === undefined) return undefined + return yield* probe(registration) +}) + +// 50ms cadence bounded at ~5s, shared by stop escalation and start readiness. +const poll = Schedule.spaced("50 millis").pipe(Schedule.both(Schedule.recurs(100))) + +const signal = (pid: number, name: NodeJS.Signals) => + Effect.try({ try: () => process.kill(pid, name), catch: (cause) => cause }).pipe(Effect.ignore) + +const stopped = Effect.fnUntraced(function* (pid: number) { + const running = yield* Effect.try({ try: () => process.kill(pid, 0), catch: () => false }).pipe( + Effect.orElseSucceed(() => false), + ) + if (!running) return true + return yield* Effect.fail(new Error(`Server process ${pid} is still running`)) +}) + +function same(left: Registration, right: Registration) { + return left.id === right.id && left.version === right.version && left.url === right.url && left.pid === right.pid +} + +const kill = Effect.fnUntraced(function* (info: Registration, options: ServiceOptions) { + // A stale registration may point at a PID that has since been reused by + // another process. Only signal the PID after authenticating the server. + const current = yield* find(options) + if (current === undefined || !same(current.registration, info)) return + + yield* signal(info.pid, "SIGTERM") + const done = yield* stopped(info.pid).pipe(Effect.retry(poll), Effect.option) + if (Option.isSome(done)) return + + const latest = yield* find(options) + if (latest === undefined || !same(latest.registration, info)) return + yield* signal(info.pid, "SIGKILL") + yield* stopped(info.pid).pipe(Effect.retry(poll)) +}) + +export * as Service from "./service.js" diff --git a/packages/client/src/generated/.httpapi-codegen.json b/packages/client/src/promise/generated/.httpapi-codegen.json similarity index 100% rename from packages/client/src/generated/.httpapi-codegen.json rename to packages/client/src/promise/generated/.httpapi-codegen.json diff --git a/packages/client/src/generated/client-error.ts b/packages/client/src/promise/generated/client-error.ts similarity index 100% rename from packages/client/src/generated/client-error.ts rename to packages/client/src/promise/generated/client-error.ts diff --git a/packages/client/src/generated/client.ts b/packages/client/src/promise/generated/client.ts similarity index 100% rename from packages/client/src/generated/client.ts rename to packages/client/src/promise/generated/client.ts diff --git a/packages/client/src/generated/index.ts b/packages/client/src/promise/generated/index.ts similarity index 100% rename from packages/client/src/generated/index.ts rename to packages/client/src/promise/generated/index.ts diff --git a/packages/client/src/generated/types.ts b/packages/client/src/promise/generated/types.ts similarity index 94% rename from packages/client/src/generated/types.ts rename to packages/client/src/promise/generated/types.ts index 24972edbca..34fc01fe4c 100644 --- a/packages/client/src/generated/types.ts +++ b/packages/client/src/promise/generated/types.ts @@ -4030,6 +4030,239 @@ export type EventSubscribeOutput = readonly todos: ReadonlyArray<{ readonly content: string; readonly status: string; readonly priority: string }> } } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "session.status" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { + readonly sessionID: string + readonly status: + | { readonly type: "idle" } + | { + readonly type: "retry" + readonly attempt: number + readonly message: string + readonly action?: { + readonly reason: string + readonly provider: string + readonly title: string + readonly message: string + readonly label: string + readonly link?: string + } + readonly next: number + } + | { readonly type: "busy" } + } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "session.idle" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { readonly sessionID: string } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "tui.prompt.append" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { readonly text: string } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "tui.command.execute" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { + readonly command: + | "session.list" + | "session.new" + | "session.share" + | "session.interrupt" + | "session.background" + | "session.compact" + | "session.page.up" + | "session.page.down" + | "session.line.up" + | "session.line.down" + | "session.half.page.up" + | "session.half.page.down" + | "session.first" + | "session.last" + | "prompt.clear" + | "prompt.submit" + | "agent.cycle" + | string + } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "tui.toast.show" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { + readonly title?: string + readonly message: string + readonly variant: "info" | "success" | "warning" | "error" + readonly duration?: number | undefined + } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "tui.session.select" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { readonly sessionID: string } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "installation.updated" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { readonly version: string } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "installation.update-available" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { readonly version: string } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "vcs.branch.updated" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { readonly branch?: string } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "mcp.status.changed" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { readonly server: string } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "permission.asked" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { + readonly id: string + readonly sessionID: string + readonly permission: string + readonly patterns: ReadonlyArray + readonly metadata: { readonly [x: string]: unknown } + readonly always: ReadonlyArray + readonly tool?: { readonly messageID: string; readonly callID: string } | undefined + } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "permission.replied" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { + readonly sessionID: string + readonly requestID: string + readonly reply: "once" | "always" | "reject" + } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "question.asked" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { + readonly id: string + readonly sessionID: string + readonly questions: ReadonlyArray<{ + readonly question: string + readonly header: string + readonly options: ReadonlyArray<{ readonly label: string; readonly description: string }> + readonly multiple?: boolean | undefined + readonly custom?: boolean | undefined + }> + readonly tool?: { readonly messageID: string; readonly callID: string } | undefined + } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "question.replied" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { + readonly sessionID: string + readonly requestID: string + readonly answers: ReadonlyArray> + } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "question.rejected" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { readonly sessionID: string; readonly requestID: string } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: unknown } + readonly type: "session.error" + readonly durable?: { readonly aggregateID: string; readonly seq: number; readonly version: number } + readonly location?: { readonly directory: string; readonly workspaceID?: string } + readonly data: { + readonly sessionID?: string | undefined + readonly error?: + | { + readonly name: "ProviderAuthError" + readonly data: { readonly providerID: string; readonly message: string } + } + | { + readonly name: "UnknownError" + readonly data: { readonly message: string; readonly ref?: string | undefined } + } + | { readonly name: "MessageOutputLengthError"; readonly data: {} } + | { readonly name: "MessageAbortedError"; readonly data: { readonly message: string } } + | { + readonly name: "StructuredOutputError" + readonly data: { readonly message: string; readonly retries: number } + } + | { + readonly name: "ContextOverflowError" + readonly data: { readonly message: string; readonly responseBody?: string | undefined } + } + | { readonly name: "ContentFilterError"; readonly data: { readonly message: string } } + | { + readonly name: "APIError" + readonly data: { + readonly message: string + readonly statusCode?: number | undefined + readonly isRetryable: boolean + readonly responseHeaders?: { readonly [x: string]: string } | undefined + readonly responseBody?: string | undefined + readonly metadata?: { readonly [x: string]: string } | undefined + } + } + | undefined + } + } | { readonly id: string readonly metadata?: { readonly [x: string]: unknown } | undefined diff --git a/packages/client/src/index.ts b/packages/client/src/promise/index.ts similarity index 78% rename from packages/client/src/index.ts rename to packages/client/src/promise/index.ts index e9e848b160..61bdcdf888 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/promise/index.ts @@ -1,3 +1,4 @@ export * from "./generated/index" +export type { Transport } from "../effect/service.js" export type { EventSubscribeOutput as OpenCodeEvent } from "./generated/types" export type OpenCodeClient = ReturnType diff --git a/packages/client/src/service/effect.ts b/packages/client/src/service/effect.ts deleted file mode 100644 index 8f58fc786a..0000000000 --- a/packages/client/src/service/effect.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Effect } from "effect" -import * as service from "./index.js" - -export type { Transport, Discover, Registration, LocalService, ServiceOptions } from "./index.js" - -export { basicAuth } from "./index.js" - -export const readRegistration = (file?: string) => Effect.promise(() => service.readRegistration(file)) -export const discover = (options?: service.ServiceOptions) => Effect.promise(() => service.discover(options)) -export const stop = (options?: service.ServiceOptions) => Effect.promise(() => service.stop(options)) -export const start = (options?: service.ServiceOptions) => - Effect.tryPromise({ - try: () => service.start(options), - catch: (cause) => new Error("Failed to start server", { cause }), - }) -export const connect = (options?: service.ServiceOptions) => - Effect.tryPromise({ - try: () => service.connect(options), - catch: (cause) => new Error("Failed to connect to server", { cause }), - }) - -export * as ServiceEffect from "./effect.js" diff --git a/packages/client/test/effect.test.ts b/packages/client/test/effect.test.ts index b6ee443aa6..445a9cf3de 100644 --- a/packages/client/test/effect.test.ts +++ b/packages/client/test/effect.test.ts @@ -1,7 +1,7 @@ import { expect, test } from "bun:test" import { DateTime, Effect, Stream } from "effect" import { HttpClient, HttpClientResponse } from "effect/unstable/http" -import { AbsolutePath, Agent, Event, Location, Model, OpenCode, Prompt, Session, SessionMessage } from "../src/effect" +import { AbsolutePath, Agent, Event, Location, Model, OpenCode, Prompt, Session, SessionMessage } from "../src/effect/index" const synced = { type: "log.synced" as const, aggregateID: "ses_test", seq: Event.Seq.make(1) } diff --git a/packages/client/test/import-boundaries.test.ts b/packages/client/test/import-boundaries.test.ts index 4875a3a5dc..1a018a032b 100644 --- a/packages/client/test/import-boundaries.test.ts +++ b/packages/client/test/import-boundaries.test.ts @@ -12,7 +12,7 @@ const server = resolve(import.meta.dir, "../../server") describe("public import boundaries", () => { test("isolates each public entrypoint", async () => { - const root = await bundleInputs("@opencode-ai/client", "browser") + const root = await bundleInputs("@opencode-ai/client/promise", "browser") expect(within(root, effect)).toEqual([]) expect(within(root, schema)).toEqual([]) @@ -20,7 +20,9 @@ describe("public import boundaries", () => { expect(within(root, core)).toEqual([]) expect(within(root, server)).toEqual([]) - const network = await bundleInputs("@opencode-ai/client/effect", "browser") + // The effect entry includes local service lifecycle (node spawn/fs), so it + // bundles for bun; the boundary assertions below are what matter. + const network = await bundleInputs("@opencode-ai/client/effect", "bun") expect(within(network, effect).length).toBeGreaterThan(0) expect(within(network, schema).length).toBeGreaterThan(0) diff --git a/packages/client/test/promise.test.ts b/packages/client/test/promise.test.ts index dd242d4fb0..6509c8f713 100644 --- a/packages/client/test/promise.test.ts +++ b/packages/client/test/promise.test.ts @@ -1,5 +1,5 @@ import { expect, test } from "bun:test" -import { isSessionNotFoundError, isUnauthorizedError, OpenCode } from "../src" +import { isSessionNotFoundError, isUnauthorizedError, OpenCode } from "../src/promise/index" test("exposes every standard HTTP API group", () => { const client = OpenCode.make({ baseUrl: "http://localhost:3000" }) diff --git a/packages/opencode/src/cli/cmd/attach.ts b/packages/opencode/src/cli/cmd/attach.ts index 51bafef779..4339892cf9 100644 --- a/packages/opencode/src/cli/cmd/attach.ts +++ b/packages/opencode/src/cli/cmd/attach.ts @@ -3,7 +3,7 @@ import { UI } from "@/cli/ui" import { errorMessage } from "@opencode-ai/tui/util/error" import { validateSession } from "../tui/validate-session" import { ServerAuth } from "@/server/auth" -import { OpenCode } from "@opencode-ai/client" +import { OpenCode } from "@opencode-ai/client/promise" import { createOpencodeClient } from "@opencode-ai/sdk/v2" export const AttachCommand = cmd({ diff --git a/packages/opencode/src/cli/cmd/tui.ts b/packages/opencode/src/cli/cmd/tui.ts index 54a0079813..60e90923b7 100644 --- a/packages/opencode/src/cli/cmd/tui.ts +++ b/packages/opencode/src/cli/cmd/tui.ts @@ -8,7 +8,7 @@ import { errorMessage } from "@opencode-ai/tui/util/error" import { withTimeout } from "@/util/timeout" import { withNetworkOptions, resolveNetworkOptionsNoConfig, hasArg } from "@/cli/network" import { Filesystem } from "@/util/filesystem" -import { OpenCode } from "@opencode-ai/client" +import { OpenCode } from "@opencode-ai/client/promise" import { createOpencodeClient } from "@opencode-ai/sdk/v2" import { writeHeapSnapshot } from "v8" import { ServerAuth } from "@/server/auth" diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index 021733d529..c1f22c8a81 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -74,9 +74,9 @@ export type Event = | EventShellCreated | EventShellExited | EventShellDeleted - | EventFormCreated - | EventFormReplied - | EventFormCancelled + | EventQuestionV2Asked + | EventQuestionV2Replied + | EventQuestionV2Rejected | EventTodoUpdated | EventLspUpdated | EventPermissionAsked @@ -1447,26 +1447,32 @@ export type GlobalEvent = { } | { id: string - type: "form.created" + type: "question.v2.asked" properties: { - form: FormFormInfo | FormUrlInfo + id: string + sessionID: string + /** + * Questions to ask + */ + questions: Array + tool?: QuestionV2Tool } } | { id: string - type: "form.replied" + type: "question.v2.replied" properties: { - id: string sessionID: string - answer: FormAnswer + requestID: string + answers: Array } } | { id: string - type: "form.cancelled" + type: "question.v2.rejected" properties: { - id: string sessionID: string + requestID: string } } | { @@ -2795,11 +2801,356 @@ export type WorkspaceWarpError = { } } +export type UnauthorizedError = { + _tag: "UnauthorizedError" + message: string +} + +export type SessionWatermarks = { + [key: string]: unknown | number +} + +export type SessionsResponse = { + data: Array + watermarks: SessionWatermarks + cursor: { + previous?: string + next?: string + } +} + +export type InvalidCursorError = { + _tag: "InvalidCursorError" + message: string +} + +export type SessionActive = { + type: "running" +} + +export type SessionNotFoundError = { + _tag: "SessionNotFoundError" + sessionID: string + message: string +} + +export type MessageNotFoundError = { + _tag: "MessageNotFoundError" + sessionID: string + messageID: string + message: string +} + +export type PromptInput = { + text: string + files?: Array + agents?: Array +} + +export type ConflictError = { + _tag: "ConflictError" + message: string + resource?: string +} + +export type CommandNotFoundError = { + _tag: "CommandNotFoundError" + command: string + message: string +} + +export type CommandEvaluationError = { + _tag: "CommandEvaluationError" + command: string + message: string +} + +export type SkillNotFoundError = { + _tag: "SkillNotFoundError" + skill: string + message: string +} + +export type ServiceUnavailableError = { + _tag: "ServiceUnavailableError" + message: string + service?: string +} + +export type UnknownError1 = { + _tag: "UnknownError" + message: string + ref?: string +} + +export type SessionDurableEvent = + | SessionNextAgentSwitched + | SessionNextModelSwitched + | SessionNextMoved + | SessionNextRenamed + | SessionNextForked + | SessionNextPrompted + | SessionNextPromptAdmitted + | SessionNextContextUpdated + | SessionNextSynthetic + | SessionNextSkillActivated + | SessionNextShellStarted + | SessionNextShellEnded + | SessionNextStepStarted + | SessionNextStepEnded + | SessionNextStepFailed + | SessionNextTextStarted + | SessionNextTextEnded + | SessionNextToolInputStarted + | SessionNextToolInputEnded + | SessionNextToolCalled + | SessionNextToolProgress + | SessionNextToolSuccess + | SessionNextToolFailed + | SessionNextReasoningStarted + | SessionNextReasoningEnded + | SessionNextRetried + | SessionNextCompactionStarted + | SessionNextCompactionEnded + | SessionNextRevertStaged + | SessionNextRevertCleared + | SessionNextRevertCommitted + +export type SessionLogItem = SessionDurableEvent | EventLogSynced + +export type SessionLogItemStream = string + +export type SessionMessagesResponse = { + data: Array + watermark?: number + cursor: { + previous?: string + next?: string + } +} + +export type GenerateTextResponse = { + data: { + text: string + } +} + +export type ProviderNotFoundError = { + _tag: "ProviderNotFoundError" + providerID: string + message: string +} + +export type OutputFormat1 = + | { + type: "text" + } + | { + type: "json_schema" + schema: JsonSchema + retryCount?: number + } + +export type Shell1 = { + id: string + status: "running" | "exited" | "timeout" | "killed" + command: string + cwd: string + shell: string + file: string + pid?: number + exit?: number | "NaN" | "Infinity" | "-Infinity" + metadata: { + [key: string]: unknown + } + time: { + started: number | "NaN" | "Infinity" | "-Infinity" + completed?: number | "NaN" | "Infinity" | "-Infinity" + } +} + +export type SessionStatus2 = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.status" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + status: SessionStatus + } +} + +export type QuestionReplied2 = { + id: string + metadata?: { + [key: string]: unknown + } + type: "question.replied" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + requestID: string + answers: Array + } +} + +export type QuestionRejected2 = { + id: string + metadata?: { + [key: string]: unknown + } + type: "question.rejected" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + requestID: string + } +} + +export type V2Event = + | ModelsDevRefreshed + | IntegrationUpdated + | IntegrationConnectionUpdated + | CatalogUpdated + | AgentUpdated + | SessionCreated + | SessionUpdated + | SessionDeleted + | MessageUpdated + | MessageRemoved + | MessagePartUpdated + | MessagePartRemoved + | SessionNextAgentSwitched + | SessionNextModelSwitched + | SessionNextMoved + | SessionNextRenamed + | SessionNextForked + | SessionNextPrompted + | SessionNextPromptAdmitted + | SessionNextExecutionSettled + | SessionNextContextUpdated + | SessionNextSynthetic + | SessionNextSkillActivated + | SessionNextShellStarted + | SessionNextShellEnded + | SessionNextStepStarted + | SessionNextStepEnded + | SessionNextStepFailed + | SessionNextTextStarted + | SessionNextTextDelta + | SessionNextTextEnded + | SessionNextReasoningStarted + | SessionNextReasoningDelta + | SessionNextReasoningEnded + | SessionNextToolInputStarted + | SessionNextToolInputDelta + | SessionNextToolInputEnded + | SessionNextToolCalled + | SessionNextToolProgress + | SessionNextToolSuccess + | SessionNextToolFailed + | SessionNextRetried + | SessionNextCompactionStarted + | SessionNextCompactionDelta + | SessionNextCompactionEnded + | SessionNextRevertStaged + | SessionNextRevertCleared + | SessionNextRevertCommitted + | MessagePartDelta + | SessionDiff + | SessionError + | InstallationUpdated + | InstallationUpdateAvailable + | FileEdited + | ReferenceUpdated + | PermissionV2Asked + | PermissionV2Replied + | PluginAdded + | ProjectDirectoriesUpdated + | CommandUpdated + | SkillUpdated + | FileWatcherUpdated + | PtyCreated + | PtyUpdated + | PtyExited + | PtyDeleted + | ShellCreated + | ShellExited + | ShellDeleted + | QuestionV2Asked + | QuestionV2Replied + | QuestionV2Rejected + | TodoUpdated + | LspUpdated + | PermissionAsked + | PermissionReplied + | TuiPromptAppend + | TuiCommandExecute + | TuiToastShow + | TuiSessionSelect + | McpToolsChanged + | McpBrowserOpenFailed + | McpStatusChanged + | CommandExecuted + | ProjectUpdated + | SessionStatus2 + | SessionIdle + | QuestionAsked + | QuestionReplied2 + | QuestionRejected2 + | SessionCompacted + | VcsBranchUpdated + | WorkspaceReady + | WorkspaceFailed + | WorkspaceStatus + | WorktreeReady + | WorktreeFailed + | ServerConnected + | GlobalDisposed + +export type V2EventStream = string + +export type ForbiddenError = { + _tag: "ForbiddenError" + message: string +} + +export type ShellNotFoundError = { + _tag: "ShellNotFoundError" + id: string + message: string +} + +export type ProjectCopyError = { + name: "ProjectCopyError" + data: { + message: string + forceRequired?: boolean + } +} + export type EffectHttpApiErrorForbidden = { _tag: "Forbidden" } -export type Shell1 = { +export type Shell2 = { id: string status: "running" | "exited" | "timeout" | "killed" command: string @@ -2984,120 +3335,40 @@ export type PermissionV2Source = { export type PermissionV2Reply = "once" | "always" | "reject" -export type FormMetadata = { - [key: string]: unknown -} - -export type FormWhen = { - key: string - op: "eq" | "neq" - value: string -} - -export type FormOption = { - value: string +export type QuestionV2Option = { + /** + * Display text (1-5 words, concise) + */ label: string - description?: string + /** + * Explanation of choice + */ + description: string } -export type FormStringField = { - key: string - title?: string - description?: string - required?: boolean - when?: FormWhen - type: "string" - format?: "email" | "uri" | "date" | "date-time" - minLength?: number - maxLength?: number - pattern?: string - placeholder?: string - default?: string - options?: Array +export type QuestionV2Info = { + /** + * Complete question + */ + question: string + /** + * Very short label (max 30 chars) + */ + header: string + /** + * Available choices + */ + options: Array + multiple?: boolean custom?: boolean } -export type FormNumberField = { - key: string - title?: string - description?: string - required?: boolean - when?: FormWhen - type: "number" - minimum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" - maximum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" - default?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" +export type QuestionV2Tool = { + messageID: string + callID: string } -export type FormIntegerField = { - key: string - title?: string - description?: string - required?: boolean - when?: FormWhen - type: "integer" - minimum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" - maximum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" - default?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" -} - -export type FormBooleanField = { - key: string - title?: string - description?: string - required?: boolean - when?: FormWhen - type: "boolean" - default?: boolean -} - -export type FormMultiselectField = { - key: string - title?: string - description?: string - required?: boolean - when?: FormWhen - type: "multiselect" - options: Array - minItems?: number - maxItems?: number - custom?: boolean - default?: Array -} - -export type FormFormInfo = { - id: string - sessionID: string - title?: string - metadata?: FormMetadata - mode: "form" - fields: Array -} - -export type FormUrlInfo = { - id: string - sessionID: string - title?: string - metadata?: FormMetadata - mode: "url" - url: string -} - -export type FormValue = - | string - | number - | "NaN" - | "Infinity" - | "-Infinity" - | "Infinity" - | "-Infinity" - | "NaN" - | boolean - | Array - -export type FormAnswer = { - [key: string]: FormValue -} +export type QuestionV2Answer = Array export type ProjectVcs = "git" @@ -3853,6 +4124,2601 @@ export type WorkspaceEventConnectionStatus = { status: "connected" | "connecting" | "disconnected" | "error" } +export type LocationInfo = { + directory: string + workspaceID?: string + project: { + id: string + directory: string + } +} + +export type ProviderSettings = { + [key: string]: unknown +} + +export type ProviderRequest = { + settings: ProviderSettings + headers: { + [key: string]: string + } + body: { + [key: string]: unknown + } +} + +export type AgentColor = string | "primary" | "secondary" | "accent" | "success" | "warning" | "error" | "info" + +export type PermissionV2Effect = "allow" | "deny" | "ask" + +export type PermissionV2Rule = { + action: string + resource: string + effect: PermissionV2Effect +} + +export type PermissionV2Ruleset = Array + +export type AgentV2Info = { + id: string + model?: ModelRef + request: ProviderRequest + system?: string + description?: string + mode: "subagent" | "primary" | "all" + hidden: boolean + color?: AgentColor + steps?: number + permissions: PermissionV2Ruleset +} + +export type PluginInfo = { + id: string +} + +export type SessionV2Info = { + id: string + parentID?: string + projectID: string + agent?: string + model?: ModelRef + cost: number + tokens: { + input: number + output: number + reasoning: number + cache: { + read: number + write: number + } + } + time: { + created: number + updated: number + archived?: number + } + title: string + location: LocationRef + subpath?: string + revert?: RevertState +} + +export type PromptInputFileAttachment = { + uri: string + name?: string + description?: string + source?: PromptSource +} + +export type SessionInputAdmitted = { + admittedSeq: number + id: string + sessionID: string + prompt: Prompt + delivery: "steer" | "queue" + timeCreated: number + promotedSeq?: number +} + +export type SessionMessageAgentSwitched = { + id: string + metadata?: { + [key: string]: unknown + } + time: { + created: number + } + type: "agent-switched" + agent: string +} + +export type SessionMessageModelSwitched = { + id: string + metadata?: { + [key: string]: unknown + } + time: { + created: number + } + type: "model-switched" + model: ModelRef +} + +export type SessionMessageUser = { + id: string + metadata?: { + [key: string]: unknown + } + time: { + created: number + } + text: string + files?: Array + agents?: Array + type: "user" +} + +export type SessionMessageSynthetic = { + id: string + metadata?: { + [key: string]: unknown + } + time: { + created: number + } + sessionID: string + text: string + description?: string + type: "synthetic" +} + +export type SessionMessageSystem = { + id: string + metadata?: { + [key: string]: unknown + } + time: { + created: number + } + type: "system" + text: string +} + +export type SessionMessageSkill = { + id: string + metadata?: { + [key: string]: unknown + } + time: { + created: number + } + type: "skill" + name: string + text: string +} + +export type SessionMessageShell = { + id: string + metadata?: { + [key: string]: unknown + } + time: { + created: number + completed?: number + } + type: "shell" + callID: string + command: string + output: string +} + +export type SessionMessageAssistantText = { + type: "text" + id: string + text: string +} + +export type SessionMessageAssistantReasoning = { + type: "reasoning" + id: string + text: string + providerMetadata?: LlmProviderMetadata + time?: { + created: number + completed?: number + } +} + +export type SessionMessageToolStatePending = { + status: "pending" + input: string +} + +export type SessionMessageToolStateRunning = { + status: "running" + input: { + [key: string]: unknown + } + structured: { + [key: string]: unknown + } + content: Array +} + +export type SessionMessageToolStateCompleted = { + status: "completed" + input: { + [key: string]: unknown + } + attachments?: Array + content: Array + outputPaths?: Array + structured: { + [key: string]: unknown + } + result?: unknown +} + +export type SessionMessageToolStateError = { + status: "error" + input: { + [key: string]: unknown + } + content: Array + structured: { + [key: string]: unknown + } + error: SessionErrorUnknown + result?: unknown +} + +export type SessionMessageAssistantTool = { + type: "tool" + id: string + name: string + provider?: { + executed: boolean + metadata?: LlmProviderMetadata + resultMetadata?: LlmProviderMetadata + } + state: + | SessionMessageToolStatePending + | SessionMessageToolStateRunning + | SessionMessageToolStateCompleted + | SessionMessageToolStateError + time: { + created: number + ran?: number + completed?: number + pruned?: number + } +} + +export type SessionMessageAssistant = { + id: string + metadata?: { + [key: string]: unknown + } + time: { + created: number + completed?: number + } + type: "assistant" + agent: string + model: ModelRef + content: Array + snapshot?: { + start?: string + end?: string + files?: Array + } + finish?: string + cost?: number + tokens?: { + input: number + output: number + reasoning: number + cache: { + read: number + write: number + } + } + error?: SessionErrorUnknown +} + +export type SessionMessageCompaction = { + type: "compaction" + reason: "auto" | "manual" + summary: string + recent: string + id: string + metadata?: { + [key: string]: unknown + } + time: { + created: number + } +} + +export type SessionMessage = + | SessionMessageAgentSwitched + | SessionMessageModelSwitched + | SessionMessageUser + | SessionMessageSynthetic + | SessionMessageSystem + | SessionMessageSkill + | SessionMessageShell + | SessionMessageAssistant + | SessionMessageCompaction + +export type SessionContextEntryKey = string + +export type SessionContextEntryInfo = { + key: SessionContextEntryKey + value: unknown +} + +export type SessionNextAgentSwitched = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.agent.switched" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + messageID: string + agent: string + } +} + +export type SessionNextModelSwitched = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.model.switched" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + messageID: string + model: ModelRef + } +} + +export type SessionNextMoved = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.moved" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + location: LocationRef + subdirectory?: string + } +} + +export type SessionNextRenamed = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.renamed" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + title: string + } +} + +export type SessionNextForked = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.forked" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + parentID: string + messageID?: string + } +} + +export type SessionNextPrompted = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.prompted" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + messageID: string + prompt: Prompt + delivery: "steer" | "queue" + } +} + +export type SessionNextPromptAdmitted = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.prompt.admitted" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + messageID: string + prompt: Prompt + delivery: "steer" | "queue" + } +} + +export type SessionNextContextUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.context.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + messageID: string + text: string + } +} + +export type SessionNextSynthetic = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.synthetic" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + messageID: string + text: string + description?: string + metadata?: { + [key: string]: unknown + } + } +} + +export type SessionNextSkillActivated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.skill.activated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + messageID: string + name: string + text: string + } +} + +export type SessionNextShellStarted = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.shell.started" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + messageID: string + callID: string + command: string + } +} + +export type SessionNextShellEnded = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.shell.ended" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + callID: string + output: string + } +} + +export type SessionNextStepStarted = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.step.started" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + agent: string + model: ModelRef + snapshot?: string + } +} + +export type SessionNextStepEnded = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.step.ended" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + finish: string + cost: number + tokens: { + input: number + output: number + reasoning: number + cache: { + read: number + write: number + } + } + snapshot?: string + files?: Array + } +} + +export type SessionNextStepFailed = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.step.failed" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + error: SessionErrorUnknown + } +} + +export type SessionNextTextStarted = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.text.started" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + textID: string + } +} + +export type SessionNextTextEnded = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.text.ended" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + textID: string + text: string + } +} + +export type SessionNextToolInputStarted = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.tool.input.started" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + callID: string + name: string + } +} + +export type SessionNextToolInputEnded = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.tool.input.ended" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + callID: string + text: string + } +} + +export type SessionNextToolCalled = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.tool.called" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + callID: string + tool: string + input: { + [key: string]: unknown + } + provider: { + executed: boolean + metadata?: LlmProviderMetadata + } + } +} + +export type SessionNextToolProgress = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.tool.progress" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + callID: string + structured: { + [key: string]: unknown + } + content: Array + } +} + +export type SessionNextToolSuccess = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.tool.success" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + callID: string + structured: { + [key: string]: unknown + } + content: Array + outputPaths?: Array + result?: unknown + provider: { + executed: boolean + metadata?: LlmProviderMetadata + } + } +} + +export type SessionNextToolFailed = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.tool.failed" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + callID: string + error: SessionErrorUnknown + result?: unknown + provider: { + executed: boolean + metadata?: LlmProviderMetadata + } + } +} + +export type SessionNextReasoningStarted = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.reasoning.started" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + reasoningID: string + providerMetadata?: LlmProviderMetadata + } +} + +export type SessionNextReasoningEnded = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.reasoning.ended" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + reasoningID: string + text: string + providerMetadata?: LlmProviderMetadata + } +} + +export type SessionNextRetried = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.retried" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + attempt: number + error: SessionNextRetryError + } +} + +export type SessionNextCompactionStarted = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.compaction.started" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + messageID: string + reason: "auto" | "manual" + } +} + +export type SessionNextCompactionEnded = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.compaction.ended" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + messageID: string + reason: "auto" | "manual" + text: string + recent: string + } +} + +export type SessionNextRevertStaged = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.revert.staged" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + revert: RevertState + } +} + +export type SessionNextRevertCleared = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.revert.cleared" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + } +} + +export type SessionNextRevertCommitted = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.revert.committed" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + messageID: string + } +} + +export type EventLogSynced = { + type: "log.synced" + aggregateID: string + seq?: number +} + +export type ModelApi = + | { + id: string + type: "aisdk" + package: string + url?: string + settings?: { + [key: string]: unknown + } + } + | { + id: string + type: "native" + url?: string + settings: { + [key: string]: unknown + } + } + +export type ModelCapabilities = { + tools: boolean + input: Array + output: Array +} + +export type ModelCost = { + tier?: { + type: "context" + size: number + } + input: number + output: number + cache: { + read: number + write: number + } +} + +export type ModelV2Info = { + id: string + providerID: string + family?: string + name: string + api: ModelApi + capabilities: ModelCapabilities + request: { + settings: ProviderSettings + headers: { + [key: string]: string + } + body: { + [key: string]: unknown + } + variant?: string + } + variants: Array<{ + id: string + settings: ProviderSettings + headers: { + [key: string]: string + } + body: { + [key: string]: unknown + } + }> + time: { + released: number + } + cost: Array + status: "alpha" | "beta" | "deprecated" | "active" + enabled: boolean + limit: { + context: number + input?: number + output: number + } +} + +export type ProviderAisdk = { + type: "aisdk" + package: string + url?: string + settings?: { + [key: string]: unknown + } +} + +export type ProviderNative = { + type: "native" + url?: string + settings: { + [key: string]: unknown + } +} + +export type ProviderApi = ProviderAisdk | ProviderNative + +export type ProviderV2Info = { + id: string + integrationID?: string + name: string + disabled?: boolean + api: ProviderApi + request: ProviderRequest +} + +export type IntegrationWhen = { + key: string + op: "eq" | "neq" + value: string +} + +export type IntegrationTextPrompt = { + type: "text" + key: string + message: string + placeholder?: string + when?: IntegrationWhen +} + +export type IntegrationSelectPrompt = { + type: "select" + key: string + message: string + options: Array<{ + label: string + value: string + hint?: string + }> + when?: IntegrationWhen +} + +export type IntegrationOAuthMethod = { + id: string + type: "oauth" + label: string + prompts?: Array +} + +export type IntegrationKeyMethod = { + type: "key" + label?: string +} + +export type IntegrationEnvMethod = { + type: "env" + names: Array +} + +export type ConnectionCredentialInfo = { + type: "credential" + id: string + label: string +} + +export type ConnectionEnvInfo = { + type: "env" + name: string +} + +export type ConnectionInfo = ConnectionCredentialInfo | ConnectionEnvInfo + +export type IntegrationInfo = { + id: string + name: string + methods: Array + connections: Array +} + +export type IntegrationAttempt = { + attemptID: string + url: string + instructions: string + mode: "auto" | "code" + time: { + created: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + expires: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + } +} + +export type IntegrationAttemptStatus = + | { + status: "pending" + time: { + created: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + expires: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + } + } + | { + status: "complete" + time: { + created: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + expires: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + } + } + | { + status: "failed" + message: string + time: { + created: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + expires: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + } + } + | { + status: "expired" + time: { + created: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + expires: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + } + } + +export type McpStatusConnected2 = { + status: "connected" +} + +export type McpStatusDisconnected = { + status: "disconnected" +} + +export type McpStatusDisabled2 = { + status: "disabled" +} + +export type McpStatusFailed2 = { + status: "failed" + error: string +} + +export type McpStatusNeedsAuth2 = { + status: "needs_auth" +} + +export type McpStatusNeedsClientRegistration2 = { + status: "needs_client_registration" + error: string +} + +export type McpServer = { + name: string + status: + | McpStatusConnected2 + | McpStatusDisconnected + | McpStatusDisabled2 + | McpStatusFailed2 + | McpStatusNeedsAuth2 + | McpStatusNeedsClientRegistration2 + integrationID?: string +} + +export type ProjectCurrent = { + id: string + directory: string +} + +export type PermissionV2Request = { + id: string + sessionID: string + action: string + resources: Array + save?: Array + metadata?: { + [key: string]: unknown + } + source?: PermissionV2Source +} + +export type PermissionSavedInfo = { + id: string + projectID: string + action: string + resource: string +} + +export type FileSystemEntry = { + path: string + type: "file" | "directory" +} + +export type CommandV2Info = { + name: string + template: string + description?: string + agent?: string + model?: ModelRef + subtask?: boolean +} + +export type SkillV2Info = { + name: string + description?: string + slash?: boolean + autoinvoke?: boolean + location: string + content: string +} + +export type ModelsDevRefreshed = { + id: string + metadata?: { + [key: string]: unknown + } + type: "models-dev.refreshed" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + [key: string]: unknown + } +} + +export type IntegrationUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "integration.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + [key: string]: unknown + } +} + +export type IntegrationConnectionUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "integration.connection.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + integrationID: string + } +} + +export type CatalogUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "catalog.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + [key: string]: unknown + } +} + +export type AgentUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "agent.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + [key: string]: unknown + } +} + +export type SessionCreated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.created" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + info: Session + } +} + +export type SessionUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + info: Session + } +} + +export type SessionDeleted = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.deleted" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + info: Session + } +} + +export type MessageUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "message.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + info: Message + } +} + +export type MessageRemoved = { + id: string + metadata?: { + [key: string]: unknown + } + type: "message.removed" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + messageID: string + } +} + +export type MessagePartUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "message.part.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + part: Part + time: number + } +} + +export type MessagePartRemoved = { + id: string + metadata?: { + [key: string]: unknown + } + type: "message.part.removed" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + messageID: string + partID: string + } +} + +export type SessionNextExecutionSettled = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.execution.settled" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + outcome: "success" | "failure" | "interrupted" + error?: SessionErrorUnknown + } +} + +export type SessionNextTextDelta = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.text.delta" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + textID: string + delta: string + } +} + +export type SessionNextReasoningDelta = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.reasoning.delta" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + reasoningID: string + delta: string + } +} + +export type SessionNextToolInputDelta = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.tool.input.delta" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + assistantMessageID: string + callID: string + delta: string + } +} + +export type SessionNextCompactionDelta = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.next.compaction.delta" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + timestamp: number + sessionID: string + messageID: string + text: string + } +} + +export type MessagePartDelta = { + id: string + metadata?: { + [key: string]: unknown + } + type: "message.part.delta" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + messageID: string + partID: string + field: string + delta: string + } +} + +export type SessionDiff = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.diff" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + diff: Array + } +} + +export type SessionError = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.error" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID?: string + error?: + | ProviderAuthError + | UnknownError + | MessageOutputLengthError + | MessageAbortedError + | StructuredOutputError + | ContextOverflowError + | ContentFilterError + | ApiError + } +} + +export type InstallationUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "installation.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + version: string + } +} + +export type InstallationUpdateAvailable = { + id: string + metadata?: { + [key: string]: unknown + } + type: "installation.update-available" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + version: string + } +} + +export type FileEdited = { + id: string + metadata?: { + [key: string]: unknown + } + type: "file.edited" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + file: string + } +} + +export type ReferenceUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "reference.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + [key: string]: unknown + } +} + +export type PermissionV2Asked = { + id: string + metadata?: { + [key: string]: unknown + } + type: "permission.v2.asked" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + id: string + sessionID: string + action: string + resources: Array + save?: Array + metadata?: { + [key: string]: unknown + } + source?: PermissionV2Source + } +} + +export type PermissionV2Replied = { + id: string + metadata?: { + [key: string]: unknown + } + type: "permission.v2.replied" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + requestID: string + reply: PermissionV2Reply + } +} + +export type PluginAdded = { + id: string + metadata?: { + [key: string]: unknown + } + type: "plugin.added" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + id: string + } +} + +export type ProjectDirectoriesUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "project.directories.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + projectID: string + } +} + +export type CommandUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "command.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + [key: string]: unknown + } +} + +export type SkillUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "skill.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + [key: string]: unknown + } +} + +export type FileWatcherUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "file.watcher.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + file: string + event: "add" | "change" | "unlink" + } +} + +export type PtyCreated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "pty.created" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + info: Pty + } +} + +export type PtyUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "pty.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + info: Pty + } +} + +export type PtyExited = { + id: string + metadata?: { + [key: string]: unknown + } + type: "pty.exited" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + id: string + exitCode: number + } +} + +export type PtyDeleted = { + id: string + metadata?: { + [key: string]: unknown + } + type: "pty.deleted" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + id: string + } +} + +export type ShellCreated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "shell.created" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + info: Shell1 + } +} + +export type ShellExited = { + id: string + metadata?: { + [key: string]: unknown + } + type: "shell.exited" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + id: string + exit?: number | "NaN" | "Infinity" | "-Infinity" + status: "running" | "exited" | "timeout" | "killed" + } +} + +export type ShellDeleted = { + id: string + metadata?: { + [key: string]: unknown + } + type: "shell.deleted" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + id: string + } +} + +export type QuestionV2Asked = { + id: string + metadata?: { + [key: string]: unknown + } + type: "question.v2.asked" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + id: string + sessionID: string + /** + * Questions to ask + */ + questions: Array + tool?: QuestionV2Tool + } +} + +export type QuestionV2Replied = { + id: string + metadata?: { + [key: string]: unknown + } + type: "question.v2.replied" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + requestID: string + answers: Array + } +} + +export type QuestionV2Rejected = { + id: string + metadata?: { + [key: string]: unknown + } + type: "question.v2.rejected" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + requestID: string + } +} + +export type TodoUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "todo.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + todos: Array + } +} + +export type LspUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "lsp.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + [key: string]: unknown + } +} + +export type PermissionAsked = { + id: string + metadata?: { + [key: string]: unknown + } + type: "permission.asked" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + id: string + sessionID: string + permission: string + patterns: Array + metadata: { + [key: string]: unknown + } + always: Array + tool?: { + messageID: string + callID: string + } + } +} + +export type PermissionReplied = { + id: string + metadata?: { + [key: string]: unknown + } + type: "permission.replied" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + requestID: string + reply: "once" | "always" | "reject" + } +} + +export type TuiPromptAppend = { + id: string + metadata?: { + [key: string]: unknown + } + type: "tui.prompt.append" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + text: string + } +} + +export type TuiCommandExecute = { + id: string + metadata?: { + [key: string]: unknown + } + type: "tui.command.execute" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + command: + | "session.list" + | "session.new" + | "session.share" + | "session.interrupt" + | "session.background" + | "session.compact" + | "session.page.up" + | "session.page.down" + | "session.line.up" + | "session.line.down" + | "session.half.page.up" + | "session.half.page.down" + | "session.first" + | "session.last" + | "prompt.clear" + | "prompt.submit" + | "agent.cycle" + | string + } +} + +export type TuiToastShow = { + id: string + metadata?: { + [key: string]: unknown + } + type: "tui.toast.show" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + title?: string + message: string + variant: "info" | "success" | "warning" | "error" + duration?: number + } +} + +export type TuiSessionSelect = { + id: string + metadata?: { + [key: string]: unknown + } + type: "tui.session.select" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + /** + * Session ID to navigate to + */ + sessionID: string + } +} + +export type McpToolsChanged = { + id: string + metadata?: { + [key: string]: unknown + } + type: "mcp.tools.changed" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + server: string + } +} + +export type McpBrowserOpenFailed = { + id: string + metadata?: { + [key: string]: unknown + } + type: "mcp.browser.open.failed" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + mcpName: string + url: string + } +} + +export type McpStatusChanged = { + id: string + metadata?: { + [key: string]: unknown + } + type: "mcp.status.changed" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + server: string + } +} + +export type CommandExecuted = { + id: string + metadata?: { + [key: string]: unknown + } + type: "command.executed" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + name: string + sessionID: string + arguments: string + messageID: string + } +} + +export type ProjectUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "project.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + id: string + worktree: string + vcs?: ProjectVcs + name?: string + icon?: ProjectIcon + commands?: ProjectCommands + time: ProjectTime + sandboxes: Array + } +} + +export type SessionIdle = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.idle" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + } +} + +export type QuestionAsked = { + id: string + metadata?: { + [key: string]: unknown + } + type: "question.asked" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + id: string + sessionID: string + /** + * Questions to ask + */ + questions: Array + tool?: QuestionTool + } +} + +export type SessionCompacted = { + id: string + metadata?: { + [key: string]: unknown + } + type: "session.compacted" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + sessionID: string + } +} + +export type VcsBranchUpdated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "vcs.branch.updated" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + branch?: string + } +} + +export type WorkspaceReady = { + id: string + metadata?: { + [key: string]: unknown + } + type: "workspace.ready" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + name: string + } +} + +export type WorkspaceFailed = { + id: string + metadata?: { + [key: string]: unknown + } + type: "workspace.failed" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + message: string + } +} + +export type WorkspaceStatus = { + id: string + metadata?: { + [key: string]: unknown + } + type: "workspace.status" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + workspaceID: string + status: "connected" | "connecting" | "disconnected" | "error" + } +} + +export type WorktreeReady = { + id: string + metadata?: { + [key: string]: unknown + } + type: "worktree.ready" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + name: string + branch?: string + } +} + +export type WorktreeFailed = { + id: string + metadata?: { + [key: string]: unknown + } + type: "worktree.failed" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + message: string + } +} + +export type ServerConnected = { + id: string + metadata?: { + [key: string]: unknown + } + type: "server.connected" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + [key: string]: unknown + } +} + +export type GlobalDisposed = { + id: string + metadata?: { + [key: string]: unknown + } + type: "global.disposed" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + [key: string]: unknown + } +} + +export type EventLogHint = { + type: "log.hint" + aggregateID: string + seq: number +} + +export type EventLogSweepRequired = { + type: "log.sweep_required" +} + +export type EventLogChange = EventLogHint | EventLogSweepRequired + +export type EventLogChangeStream = string + +export type QuestionV2Request = { + id: string + sessionID: string + /** + * Questions to ask + */ + questions: Array + tool?: QuestionV2Tool +} + +export type QuestionV2Reply = { + /** + * User answers in order of questions (each answer is an array of selected labels) + */ + answers: Array +} + +export type ReferenceLocalSource = { + type: "local" + path: string + description?: string + hidden?: boolean +} + +export type ReferenceGitSource = { + type: "git" + repository: string + branch?: string + description?: string + hidden?: boolean +} + +export type ReferenceSource = ReferenceLocalSource | ReferenceGitSource + +export type ReferenceInfo = { + name: string + path: string + description?: string + hidden?: boolean + source: ReferenceSource +} + +export type ProjectCopyCopy = { + directory: string +} + export type EventModelsDevRefreshed = { id: string type: "models-dev.refreshed" @@ -4584,7 +7450,7 @@ export type EventShellCreated = { id: string type: "shell.created" properties: { - info: Shell1 + info: Shell2 } } @@ -4606,56 +7472,36 @@ export type EventShellDeleted = { } } -export type FormNumberField1 = { - key: string - title?: string - description?: string - required?: boolean - when?: FormWhen - type: "number" - minimum?: number | "NaN" | "Infinity" | "-Infinity" - maximum?: number | "NaN" | "Infinity" | "-Infinity" - default?: number | "NaN" | "Infinity" | "-Infinity" -} - -export type FormIntegerField1 = { - key: string - title?: string - description?: string - required?: boolean - when?: FormWhen - type: "integer" - minimum?: number | "NaN" | "Infinity" | "-Infinity" - maximum?: number | "NaN" | "Infinity" | "-Infinity" - default?: number | "NaN" | "Infinity" | "-Infinity" -} - -export type EventFormCreated = { +export type EventQuestionV2Asked = { id: string - type: "form.created" - properties: { - form: FormFormInfo | FormUrlInfo - } -} - -export type FormValue1 = string | number | "NaN" | "Infinity" | "-Infinity" | boolean | Array - -export type EventFormReplied = { - id: string - type: "form.replied" + type: "question.v2.asked" properties: { id: string sessionID: string - answer: FormAnswer + /** + * Questions to ask + */ + questions: Array + tool?: QuestionV2Tool } } -export type EventFormCancelled = { +export type EventQuestionV2Replied = { id: string - type: "form.cancelled" + type: "question.v2.replied" properties: { - id: string sessionID: string + requestID: string + answers: Array + } +} + +export type EventQuestionV2Rejected = { + id: string + type: "question.v2.rejected" + properties: { + sessionID: string + requestID: string } } @@ -4899,49 +7745,6 @@ export type CredentialKey = { } } -export type IntegrationWhen = { - key: string - op: "eq" | "neq" - value: string -} - -export type IntegrationTextPrompt = { - type: "text" - key: string - message: string - placeholder?: string - when?: IntegrationWhen -} - -export type IntegrationSelectPrompt = { - type: "select" - key: string - message: string - options: Array<{ - label: string - value: string - hint?: string - }> - when?: IntegrationWhen -} - -export type IntegrationOAuthMethod = { - id: string - type: "oauth" - label: string - prompts?: Array -} - -export type IntegrationKeyMethod = { - type: "key" - label?: string -} - -export type IntegrationEnvMethod = { - type: "env" - names: Array -} - export type SkillV2DirectorySource = { type: "directory" path: string @@ -4952,15 +7755,6 @@ export type SkillV2UrlSource = { url: string } -export type SkillV2Info = { - name: string - description?: string - slash?: boolean - autoinvoke?: boolean - location: string - content: string -} - export type SkillV2EmbeddedSource = { type: "embedded" skill: SkillV2Info @@ -4974,7 +7768,7 @@ export type BadRequestError = { } } -export type UnauthorizedError = { +export type UnauthorizedErrorV2 = { _tag: "UnauthorizedError" message: string } @@ -4986,7 +7780,7 @@ export type InvalidRequestErrorV2 = { field?: string | null } -export type LocationInfo = { +export type LocationInfo2 = { directory: string workspaceID?: string project: { @@ -5001,12 +7795,12 @@ export type ModelRef2 = { variant?: string } -export type ProviderSettings = { +export type ProviderSettings2 = { [key: string]: unknown } -export type ProviderRequest = { - settings: ProviderSettings +export type ProviderRequest2 = { + settings: ProviderSettings2 headers: { [key: string]: string } @@ -5015,32 +7809,32 @@ export type ProviderRequest = { } } -export type AgentColor = string | "primary" | "secondary" | "accent" | "success" | "warning" | "error" | "info" +export type AgentColor2 = string | "primary" | "secondary" | "accent" | "success" | "warning" | "error" | "info" -export type PermissionV2Effect = "allow" | "deny" | "ask" +export type PermissionV2Effect2 = "allow" | "deny" | "ask" -export type PermissionV2Rule = { +export type PermissionV2Rule2 = { action: string resource: string - effect: PermissionV2Effect + effect: PermissionV2Effect2 } -export type PermissionV2Ruleset = Array +export type PermissionV2Ruleset2 = Array -export type AgentV2Info = { +export type AgentV2Info2 = { id: string model?: ModelRef2 - request: ProviderRequest + request: ProviderRequest2 system?: string description?: string mode: "subagent" | "primary" | "all" hidden: boolean - color?: AgentColor + color?: AgentColor2 steps?: number - permissions: PermissionV2Ruleset + permissions: PermissionV2Ruleset2 } -export type PluginInfo = { +export type PluginInfo2 = { id: string } @@ -5065,7 +7859,7 @@ export type RevertState2 = { files?: Array } -export type SessionV2Info = { +export type SessionV2Info2 = { id: string parentID?: string projectID: string @@ -5095,20 +7889,20 @@ export type SessionV2Info = { /** * Durable log seq each session's snapshot was computed at. Attach a live log read after the watermark to compose fetch and stream gap-free; apply a snapshot only where its watermark is at or beyond already-applied events. Sessions without durable events are absent. */ -export type SessionWatermarks = { +export type SessionWatermarksV2 = { [key: string]: unknown | number } -export type SessionsResponse = { - data: Array - watermarks: SessionWatermarks +export type SessionsResponseV2 = { + data: Array + watermarks: SessionWatermarksV2 cursor: { previous?: string | null next?: string | null } } -export type InvalidCursorError = { +export type InvalidCursorErrorV2 = { _tag: "InvalidCursorError" message: string } @@ -5120,17 +7914,17 @@ export type InvalidRequestError1 = { field?: string | null } -export type SessionActive = { +export type SessionActiveV2 = { type: "running" } -export type SessionNotFoundError = { +export type SessionNotFoundErrorV2 = { _tag: "SessionNotFoundError" sessionID: string message: string } -export type MessageNotFoundError = { +export type MessageNotFoundErrorV2 = { _tag: "MessageNotFoundError" sessionID: string messageID: string @@ -5143,7 +7937,7 @@ export type PromptSource2 = { text: string } -export type PromptInputFileAttachment = { +export type PromptInputFileAttachment2 = { uri: string name?: string description?: string @@ -5155,9 +7949,9 @@ export type PromptAgentAttachment2 = { source?: PromptSource2 } -export type PromptInput = { +export type PromptInputV2 = { text: string - files?: Array + files?: Array agents?: Array } @@ -5175,7 +7969,7 @@ export type PromptV2 = { agents?: Array } -export type SessionInputAdmitted = { +export type SessionInputAdmitted2 = { admittedSeq: number id: string sessionID: string @@ -5185,25 +7979,25 @@ export type SessionInputAdmitted = { promotedSeq?: number } -export type ConflictError = { +export type ConflictErrorV2 = { _tag: "ConflictError" message: string resource?: string | null } -export type CommandNotFoundError = { +export type CommandNotFoundErrorV2 = { _tag: "CommandNotFoundError" command: string message: string } -export type CommandEvaluationError = { +export type CommandEvaluationErrorV2 = { _tag: "CommandEvaluationError" command: string message: string } -export type SkillNotFoundError = { +export type SkillNotFoundErrorV2 = { _tag: "SkillNotFoundError" skill: string message: string @@ -5215,7 +8009,7 @@ export type SessionBusyErrorV2 = { message: string } -export type ServiceUnavailableError = { +export type ServiceUnavailableErrorV2 = { _tag: "ServiceUnavailableError" message: string service?: string | null @@ -5227,7 +8021,7 @@ export type UnknownErrorV2 = { ref?: string | null } -export type SessionMessageAgentSwitched = { +export type SessionMessageAgentSwitched2 = { id: string metadata?: { [key: string]: unknown @@ -5239,7 +8033,7 @@ export type SessionMessageAgentSwitched = { agent: string } -export type SessionMessageModelSwitched = { +export type SessionMessageModelSwitched2 = { id: string metadata?: { [key: string]: unknown @@ -5251,7 +8045,7 @@ export type SessionMessageModelSwitched = { model: ModelRef2 } -export type SessionMessageUser = { +export type SessionMessageUser2 = { id: string metadata?: { [key: string]: unknown @@ -5265,7 +8059,7 @@ export type SessionMessageUser = { type: "user" } -export type SessionMessageSynthetic = { +export type SessionMessageSynthetic2 = { id: string metadata?: { [key: string]: unknown @@ -5279,7 +8073,7 @@ export type SessionMessageSynthetic = { type: "synthetic" } -export type SessionMessageSystem = { +export type SessionMessageSystem2 = { id: string metadata?: { [key: string]: unknown @@ -5291,7 +8085,7 @@ export type SessionMessageSystem = { text: string } -export type SessionMessageSkill = { +export type SessionMessageSkill2 = { id: string metadata?: { [key: string]: unknown @@ -5304,7 +8098,7 @@ export type SessionMessageSkill = { text: string } -export type SessionMessageShell = { +export type SessionMessageShell2 = { id: string metadata?: { [key: string]: unknown @@ -5319,7 +8113,7 @@ export type SessionMessageShell = { output: string } -export type SessionMessageAssistantText = { +export type SessionMessageAssistantText2 = { type: "text" id: string text: string @@ -5331,7 +8125,7 @@ export type LlmProviderMetadata2 = { } } -export type SessionMessageAssistantReasoning = { +export type SessionMessageAssistantReasoning2 = { type: "reasoning" id: string text: string @@ -5342,7 +8136,7 @@ export type SessionMessageAssistantReasoning = { } } -export type SessionMessageToolStatePending = { +export type SessionMessageToolStatePending2 = { status: "pending" input: string } @@ -5361,7 +8155,7 @@ export type ToolFileContent2 = { export type LlmToolContent2 = ToolTextContent2 | ToolFileContent2 -export type SessionMessageToolStateRunning = { +export type SessionMessageToolStateRunning2 = { status: "running" input: { [key: string]: unknown @@ -5372,7 +8166,7 @@ export type SessionMessageToolStateRunning = { content: Array } -export type SessionMessageToolStateCompleted = { +export type SessionMessageToolStateCompleted2 = { status: "completed" input: { [key: string]: unknown @@ -5391,7 +8185,7 @@ export type SessionErrorUnknown2 = { message: string } -export type SessionMessageToolStateError = { +export type SessionMessageToolStateError2 = { status: "error" input: { [key: string]: unknown @@ -5404,7 +8198,7 @@ export type SessionMessageToolStateError = { result?: unknown } -export type SessionMessageAssistantTool = { +export type SessionMessageAssistantTool2 = { type: "tool" id: string name: string @@ -5414,10 +8208,10 @@ export type SessionMessageAssistantTool = { resultMetadata?: LlmProviderMetadata2 } state: - | SessionMessageToolStatePending - | SessionMessageToolStateRunning - | SessionMessageToolStateCompleted - | SessionMessageToolStateError + | SessionMessageToolStatePending2 + | SessionMessageToolStateRunning2 + | SessionMessageToolStateCompleted2 + | SessionMessageToolStateError2 time: { created: number ran?: number @@ -5426,7 +8220,7 @@ export type SessionMessageAssistantTool = { } } -export type SessionMessageAssistant = { +export type SessionMessageAssistant2 = { id: string metadata?: { [key: string]: unknown @@ -5438,7 +8232,7 @@ export type SessionMessageAssistant = { type: "assistant" agent: string model: ModelRef2 - content: Array + content: Array snapshot?: { start?: string end?: string @@ -5458,7 +8252,7 @@ export type SessionMessageAssistant = { error?: SessionErrorUnknown2 } -export type SessionMessageCompaction = { +export type SessionMessageCompaction2 = { type: "compaction" reason: "auto" | "manual" summary: string @@ -5472,28 +8266,28 @@ export type SessionMessageCompaction = { } } -export type SessionMessage = - | SessionMessageAgentSwitched - | SessionMessageModelSwitched - | SessionMessageUser - | SessionMessageSynthetic - | SessionMessageSystem - | SessionMessageSkill - | SessionMessageShell - | SessionMessageAssistant - | SessionMessageCompaction +export type SessionMessage2 = + | SessionMessageAgentSwitched2 + | SessionMessageModelSwitched2 + | SessionMessageUser2 + | SessionMessageSynthetic2 + | SessionMessageSystem2 + | SessionMessageSkill2 + | SessionMessageShell2 + | SessionMessageAssistant2 + | SessionMessageCompaction2 /** * Context entry key (lowercase alphanumerics plus . _ -) */ -export type SessionContextEntryKey = string +export type SessionContextEntryKey2 = string -export type SessionContextEntryInfo = { - key: SessionContextEntryKey +export type SessionContextEntryInfo2 = { + key: SessionContextEntryKey2 value: unknown } -export type SessionNextAgentSwitched = { +export type SessionNextAgentSwitched2 = { id: string metadata?: { [key: string]: unknown @@ -5513,7 +8307,7 @@ export type SessionNextAgentSwitched = { } } -export type SessionNextModelSwitched = { +export type SessionNextModelSwitched2 = { id: string metadata?: { [key: string]: unknown @@ -5533,7 +8327,7 @@ export type SessionNextModelSwitched = { } } -export type SessionNextMoved = { +export type SessionNextMoved2 = { id: string metadata?: { [key: string]: unknown @@ -5553,7 +8347,7 @@ export type SessionNextMoved = { } } -export type SessionNextRenamed = { +export type SessionNextRenamed2 = { id: string metadata?: { [key: string]: unknown @@ -5572,7 +8366,7 @@ export type SessionNextRenamed = { } } -export type SessionNextForked = { +export type SessionNextForked2 = { id: string metadata?: { [key: string]: unknown @@ -5592,7 +8386,7 @@ export type SessionNextForked = { } } -export type SessionNextPrompted = { +export type SessionNextPrompted2 = { id: string metadata?: { [key: string]: unknown @@ -5613,7 +8407,7 @@ export type SessionNextPrompted = { } } -export type SessionNextPromptAdmitted = { +export type SessionNextPromptAdmitted2 = { id: string metadata?: { [key: string]: unknown @@ -5634,7 +8428,7 @@ export type SessionNextPromptAdmitted = { } } -export type SessionNextContextUpdated = { +export type SessionNextContextUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -5654,7 +8448,7 @@ export type SessionNextContextUpdated = { } } -export type SessionNextSynthetic = { +export type SessionNextSynthetic2 = { id: string metadata?: { [key: string]: unknown @@ -5678,7 +8472,7 @@ export type SessionNextSynthetic = { } } -export type SessionNextSkillActivated = { +export type SessionNextSkillActivated2 = { id: string metadata?: { [key: string]: unknown @@ -5699,7 +8493,7 @@ export type SessionNextSkillActivated = { } } -export type SessionNextShellStarted = { +export type SessionNextShellStarted2 = { id: string metadata?: { [key: string]: unknown @@ -5720,7 +8514,7 @@ export type SessionNextShellStarted = { } } -export type SessionNextShellEnded = { +export type SessionNextShellEnded2 = { id: string metadata?: { [key: string]: unknown @@ -5740,7 +8534,7 @@ export type SessionNextShellEnded = { } } -export type SessionNextStepStarted = { +export type SessionNextStepStarted2 = { id: string metadata?: { [key: string]: unknown @@ -5762,7 +8556,7 @@ export type SessionNextStepStarted = { } } -export type SessionNextStepEnded = { +export type SessionNextStepEnded2 = { id: string metadata?: { [key: string]: unknown @@ -5794,7 +8588,7 @@ export type SessionNextStepEnded = { } } -export type SessionNextStepFailed = { +export type SessionNextStepFailed2 = { id: string metadata?: { [key: string]: unknown @@ -5814,7 +8608,7 @@ export type SessionNextStepFailed = { } } -export type SessionNextTextStarted = { +export type SessionNextTextStarted2 = { id: string metadata?: { [key: string]: unknown @@ -5834,7 +8628,7 @@ export type SessionNextTextStarted = { } } -export type SessionNextTextEnded = { +export type SessionNextTextEnded2 = { id: string metadata?: { [key: string]: unknown @@ -5855,7 +8649,7 @@ export type SessionNextTextEnded = { } } -export type SessionNextToolInputStarted = { +export type SessionNextToolInputStarted2 = { id: string metadata?: { [key: string]: unknown @@ -5876,7 +8670,7 @@ export type SessionNextToolInputStarted = { } } -export type SessionNextToolInputEnded = { +export type SessionNextToolInputEnded2 = { id: string metadata?: { [key: string]: unknown @@ -5903,7 +8697,7 @@ export type LlmProviderMetadata3 = { } } -export type SessionNextToolCalled = { +export type SessionNextToolCalled2 = { id: string metadata?: { [key: string]: unknown @@ -5931,7 +8725,7 @@ export type SessionNextToolCalled = { } } -export type SessionNextToolProgress = { +export type SessionNextToolProgress2 = { id: string metadata?: { [key: string]: unknown @@ -5961,7 +8755,7 @@ export type LlmProviderMetadata4 = { } } -export type SessionNextToolSuccess = { +export type SessionNextToolSuccess2 = { id: string metadata?: { [key: string]: unknown @@ -5997,7 +8791,7 @@ export type LlmProviderMetadata5 = { } } -export type SessionNextToolFailed = { +export type SessionNextToolFailed2 = { id: string metadata?: { [key: string]: unknown @@ -6029,7 +8823,7 @@ export type LlmProviderMetadata6 = { } } -export type SessionNextReasoningStarted = { +export type SessionNextReasoningStarted2 = { id: string metadata?: { [key: string]: unknown @@ -6056,7 +8850,7 @@ export type LlmProviderMetadata7 = { } } -export type SessionNextReasoningEnded = { +export type SessionNextReasoningEnded2 = { id: string metadata?: { [key: string]: unknown @@ -6091,7 +8885,7 @@ export type SessionNextRetryError2 = { } } -export type SessionNextRetried = { +export type SessionNextRetried2 = { id: string metadata?: { [key: string]: unknown @@ -6111,7 +8905,7 @@ export type SessionNextRetried = { } } -export type SessionNextCompactionStarted = { +export type SessionNextCompactionStarted2 = { id: string metadata?: { [key: string]: unknown @@ -6131,7 +8925,7 @@ export type SessionNextCompactionStarted = { } } -export type SessionNextCompactionEnded = { +export type SessionNextCompactionEnded2 = { id: string metadata?: { [key: string]: unknown @@ -6153,7 +8947,7 @@ export type SessionNextCompactionEnded = { } } -export type SessionNextRevertStaged = { +export type SessionNextRevertStaged2 = { id: string metadata?: { [key: string]: unknown @@ -6172,7 +8966,7 @@ export type SessionNextRevertStaged = { } } -export type SessionNextRevertCleared = { +export type SessionNextRevertCleared2 = { id: string metadata?: { [key: string]: unknown @@ -6190,7 +8984,7 @@ export type SessionNextRevertCleared = { } } -export type SessionNextRevertCommitted = { +export type SessionNextRevertCommitted2 = { id: string metadata?: { [key: string]: unknown @@ -6209,54 +9003,54 @@ export type SessionNextRevertCommitted = { } } -export type SessionDurableEvent = - | SessionNextAgentSwitched - | SessionNextModelSwitched - | SessionNextMoved - | SessionNextRenamed - | SessionNextForked - | SessionNextPrompted - | SessionNextPromptAdmitted - | SessionNextContextUpdated - | SessionNextSynthetic - | SessionNextSkillActivated - | SessionNextShellStarted - | SessionNextShellEnded - | SessionNextStepStarted - | SessionNextStepEnded - | SessionNextStepFailed - | SessionNextTextStarted - | SessionNextTextEnded - | SessionNextToolInputStarted - | SessionNextToolInputEnded - | SessionNextToolCalled - | SessionNextToolProgress - | SessionNextToolSuccess - | SessionNextToolFailed - | SessionNextReasoningStarted - | SessionNextReasoningEnded - | SessionNextRetried - | SessionNextCompactionStarted - | SessionNextCompactionEnded - | SessionNextRevertStaged - | SessionNextRevertCleared - | SessionNextRevertCommitted +export type SessionDurableEventV2 = + | SessionNextAgentSwitched2 + | SessionNextModelSwitched2 + | SessionNextMoved2 + | SessionNextRenamed2 + | SessionNextForked2 + | SessionNextPrompted2 + | SessionNextPromptAdmitted2 + | SessionNextContextUpdated2 + | SessionNextSynthetic2 + | SessionNextSkillActivated2 + | SessionNextShellStarted2 + | SessionNextShellEnded2 + | SessionNextStepStarted2 + | SessionNextStepEnded2 + | SessionNextStepFailed2 + | SessionNextTextStarted2 + | SessionNextTextEnded2 + | SessionNextToolInputStarted2 + | SessionNextToolInputEnded2 + | SessionNextToolCalled2 + | SessionNextToolProgress2 + | SessionNextToolSuccess2 + | SessionNextToolFailed2 + | SessionNextReasoningStarted2 + | SessionNextReasoningEnded2 + | SessionNextRetried2 + | SessionNextCompactionStarted2 + | SessionNextCompactionEnded2 + | SessionNextRevertStaged2 + | SessionNextRevertCleared2 + | SessionNextRevertCommitted2 /** * Marker emitted once when a log read reaches its captured watermark. The reader holds every event committed at or below seq. */ -export type EventLogSynced = { +export type EventLogSynced2 = { type: "log.synced" aggregateID: string seq?: number } -export type SessionLogItem = SessionDurableEvent | EventLogSynced +export type SessionLogItemV2 = SessionDurableEventV2 | EventLogSynced2 -export type SessionLogItemStream = string +export type SessionLogItemStreamV2 = string -export type SessionMessagesResponse = { - data: Array +export type SessionMessagesResponseV2 = { + data: Array watermark?: number cursor: { previous?: string | null @@ -6264,7 +9058,7 @@ export type SessionMessagesResponse = { } } -export type ModelApi = +export type ModelApi2 = | { id: string type: "aisdk" @@ -6283,13 +9077,13 @@ export type ModelApi = } } -export type ModelCapabilities = { +export type ModelCapabilities2 = { tools: boolean input: Array output: Array } -export type ModelCost = { +export type ModelCost2 = { tier?: { type: "context" size: number @@ -6302,15 +9096,15 @@ export type ModelCost = { } } -export type ModelV2Info = { +export type ModelV2Info2 = { id: string providerID: string family?: string name: string - api: ModelApi - capabilities: ModelCapabilities + api: ModelApi2 + capabilities: ModelCapabilities2 request: { - settings: ProviderSettings + settings: ProviderSettings2 headers: { [key: string]: string } @@ -6321,7 +9115,7 @@ export type ModelV2Info = { } variants: Array<{ id: string - settings: ProviderSettings + settings: ProviderSettings2 headers: { [key: string]: string } @@ -6332,7 +9126,7 @@ export type ModelV2Info = { time: { released: number } - cost: Array + cost: Array status: "alpha" | "beta" | "deprecated" | "active" enabled: boolean limit: { @@ -6342,13 +9136,13 @@ export type ModelV2Info = { } } -export type GenerateTextResponse = { +export type GenerateTextResponseV2 = { data: { text: string } } -export type ProviderAisdk = { +export type ProviderAisdk2 = { type: "aisdk" package: string url?: string @@ -6357,7 +9151,7 @@ export type ProviderAisdk = { } } -export type ProviderNative = { +export type ProviderNative2 = { type: "native" url?: string settings: { @@ -6365,18 +9159,18 @@ export type ProviderNative = { } } -export type ProviderApi = ProviderAisdk | ProviderNative +export type ProviderApi2 = ProviderAisdk2 | ProviderNative2 -export type ProviderV2Info = { +export type ProviderV2Info2 = { id: string integrationID?: string name: string disabled?: boolean - api: ProviderApi - request: ProviderRequest + api: ProviderApi2 + request: ProviderRequest2 } -export type ProviderNotFoundError = { +export type ProviderNotFoundErrorV2 = { _tag: "ProviderNotFoundError" providerID: string message: string @@ -6427,27 +9221,27 @@ export type IntegrationEnvMethod2 = { export type IntegrationMethod2 = IntegrationOAuthMethod2 | IntegrationKeyMethod2 | IntegrationEnvMethod2 -export type ConnectionCredentialInfo = { +export type ConnectionCredentialInfo2 = { type: "credential" id: string label: string } -export type ConnectionEnvInfo = { +export type ConnectionEnvInfo2 = { type: "env" name: string } -export type ConnectionInfo = ConnectionCredentialInfo | ConnectionEnvInfo +export type ConnectionInfo2 = ConnectionCredentialInfo2 | ConnectionEnvInfo2 -export type IntegrationInfo = { +export type IntegrationInfo2 = { id: string name: string methods: Array - connections: Array + connections: Array } -export type IntegrationAttempt = { +export type IntegrationAttempt2 = { attemptID: string url: string instructions: string @@ -6458,7 +9252,7 @@ export type IntegrationAttempt = { } } -export type IntegrationAttemptStatus = +export type IntegrationAttemptStatus2 = | { status: "pending" time: { @@ -6489,45 +9283,45 @@ export type IntegrationAttemptStatus = } } -export type McpStatusConnected2 = { +export type McpStatusConnected3 = { status: "connected" } -export type McpStatusDisconnected = { +export type McpStatusDisconnected2 = { status: "disconnected" } -export type McpStatusDisabled2 = { +export type McpStatusDisabled3 = { status: "disabled" } -export type McpStatusFailed2 = { +export type McpStatusFailed3 = { status: "failed" error: string } -export type McpStatusNeedsAuth2 = { +export type McpStatusNeedsAuth3 = { status: "needs_auth" } -export type McpStatusNeedsClientRegistration2 = { +export type McpStatusNeedsClientRegistration3 = { status: "needs_client_registration" error: string } -export type McpServer = { +export type McpServer2 = { name: string status: - | McpStatusConnected2 - | McpStatusDisconnected - | McpStatusDisabled2 - | McpStatusFailed2 - | McpStatusNeedsAuth2 - | McpStatusNeedsClientRegistration2 + | McpStatusConnected3 + | McpStatusDisconnected2 + | McpStatusDisabled3 + | McpStatusFailed3 + | McpStatusNeedsAuth3 + | McpStatusNeedsClientRegistration3 integrationID?: string } -export type ProjectCurrent = { +export type ProjectCurrent2 = { id: string directory: string } @@ -6539,173 +9333,13 @@ export type ProjectDirectory2 = { export type ProjectDirectories2 = Array -export type FormMetadata2 = { - [key: string]: unknown -} - -export type FormWhen2 = { - key: string - op: "eq" | "neq" - value: string -} - -export type FormOption2 = { - value: string - label: string - description?: string -} - -export type FormStringField2 = { - key: string - title?: string - description?: string - required?: boolean - when?: FormWhen2 - type: "string" - format?: "email" | "uri" | "date" | "date-time" - minLength?: number - maxLength?: number - pattern?: string - placeholder?: string - default?: string - options?: Array - custom?: boolean -} - -export type FormNumberField2 = { - key: string - title?: string - description?: string - required?: boolean - when?: FormWhen2 - type: "number" - minimum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" - maximum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" - default?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" -} - -export type FormIntegerField2 = { - key: string - title?: string - description?: string - required?: boolean - when?: FormWhen2 - type: "integer" - minimum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" - maximum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" - default?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" -} - -export type FormBooleanField2 = { - key: string - title?: string - description?: string - required?: boolean - when?: FormWhen2 - type: "boolean" - default?: boolean -} - -export type FormMultiselectField2 = { - key: string - title?: string - description?: string - required?: boolean - when?: FormWhen2 - type: "multiselect" - options: Array - minItems?: number - maxItems?: number - custom?: boolean - default?: Array -} - -export type FormFormInfo2 = { - id: string - sessionID: string - title?: string - metadata?: FormMetadata2 - mode: "form" - fields: Array -} - -export type FormUrlInfo2 = { - id: string - sessionID: string - title?: string - metadata?: FormMetadata2 - mode: "url" - url: string -} - -export type FormCreatePayload = { - id?: string | null - title?: string - metadata?: FormMetadata2 - mode: "form" | "url" - fields?: Array< - FormStringField2 | FormNumberField2 | FormIntegerField2 | FormBooleanField2 | FormMultiselectField2 - > | null - url?: string | null -} - -export type FormNotFoundError = { - _tag: "FormNotFoundError" - id: string - message: string -} - -export type FormValue2 = - | string - | number - | "NaN" - | "Infinity" - | "-Infinity" - | "Infinity" - | "-Infinity" - | "NaN" - | boolean - | Array - -export type FormAnswer2 = { - [key: string]: FormValue2 -} - -export type FormState = - | { - status: "pending" - } - | { - status: "answered" - answer: FormAnswer2 - } - | { - status: "cancelled" - } - -export type FormReply = { - answer: FormAnswer2 -} - -export type FormAlreadySettledError = { - _tag: "FormAlreadySettledError" - id: string - message: string -} - -export type FormInvalidAnswerError = { - _tag: "FormInvalidAnswerError" - id: string - message: string -} - export type PermissionV2Source2 = { type: "tool" messageID: string callID: string } -export type PermissionV2Request = { +export type PermissionV2Request2 = { id: string sessionID: string action: string @@ -6717,7 +9351,7 @@ export type PermissionV2Request = { source?: PermissionV2Source2 } -export type PermissionSavedInfo = { +export type PermissionSavedInfo2 = { id: string projectID: string action: string @@ -6732,12 +9366,12 @@ export type PermissionNotFoundErrorV2 = { export type PermissionV2Reply2 = "once" | "always" | "reject" -export type FileSystemEntry = { +export type FileSystemEntry2 = { path: string type: "file" | "directory" } -export type CommandV2Info = { +export type CommandV2Info2 = { name: string template: string description?: string @@ -6755,7 +9389,7 @@ export type SkillV2Info2 = { content: string } -export type ModelsDevRefreshed = { +export type ModelsDevRefreshed2 = { id: string metadata?: { [key: string]: unknown @@ -6774,7 +9408,7 @@ export type ModelsDevRefreshed = { | Array } -export type IntegrationUpdated = { +export type IntegrationUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -6793,7 +9427,7 @@ export type IntegrationUpdated = { | Array } -export type IntegrationConnectionUpdated = { +export type IntegrationConnectionUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -6810,7 +9444,7 @@ export type IntegrationConnectionUpdated = { } } -export type CatalogUpdated = { +export type CatalogUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -6829,7 +9463,7 @@ export type CatalogUpdated = { | Array } -export type AgentUpdated = { +export type AgentUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -6919,7 +9553,7 @@ export type SessionV2 = { } } -export type SessionCreated = { +export type SessionCreated2 = { id: string metadata?: { [key: string]: unknown @@ -6937,7 +9571,7 @@ export type SessionCreated = { } } -export type SessionUpdated = { +export type SessionUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -6955,7 +9589,7 @@ export type SessionUpdated = { } } -export type SessionDeleted = { +export type SessionDeleted2 = { id: string metadata?: { [key: string]: unknown @@ -7020,7 +9654,7 @@ export type ProviderAuthErrorV2 = { } } -export type UnknownError1 = { +export type UnknownError1V2 = { name: "UnknownError" data: { message: string @@ -7093,7 +9727,7 @@ export type AssistantMessageV2 = { } error?: | ProviderAuthErrorV2 - | UnknownError1 + | UnknownError1V2 | MessageOutputLengthErrorV2 | MessageAbortedErrorV2 | StructuredOutputErrorV2 @@ -7129,7 +9763,7 @@ export type AssistantMessageV2 = { export type MessageV2 = UserMessageV2 | AssistantMessageV2 -export type MessageUpdated = { +export type MessageUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -7147,7 +9781,7 @@ export type MessageUpdated = { } } -export type MessageRemoved = { +export type MessageRemoved2 = { id: string metadata?: { [key: string]: unknown @@ -7428,7 +10062,7 @@ export type PartV2 = | RetryPartV2 | CompactionPartV2 -export type MessagePartUpdated = { +export type MessagePartUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -7447,7 +10081,7 @@ export type MessagePartUpdated = { } } -export type MessagePartRemoved = { +export type MessagePartRemoved2 = { id: string metadata?: { [key: string]: unknown @@ -7466,7 +10100,7 @@ export type MessagePartRemoved = { } } -export type SessionNextExecutionSettled = { +export type SessionNextExecutionSettled2 = { id: string metadata?: { [key: string]: unknown @@ -7486,7 +10120,7 @@ export type SessionNextExecutionSettled = { } } -export type SessionNextTextDelta = { +export type SessionNextTextDelta2 = { id: string metadata?: { [key: string]: unknown @@ -7507,7 +10141,7 @@ export type SessionNextTextDelta = { } } -export type SessionNextReasoningDelta = { +export type SessionNextReasoningDelta2 = { id: string metadata?: { [key: string]: unknown @@ -7528,7 +10162,7 @@ export type SessionNextReasoningDelta = { } } -export type SessionNextToolInputDelta = { +export type SessionNextToolInputDelta2 = { id: string metadata?: { [key: string]: unknown @@ -7549,7 +10183,7 @@ export type SessionNextToolInputDelta = { } } -export type SessionNextCompactionDelta = { +export type SessionNextCompactionDelta2 = { id: string metadata?: { [key: string]: unknown @@ -7569,7 +10203,7 @@ export type SessionNextCompactionDelta = { } } -export type FileEdited = { +export type FileEdited2 = { id: string metadata?: { [key: string]: unknown @@ -7586,7 +10220,7 @@ export type FileEdited = { } } -export type ReferenceUpdated = { +export type ReferenceUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -7605,7 +10239,7 @@ export type ReferenceUpdated = { | Array } -export type PermissionV2Asked = { +export type PermissionV2Asked2 = { id: string metadata?: { [key: string]: unknown @@ -7630,7 +10264,7 @@ export type PermissionV2Asked = { } } -export type PermissionV2Replied = { +export type PermissionV2Replied2 = { id: string metadata?: { [key: string]: unknown @@ -7649,7 +10283,7 @@ export type PermissionV2Replied = { } } -export type PluginAdded = { +export type PluginAdded2 = { id: string metadata?: { [key: string]: unknown @@ -7666,7 +10300,7 @@ export type PluginAdded = { } } -export type ProjectDirectoriesUpdated = { +export type ProjectDirectoriesUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -7683,7 +10317,7 @@ export type ProjectDirectoriesUpdated = { } } -export type CommandUpdated = { +export type CommandUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -7702,7 +10336,7 @@ export type CommandUpdated = { | Array } -export type SkillUpdated = { +export type SkillUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -7721,7 +10355,7 @@ export type SkillUpdated = { | Array } -export type FileWatcherUpdated = { +export type FileWatcherUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -7750,7 +10384,7 @@ export type PtyV2 = { exitCode?: number } -export type PtyCreated = { +export type PtyCreated2 = { id: string metadata?: { [key: string]: unknown @@ -7767,7 +10401,7 @@ export type PtyCreated = { } } -export type PtyUpdated = { +export type PtyUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -7784,7 +10418,7 @@ export type PtyUpdated = { } } -export type PtyExited = { +export type PtyExited2 = { id: string metadata?: { [key: string]: unknown @@ -7802,7 +10436,7 @@ export type PtyExited = { } } -export type PtyDeleted = { +export type PtyDeleted2 = { id: string metadata?: { [key: string]: unknown @@ -7837,7 +10471,7 @@ export type ShellV2 = { } } -export type ShellCreated = { +export type ShellCreated2 = { id: string metadata?: { [key: string]: unknown @@ -7854,7 +10488,7 @@ export type ShellCreated = { } } -export type ShellExited = { +export type ShellExited2 = { id: string metadata?: { [key: string]: unknown @@ -7873,7 +10507,7 @@ export type ShellExited = { } } -export type ShellDeleted = { +export type ShellDeleted2 = { id: string metadata?: { [key: string]: unknown @@ -7890,81 +10524,45 @@ export type ShellDeleted = { } } -export type FormMetadata1 = { - [key: string]: unknown +export type QuestionV2Option2 = { + /** + * Display text (1-5 words, concise) + */ + label: string + /** + * Explanation of choice + */ + description: string } -export type FormNumberField12 = { - key: string - title?: string - description?: string - required?: boolean - when?: FormWhen2 - type: "number" - minimum?: number | "NaN" | "Infinity" | "-Infinity" - maximum?: number | "NaN" | "Infinity" | "-Infinity" - default?: number | "NaN" | "Infinity" | "-Infinity" +export type QuestionV2Info2 = { + /** + * Complete question + */ + question: string + /** + * Very short label (max 30 chars) + */ + header: string + /** + * Available choices + */ + options: Array + multiple?: boolean + custom?: boolean } -export type FormIntegerField12 = { - key: string - title?: string - description?: string - required?: boolean - when?: FormWhen2 - type: "integer" - minimum?: number | "NaN" | "Infinity" | "-Infinity" - maximum?: number | "NaN" | "Infinity" | "-Infinity" - default?: number | "NaN" | "Infinity" | "-Infinity" +export type QuestionV2Tool2 = { + messageID: string + callID: string } -export type FormFormInfo1 = { - id: string - sessionID: string - title?: string - metadata?: FormMetadata1 - mode: "form" - fields: Array -} - -export type FormUrlInfo1 = { - id: string - sessionID: string - title?: string - metadata?: FormMetadata1 - mode: "url" - url: string -} - -export type FormCreated = { +export type QuestionV2Asked2 = { id: string metadata?: { [key: string]: unknown } - type: "form.created" - durable?: { - aggregateID: string - seq: number - version: number - } - location?: LocationRef2 - data: { - form: FormFormInfo1 | FormUrlInfo1 - } -} - -export type FormValue12 = string | number | "NaN" | "Infinity" | "-Infinity" | boolean | Array - -export type FormAnswer1 = { - [key: string]: FormValue12 -} - -export type FormReplied = { - id: string - metadata?: { - [key: string]: unknown - } - type: "form.replied" + type: "question.v2.asked" durable?: { aggregateID: string seq: number @@ -7974,16 +10572,22 @@ export type FormReplied = { data: { id: string sessionID: string - answer: FormAnswer1 + /** + * Questions to ask + */ + questions: Array + tool?: QuestionV2Tool2 } } -export type FormCancelled = { +export type QuestionV2Answer2 = Array + +export type QuestionV2Replied2 = { id: string metadata?: { [key: string]: unknown } - type: "form.cancelled" + type: "question.v2.replied" durable?: { aggregateID: string seq: number @@ -7991,8 +10595,27 @@ export type FormCancelled = { } location?: LocationRef2 data: { - id: string sessionID: string + requestID: string + answers: Array + } +} + +export type QuestionV2Rejected2 = { + id: string + metadata?: { + [key: string]: unknown + } + type: "question.v2.rejected" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef2 + data: { + sessionID: string + requestID: string } } @@ -8011,7 +10634,7 @@ export type TodoV2 = { priority: string } -export type TodoUpdated = { +export type TodoUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -8051,7 +10674,7 @@ export type SessionStatusV2 = type: "busy" } -export type SessionStatus2 = { +export type SessionStatusV22 = { id: string metadata?: { [key: string]: unknown @@ -8069,7 +10692,7 @@ export type SessionStatus2 = { } } -export type SessionIdle = { +export type SessionIdle2 = { id: string metadata?: { [key: string]: unknown @@ -8086,7 +10709,7 @@ export type SessionIdle = { } } -export type TuiPromptAppend = { +export type TuiPromptAppend2 = { id: string metadata?: { [key: string]: unknown @@ -8103,7 +10726,7 @@ export type TuiPromptAppend = { } } -export type TuiCommandExecute = { +export type TuiCommandExecute2 = { id: string metadata?: { [key: string]: unknown @@ -8138,7 +10761,7 @@ export type TuiCommandExecute = { } } -export type TuiToastShow = { +export type TuiToastShow2 = { id: string metadata?: { [key: string]: unknown @@ -8158,7 +10781,7 @@ export type TuiToastShow = { } } -export type TuiSessionSelect = { +export type TuiSessionSelect2 = { id: string metadata?: { [key: string]: unknown @@ -8178,7 +10801,7 @@ export type TuiSessionSelect = { } } -export type InstallationUpdated = { +export type InstallationUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -8195,7 +10818,7 @@ export type InstallationUpdated = { } } -export type InstallationUpdateAvailable = { +export type InstallationUpdateAvailable2 = { id: string metadata?: { [key: string]: unknown @@ -8212,7 +10835,7 @@ export type InstallationUpdateAvailable = { } } -export type VcsBranchUpdated = { +export type VcsBranchUpdated2 = { id: string metadata?: { [key: string]: unknown @@ -8229,7 +10852,7 @@ export type VcsBranchUpdated = { } } -export type McpStatusChanged = { +export type McpStatusChanged2 = { id: string metadata?: { [key: string]: unknown @@ -8246,7 +10869,7 @@ export type McpStatusChanged = { } } -export type PermissionAsked = { +export type PermissionAsked2 = { id: string metadata?: { [key: string]: unknown @@ -8274,7 +10897,7 @@ export type PermissionAsked = { } } -export type PermissionReplied = { +export type PermissionReplied2 = { id: string metadata?: { [key: string]: unknown @@ -8332,7 +10955,7 @@ export type QuestionToolV2 = { callID: string } -export type QuestionAsked = { +export type QuestionAsked2 = { id: string metadata?: { [key: string]: unknown @@ -8357,7 +10980,7 @@ export type QuestionAsked = { export type QuestionAnswerV2 = Array -export type QuestionReplied2 = { +export type QuestionRepliedV2 = { id: string metadata?: { [key: string]: unknown @@ -8376,7 +10999,7 @@ export type QuestionReplied2 = { } } -export type QuestionRejected2 = { +export type QuestionRejectedV2 = { id: string metadata?: { [key: string]: unknown @@ -8394,7 +11017,7 @@ export type QuestionRejected2 = { } } -export type SessionError = { +export type SessionError2 = { id: string metadata?: { [key: string]: unknown @@ -8410,7 +11033,7 @@ export type SessionError = { sessionID?: string | null error?: | ProviderAuthErrorV2 - | UnknownError1 + | UnknownError1V2 | MessageOutputLengthErrorV2 | MessageAbortedErrorV2 | StructuredOutputErrorV2 @@ -8440,99 +11063,99 @@ export type V2EventServerConnected = { | Array } -export type V2Event = - | ModelsDevRefreshed - | IntegrationUpdated - | IntegrationConnectionUpdated - | CatalogUpdated - | AgentUpdated - | SessionCreated - | SessionUpdated - | SessionDeleted - | MessageUpdated - | MessageRemoved - | MessagePartUpdated - | MessagePartRemoved - | SessionNextAgentSwitched - | SessionNextModelSwitched - | SessionNextMoved - | SessionNextRenamed - | SessionNextForked - | SessionNextPrompted - | SessionNextPromptAdmitted - | SessionNextExecutionSettled - | SessionNextContextUpdated - | SessionNextSynthetic - | SessionNextSkillActivated - | SessionNextShellStarted - | SessionNextShellEnded - | SessionNextStepStarted - | SessionNextStepEnded - | SessionNextStepFailed - | SessionNextTextStarted - | SessionNextTextDelta - | SessionNextTextEnded - | SessionNextReasoningStarted - | SessionNextReasoningDelta - | SessionNextReasoningEnded - | SessionNextToolInputStarted - | SessionNextToolInputDelta - | SessionNextToolInputEnded - | SessionNextToolCalled - | SessionNextToolProgress - | SessionNextToolSuccess - | SessionNextToolFailed - | SessionNextRetried - | SessionNextCompactionStarted - | SessionNextCompactionDelta - | SessionNextCompactionEnded - | SessionNextRevertStaged - | SessionNextRevertCleared - | SessionNextRevertCommitted - | FileEdited - | ReferenceUpdated - | PermissionV2Asked - | PermissionV2Replied - | PluginAdded - | ProjectDirectoriesUpdated - | CommandUpdated - | SkillUpdated - | FileWatcherUpdated - | PtyCreated - | PtyUpdated - | PtyExited - | PtyDeleted - | ShellCreated - | ShellExited - | ShellDeleted - | FormCreated - | FormReplied - | FormCancelled - | TodoUpdated - | SessionStatus2 - | SessionIdle - | TuiPromptAppend - | TuiCommandExecute - | TuiToastShow - | TuiSessionSelect - | InstallationUpdated - | InstallationUpdateAvailable - | VcsBranchUpdated - | McpStatusChanged - | PermissionAsked - | PermissionReplied - | QuestionAsked - | QuestionReplied2 - | QuestionRejected2 - | SessionError +export type V2EventV2 = + | ModelsDevRefreshed2 + | IntegrationUpdated2 + | IntegrationConnectionUpdated2 + | CatalogUpdated2 + | AgentUpdated2 + | SessionCreated2 + | SessionUpdated2 + | SessionDeleted2 + | MessageUpdated2 + | MessageRemoved2 + | MessagePartUpdated2 + | MessagePartRemoved2 + | SessionNextAgentSwitched2 + | SessionNextModelSwitched2 + | SessionNextMoved2 + | SessionNextRenamed2 + | SessionNextForked2 + | SessionNextPrompted2 + | SessionNextPromptAdmitted2 + | SessionNextExecutionSettled2 + | SessionNextContextUpdated2 + | SessionNextSynthetic2 + | SessionNextSkillActivated2 + | SessionNextShellStarted2 + | SessionNextShellEnded2 + | SessionNextStepStarted2 + | SessionNextStepEnded2 + | SessionNextStepFailed2 + | SessionNextTextStarted2 + | SessionNextTextDelta2 + | SessionNextTextEnded2 + | SessionNextReasoningStarted2 + | SessionNextReasoningDelta2 + | SessionNextReasoningEnded2 + | SessionNextToolInputStarted2 + | SessionNextToolInputDelta2 + | SessionNextToolInputEnded2 + | SessionNextToolCalled2 + | SessionNextToolProgress2 + | SessionNextToolSuccess2 + | SessionNextToolFailed2 + | SessionNextRetried2 + | SessionNextCompactionStarted2 + | SessionNextCompactionDelta2 + | SessionNextCompactionEnded2 + | SessionNextRevertStaged2 + | SessionNextRevertCleared2 + | SessionNextRevertCommitted2 + | FileEdited2 + | ReferenceUpdated2 + | PermissionV2Asked2 + | PermissionV2Replied2 + | PluginAdded2 + | ProjectDirectoriesUpdated2 + | CommandUpdated2 + | SkillUpdated2 + | FileWatcherUpdated2 + | PtyCreated2 + | PtyUpdated2 + | PtyExited2 + | PtyDeleted2 + | ShellCreated2 + | ShellExited2 + | ShellDeleted2 + | QuestionV2Asked2 + | QuestionV2Replied2 + | QuestionV2Rejected2 + | TodoUpdated2 + | SessionStatusV22 + | SessionIdle2 + | TuiPromptAppend2 + | TuiCommandExecute2 + | TuiToastShow2 + | TuiSessionSelect2 + | InstallationUpdated2 + | InstallationUpdateAvailable2 + | VcsBranchUpdated2 + | McpStatusChanged2 + | PermissionAsked2 + | PermissionReplied2 + | QuestionAsked2 + | QuestionRepliedV2 + | QuestionRejectedV2 + | SessionError2 | V2EventServerConnected -export type V2EventStream = string +export type V2EventStreamV2 = string /** * Payload-free change hint: the aggregate's durable log advanced to at least seq. Hints coalesce under backpressure (latest per aggregate) and are never a delivery guarantee. */ -export type EventLogHint = { +export type EventLogHint2 = { type: "log.hint" aggregateID: string seq: number @@ -8541,13 +11164,13 @@ export type EventLogHint = { /** * Hints may have been lost; treat every aggregate as potentially dirty and recover via bounded sweep plus durable log reads. Emitted first on every (re)subscribe. */ -export type EventLogSweepRequired = { +export type EventLogSweepRequired2 = { type: "log.sweep_required" } -export type EventLogChange = EventLogHint | EventLogSweepRequired +export type EventLogChange2 = EventLogHint2 | EventLogSweepRequired2 -export type EventLogChangeStream = string +export type EventLogChangeStream2 = string export type PtyNotFoundErrorV2 = { _tag: "PtyNotFoundError" @@ -8560,7 +11183,7 @@ export type PtyTicketConnectToken2 = { expires_in: number } -export type ForbiddenError = { +export type ForbiddenErrorV2 = { _tag: "ForbiddenError" message: string } @@ -8583,20 +11206,43 @@ export type Shell1V2 = { } } -export type ShellNotFoundError = { +export type ShellNotFoundErrorV2 = { _tag: "ShellNotFoundError" id: string message: string } -export type ReferenceLocalSource = { +export type QuestionV2Request2 = { + id: string + sessionID: string + /** + * Questions to ask + */ + questions: Array + tool?: QuestionV2Tool2 +} + +export type QuestionV2Reply2 = { + /** + * User answers in order of questions (each answer is an array of selected labels) + */ + answers: Array +} + +export type QuestionNotFoundErrorV2 = { + _tag: "QuestionNotFoundError" + requestID: string + message: string +} + +export type ReferenceLocalSource2 = { type: "local" path: string description?: string hidden?: boolean } -export type ReferenceGitSource = { +export type ReferenceGitSource2 = { type: "git" repository: string branch?: string @@ -8604,21 +11250,21 @@ export type ReferenceGitSource = { hidden?: boolean } -export type ReferenceSource = ReferenceLocalSource | ReferenceGitSource +export type ReferenceSource2 = ReferenceLocalSource2 | ReferenceGitSource2 -export type ReferenceInfo = { +export type ReferenceInfo2 = { name: string path: string description?: string hidden?: boolean - source: ReferenceSource + source: ReferenceSource2 } -export type ProjectCopyCopy = { +export type ProjectCopyCopy2 = { directory: string } -export type ProjectCopyError = { +export type ProjectCopyErrorV2 = { name: "ProjectCopyError" data: { message: string @@ -12759,42 +15405,6 @@ export type ExperimentalWorkspaceWarpResponses = { export type ExperimentalWorkspaceWarpResponse = ExperimentalWorkspaceWarpResponses[keyof ExperimentalWorkspaceWarpResponses] -export type PtyConnectData = { - body?: never - path: { - ptyID: string - } - query?: { - directory?: string - workspace?: string - cursor?: string - ticket?: string - } - url: "/pty/{ptyID}/connect" -} - -export type PtyConnectErrors = { - /** - * Forbidden - */ - 403: EffectHttpApiErrorForbidden - /** - * 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 V2HealthGetData = { body?: never path?: never @@ -12810,7 +15420,7 @@ export type V2HealthGetErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2HealthGetError = V2HealthGetErrors[keyof V2HealthGetErrors] @@ -12846,7 +15456,7 @@ export type V2LocationGetErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2LocationGetError = V2LocationGetErrors[keyof V2LocationGetErrors] @@ -12855,7 +15465,7 @@ export type V2LocationGetResponses = { /** * Location.Info */ - 200: LocationInfo + 200: LocationInfo2 } export type V2LocationGetResponse = V2LocationGetResponses[keyof V2LocationGetResponses] @@ -12880,7 +15490,7 @@ export type V2AgentListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2AgentListError = V2AgentListErrors[keyof V2AgentListErrors] @@ -12890,8 +15500,8 @@ export type V2AgentListResponses = { * Success */ 200: { - location: LocationInfo - data: Array + location: LocationInfo2 + data: Array } } @@ -12917,7 +15527,7 @@ export type V2PluginListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2PluginListError = V2PluginListErrors[keyof V2PluginListErrors] @@ -12927,8 +15537,8 @@ export type V2PluginListResponses = { * Success */ 200: { - location: LocationInfo - data: Array + location: LocationInfo2 + data: Array } } @@ -12942,7 +15552,7 @@ export type V2SessionListData = { /** * Maximum number of sessions to return. Defaults to the newest 50 sessions. */ - limit?: string | null + limit?: number | null /** * Session order for the first page. Use desc for newest first or asc for oldest first. */ @@ -12961,11 +15571,11 @@ export type V2SessionListErrors = { /** * InvalidCursorError | InvalidRequestError */ - 400: InvalidCursorError | InvalidRequestError1 | InvalidRequestErrorV2 + 400: InvalidCursorErrorV2 | InvalidRequestError1 | InvalidRequestErrorV2 /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2SessionListError = V2SessionListErrors[keyof V2SessionListErrors] @@ -12974,7 +15584,7 @@ export type V2SessionListResponses = { /** * SessionsResponse */ - 200: SessionsResponse + 200: SessionsResponseV2 } export type V2SessionListResponse = V2SessionListResponses[keyof V2SessionListResponses] @@ -12999,7 +15609,7 @@ export type V2SessionCreateErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2SessionCreateError = V2SessionCreateErrors[keyof V2SessionCreateErrors] @@ -13009,7 +15619,7 @@ export type V2SessionCreateResponses = { * Success */ 200: { - data: SessionV2Info + data: SessionV2Info2 } } @@ -13030,7 +15640,7 @@ export type V2SessionActiveErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2SessionActiveError = V2SessionActiveErrors[keyof V2SessionActiveErrors] @@ -13041,9 +15651,9 @@ export type V2SessionActiveResponses = { */ 200: { data: { - [key: string]: unknown | SessionActive + [key: string]: unknown | SessionActiveV2 } - watermarks: SessionWatermarks + watermarks: SessionWatermarksV2 } } @@ -13066,11 +15676,11 @@ export type V2SessionGetErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 } export type V2SessionGetError = V2SessionGetErrors[keyof V2SessionGetErrors] @@ -13080,7 +15690,7 @@ export type V2SessionGetResponses = { * Success */ 200: { - data: SessionV2Info + data: SessionV2Info2 } } @@ -13105,11 +15715,11 @@ export type V2SessionForkErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError | MessageNotFoundError */ - 404: MessageNotFoundError | SessionNotFoundError + 404: MessageNotFoundErrorV2 | SessionNotFoundErrorV2 } export type V2SessionForkError = V2SessionForkErrors[keyof V2SessionForkErrors] @@ -13119,7 +15729,7 @@ export type V2SessionForkResponses = { * Success */ 200: { - data: SessionV2Info + data: SessionV2Info2 } } @@ -13144,11 +15754,11 @@ export type V2SessionSwitchAgentErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 } export type V2SessionSwitchAgentError = V2SessionSwitchAgentErrors[keyof V2SessionSwitchAgentErrors] @@ -13181,11 +15791,11 @@ export type V2SessionSwitchModelErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 } export type V2SessionSwitchModelError = V2SessionSwitchModelErrors[keyof V2SessionSwitchModelErrors] @@ -13218,11 +15828,11 @@ export type V2SessionRenameErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 } export type V2SessionRenameError = V2SessionRenameErrors[keyof V2SessionRenameErrors] @@ -13239,7 +15849,7 @@ export type V2SessionRenameResponse = V2SessionRenameResponses[keyof V2SessionRe export type V2SessionPromptData = { body: { id?: string | null - prompt: PromptInput + prompt: PromptInputV2 delivery?: "steer" | "queue" | null resume?: boolean | null } @@ -13258,15 +15868,15 @@ export type V2SessionPromptErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 /** * ConflictError */ - 409: ConflictError + 409: ConflictErrorV2 } export type V2SessionPromptError = V2SessionPromptErrors[keyof V2SessionPromptErrors] @@ -13276,7 +15886,7 @@ export type V2SessionPromptResponses = { * Success */ 200: { - data: SessionInputAdmitted + data: SessionInputAdmitted2 } } @@ -13289,7 +15899,7 @@ export type V2SessionCommandData = { arguments?: string | null agent?: string | null model?: ModelRef2 | null - files?: Array + files?: Array agents?: Array delivery?: "steer" | "queue" | null resume?: boolean | null @@ -13309,19 +15919,19 @@ export type V2SessionCommandErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError | CommandNotFoundError */ - 404: CommandNotFoundError | SessionNotFoundError + 404: CommandNotFoundErrorV2 | SessionNotFoundErrorV2 /** * ConflictError */ - 409: ConflictError + 409: ConflictErrorV2 /** * CommandEvaluationError */ - 500: CommandEvaluationError + 500: CommandEvaluationErrorV2 } export type V2SessionCommandError = V2SessionCommandErrors[keyof V2SessionCommandErrors] @@ -13331,7 +15941,7 @@ export type V2SessionCommandResponses = { * Success */ 200: { - data: SessionInputAdmitted + data: SessionInputAdmitted2 } } @@ -13358,11 +15968,11 @@ export type V2SessionSkillErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError | SkillNotFoundError */ - 404: SkillNotFoundError | SessionNotFoundError + 404: SkillNotFoundErrorV2 | SessionNotFoundErrorV2 } export type V2SessionSkillError = V2SessionSkillErrors[keyof V2SessionSkillErrors] @@ -13399,11 +16009,11 @@ export type V2SessionSyntheticErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 } export type V2SessionSyntheticError = V2SessionSyntheticErrors[keyof V2SessionSyntheticErrors] @@ -13434,11 +16044,11 @@ export type V2SessionCompactErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 /** * SessionBusyError */ @@ -13450,7 +16060,7 @@ export type V2SessionCompactErrors = { /** * ServiceUnavailableError */ - 503: ServiceUnavailableError + 503: ServiceUnavailableErrorV2 } export type V2SessionCompactError = V2SessionCompactErrors[keyof V2SessionCompactErrors] @@ -13481,15 +16091,15 @@ export type V2SessionWaitErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 /** * ServiceUnavailableError */ - 503: ServiceUnavailableError + 503: ServiceUnavailableErrorV2 } export type V2SessionWaitError = V2SessionWaitErrors[keyof V2SessionWaitErrors] @@ -13523,11 +16133,11 @@ export type V2SessionRevertStageErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * MessageNotFoundError | SessionNotFoundError */ - 404: MessageNotFoundError | SessionNotFoundError + 404: MessageNotFoundErrorV2 | SessionNotFoundErrorV2 /** * SessionBusyError */ @@ -13568,11 +16178,11 @@ export type V2SessionRevertClearErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 /** * SessionBusyError */ @@ -13611,11 +16221,11 @@ export type V2SessionRevertCommitErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 /** * SessionBusyError */ @@ -13650,11 +16260,11 @@ export type V2SessionContextErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 /** * UnknownError */ @@ -13668,7 +16278,7 @@ export type V2SessionContextResponses = { * Success */ 200: { - data: Array + data: Array } } @@ -13691,11 +16301,11 @@ export type V2SessionContextEntryListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 } export type V2SessionContextEntryListError = V2SessionContextEntryListErrors[keyof V2SessionContextEntryListErrors] @@ -13705,7 +16315,7 @@ export type V2SessionContextEntryListResponses = { * Success */ 200: { - data: Array + data: Array } } @@ -13716,7 +16326,7 @@ export type V2SessionContextEntryRemoveData = { body?: never path: { sessionID: string - key: SessionContextEntryKey + key: SessionContextEntryKey2 } query?: never url: "/api/session/{sessionID}/context-entry/{key}" @@ -13730,11 +16340,11 @@ export type V2SessionContextEntryRemoveErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 } export type V2SessionContextEntryRemoveError = @@ -13756,7 +16366,7 @@ export type V2SessionContextEntryPutData = { } path: { sessionID: string - key: SessionContextEntryKey + key: SessionContextEntryKey2 } query?: never url: "/api/session/{sessionID}/context-entry/{key}" @@ -13770,11 +16380,11 @@ export type V2SessionContextEntryPutErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 } export type V2SessionContextEntryPutError = V2SessionContextEntryPutErrors[keyof V2SessionContextEntryPutErrors] @@ -13809,11 +16419,11 @@ export type V2SessionLogErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 } export type V2SessionLogError = V2SessionLogErrors[keyof V2SessionLogErrors] @@ -13825,7 +16435,7 @@ export type V2SessionLogResponses = { 200: { id: string | null event: string - data: SessionLogItemStream + data: SessionLogItemStreamV2 } } @@ -13848,11 +16458,11 @@ export type V2SessionInterruptErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 } export type V2SessionInterruptError = V2SessionInterruptErrors[keyof V2SessionInterruptErrors] @@ -13883,11 +16493,11 @@ export type V2SessionBackgroundErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 } export type V2SessionBackgroundError = V2SessionBackgroundErrors[keyof V2SessionBackgroundErrors] @@ -13919,11 +16529,11 @@ export type V2SessionMessageErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError | MessageNotFoundError */ - 404: MessageNotFoundError | SessionNotFoundError + 404: MessageNotFoundErrorV2 | SessionNotFoundErrorV2 } export type V2SessionMessageError = V2SessionMessageErrors[keyof V2SessionMessageErrors] @@ -13933,7 +16543,7 @@ export type V2SessionMessageResponses = { * Success */ 200: { - data: SessionMessage + data: SessionMessage2 } } @@ -13948,7 +16558,7 @@ export type V2SessionMessagesData = { /** * Maximum number of messages to return. When omitted, the endpoint returns its default page size. */ - limit?: string | null + limit?: number | null /** * Message order for the first page. Use desc for newest first or asc for oldest first. */ @@ -13962,15 +16572,15 @@ export type V2SessionMessagesErrors = { /** * InvalidCursorError | InvalidRequestError */ - 400: InvalidCursorError | InvalidRequestErrorV2 + 400: InvalidCursorErrorV2 | InvalidRequestErrorV2 /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 /** * UnknownError */ @@ -13983,7 +16593,7 @@ export type V2SessionMessagesResponses = { /** * SessionMessagesResponse */ - 200: SessionMessagesResponse + 200: SessionMessagesResponseV2 } export type V2SessionMessagesResponse = V2SessionMessagesResponses[keyof V2SessionMessagesResponses] @@ -14008,11 +16618,11 @@ export type V2ModelListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * ServiceUnavailableError */ - 503: ServiceUnavailableError + 503: ServiceUnavailableErrorV2 } export type V2ModelListError = V2ModelListErrors[keyof V2ModelListErrors] @@ -14022,8 +16632,8 @@ export type V2ModelListResponses = { * Success */ 200: { - location: LocationInfo - data: Array + location: LocationInfo2 + data: Array } } @@ -14049,11 +16659,11 @@ export type V2ModelDefaultErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * ServiceUnavailableError */ - 503: ServiceUnavailableError + 503: ServiceUnavailableErrorV2 } export type V2ModelDefaultError = V2ModelDefaultErrors[keyof V2ModelDefaultErrors] @@ -14063,8 +16673,8 @@ export type V2ModelDefaultResponses = { * Success */ 200: { - location: LocationInfo - data: ModelV2Info | null + location: LocationInfo2 + data: ModelV2Info2 | null } } @@ -14093,11 +16703,11 @@ export type V2GenerateTextErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * ServiceUnavailableError */ - 503: ServiceUnavailableError + 503: ServiceUnavailableErrorV2 } export type V2GenerateTextError = V2GenerateTextErrors[keyof V2GenerateTextErrors] @@ -14106,7 +16716,7 @@ export type V2GenerateTextResponses = { /** * GenerateTextResponse */ - 200: GenerateTextResponse + 200: GenerateTextResponseV2 } export type V2GenerateTextResponse = V2GenerateTextResponses[keyof V2GenerateTextResponses] @@ -14131,11 +16741,11 @@ export type V2ProviderListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * ServiceUnavailableError */ - 503: ServiceUnavailableError + 503: ServiceUnavailableErrorV2 } export type V2ProviderListError = V2ProviderListErrors[keyof V2ProviderListErrors] @@ -14145,8 +16755,8 @@ export type V2ProviderListResponses = { * Success */ 200: { - location: LocationInfo - data: Array + location: LocationInfo2 + data: Array } } @@ -14174,15 +16784,15 @@ export type V2ProviderGetErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * ProviderNotFoundError */ - 404: ProviderNotFoundError + 404: ProviderNotFoundErrorV2 /** * ServiceUnavailableError */ - 503: ServiceUnavailableError + 503: ServiceUnavailableErrorV2 } export type V2ProviderGetError = V2ProviderGetErrors[keyof V2ProviderGetErrors] @@ -14192,8 +16802,8 @@ export type V2ProviderGetResponses = { * Success */ 200: { - location: LocationInfo - data: ProviderV2Info + location: LocationInfo2 + data: ProviderV2Info2 } } @@ -14219,7 +16829,7 @@ export type V2IntegrationListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2IntegrationListError = V2IntegrationListErrors[keyof V2IntegrationListErrors] @@ -14229,8 +16839,8 @@ export type V2IntegrationListResponses = { * Success */ 200: { - location: LocationInfo - data: Array + location: LocationInfo2 + data: Array } } @@ -14258,7 +16868,7 @@ export type V2IntegrationGetErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2IntegrationGetError = V2IntegrationGetErrors[keyof V2IntegrationGetErrors] @@ -14268,8 +16878,8 @@ export type V2IntegrationGetResponses = { * Success */ 200: { - location: LocationInfo - data: IntegrationInfo | null + location: LocationInfo2 + data: IntegrationInfo2 | null } } @@ -14300,7 +16910,7 @@ export type V2IntegrationConnectKeyErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2IntegrationConnectKeyError = V2IntegrationConnectKeyErrors[keyof V2IntegrationConnectKeyErrors] @@ -14342,7 +16952,7 @@ export type V2IntegrationConnectOauthErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2IntegrationConnectOauthError = V2IntegrationConnectOauthErrors[keyof V2IntegrationConnectOauthErrors] @@ -14352,8 +16962,8 @@ export type V2IntegrationConnectOauthResponses = { * Success */ 200: { - location: LocationInfo - data: IntegrationAttempt + location: LocationInfo2 + data: IntegrationAttempt2 } } @@ -14382,7 +16992,7 @@ export type V2IntegrationAttemptCancelErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2IntegrationAttemptCancelError = V2IntegrationAttemptCancelErrors[keyof V2IntegrationAttemptCancelErrors] @@ -14419,7 +17029,7 @@ export type V2IntegrationAttemptStatusErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2IntegrationAttemptStatusError = V2IntegrationAttemptStatusErrors[keyof V2IntegrationAttemptStatusErrors] @@ -14429,8 +17039,8 @@ export type V2IntegrationAttemptStatusResponses = { * Success */ 200: { - location: LocationInfo - data: IntegrationAttemptStatus + location: LocationInfo2 + data: IntegrationAttemptStatus2 } } @@ -14461,7 +17071,7 @@ export type V2IntegrationAttemptCompleteErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2IntegrationAttemptCompleteError = @@ -14497,7 +17107,7 @@ export type V2McpListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2McpListError = V2McpListErrors[keyof V2McpListErrors] @@ -14507,8 +17117,8 @@ export type V2McpListResponses = { * Success */ 200: { - location: LocationInfo - data: Array + location: LocationInfo2 + data: Array } } @@ -14536,7 +17146,7 @@ export type V2CredentialRemoveErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2CredentialRemoveError = V2CredentialRemoveErrors[keyof V2CredentialRemoveErrors] @@ -14574,7 +17184,7 @@ export type V2CredentialUpdateErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2CredentialUpdateError = V2CredentialUpdateErrors[keyof V2CredentialUpdateErrors] @@ -14608,7 +17218,7 @@ export type V2ProjectCurrentErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2ProjectCurrentError = V2ProjectCurrentErrors[keyof V2ProjectCurrentErrors] @@ -14617,7 +17227,7 @@ export type V2ProjectCurrentResponses = { /** * Project.Current */ - 200: ProjectCurrent + 200: ProjectCurrent2 } export type V2ProjectCurrentResponse = V2ProjectCurrentResponses[keyof V2ProjectCurrentResponses] @@ -14644,7 +17254,7 @@ export type V2ProjectDirectoriesErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2ProjectDirectoriesError = V2ProjectDirectoriesErrors[keyof V2ProjectDirectoriesErrors] @@ -14658,311 +17268,6 @@ export type V2ProjectDirectoriesResponses = { export type V2ProjectDirectoriesResponse = V2ProjectDirectoriesResponses[keyof V2ProjectDirectoriesResponses] -export type V2FormRequestListData = { - body?: never - path?: never - query?: { - location?: { - directory?: string | null - workspace?: string | null - } | null - } - url: "/api/form/request" -} - -export type V2FormRequestListErrors = { - /** - * InvalidRequestError - */ - 400: InvalidRequestErrorV2 - /** - * UnauthorizedError - */ - 401: UnauthorizedError -} - -export type V2FormRequestListError = V2FormRequestListErrors[keyof V2FormRequestListErrors] - -export type V2FormRequestListResponses = { - /** - * Success - */ - 200: { - location: LocationInfo - data: Array - } -} - -export type V2FormRequestListResponse = V2FormRequestListResponses[keyof V2FormRequestListResponses] - -export type V2SessionFormListData = { - body?: never - path: { - sessionID: string - } - query?: { - location?: { - directory?: string | null - workspace?: string | null - } | null - } - url: "/api/session/{sessionID}/form" -} - -export type V2SessionFormListErrors = { - /** - * InvalidRequestError - */ - 400: InvalidRequestErrorV2 - /** - * UnauthorizedError - */ - 401: UnauthorizedError - /** - * SessionNotFoundError - */ - 404: SessionNotFoundError -} - -export type V2SessionFormListError = V2SessionFormListErrors[keyof V2SessionFormListErrors] - -export type V2SessionFormListResponses = { - /** - * Success - */ - 200: { - location: LocationInfo - data: Array - } -} - -export type V2SessionFormListResponse = V2SessionFormListResponses[keyof V2SessionFormListResponses] - -export type V2SessionFormCreateData = { - body: FormCreatePayload - path: { - sessionID: string - } - query?: { - location?: { - directory?: string | null - workspace?: string | null - } | null - } - url: "/api/session/{sessionID}/form" -} - -export type V2SessionFormCreateErrors = { - /** - * InvalidRequestError - */ - 400: InvalidRequestError1 | InvalidRequestErrorV2 - /** - * UnauthorizedError - */ - 401: UnauthorizedError - /** - * SessionNotFoundError - */ - 404: SessionNotFoundError - /** - * ConflictError - */ - 409: ConflictError -} - -export type V2SessionFormCreateError = V2SessionFormCreateErrors[keyof V2SessionFormCreateErrors] - -export type V2SessionFormCreateResponses = { - /** - * Success - */ - 200: { - location: LocationInfo - data: FormFormInfo2 | FormUrlInfo2 - } -} - -export type V2SessionFormCreateResponse = V2SessionFormCreateResponses[keyof V2SessionFormCreateResponses] - -export type V2SessionFormGetData = { - body?: never - path: { - sessionID: string - formID: string - } - query?: { - location?: { - directory?: string | null - workspace?: string | null - } | null - } - url: "/api/session/{sessionID}/form/{formID}" -} - -export type V2SessionFormGetErrors = { - /** - * InvalidRequestError - */ - 400: InvalidRequestErrorV2 - /** - * UnauthorizedError - */ - 401: UnauthorizedError - /** - * FormNotFoundError | SessionNotFoundError - */ - 404: FormNotFoundError | SessionNotFoundError -} - -export type V2SessionFormGetError = V2SessionFormGetErrors[keyof V2SessionFormGetErrors] - -export type V2SessionFormGetResponses = { - /** - * Success - */ - 200: { - location: LocationInfo - data: FormFormInfo2 | FormUrlInfo2 - } -} - -export type V2SessionFormGetResponse = V2SessionFormGetResponses[keyof V2SessionFormGetResponses] - -export type V2SessionFormStateData = { - body?: never - path: { - sessionID: string - formID: string - } - query?: { - location?: { - directory?: string | null - workspace?: string | null - } | null - } - url: "/api/session/{sessionID}/form/{formID}/state" -} - -export type V2SessionFormStateErrors = { - /** - * InvalidRequestError - */ - 400: InvalidRequestErrorV2 - /** - * UnauthorizedError - */ - 401: UnauthorizedError - /** - * FormNotFoundError | SessionNotFoundError - */ - 404: FormNotFoundError | SessionNotFoundError -} - -export type V2SessionFormStateError = V2SessionFormStateErrors[keyof V2SessionFormStateErrors] - -export type V2SessionFormStateResponses = { - /** - * Success - */ - 200: { - location: LocationInfo - data: FormState - } -} - -export type V2SessionFormStateResponse = V2SessionFormStateResponses[keyof V2SessionFormStateResponses] - -export type V2SessionFormReplyData = { - body: FormReply - path: { - sessionID: string - formID: string - } - query?: { - location?: { - directory?: string | null - workspace?: string | null - } | null - } - url: "/api/session/{sessionID}/form/{formID}/reply" -} - -export type V2SessionFormReplyErrors = { - /** - * FormInvalidAnswerError | InvalidRequestError - */ - 400: FormInvalidAnswerError | InvalidRequestErrorV2 - /** - * UnauthorizedError - */ - 401: UnauthorizedError - /** - * FormNotFoundError | SessionNotFoundError - */ - 404: FormNotFoundError | SessionNotFoundError - /** - * FormAlreadySettledError - */ - 409: FormAlreadySettledError -} - -export type V2SessionFormReplyError = V2SessionFormReplyErrors[keyof V2SessionFormReplyErrors] - -export type V2SessionFormReplyResponses = { - /** - * - */ - 204: void -} - -export type V2SessionFormReplyResponse = V2SessionFormReplyResponses[keyof V2SessionFormReplyResponses] - -export type V2SessionFormCancelData = { - body?: never - path: { - sessionID: string - formID: string - } - query?: { - location?: { - directory?: string | null - workspace?: string | null - } | null - } - url: "/api/session/{sessionID}/form/{formID}/cancel" -} - -export type V2SessionFormCancelErrors = { - /** - * InvalidRequestError - */ - 400: InvalidRequestErrorV2 - /** - * UnauthorizedError - */ - 401: UnauthorizedError - /** - * FormNotFoundError | SessionNotFoundError - */ - 404: FormNotFoundError | SessionNotFoundError - /** - * FormAlreadySettledError - */ - 409: FormAlreadySettledError -} - -export type V2SessionFormCancelError = V2SessionFormCancelErrors[keyof V2SessionFormCancelErrors] - -export type V2SessionFormCancelResponses = { - /** - * - */ - 204: void -} - -export type V2SessionFormCancelResponse = V2SessionFormCancelResponses[keyof V2SessionFormCancelResponses] - export type V2PermissionRequestListData = { body?: never path?: never @@ -14983,7 +17288,7 @@ export type V2PermissionRequestListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2PermissionRequestListError = V2PermissionRequestListErrors[keyof V2PermissionRequestListErrors] @@ -14993,8 +17298,8 @@ export type V2PermissionRequestListResponses = { * Success */ 200: { - location: LocationInfo - data: Array + location: LocationInfo2 + data: Array } } @@ -15017,7 +17322,7 @@ export type V2PermissionSavedListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2PermissionSavedListError = V2PermissionSavedListErrors[keyof V2PermissionSavedListErrors] @@ -15027,7 +17332,7 @@ export type V2PermissionSavedListResponses = { * Success */ 200: { - data: Array + data: Array } } @@ -15050,7 +17355,7 @@ export type V2PermissionSavedRemoveErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2PermissionSavedRemoveError = V2PermissionSavedRemoveErrors[keyof V2PermissionSavedRemoveErrors] @@ -15081,11 +17386,11 @@ export type V2SessionPermissionListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 } export type V2SessionPermissionListError = V2SessionPermissionListErrors[keyof V2SessionPermissionListErrors] @@ -15095,7 +17400,7 @@ export type V2SessionPermissionListResponses = { * Success */ 200: { - data: Array + data: Array } } @@ -15128,11 +17433,11 @@ export type V2SessionPermissionCreateErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError */ - 404: SessionNotFoundError + 404: SessionNotFoundErrorV2 } export type V2SessionPermissionCreateError = V2SessionPermissionCreateErrors[keyof V2SessionPermissionCreateErrors] @@ -15144,7 +17449,7 @@ export type V2SessionPermissionCreateResponses = { 200: { data: { id: string - effect: PermissionV2Effect + effect: PermissionV2Effect2 } } } @@ -15170,11 +17475,11 @@ export type V2SessionPermissionGetErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError | PermissionNotFoundError */ - 404: PermissionNotFoundErrorV2 | SessionNotFoundError + 404: PermissionNotFoundErrorV2 | SessionNotFoundErrorV2 } export type V2SessionPermissionGetError = V2SessionPermissionGetErrors[keyof V2SessionPermissionGetErrors] @@ -15184,7 +17489,7 @@ export type V2SessionPermissionGetResponses = { * Success */ 200: { - data: PermissionV2Request + data: PermissionV2Request2 } } @@ -15211,11 +17516,11 @@ export type V2SessionPermissionReplyErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * SessionNotFoundError | PermissionNotFoundError */ - 404: PermissionNotFoundErrorV2 | SessionNotFoundError + 404: PermissionNotFoundErrorV2 | SessionNotFoundErrorV2 } export type V2SessionPermissionReplyError = V2SessionPermissionReplyErrors[keyof V2SessionPermissionReplyErrors] @@ -15250,7 +17555,7 @@ export type V2FsReadErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2FsReadError = V2FsReadErrors[keyof V2FsReadErrors] @@ -15285,7 +17590,7 @@ export type V2FsListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2FsListError = V2FsListErrors[keyof V2FsListErrors] @@ -15295,8 +17600,8 @@ export type V2FsListResponses = { * Success */ 200: { - location: LocationInfo - data: Array + location: LocationInfo2 + data: Array } } @@ -15325,7 +17630,7 @@ export type V2FsFindErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2FsFindError = V2FsFindErrors[keyof V2FsFindErrors] @@ -15335,8 +17640,8 @@ export type V2FsFindResponses = { * Success */ 200: { - location: LocationInfo - data: Array + location: LocationInfo2 + data: Array } } @@ -15362,7 +17667,7 @@ export type V2CommandListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2CommandListError = V2CommandListErrors[keyof V2CommandListErrors] @@ -15372,8 +17677,8 @@ export type V2CommandListResponses = { * Success */ 200: { - location: LocationInfo - data: Array + location: LocationInfo2 + data: Array } } @@ -15399,7 +17704,7 @@ export type V2SkillListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2SkillListError = V2SkillListErrors[keyof V2SkillListErrors] @@ -15409,7 +17714,7 @@ export type V2SkillListResponses = { * Success */ 200: { - location: LocationInfo + location: LocationInfo2 data: Array } } @@ -15431,7 +17736,7 @@ export type V2EventSubscribeErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2EventSubscribeError = V2EventSubscribeErrors[keyof V2EventSubscribeErrors] @@ -15440,11 +17745,7 @@ export type V2EventSubscribeResponses = { /** * Success */ - 200: { - id: string | null - event: string - data: V2EventStream - } + 200: V2Event } export type V2EventSubscribeResponse = V2EventSubscribeResponses[keyof V2EventSubscribeResponses] @@ -15464,7 +17765,7 @@ export type V2EventChangesErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2EventChangesError = V2EventChangesErrors[keyof V2EventChangesErrors] @@ -15476,7 +17777,7 @@ export type V2EventChangesResponses = { 200: { id: string | null event: string - data: EventLogChangeStream + data: EventLogChangeStream2 } } @@ -15502,7 +17803,7 @@ export type V2PtyListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2PtyListError = V2PtyListErrors[keyof V2PtyListErrors] @@ -15512,7 +17813,7 @@ export type V2PtyListResponses = { * Success */ 200: { - location: LocationInfo + location: LocationInfo2 data: Array } } @@ -15547,7 +17848,7 @@ export type V2PtyCreateErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2PtyCreateError = V2PtyCreateErrors[keyof V2PtyCreateErrors] @@ -15557,7 +17858,7 @@ export type V2PtyCreateResponses = { * Success */ 200: { - location: LocationInfo + location: LocationInfo2 data: PtyV2 } } @@ -15586,7 +17887,7 @@ export type V2PtyRemoveErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * PtyNotFoundError */ @@ -15626,7 +17927,7 @@ export type V2PtyGetErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * PtyNotFoundError */ @@ -15640,7 +17941,7 @@ export type V2PtyGetResponses = { * Success */ 200: { - location: LocationInfo + location: LocationInfo2 data: PtyV2 } } @@ -15675,7 +17976,7 @@ export type V2PtyUpdateErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * PtyNotFoundError */ @@ -15689,7 +17990,7 @@ export type V2PtyUpdateResponses = { * Success */ 200: { - location: LocationInfo + location: LocationInfo2 data: PtyV2 } } @@ -15718,11 +18019,11 @@ export type V2PtyConnectTokenErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * ForbiddenError */ - 403: ForbiddenError + 403: ForbiddenErrorV2 /** * PtyNotFoundError */ @@ -15736,7 +18037,7 @@ export type V2PtyConnectTokenResponses = { * Success */ 200: { - location: LocationInfo + location: LocationInfo2 data: PtyTicketConnectToken2 } } @@ -15765,11 +18066,11 @@ export type V2PtyConnectErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * ForbiddenError */ - 403: ForbiddenError + 403: ForbiddenErrorV2 /** * PtyNotFoundError */ @@ -15807,7 +18108,7 @@ export type V2ShellListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2ShellListError = V2ShellListErrors[keyof V2ShellListErrors] @@ -15817,7 +18118,7 @@ export type V2ShellListResponses = { * Success */ 200: { - location: LocationInfo + location: LocationInfo2 data: Array } } @@ -15851,7 +18152,7 @@ export type V2ShellCreateErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2ShellCreateError = V2ShellCreateErrors[keyof V2ShellCreateErrors] @@ -15861,7 +18162,7 @@ export type V2ShellCreateResponses = { * Success */ 200: { - location: LocationInfo + location: LocationInfo2 data: Shell1V2 } } @@ -15890,11 +18191,11 @@ export type V2ShellRemoveErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * ShellNotFoundError */ - 404: ShellNotFoundError + 404: ShellNotFoundErrorV2 } export type V2ShellRemoveError = V2ShellRemoveErrors[keyof V2ShellRemoveErrors] @@ -15930,11 +18231,11 @@ export type V2ShellGetErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * ShellNotFoundError */ - 404: ShellNotFoundError + 404: ShellNotFoundErrorV2 } export type V2ShellGetError = V2ShellGetErrors[keyof V2ShellGetErrors] @@ -15944,7 +18245,7 @@ export type V2ShellGetResponses = { * Success */ 200: { - location: LocationInfo + location: LocationInfo2 data: Shell1V2 } } @@ -15975,11 +18276,11 @@ export type V2ShellOutputErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 /** * ShellNotFoundError */ - 404: ShellNotFoundError + 404: ShellNotFoundErrorV2 } export type V2ShellOutputError = V2ShellOutputErrors[keyof V2ShellOutputErrors] @@ -15989,7 +18290,7 @@ export type V2ShellOutputResponses = { * Success */ 200: { - location: LocationInfo + location: LocationInfo2 data: { output: string cursor: number @@ -16001,6 +18302,152 @@ export type V2ShellOutputResponses = { export type V2ShellOutputResponse = V2ShellOutputResponses[keyof V2ShellOutputResponses] +export type V2QuestionRequestListData = { + body?: never + path?: never + query?: { + location?: { + directory?: string | null + workspace?: string | null + } | null + } + url: "/api/question/request" +} + +export type V2QuestionRequestListErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestErrorV2 + /** + * UnauthorizedError + */ + 401: UnauthorizedErrorV2 +} + +export type V2QuestionRequestListError = V2QuestionRequestListErrors[keyof V2QuestionRequestListErrors] + +export type V2QuestionRequestListResponses = { + /** + * Success + */ + 200: { + location: LocationInfo2 + data: Array + } +} + +export type V2QuestionRequestListResponse = V2QuestionRequestListResponses[keyof V2QuestionRequestListResponses] + +export type V2SessionQuestionListData = { + body?: never + path: { + sessionID: string + } + query?: never + url: "/api/session/{sessionID}/question" +} + +export type V2SessionQuestionListErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestErrorV2 + /** + * UnauthorizedError + */ + 401: UnauthorizedErrorV2 + /** + * SessionNotFoundError + */ + 404: SessionNotFoundErrorV2 +} + +export type V2SessionQuestionListError = V2SessionQuestionListErrors[keyof V2SessionQuestionListErrors] + +export type V2SessionQuestionListResponses = { + /** + * Success + */ + 200: { + data: Array + } +} + +export type V2SessionQuestionListResponse = V2SessionQuestionListResponses[keyof V2SessionQuestionListResponses] + +export type V2SessionQuestionReplyData = { + body: QuestionV2Reply2 + path: { + sessionID: string + requestID: string + } + query?: never + url: "/api/session/{sessionID}/question/{requestID}/reply" +} + +export type V2SessionQuestionReplyErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestErrorV2 + /** + * UnauthorizedError + */ + 401: UnauthorizedErrorV2 + /** + * SessionNotFoundError | QuestionNotFoundError + */ + 404: QuestionNotFoundErrorV2 | SessionNotFoundErrorV2 +} + +export type V2SessionQuestionReplyError = V2SessionQuestionReplyErrors[keyof V2SessionQuestionReplyErrors] + +export type V2SessionQuestionReplyResponses = { + /** + * + */ + 204: void +} + +export type V2SessionQuestionReplyResponse = V2SessionQuestionReplyResponses[keyof V2SessionQuestionReplyResponses] + +export type V2SessionQuestionRejectData = { + body?: never + path: { + sessionID: string + requestID: string + } + query?: never + url: "/api/session/{sessionID}/question/{requestID}/reject" +} + +export type V2SessionQuestionRejectErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestErrorV2 + /** + * UnauthorizedError + */ + 401: UnauthorizedErrorV2 + /** + * SessionNotFoundError | QuestionNotFoundError + */ + 404: QuestionNotFoundErrorV2 | SessionNotFoundErrorV2 +} + +export type V2SessionQuestionRejectError = V2SessionQuestionRejectErrors[keyof V2SessionQuestionRejectErrors] + +export type V2SessionQuestionRejectResponses = { + /** + * + */ + 204: void +} + +export type V2SessionQuestionRejectResponse = V2SessionQuestionRejectResponses[keyof V2SessionQuestionRejectResponses] + export type V2ReferenceListData = { body?: never path?: never @@ -16021,7 +18468,7 @@ export type V2ReferenceListErrors = { /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2ReferenceListError = V2ReferenceListErrors[keyof V2ReferenceListErrors] @@ -16031,8 +18478,8 @@ export type V2ReferenceListResponses = { * Success */ 200: { - location: LocationInfo - data: Array + location: LocationInfo2 + data: Array } } @@ -16059,11 +18506,11 @@ export type V2ProjectCopyRemoveErrors = { /** * ProjectCopyError | InvalidRequestError */ - 400: ProjectCopyError | InvalidRequestErrorV2 + 400: ProjectCopyErrorV2 | InvalidRequestErrorV2 /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2ProjectCopyRemoveError = V2ProjectCopyRemoveErrors[keyof V2ProjectCopyRemoveErrors] @@ -16099,11 +18546,11 @@ export type V2ProjectCopyCreateErrors = { /** * ProjectCopyError | InvalidRequestError */ - 400: ProjectCopyError | InvalidRequestErrorV2 + 400: ProjectCopyErrorV2 | InvalidRequestErrorV2 /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2ProjectCopyCreateError = V2ProjectCopyCreateErrors[keyof V2ProjectCopyCreateErrors] @@ -16112,7 +18559,7 @@ export type V2ProjectCopyCreateResponses = { /** * ProjectCopy.Copy */ - 200: ProjectCopyCopy + 200: ProjectCopyCopy2 } export type V2ProjectCopyCreateResponse = V2ProjectCopyCreateResponses[keyof V2ProjectCopyCreateResponses] @@ -16135,11 +18582,11 @@ export type V2ProjectCopyRefreshErrors = { /** * ProjectCopyError | InvalidRequestError */ - 400: ProjectCopyError | InvalidRequestErrorV2 + 400: ProjectCopyErrorV2 | InvalidRequestErrorV2 /** * UnauthorizedError */ - 401: UnauthorizedError + 401: UnauthorizedErrorV2 } export type V2ProjectCopyRefreshError = V2ProjectCopyRefreshErrors[keyof V2ProjectCopyRefreshErrors] @@ -16152,3 +18599,39 @@ export type V2ProjectCopyRefreshResponses = { } export type V2ProjectCopyRefreshResponse = V2ProjectCopyRefreshResponses[keyof V2ProjectCopyRefreshResponses] + +export type PtyConnectData = { + body?: never + path: { + ptyID: string + } + query?: { + directory?: string + workspace?: string + cursor?: string + ticket?: string + } + url: "/pty/{ptyID}/connect" +} + +export type PtyConnectErrors = { + /** + * Forbidden + */ + 403: EffectHttpApiErrorForbidden + /** + * Not found + */ + 404: NotFoundError +} + +export type PtyConnectError = PtyConnectErrors[keyof PtyConnectErrors] + +export type PtyConnectResponses = { + /** + * Connected session + */ + 200: boolean +} + +export type PtyConnectResponse = PtyConnectResponses[keyof PtyConnectResponses] diff --git a/packages/tui/src/app.tsx b/packages/tui/src/app.tsx index 7c874ddf8d..ccde2fa5e6 100644 --- a/packages/tui/src/app.tsx +++ b/packages/tui/src/app.tsx @@ -77,7 +77,7 @@ import { useOpencodeKeymap, } from "./keymap" -import type { OpenCodeClient } from "@opencode-ai/client" +import type { OpenCodeClient } from "@opencode-ai/client/promise" import type { OpencodeClient } from "@opencode-ai/sdk/v2" import { DialogVariant } from "./component/dialog-variant" import { createTuiAttention } from "./attention" diff --git a/packages/tui/src/component/dialog-integration.tsx b/packages/tui/src/component/dialog-integration.tsx index 3b4b922134..cd8780ddfb 100644 --- a/packages/tui/src/component/dialog-integration.tsx +++ b/packages/tui/src/component/dialog-integration.tsx @@ -1,5 +1,5 @@ import { TextAttributes } from "@opentui/core" -import type { IntegrationConnectOauthOutput } from "@opencode-ai/client" +import type { IntegrationConnectOauthOutput } from "@opencode-ai/client/promise" import type { ConnectionInfo, IntegrationInfo, IntegrationOAuthMethod } from "@opencode-ai/sdk/v2" import { createMemo, createSignal, onCleanup, onMount, Show } from "solid-js" import { useClipboard } from "../context/clipboard" diff --git a/packages/tui/src/component/dialog-move-session.tsx b/packages/tui/src/component/dialog-move-session.tsx index 7cf6bc1ad7..405f2e0693 100644 --- a/packages/tui/src/component/dialog-move-session.tsx +++ b/packages/tui/src/component/dialog-move-session.tsx @@ -17,7 +17,7 @@ import { useCommandShortcut } from "../keymap" import { useProject } from "../context/project" import { Spinner } from "./spinner" import { DialogWorkspaceFileChanges } from "./dialog-workspace-file-changes" -import type { ProjectDirectoriesOutput } from "@opencode-ai/client" +import type { ProjectDirectoriesOutput } from "@opencode-ai/client/promise" import { useRoute } from "../context/route" export type MoveSessionSelection = { type: "directory"; directory: string; subdirectory: boolean } | { type: "new" } diff --git a/packages/tui/src/context/sdk.tsx b/packages/tui/src/context/sdk.tsx index 390eb8aa4a..7686ed6e94 100644 --- a/packages/tui/src/context/sdk.tsx +++ b/packages/tui/src/context/sdk.tsx @@ -1,4 +1,4 @@ -import type { OpenCodeClient } from "@opencode-ai/client" +import type { OpenCodeClient } from "@opencode-ai/client/promise" import type { OpencodeClient, V2Event } from "@opencode-ai/sdk/v2" import { createGlobalEmitter } from "@solid-primitives/event-bus" import { onCleanup, onMount } from "solid-js" diff --git a/packages/tui/test/cli/tui/use-event.test.tsx b/packages/tui/test/cli/tui/use-event.test.tsx index dd87100714..6ba38a83b8 100644 --- a/packages/tui/test/cli/tui/use-event.test.tsx +++ b/packages/tui/test/cli/tui/use-event.test.tsx @@ -1,6 +1,6 @@ /** @jsxImportSource @opentui/solid */ import { describe, expect, test } from "bun:test" -import type { OpenCodeClient } from "@opencode-ai/client" +import type { OpenCodeClient } from "@opencode-ai/client/promise" import { testRender } from "@opentui/solid" import type { OpencodeClient, V2Event } from "@opencode-ai/sdk/v2" import { onMount } from "solid-js" diff --git a/packages/tui/test/fixture/tui-sdk.ts b/packages/tui/test/fixture/tui-sdk.ts index 472ba4f78f..a486e6445d 100644 --- a/packages/tui/test/fixture/tui-sdk.ts +++ b/packages/tui/test/fixture/tui-sdk.ts @@ -1,4 +1,4 @@ -import { OpenCode } from "@opencode-ai/client" +import { OpenCode } from "@opencode-ai/client/promise" import { createOpencodeClient } from "@opencode-ai/sdk/v2" import type { V2Event } from "@opencode-ai/sdk/v2"