@@ -1132,7 +1137,7 @@ function HomeSessionSearchResultRow(props: {
function HomeSessionGroupHeader(props: { title: string; onNewSession?: () => void }) {
const language = useLanguage()
return (
-
+
{props.title}
{(onNewSession) => (
@@ -1189,22 +1194,24 @@ function HomeSessionRow(props: {
-
-
- }
- aria-label={language.t("common.archive")}
- onClick={(event) => {
- event.preventDefault()
- event.stopPropagation()
- void props.archiveSession(props.record.session)
- }}
- />
-
-
+
+
+
+ }
+ aria-label={language.t("common.archive")}
+ onClick={(event) => {
+ event.preventDefault()
+ event.stopPropagation()
+ void props.archiveSession(props.record.session)
+ }}
+ />
+
+
+
)
}
diff --git a/packages/app/src/pages/layout-new.tsx b/packages/app/src/pages/layout-new.tsx
index f9222cdeb7..329b7c56b0 100644
--- a/packages/app/src/pages/layout-new.tsx
+++ b/packages/app/src/pages/layout-new.tsx
@@ -1,26 +1,18 @@
import { createEffect, Suspense, type ParentProps } from "solid-js"
-import { useNavigate, useParams } from "@solidjs/router"
+import { useNavigate } from "@solidjs/router"
import { DebugBar } from "@/components/debug-bar"
import { HelpButton } from "@/components/help-button"
import { Titlebar, type TitlebarUpdate } from "@/components/titlebar"
-import { useNotification } from "@/context/notification"
import { usePlatform } from "@/context/platform"
import { setNavigate } from "@/utils/notification-click"
import { setV2Toast, ToastRegion } from "@/utils/toast"
export default function NewLayout(props: ParentProps) {
const platform = usePlatform()
- const notification = useNotification()
const navigate = useNavigate()
- const params = useParams<{ id?: string }>()
setNavigate(navigate)
createEffect(() => setV2Toast(true))
- createEffect(() => {
- if (!notification.ready() || !params.id) return
- if (notification.session.unseenCount(params.id) === 0) return
- notification.session.markViewed(params.id)
- })
const update: TitlebarUpdate = {
version: () => {
@@ -44,7 +36,7 @@ export default function NewLayout(props: ParentProps) {
{props.children}
- {import.meta.env.DEV &&
}
+ {import.meta.env.DEV &&
}
diff --git a/packages/cli/AGENTS.md b/packages/cli/AGENTS.md
new file mode 100644
index 0000000000..c7215121e5
--- /dev/null
+++ b/packages/cli/AGENTS.md
@@ -0,0 +1,98 @@
+# V2 CLI and TUI development guide
+
+## Migration context
+
+- The TUI is being ported from legacy APIs to the new V2 APIs. New and migrated TUI behavior should use `sdk.client.v2` and the location-scoped data in `packages/tui/src/context/data.tsx` instead of adding dependencies on legacy sync state.
+- Preserve established TUI behavior unless the task intentionally changes it. When behavior, copy, keyboard interaction, or layout is unclear, compare the local V2 TUI with the latest released legacy TUI.
+- Run both versions in separate Terminal Control sessions and save PNG-only captures at equivalent states:
+
+```bash
+# From packages/cli: local V2 TUI
+termctrl start opencode-v2-dev --host opentui --cols 112 --rows 34 -- bun dev --standalone
+
+# Released legacy TUI behavior reference
+termctrl start opencode-legacy --host opentui --cols 112 --rows 34 -- bunx opencode-ai@latest
+
+termctrl save opencode-v2-dev --format png --out /tmp/opencode/v2.png
+termctrl save opencode-legacy --format png --out /tmp/opencode/legacy.png
+```
+
+- Use the same viewport and send equivalent inputs to both sessions before comparing screenshots. The released CLI is a behavioral reference, not a source of V2 API design; keep the local implementation on V2 endpoints.
+- Stop both sessions after comparison: `termctrl stop opencode-v2-dev` and `termctrl stop opencode-legacy`.
+
+## Interactive debugging
+
+- This package is the V2 CLI adapter. Run its `dev` script when testing the TUI; do not use the repository-root `bun dev`, which launches the legacy `packages/opencode` CLI.
+- Run commands from `packages/cli`. Use `bun dev --standalone` for most debugging so the TUI starts with a private V2 server instead of depending on the background service.
+- Use `termctrl` for interactive checks instead of starting the TUI as a blocking foreground process. It provides a real PTY, handles OpenTUI's host handshake, and can save reviewable screenshots.
+- Use a dedicated session name and do not reuse or kill an unrelated session.
+
+```bash
+termctrl start opencode-v2-dev --host opentui --cols 112 --rows 34 -- bun dev --standalone
+termctrl wait opencode-v2-dev "Ask anything" --timeout 20000
+termctrl show opencode-v2-dev
+```
+
+- Wait for visible text before interacting instead of relying on fixed sleeps. Use the text expected from the screen under test, such as `Ask anything` or `Connect a provider`.
+- Drive the running TUI with `termctrl send`. Prefix typed input with `text:` and send control keys separately so the interaction matches real terminal input.
+
+```bash
+termctrl send opencode-v2-dev 'text:example prompt' enter
+termctrl send opencode-v2-dev ctrl-c
+```
+
+- Use `termctrl show` after each meaningful interaction and inspect the full visible screen for rendering errors, stale state, error toasts, and unexpected exits.
+- Save PNG evidence for every user-visible bug and fix. Do not save text captures; inspect the rendered PNG. Write temporary captures outside the repository unless the artifact is intended to be committed.
+
+```bash
+termctrl save opencode-v2-dev --format png --out /tmp/opencode/v2-tui.png
+```
+
+- For resize-sensitive changes, resize the viewport, wait for the expected content, and capture the screen again:
+
+```bash
+termctrl resize opencode-v2-dev --cols 100 --rows 30
+termctrl show opencode-v2-dev
+```
+
+- Source changes may require restarting the process. Use `termctrl restart opencode-v2-dev` rather than assuming the running TUI reloaded the change.
+- To exercise background-service behavior, omit `--standalone`. Service lifecycle commands are available through `bun dev service start`, `bun dev service status`, and `bun dev service stop`.
+- Always clean up the Terminal Control session when the check is complete:
+
+```bash
+termctrl stop opencode-v2-dev
+```
+
+## Server/API debugging
+
+- Use `bun dev api --help` from `packages/cli` to inspect the API debugging command. It sends one request to the V2 server using the same daemon discovery/auth path as the CLI.
+- Use `bun dev api` to introspect the server-side data backing the TUI. This is useful when debugging UI bugs: compare what the screen renders with the raw session, message, event, agent, or health data returned by the API to determine whether the bug is in the server state, the client data layer, or the TUI rendering.
+- `bun dev api` accepts either an OpenAPI operation ID or a raw HTTP method plus path:
+
+```bash
+bun dev api get /health
+bun dev api get /openapi.json
+bun dev api
--param key=value
+```
+
+- Pass JSON request bodies with `--data`/`-d`; the command sets `content-type: application/json` automatically unless you provide a header. Add extra headers with `--header`/`-H name:value`.
+- If no compatible background server is registered, `bun dev api` starts one through the daemon service. Use `bun dev service status`, `bun dev service restart`, and `bun dev service stop` when you need explicit lifecycle control.
+- Prefer raw method/path calls for quick server debugging and operation IDs when exercising documented OpenAPI routes with path or query parameters.
+
+## Debugger
+
+- To debug the V2 CLI or TUI with Bun's inspector, launch the CLI entrypoint through Terminal Control with an inspector URL, then attach a debugger to that URL:
+
+```bash
+termctrl start opencode-v2-debug --host opentui --cols 112 --rows 34 -- \
+ bun run --inspect=ws://localhost:6499/ src/index.ts --standalone
+```
+
+- Use `--inspect-wait` or `--inspect-brk` when execution must pause until the debugger attaches.
+- Use `termctrl logs opencode-v2-debug` for inspector output or startup failures emitted before the TUI renderer starts. Use `termctrl show` for the visible full-screen TUI.
+
+## Verification
+
+- Run `bun typecheck` from `packages/cli` after CLI adapter changes.
+- Run `bun typecheck` and `bun test` from `packages/tui` after shared TUI changes. Do not run tests from the repository root.
+- Treat automated checks and Terminal Control smoke tests as complementary. For user-visible changes, verify initial render, the changed interaction, Ctrl-C exit behavior, and save a screenshot of the corrected state.
diff --git a/packages/cli/bin/lildax.cjs b/packages/cli/bin/opencode2.cjs
similarity index 96%
rename from packages/cli/bin/lildax.cjs
rename to packages/cli/bin/opencode2.cjs
index ab99b84b0f..8795c71cd2 100644
--- a/packages/cli/bin/lildax.cjs
+++ b/packages/cli/bin/opencode2.cjs
@@ -31,11 +31,11 @@ function run(target) {
const envPath = process.env.OPENCODE_BIN_PATH
const scriptDir = path.dirname(fs.realpathSync(__filename))
-const cached = path.join(scriptDir, ".lildax")
+const cached = path.join(scriptDir, ".opencode2")
const platform = { darwin: "darwin", linux: "linux", win32: "windows" }[os.platform()] || os.platform()
const arch = { x64: "x64", arm64: "arm64", arm: "arm" }[os.arch()] || os.arch()
const base = "@opencode-ai/cli-" + platform + "-" + arch
-const binary = platform === "windows" ? "lildax.exe" : "lildax"
+const binary = platform === "windows" ? "opencode2.exe" : "opencode2"
function supportsAvx2() {
if (arch !== "x64") return false
@@ -121,7 +121,7 @@ function findBinary(startDir) {
const resolved = envPath || (fs.existsSync(cached) ? cached : findBinary(scriptDir))
if (!resolved) {
console.error(
- "It seems that your package manager failed to install the right lildax CLI package. Try manually installing " +
+ "It seems that your package manager failed to install the right opencode2 CLI package. Try manually installing " +
names.map((name) => `"${name}"`).join(" or ") +
" package",
)
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 1ea11f0864..2ca7a5ad66 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -5,7 +5,7 @@
"type": "module",
"license": "MIT",
"bin": {
- "lildax": "./bin/lildax.cjs"
+ "opencode2": "./bin/opencode2.cjs"
},
"files": [
"bin"
@@ -25,12 +25,15 @@
"@opentui/solid": "catalog:",
"@parcel/watcher": "2.5.1",
"effect": "catalog:",
+ "jsonc-parser": "3.3.1",
+ "semver": "catalog:",
"solid-js": "catalog:"
},
"devDependencies": {
"@opencode-ai/script": "workspace:*",
"@tsconfig/bun": "catalog:",
"@types/bun": "catalog:",
+ "@types/semver": "catalog:",
"@typescript/native-preview": "catalog:"
}
}
diff --git a/packages/cli/script/build.ts b/packages/cli/script/build.ts
index 55869a6295..9c8e1e69b5 100755
--- a/packages/cli/script/build.ts
+++ b/packages/cli/script/build.ts
@@ -10,7 +10,7 @@ import pkg from "../package.json"
import { modelsData } from "./generate"
const dir = path.resolve(import.meta.dirname, "..")
-const binary = "lildax"
+const binary = "opencode2"
process.chdir(dir)
await rm("dist", { recursive: true, force: true })
diff --git a/packages/cli/script/publish.ts b/packages/cli/script/publish.ts
index d2855413ca..116e5efa32 100755
--- a/packages/cli/script/publish.ts
+++ b/packages/cli/script/publish.ts
@@ -25,14 +25,15 @@ for (const filepath of new Bun.Glob("*/package.json").scanSync({ cwd: "./dist" }
}
console.log("binaries", binaries)
const version = Object.values(binaries)[0]
+const name = pkg.name
-await $`mkdir -p ./dist/${pkg.name}/bin`
-await $`cp ./bin/lildax.cjs ./dist/${pkg.name}/bin/lildax`
-await Bun.file(`./dist/${pkg.name}/package.json`).write(
+await $`mkdir -p ./dist/${name}/bin`
+await $`cp ./bin/opencode2.cjs ./dist/${name}/bin/opencode2`
+await Bun.file(`./dist/${name}/package.json`).write(
JSON.stringify(
{
- name: pkg.name,
- bin: { lildax: "./bin/lildax" },
+ name,
+ bin: { opencode2: "./bin/opencode2" },
version,
license: pkg.license,
repository: { type: "git", url: "git+https://github.com/anomalyco/opencode.git" },
@@ -50,4 +51,4 @@ await Promise.all(
publish(`./dist/${name.replace("@opencode-ai/", "")}`, name, version),
),
)
-await publish(`./dist/${pkg.name}`, pkg.name, version)
+await publish(`./dist/${name}`, name, version)
diff --git a/packages/cli/src/commands/commands.ts b/packages/cli/src/commands/commands.ts
index 19d1f5e68b..18db4006a8 100644
--- a/packages/cli/src/commands/commands.ts
+++ b/packages/cli/src/commands/commands.ts
@@ -5,6 +5,16 @@ declare const OPENCODE_CLI_NAME: string | undefined
export const Commands = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME : "opencode", {
description: "OpenCode 2.0 preview command line interface",
+ params: {
+ directory: Argument.string("directory").pipe(
+ Argument.withDescription("Directory to start OpenCode in"),
+ Argument.optional,
+ ),
+ standalone: Flag.boolean("standalone").pipe(
+ Flag.withDescription("Run with a private server instead of the background service"),
+ Flag.withDefault(false),
+ ),
+ },
commands: [
Spec.make("api", {
description: "Make a request to the running server",
@@ -46,6 +56,7 @@ export const Commands = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCO
hostname: Flag.string("hostname").pipe(Flag.withDefault("127.0.0.1")),
port: Flag.integer("port").pipe(Flag.optional),
register: Flag.boolean("register").pipe(Flag.withDefault(false)),
+ stdio: Flag.boolean("stdio").pipe(Flag.withDefault(false)),
},
}),
],
diff --git a/packages/cli/src/commands/handlers/default.ts b/packages/cli/src/commands/handlers/default.ts
index d0a9968e5d..fbd359c3ba 100644
--- a/packages/cli/src/commands/handlers/default.ts
+++ b/packages/cli/src/commands/handlers/default.ts
@@ -1,13 +1,27 @@
import { Commands } from "../commands"
import { Runtime } from "../../framework/runtime"
-import { Effect } from "effect"
+import { Effect, Option } from "effect"
import { Daemon } from "../../services/daemon"
+import { Standalone } from "../../services/standalone"
+import { Updater } from "../../services/updater"
-export default Runtime.handler(Commands, () =>
+export default Runtime.handler(Commands, (input) =>
Effect.gen(function* () {
+ const directory = Option.getOrUndefined(input.directory)
+ if (directory !== undefined) process.chdir(directory)
+ const updater = yield* Updater.Service
+ yield* updater.check()
const daemon = yield* Daemon.Service
- const transport = yield* daemon.transport()
+ const transport = yield* (input.standalone ? Standalone.transport() : daemon.transport())
const { runTui } = yield* Effect.promise(() => import("../../tui"))
- yield* runTui(transport)
+ yield* runTui(
+ transport,
+ input.standalone
+ ? undefined
+ : async () => {
+ await Effect.runPromise(daemon.stop())
+ return Effect.runPromise(daemon.transport())
+ },
+ )
}),
)
diff --git a/packages/cli/src/commands/handlers/serve.ts b/packages/cli/src/commands/handlers/serve.ts
index d4ecfed974..e847ad496e 100644
--- a/packages/cli/src/commands/handlers/serve.ts
+++ b/packages/cli/src/commands/handlers/serve.ts
@@ -6,9 +6,12 @@ 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 { createOpencodeClient } from "@opencode-ai/sdk/v2/client"
import { Commands } from "../commands"
import { Runtime } from "../../framework/runtime"
import { Daemon } from "../../services/daemon"
+import { Updater } from "../../services/updater"
export default Runtime.handler(
Commands.commands.serve,
@@ -16,15 +19,43 @@ export default Runtime.handler(
return yield* Effect.scoped(
Effect.gen(function* () {
const daemon = yield* Daemon.Service
- const address = yield* listen(input.hostname, input.port, yield* daemon.password())
+ const standalonePassword = process.env.OPENCODE_SERVER_PASSWORD
+ if (input.stdio) delete process.env.OPENCODE_SERVER_PASSWORD
+ const password = input.stdio ? standalonePassword : yield* daemon.password()
+ if (!password) return yield* Effect.fail(new Error("Missing server password"))
+ const address = yield* listen(input.hostname, input.port, password)
+ yield* Effect.tryPromise(() =>
+ createOpencodeClient({
+ baseUrl: HttpServer.formatAddress(address),
+ headers: ServerAuth.headers({ password }),
+ }).v2.location.get(undefined, { throwOnError: true }),
+ )
if (input.register) yield* daemon.register(address)
- console.log(`server listening on ${HttpServer.formatAddress(address)}`)
- return yield* Effect.never
- }),
+ const url = HttpServer.formatAddress(address)
+ console.log(input.stdio ? JSON.stringify({ url }) : `server listening on ${url}`)
+ const updater = yield* Updater.Service
+ yield* updater.check().pipe(Effect.forkScoped)
+ return yield* (input.stdio ? waitForStdinClose() : Effect.never)
+ }).pipe(Effect.annotateLogs({ role: "server" })),
)
}),
)
+function waitForStdinClose() {
+ return Effect.callback((resume) => {
+ const close = () => resume(Effect.void)
+ process.stdin.once("end", close)
+ process.stdin.once("close", close)
+ process.stdin.resume()
+ if (process.stdin.readableEnded || process.stdin.destroyed) close()
+ return Effect.sync(() => {
+ process.stdin.off("end", close)
+ process.stdin.off("close", close)
+ process.stdin.pause()
+ })
+ })
+}
+
function listen(hostname: string, port: Option.Option, password: string) {
if (Option.isSome(port)) return bind(hostname, port.value, password)
const next = (port: number): ReturnType =>
@@ -35,11 +66,15 @@ function listen(hostname: string, port: Option.Option, password: string)
}
function bind(hostname: string, port: number, password: string) {
+ const server = createServer()
return Layer.build(
HttpRouter.serve(createRoutes(password), { disableListenLog: true, disableLogger: true }).pipe(
- Layer.provideMerge(NodeHttpServer.layer(() => createServer(), { port, host: hostname })),
+ Layer.provideMerge(NodeHttpServer.layer(() => server, { port, host: hostname })),
Layer.provide(Credential.defaultLayer),
Layer.provide(PermissionSaved.defaultLayer),
),
- ).pipe(Effect.map((context) => Context.get(context, HttpServer.HttpServer).address))
+ ).pipe(
+ Effect.tap(() => Effect.addFinalizer(() => Effect.sync(() => server.closeAllConnections()))),
+ Effect.map((context) => Context.get(context, HttpServer.HttpServer).address),
+ )
}
diff --git a/packages/cli/src/commands/handlers/service/status.ts b/packages/cli/src/commands/handlers/service/status.ts
index d409970e8b..779d456c78 100644
--- a/packages/cli/src/commands/handlers/service/status.ts
+++ b/packages/cli/src/commands/handlers/service/status.ts
@@ -8,6 +8,6 @@ export default Runtime.handler(
Commands.commands.service.commands.status,
Effect.fn("cli.service.status")(function* () {
const url = yield* (yield* Daemon.Service).status()
- process.stdout.write((url ? `running ${url}` : "stopped") + EOL)
+ process.stdout.write((url ? url : "stopped") + EOL)
}),
)
diff --git a/packages/cli/src/framework/runtime.ts b/packages/cli/src/framework/runtime.ts
index 97247e4d6b..44ed78ea72 100644
--- a/packages/cli/src/framework/runtime.ts
+++ b/packages/cli/src/framework/runtime.ts
@@ -2,6 +2,8 @@ import * as Effect from "effect/Effect"
import * as Command from "effect/unstable/cli/Command"
import { Spec } from "./spec"
import { Daemon } from "../services/daemon"
+import { Updater } from "../services/updater"
+import { Scope } from "effect"
export type Input =
Value extends Spec.Node
@@ -10,11 +12,11 @@ export type Input =
? Input
: never
-type RuntimeHandler = (input: unknown) => Effect.Effect
+type RuntimeHandler = (input: unknown) => Effect.Effect
type Loader = () => Promise<{
- default: (input: Input) => Effect.Effect
+ default: (input: Input) => Effect.Effect
}>
-type ProvidedCommand = Command.Command
+type ProvidedCommand = Command.Command
export type Handlers = keyof Node["commands"] extends never
? Loader
diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts
index 4507fcba6e..f8a95977df 100755
--- a/packages/cli/src/index.ts
+++ b/packages/cli/src/index.ts
@@ -2,10 +2,21 @@
import * as NodeRuntime from "@effect/platform-node/NodeRuntime"
import * as NodeServices from "@effect/platform-node/NodeServices"
+import { NodeFileSystem } from "@effect/platform-node"
import * as Effect from "effect/Effect"
+import { Layer, Logger, References } from "effect"
import { Commands } from "./commands/commands"
import { Runtime } from "./framework/runtime"
import { Daemon } from "./services/daemon"
+import { Logging } from "@opencode-ai/core/observability/logging"
+import { Updater } from "./services/updater"
+import { InstallationChannel, InstallationVersion, InstallationLocal } from "@opencode-ai/core/installation/version"
+
+const LoggingLayer = Logger.layer(Logging.loggers(), { mergeWithExisting: false }).pipe(
+ Layer.provide(NodeFileSystem.layer),
+ Layer.orDie,
+ Layer.merge(Layer.succeed(References.MinimumLogLevel, Logging.minimumLogLevel())),
+)
const Handlers = Runtime.handlers(Commands, {
$: () => import("./commands/handlers/default"),
@@ -24,9 +35,14 @@ const Handlers = Runtime.handlers(Commands, {
serve: () => import("./commands/handlers/serve"),
})
-Runtime.run(Commands, Handlers, { version: "local" }).pipe(
+Effect.logInfo("cli starting", { version: InstallationVersion, channel: InstallationChannel, local: InstallationLocal }).pipe(
+ Effect.flatMap(() => Runtime.run(Commands, Handlers, { version: InstallationVersion })),
+ Effect.annotateLogs({ role: "cli" }),
Effect.provide(Daemon.defaultLayer),
+ Effect.provide(Updater.defaultLayer),
+ Effect.provide(LoggingLayer),
Effect.provide(NodeServices.layer),
Effect.scoped,
+ Effect.tap(() => Effect.sync(() => process.exit(0))),
NodeRuntime.runMain,
)
diff --git a/packages/cli/src/services/daemon.ts b/packages/cli/src/services/daemon.ts
index 2e1f5bee4e..964822d1d2 100644
--- a/packages/cli/src/services/daemon.ts
+++ b/packages/cli/src/services/daemon.ts
@@ -1,5 +1,5 @@
import { Global } from "@opencode-ai/core/global"
-import { InstallationVersion } from "@opencode-ai/core/installation/version"
+import { InstallationChannel, InstallationVersion } from "@opencode-ai/core/installation/version"
import { createOpencodeClient } from "@opencode-ai/sdk/v2/client"
import { ServerAuth } from "@opencode-ai/server/auth"
import { Context, Effect, FileSystem, Layer, Option, Schedule, Schema, Scope } from "effect"
@@ -28,6 +28,10 @@ const Registration = Schema.Struct({
})
type Registration = typeof Registration.Type
+const Config = Schema.Struct({
+ password: Schema.optional(Schema.String),
+})
+
function sameRegistration(left: Registration, right: Registration) {
return left.id === right.id && left.version === right.version && left.url === right.url && left.pid === right.pid
}
@@ -37,22 +41,30 @@ export const layer = Layer.effect(
Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem
const directory = Global.Path.state
- const file = path.join(directory, "server.json")
- const passwordFile = path.join(directory, "password")
+ const file = path.join(directory, InstallationChannel === "local" ? "server-local.json" : "server.json")
+ const configFile = path.join(Global.Path.config, "service.json")
+ const legacyPasswordFile = path.join(directory, "password")
const decodeRegistration = Schema.decodeUnknownEffect(Schema.fromJsonString(Registration))
+ const decodeConfig = Schema.decodeUnknownEffect(Schema.fromJsonString(Config))
const password = Effect.fn("cli.daemon.password")(function* (value?: string) {
- const existing = yield* fs.readFileString(passwordFile).pipe(Effect.catch(() => Effect.succeed(undefined)))
- if (value === undefined && existing) return existing
+ const config = yield* fs
+ .readFileString(configFile)
+ .pipe(Effect.flatMap(decodeConfig), Effect.catch(() => Effect.succeed(undefined)))
+ if (value === undefined && config?.password) return config.password
+
+ const legacy = yield* fs
+ .readFileString(legacyPasswordFile)
+ .pipe(Effect.catch(() => Effect.succeed(undefined)))
+ const next = value ?? legacy ?? randomBytes(32).toString("base64url")
// Keep one private credential across server restarts so discovered clients
// can reconnect without exposing a password flag or environment variable.
- const generated = value ?? randomBytes(32).toString("base64url")
- const temp = passwordFile + ".tmp"
- yield* fs.makeDirectory(directory, { recursive: true })
- yield* fs.writeFileString(temp, generated, { mode: 0o600 })
- yield* fs.rename(temp, passwordFile)
- return generated
+ const temp = configFile + ".tmp"
+ yield* fs.writeFileString(temp, JSON.stringify({ password: next }, null, 2) + "\n", { mode: 0o600 })
+ yield* fs.rename(temp, configFile)
+ if (legacy) yield* fs.remove(legacyPasswordFile).pipe(Effect.ignore)
+ return next
})
const registration = Effect.fnUntraced(function* () {
@@ -111,7 +123,7 @@ export const layer = Layer.effect(
const existing = yield* healthy().pipe(Effect.option)
const found = Option.getOrUndefined(existing)
const compiled = path.basename(process.execPath).replace(/\.exe$/, "") !== "bun"
- if (found?.version === InstallationVersion && compiled) return found.url
+ if (found?.version === InstallationVersion) return found.url
if (found) yield* stopProcess(found).pipe(Effect.ignore)
const entrypoint = compiled ? undefined : process.argv[1]
diff --git a/packages/cli/src/services/standalone.ts b/packages/cli/src/services/standalone.ts
new file mode 100644
index 0000000000..b17005e6d2
--- /dev/null
+++ b/packages/cli/src/services/standalone.ts
@@ -0,0 +1,41 @@
+import { ServerAuth } from "@opencode-ai/server/auth"
+import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
+import { Effect, Schema, Stream } from "effect"
+import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
+import { randomBytes } from "node:crypto"
+import path from "node:path"
+
+const Ready = Schema.Struct({ url: Schema.String })
+const decodeReady = Schema.decodeUnknownPromise(Schema.fromJsonString(Ready))
+
+function command(password: string) {
+ const compiled = path.basename(process.execPath).replace(/\.exe$/, "") !== "bun"
+ const entrypoint = compiled ? [] : process.argv[1] ? [process.argv[1]] : []
+ if (!compiled && entrypoint.length === 0) throw new Error("Failed to resolve CLI entrypoint")
+ return ChildProcess.make(process.execPath, [...entrypoint, "serve", "--stdio", "--port", "0"], {
+ cwd: process.cwd(),
+ env: { OPENCODE_SERVER_PASSWORD: password },
+ extendEnv: true,
+ // The server treats EOF on this pipe as the end of its ownership lease.
+ // The OS closes it even when the TUI is killed before Effect finalizers run.
+ stdin: "pipe",
+ stderr: "ignore",
+ killSignal: "SIGTERM",
+ forceKillAfter: "3 seconds",
+ })
+}
+
+export const transport = Effect.fn("cli.standalone.transport")(
+ function* () {
+ const password = randomBytes(32).toString("base64url")
+ const spawner = yield* ChildProcessSpawner.ChildProcessSpawner
+ const proc = yield* spawner.spawn(command(password))
+ const output = yield* proc.stdout.pipe(Stream.decodeText(), Stream.splitLines, Stream.take(1), Stream.mkString)
+ if (!output) return yield* Effect.fail(new Error("Standalone server exited before reporting readiness"))
+ const ready = yield* Effect.tryPromise(() => decodeReady(output))
+ return { url: ready.url, headers: ServerAuth.headers({ password }), pid: proc.pid }
+ },
+ Effect.provide(CrossSpawnSpawner.defaultLayer),
+)
+
+export * as Standalone from "./standalone"
diff --git a/packages/cli/src/services/updater.test.ts b/packages/cli/src/services/updater.test.ts
new file mode 100644
index 0000000000..e11de2a0d9
--- /dev/null
+++ b/packages/cli/src/services/updater.test.ts
@@ -0,0 +1,33 @@
+import { describe, expect, test } from "bun:test"
+import { action, decodePolicy } from "./updater"
+
+describe("updater", () => {
+ test("reads autoupdate from JSONC", () => {
+ expect(decodePolicy('{ // preference\n "autoupdate": "notify",\n}')).toBe("notify")
+ expect(decodePolicy('{ "autoupdate": false }')).toBe(false)
+ expect(decodePolicy('{ "autoupdate": "invalid" }')).toBeUndefined()
+ })
+
+ test("automatically updates patches and minors", () => {
+ expect(action("1.2.3", "1.2.4", true)).toBe("upgrade")
+ expect(action("1.2.3", "1.3.0", true)).toBe("upgrade")
+ expect(action("1.2.3", "1.2.4", "notify")).toBe("upgrade")
+ expect(action("1.2.3", "1.3.0", "notify")).toBe("upgrade")
+ })
+
+ test("skips when autoupdate is disabled", () => {
+ expect(action("1.2.3", "1.2.4", false)).toBe("none")
+ })
+
+ test("never automatically updates majors", () => {
+ expect(action("1.2.3", "2.0.0", true)).toBe("none")
+ })
+
+ test("reports up-to-date only when versions match", () => {
+ expect(action("1.2.3", "1.2.3", true)).toBe("none")
+ })
+
+ test("upgrades when latest is lower (rollback)", () => {
+ expect(action("1.2.4", "1.2.3", true)).toBe("upgrade")
+ })
+})
diff --git a/packages/cli/src/services/updater.ts b/packages/cli/src/services/updater.ts
new file mode 100644
index 0000000000..fd30e88443
--- /dev/null
+++ b/packages/cli/src/services/updater.ts
@@ -0,0 +1,158 @@
+import { Global } from "@opencode-ai/core/global"
+import { Flag } from "@opencode-ai/core/flag/flag"
+import { AppProcess } from "@opencode-ai/core/process"
+import {
+ InstallationChannel,
+ InstallationLocal,
+ InstallationVersion,
+} from "@opencode-ai/core/installation/version"
+import { Context, Duration, Effect, FileSystem, Layer } from "effect"
+import { ChildProcess } from "effect/unstable/process"
+import { parse, type ParseError } from "jsonc-parser"
+import path from "node:path"
+import semver from "semver"
+
+export type Policy = boolean | "notify"
+export type Action = "none" | "upgrade"
+type Method = "npm" | "pnpm" | "bun" | "yarn"
+
+const packageName = "@opencode-ai/cli"
+
+export interface Interface {
+ readonly check: () => Effect.Effect
+}
+
+export class Service extends Context.Service()("@opencode/cli/Updater") {}
+
+export function decodePolicy(text: string): Policy | undefined {
+ // The CLI only projects this host-level preference instead of initializing
+ // the location-scoped server configuration graph.
+ const errors: ParseError[] = []
+ const input: unknown = parse(text, errors, { allowTrailingComma: true })
+ if (errors.length || typeof input !== "object" || input === null || !("autoupdate" in input)) return
+ const value = input.autoupdate
+ if (typeof value === "boolean" || value === "notify") return value
+}
+
+export function action(current: string, latest: string, policy: Policy): Action {
+ if (policy === false) return "none"
+ if (!semver.valid(current) || !semver.valid(latest) || semver.eq(latest, current)) return "none"
+ // Major upgrades are never installed automatically.
+ if (semver.major(latest) !== semver.major(current)) return "none"
+ return "upgrade"
+}
+
+export const layer = Layer.effect(
+ Service,
+ Effect.gen(function* () {
+ const fs = yield* FileSystem.FileSystem
+ const global = yield* Global.Service
+ const appProcess = yield* AppProcess.Service
+ const channel = InstallationChannel.replace(/[^a-zA-Z0-9._-]/g, "-")
+
+ const readPolicy = Effect.fnUntraced(function* () {
+ const values = yield* Effect.forEach(["config.json", "opencode.json", "opencode.jsonc"], (name) =>
+ fs
+ .readFileString(path.join(global.config, name))
+ .pipe(Effect.map(decodePolicy), Effect.catch(() => Effect.succeed(undefined))),
+ )
+ return values.findLast((value) => value !== undefined) ?? true
+ })
+
+ const run = Effect.fnUntraced(function* (command: string[], timeout: Duration.Input = "10 seconds") {
+ return yield* appProcess
+ .run(ChildProcess.make(command[0], command.slice(1)), {
+ timeout,
+ maxOutputBytes: 100_000,
+ maxErrorBytes: 100_000,
+ })
+ .pipe(
+ Effect.map((result) => ({
+ code: result.exitCode,
+ stdout: result.stdout.toString("utf8"),
+ stderr: result.stderr.toString("utf8"),
+ })),
+ Effect.catch(() => Effect.succeed({ code: 1, stdout: "", stderr: "" })),
+ )
+ })
+
+ const method = Effect.fnUntraced(function* () {
+ const checks: ReadonlyArray<{ method: Method; command: string[] }> = [
+ { method: "npm", command: ["npm", "list", "-g", "--depth=0", packageName] },
+ { method: "pnpm", command: ["pnpm", "list", "-g", "--depth=0", packageName] },
+ { method: "bun", command: ["bun", "pm", "ls", "-g"] },
+ { method: "yarn", command: ["yarn", "global", "list"] },
+ ]
+ const results = yield* Effect.forEach(
+ checks,
+ (check) => run(check.command).pipe(Effect.map((result) => ({ check, result }))),
+ { concurrency: "unbounded" },
+ )
+ return results.find((result) => result.result.stdout.includes(packageName))?.check.method
+ })
+
+ const latest = Effect.fnUntraced(function* () {
+ const response = yield* Effect.tryPromise({
+ try: () =>
+ fetch(
+ `https://registry.npmjs.org/${encodeURIComponent(packageName)}/${encodeURIComponent(InstallationChannel)}`,
+ { headers: { "User-Agent": `opencode/${InstallationVersion}` }, signal: AbortSignal.timeout(10_000) },
+ ),
+ catch: (cause) => new Error("Failed to check for updates", { cause }),
+ })
+ if (!response.ok) return yield* Effect.fail(new Error(`Update check failed with status ${response.status}`))
+ const data = yield* Effect.tryPromise({
+ try: () => response.json(),
+ catch: (cause) => new Error("Failed to read update information", { cause }),
+ })
+ if (typeof data !== "object" || data === null || !("version" in data) || typeof data.version !== "string") {
+ return yield* Effect.fail(new Error("Update information did not include a version"))
+ }
+ return data.version
+ })
+
+ const upgrade = Effect.fnUntraced(function* (method: Method, version: string) {
+ const target = `${packageName}@${version}`
+ const commands: Record = {
+ npm: ["npm", "install", "--global", target],
+ pnpm: ["pnpm", "install", "--global", target],
+ bun: ["bun", "install", "--global", target],
+ yarn: ["yarn", "global", "add", target],
+ }
+ const result = yield* run(commands[method], "5 minutes")
+ if (result.code === 0) return
+ return yield* Effect.fail(new Error(result.stderr.trim() || `Failed to update with ${method}`))
+ })
+
+ const check = Effect.fn("cli.updater.check")(function* () {
+ if (InstallationLocal || Flag.OPENCODE_DISABLE_AUTOUPDATE)
+ return yield* Effect.logInfo("update check skipped", {
+ reason: InstallationLocal ? "local-install" : "disabled",
+ version: InstallationVersion,
+ channel: InstallationChannel,
+ })
+ const policy = yield* readPolicy()
+ if (policy === false) return yield* Effect.logInfo("update check skipped", { reason: "policy-disabled" })
+
+ return yield* Effect.gen(function* () {
+ const version = yield* latest()
+ yield* Effect.logInfo("update check", {
+ current: InstallationVersion,
+ latest: version,
+ })
+ const next = action(InstallationVersion, version, policy)
+ if (next === "none") return yield* Effect.logInfo("update check done", { action: "up-to-date" })
+ const detected = yield* method()
+ if (!detected) return yield* Effect.logWarning("automatic update skipped: installation method not found")
+ yield* upgrade(detected, version)
+ yield* Effect.logInfo("updated OpenCode", { from: InstallationVersion, to: version, method: detected })
+ })
+ }, Effect.catchCause((cause) => Effect.logWarning("automatic update failed", { cause })))
+
+ return Service.of({ check })
+ }),
+)
+
+export const defaultLayer = layer.pipe(Layer.provide(AppProcess.defaultLayer), Layer.provide(Global.defaultLayer))
+
+export * as Updater from "./updater"
diff --git a/packages/cli/src/tui.ts b/packages/cli/src/tui.ts
index 4722441b2c..32a225265c 100644
--- a/packages/cli/src/tui.ts
+++ b/packages/cli/src/tui.ts
@@ -2,35 +2,45 @@ import { run } from "@opencode-ai/tui"
import { TuiConfig } from "@opencode-ai/tui/config"
import { Effect } from "effect"
import { Global } from "@opencode-ai/core/global"
+import { loadBuiltinPlugins } from "@opencode-ai/tui/builtins"
+import { createOpencodeClient } from "@opencode-ai/sdk/v2/client"
-export function runTui(transport: { url: string; headers: RequestInit["headers"] }) {
+type Transport = { url: string; headers: RequestInit["headers"] }
+
+export function runTui(transport: Transport, reload?: () => Promise) {
const config = TuiConfig.resolve({}, { terminalSuspend: false })
- return run({
- ...transport,
- args: {},
- config,
- fetch: gracefulFetch,
- pluginHost: {
- async start() {},
- async dispose() {},
- },
+ let disposeSlots: (() => void) | undefined
+ return Effect.gen(function* () {
+ const options = { baseUrl: transport.url, headers: transport.headers }
+ const client = createOpencodeClient(options)
+ const directory = yield* Effect.tryPromise(() =>
+ client.v2.fs.list({ location: { directory: process.cwd() } }, { throwOnError: true }),
+ ).pipe(
+ Effect.map((response) => response.data.location.directory),
+ Effect.catch(() =>
+ Effect.tryPromise(() => client.v2.location.get(undefined, { throwOnError: true })).pipe(
+ Effect.map((response) => response.data.directory),
+ ),
+ ),
+ )
+ return yield* run({
+ client: createOpencodeClient({ ...options, directory }),
+ reload: reload
+ ? async () => {
+ const next = await reload()
+ return createOpencodeClient({ baseUrl: next.url, headers: next.headers, directory })
+ }
+ : undefined,
+ args: {},
+ config,
+ pluginHost: {
+ async start(input) {
+ disposeSlots = await loadBuiltinPlugins(input.api, input.runtime)
+ },
+ async dispose() {
+ disposeSlots?.()
+ },
+ },
+ })
}).pipe(Effect.provide(Global.defaultLayer))
}
-
-const legacyDefaults: Record = {
- "/config/providers": { providers: [], default: {} },
- "/provider": { all: [], default: {}, connected: [] },
- "/agent": [],
- "/config": {},
-}
-
-const gracefulFetch = Object.assign(
- async (input: RequestInfo | URL, init?: RequestInit) => {
- const response = await fetch(input, init)
- if (response.status !== 404) return response
- const fallback = legacyDefaults[new URL(input instanceof Request ? input.url : input).pathname]
- if (fallback === undefined) return response
- return Response.json(fallback)
- },
- { preconnect: fetch.preconnect },
-)
diff --git a/packages/cli/test/fixture/standalone-owner.ts b/packages/cli/test/fixture/standalone-owner.ts
new file mode 100644
index 0000000000..6149f614de
--- /dev/null
+++ b/packages/cli/test/fixture/standalone-owner.ts
@@ -0,0 +1,15 @@
+import { Effect } from "effect"
+import path from "node:path"
+import { Standalone } from "../../src/services/standalone"
+
+process.argv[1] = path.join(import.meta.dir, "../../src/index.ts")
+
+await Effect.runPromise(
+ Effect.scoped(
+ Effect.gen(function* () {
+ const transport = yield* Standalone.transport()
+ console.log(`${transport.pid} ${transport.url}`)
+ return yield* Effect.never
+ }),
+ ),
+)
diff --git a/packages/cli/test/standalone.test.ts b/packages/cli/test/standalone.test.ts
new file mode 100644
index 0000000000..1a309477f3
--- /dev/null
+++ b/packages/cli/test/standalone.test.ts
@@ -0,0 +1,65 @@
+import { expect, test } from "bun:test"
+import path from "node:path"
+
+test("standalone server exits when its owner is killed", async () => {
+ const owner = Bun.spawn([process.execPath, path.join(import.meta.dir, "fixture/standalone-owner.ts")], {
+ cwd: path.join(import.meta.dir, ".."),
+ env: process.env,
+ stdin: "ignore",
+ stdout: "pipe",
+ stderr: "pipe",
+ })
+ const line = await Promise.race([readLine(owner.stdout), Bun.sleep(10_000).then(() => undefined)])
+ const [rawPID, url] = line?.split(" ") ?? []
+ const pid = Number(rawPID)
+
+ try {
+ expect(pid).toBeGreaterThan(0)
+ expect(url).toStartWith("http://127.0.0.1:")
+ expect(running(pid)).toBe(true)
+
+ owner.kill("SIGKILL")
+ await owner.exited
+
+ expect(await waitForExit(pid)).toBe(true)
+ } finally {
+ owner.kill("SIGKILL")
+ if (running(pid)) process.kill(pid, "SIGKILL")
+ }
+})
+
+async function readLine(stream: ReadableStream) {
+ const reader = stream.getReader()
+ const decoder = new TextDecoder()
+ const chunks: string[] = []
+ while (true) {
+ const result = await reader.read()
+ if (result.done) break
+ chunks.push(decoder.decode(result.value, { stream: true }))
+ const output = chunks.join("")
+ const newline = output.indexOf("\n")
+ if (newline !== -1) {
+ reader.releaseLock()
+ return output.slice(0, newline)
+ }
+ }
+ reader.releaseLock()
+ return chunks.join("") + decoder.decode()
+}
+
+async function waitForExit(pid: number, attempts = 100): Promise {
+ if (!running(pid)) return true
+ if (attempts === 0) return false
+ await Bun.sleep(50)
+ return waitForExit(pid, attempts - 1)
+}
+
+function running(pid: number) {
+ if (!Number.isSafeInteger(pid) || pid <= 0) return false
+ try {
+ process.kill(pid, 0)
+ return true
+ } catch {
+ return false
+ }
+}
diff --git a/packages/client/README.md b/packages/client/README.md
index fc16795075..8c53e47c7e 100644
--- a/packages/client/README.md
+++ b/packages/client/README.md
@@ -7,7 +7,7 @@ Private generation target for clients derived directly from OpenCode's authorita
- `@opencode-ai/client`: zero-Effect Promise client using `fetch`.
- `@opencode-ai/client/effect`: rich Effect network client using an environment-provided `HttpClient`.
-The generated surface starts with the Session group from Server's concrete API. The build compiler reads `@opencode-ai/server/api`; the generated Effect runtime imports a client-local projection built from Protocol, with a generation-equivalence test preventing transport drift. Run `bun run generate` after changing the contract and `bun run check:generated` to detect committed-output drift.
+The generated surface includes every standard HTTP group from Server's concrete API. The build compiler reads `@opencode-ai/server/api`; the generated Effect runtime imports a client-local projection built from Protocol, with a generation-equivalence test preventing transport drift. Custom transports such as the PTY WebSocket connection remain outside the generic HTTP client. Run `bun run generate` after changing the contract and `bun run check:generated` to detect committed-output drift.
The Effect entrypoint uses canonical decoded values such as `Session.ID`, `Location.Ref`, and `Prompt`. These datatypes come from the lightweight `@opencode-ai/schema` package and are re-exported so callers depend only on the client surface. Protocol owns endpoint construction and middleware placement; Server supplies the concrete middleware keys used by the build-time API.
diff --git a/packages/client/script/build.ts b/packages/client/script/build.ts
index 35ce8387a8..aeec4b3e34 100644
--- a/packages/client/script/build.ts
+++ b/packages/client/script/build.ts
@@ -1,20 +1,27 @@
import { NodeFileSystem } from "@effect/platform-node"
import { compile, emitEffectImported, emitPromise, write } from "@opencode-ai/httpapi-codegen"
-import { Api } from "@opencode-ai/server/api"
+import { ClientApi, endpointNames, groupNames, omitEndpoints } from "../src/contract"
import { Effect } from "effect"
-import { HttpApi } from "effect/unstable/httpapi"
import { fileURLToPath } from "url"
-const contract = compile(HttpApi.make("opencode-client").add(Api.groups["server.session"]), {
- groupNames: { "server.session": "sessions" },
-})
+const contract = compile(ClientApi, { groupNames, endpointNames, omitEndpoints })
await Effect.runPromise(
Effect.all(
[
- write(emitPromise(contract), fileURLToPath(new URL("../src/generated", import.meta.url))),
write(
- emitEffectImported(contract, { module: "../contract", group: "SessionGroup" }),
+ emitPromise(contract, {
+ outputTypes: {
+ "events.subscribe": {
+ name: "OpenCodeEventEncoded",
+ import: 'import type { OpenCodeEventEncoded } from "@opencode-ai/protocol/groups/event"',
+ },
+ },
+ }),
+ fileURLToPath(new URL("../src/generated", import.meta.url)),
+ ),
+ write(
+ emitEffectImported(contract, { module: "../contract", api: "ClientApi" }),
fileURLToPath(new URL("../src/generated-effect", import.meta.url)),
),
],
diff --git a/packages/client/src/contract.ts b/packages/client/src/contract.ts
index 2190c130ca..413fea9dc3 100644
--- a/packages/client/src/contract.ts
+++ b/packages/client/src/contract.ts
@@ -11,9 +11,43 @@ class SessionLocationMiddleware extends HttpApiMiddleware.Service
+type RawClient = HttpApiClient.ForApi
const mapClientError = (error: E) =>
HttpClientError.isHttpClientError(error) || Schema.isSchemaError(error) || Sse.Retry.is(error)
? new ClientError({ cause: error })
: error
-type Endpoint0_0Request = Parameters[0]
-type Endpoint0_0Input = {
- readonly workspace?: Endpoint0_0Request["query"]["workspace"]
- readonly limit?: Endpoint0_0Request["query"]["limit"]
- readonly order?: Endpoint0_0Request["query"]["order"]
- readonly search?: Endpoint0_0Request["query"]["search"]
- readonly directory?: Endpoint0_0Request["query"]["directory"]
- readonly project?: Endpoint0_0Request["query"]["project"]
- readonly subpath?: Endpoint0_0Request["query"]["subpath"]
- readonly cursor?: Endpoint0_0Request["query"]["cursor"]
+const Endpoint0_0 = (raw: RawClient["server.health"]) => () =>
+ raw["health.get"]({}).pipe(Effect.mapError(mapClientError))
+
+const adaptGroup0 = (raw: RawClient["server.health"]) => ({ get: Endpoint0_0(raw) })
+
+type Endpoint1_0Request = Parameters[0]
+type Endpoint1_0Input = { readonly location?: Endpoint1_0Request["query"]["location"] }
+const Endpoint1_0 = (raw: RawClient["server.location"]) => (input?: Endpoint1_0Input) =>
+ raw["location.get"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
+
+const adaptGroup1 = (raw: RawClient["server.location"]) => ({ get: Endpoint1_0(raw) })
+
+type Endpoint2_0Request = Parameters[0]
+type Endpoint2_0Input = { readonly location?: Endpoint2_0Request["query"]["location"] }
+const Endpoint2_0 = (raw: RawClient["server.agent"]) => (input?: Endpoint2_0Input) =>
+ raw["agent.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
+
+const adaptGroup2 = (raw: RawClient["server.agent"]) => ({ list: Endpoint2_0(raw) })
+
+type Endpoint3_0Request = Parameters[0]
+type Endpoint3_0Input = {
+ readonly workspace?: Endpoint3_0Request["query"]["workspace"]
+ readonly limit?: Endpoint3_0Request["query"]["limit"]
+ readonly order?: Endpoint3_0Request["query"]["order"]
+ readonly search?: Endpoint3_0Request["query"]["search"]
+ readonly directory?: Endpoint3_0Request["query"]["directory"]
+ readonly project?: Endpoint3_0Request["query"]["project"]
+ readonly subpath?: Endpoint3_0Request["query"]["subpath"]
+ readonly cursor?: Endpoint3_0Request["query"]["cursor"]
}
-const Endpoint0_0 = (raw: RawClient["server.session"]) => (input?: Endpoint0_0Input) =>
+const Endpoint3_0 = (raw: RawClient["server.session"]) => (input?: Endpoint3_0Input) =>
raw["session.list"]({
query: {
- workspace: input?.workspace,
- limit: input?.limit,
- order: input?.order,
- search: input?.search,
- directory: input?.directory,
- project: input?.project,
- subpath: input?.subpath,
- cursor: input?.cursor,
+ workspace: input?.["workspace"],
+ limit: input?.["limit"],
+ order: input?.["order"],
+ search: input?.["search"],
+ directory: input?.["directory"],
+ project: input?.["project"],
+ subpath: input?.["subpath"],
+ cursor: input?.["cursor"],
},
}).pipe(Effect.mapError(mapClientError))
-type Endpoint0_1Request = Parameters[0]
-type Endpoint0_1Input = {
- readonly id?: Endpoint0_1Request["payload"]["id"]
- readonly agent?: Endpoint0_1Request["payload"]["agent"]
- readonly model?: Endpoint0_1Request["payload"]["model"]
- readonly location?: Endpoint0_1Request["payload"]["location"]
+type Endpoint3_1Request = Parameters[0]
+type Endpoint3_1Input = {
+ readonly id?: Endpoint3_1Request["payload"]["id"]
+ readonly agent?: Endpoint3_1Request["payload"]["agent"]
+ readonly model?: Endpoint3_1Request["payload"]["model"]
+ readonly location?: Endpoint3_1Request["payload"]["location"]
}
-const Endpoint0_1 = (raw: RawClient["server.session"]) => (input?: Endpoint0_1Input) =>
+const Endpoint3_1 = (raw: RawClient["server.session"]) => (input?: Endpoint3_1Input) =>
raw["session.create"]({
- payload: { id: input?.id, agent: input?.agent, model: input?.model, location: input?.location },
+ payload: { id: input?.["id"], agent: input?.["agent"], model: input?.["model"], location: input?.["location"] },
}).pipe(
Effect.mapError(mapClientError),
Effect.map((value) => value.data),
)
-const Endpoint0_2 = (raw: RawClient["server.session"]) => () =>
+const Endpoint3_2 = (raw: RawClient["server.session"]) => () =>
raw["session.active"]({}).pipe(
Effect.mapError(mapClientError),
Effect.map((value) => value.data),
)
-type Endpoint0_3Request = Parameters[0]
-type Endpoint0_3Input = { readonly sessionID: Endpoint0_3Request["params"]["sessionID"] }
-const Endpoint0_3 = (raw: RawClient["server.session"]) => (input: Endpoint0_3Input) =>
- raw["session.get"]({ params: { sessionID: input.sessionID } }).pipe(
+type Endpoint3_3Request = Parameters[0]
+type Endpoint3_3Input = { readonly sessionID: Endpoint3_3Request["params"]["sessionID"] }
+const Endpoint3_3 = (raw: RawClient["server.session"]) => (input: Endpoint3_3Input) =>
+ raw["session.get"]({ params: { sessionID: input["sessionID"] } }).pipe(
Effect.mapError(mapClientError),
Effect.map((value) => value.data),
)
-type Endpoint0_4Request = Parameters[0]
-type Endpoint0_4Input = {
- readonly sessionID: Endpoint0_4Request["params"]["sessionID"]
- readonly agent: Endpoint0_4Request["payload"]["agent"]
+type Endpoint3_4Request = Parameters[0]
+type Endpoint3_4Input = {
+ readonly sessionID: Endpoint3_4Request["params"]["sessionID"]
+ readonly messageID?: Endpoint3_4Request["payload"]["messageID"]
}
-const Endpoint0_4 = (raw: RawClient["server.session"]) => (input: Endpoint0_4Input) =>
- raw["session.switchAgent"]({ params: { sessionID: input.sessionID }, payload: { agent: input.agent } }).pipe(
+const Endpoint3_4 = (raw: RawClient["server.session"]) => (input: Endpoint3_4Input) =>
+ raw["session.fork"]({ params: { sessionID: input["sessionID"] }, payload: { messageID: input["messageID"] } }).pipe(
+ Effect.mapError(mapClientError),
+ Effect.map((value) => value.data),
+ )
+
+type Endpoint3_5Request = Parameters[0]
+type Endpoint3_5Input = {
+ readonly sessionID: Endpoint3_5Request["params"]["sessionID"]
+ readonly agent: Endpoint3_5Request["payload"]["agent"]
+}
+const Endpoint3_5 = (raw: RawClient["server.session"]) => (input: Endpoint3_5Input) =>
+ raw["session.switchAgent"]({ params: { sessionID: input["sessionID"] }, payload: { agent: input["agent"] } }).pipe(
Effect.mapError(mapClientError),
)
-type Endpoint0_5Request = Parameters[0]
-type Endpoint0_5Input = {
- readonly sessionID: Endpoint0_5Request["params"]["sessionID"]
- readonly model: Endpoint0_5Request["payload"]["model"]
+type Endpoint3_6Request = Parameters[0]
+type Endpoint3_6Input = {
+ readonly sessionID: Endpoint3_6Request["params"]["sessionID"]
+ readonly model: Endpoint3_6Request["payload"]["model"]
}
-const Endpoint0_5 = (raw: RawClient["server.session"]) => (input: Endpoint0_5Input) =>
- raw["session.switchModel"]({ params: { sessionID: input.sessionID }, payload: { model: input.model } }).pipe(
+const Endpoint3_6 = (raw: RawClient["server.session"]) => (input: Endpoint3_6Input) =>
+ raw["session.switchModel"]({ params: { sessionID: input["sessionID"] }, payload: { model: input["model"] } }).pipe(
Effect.mapError(mapClientError),
)
-type Endpoint0_6Request = Parameters[0]
-type Endpoint0_6Input = {
- readonly sessionID: Endpoint0_6Request["params"]["sessionID"]
- readonly id?: Endpoint0_6Request["payload"]["id"]
- readonly prompt: Endpoint0_6Request["payload"]["prompt"]
- readonly delivery?: Endpoint0_6Request["payload"]["delivery"]
- readonly resume?: Endpoint0_6Request["payload"]["resume"]
+type Endpoint3_7Request = Parameters[0]
+type Endpoint3_7Input = {
+ readonly sessionID: Endpoint3_7Request["params"]["sessionID"]
+ readonly title: Endpoint3_7Request["payload"]["title"]
}
-const Endpoint0_6 = (raw: RawClient["server.session"]) => (input: Endpoint0_6Input) =>
+const Endpoint3_7 = (raw: RawClient["server.session"]) => (input: Endpoint3_7Input) =>
+ raw["session.rename"]({ params: { sessionID: input["sessionID"] }, payload: { title: input["title"] } }).pipe(
+ Effect.mapError(mapClientError),
+ )
+
+type Endpoint3_8Request = Parameters[0]
+type Endpoint3_8Input = {
+ readonly sessionID: Endpoint3_8Request["params"]["sessionID"]
+ readonly id?: Endpoint3_8Request["payload"]["id"]
+ readonly prompt: Endpoint3_8Request["payload"]["prompt"]
+ readonly delivery?: Endpoint3_8Request["payload"]["delivery"]
+ readonly resume?: Endpoint3_8Request["payload"]["resume"]
+}
+const Endpoint3_8 = (raw: RawClient["server.session"]) => (input: Endpoint3_8Input) =>
raw["session.prompt"]({
- params: { sessionID: input.sessionID },
- payload: { id: input.id, prompt: input.prompt, delivery: input.delivery, resume: input.resume },
+ params: { sessionID: input["sessionID"] },
+ payload: { id: input["id"], prompt: input["prompt"], delivery: input["delivery"], resume: input["resume"] },
}).pipe(
Effect.mapError(mapClientError),
Effect.map((value) => value.data),
)
-type Endpoint0_7Request = Parameters[0]
-type Endpoint0_7Input = { readonly sessionID: Endpoint0_7Request["params"]["sessionID"] }
-const Endpoint0_7 = (raw: RawClient["server.session"]) => (input: Endpoint0_7Input) =>
- raw["session.compact"]({ params: { sessionID: input.sessionID } }).pipe(Effect.mapError(mapClientError))
+type Endpoint3_9Request = Parameters[0]
+type Endpoint3_9Input = { readonly sessionID: Endpoint3_9Request["params"]["sessionID"] }
+const Endpoint3_9 = (raw: RawClient["server.session"]) => (input: Endpoint3_9Input) =>
+ raw["session.compact"]({ params: { sessionID: input["sessionID"] } }).pipe(Effect.mapError(mapClientError))
-type Endpoint0_8Request = Parameters[0]
-type Endpoint0_8Input = { readonly sessionID: Endpoint0_8Request["params"]["sessionID"] }
-const Endpoint0_8 = (raw: RawClient["server.session"]) => (input: Endpoint0_8Input) =>
- raw["session.wait"]({ params: { sessionID: input.sessionID } }).pipe(Effect.mapError(mapClientError))
+type Endpoint3_10Request = Parameters[0]
+type Endpoint3_10Input = { readonly sessionID: Endpoint3_10Request["params"]["sessionID"] }
+const Endpoint3_10 = (raw: RawClient["server.session"]) => (input: Endpoint3_10Input) =>
+ raw["session.wait"]({ params: { sessionID: input["sessionID"] } }).pipe(Effect.mapError(mapClientError))
-type Endpoint0_9Request = Parameters[0]
-type Endpoint0_9Input = {
- readonly sessionID: Endpoint0_9Request["params"]["sessionID"]
- readonly messageID: Endpoint0_9Request["payload"]["messageID"]
- readonly files?: Endpoint0_9Request["payload"]["files"]
+type Endpoint3_11Request = Parameters[0]
+type Endpoint3_11Input = {
+ readonly sessionID: Endpoint3_11Request["params"]["sessionID"]
+ readonly messageID: Endpoint3_11Request["payload"]["messageID"]
+ readonly files?: Endpoint3_11Request["payload"]["files"]
}
-const Endpoint0_9 = (raw: RawClient["server.session"]) => (input: Endpoint0_9Input) =>
+const Endpoint3_11 = (raw: RawClient["server.session"]) => (input: Endpoint3_11Input) =>
raw["session.revert.stage"]({
- params: { sessionID: input.sessionID },
- payload: { messageID: input.messageID, files: input.files },
+ params: { sessionID: input["sessionID"] },
+ payload: { messageID: input["messageID"], files: input["files"] },
}).pipe(
Effect.mapError(mapClientError),
Effect.map((value) => value.data),
)
-type Endpoint0_10Request = Parameters[0]
-type Endpoint0_10Input = { readonly sessionID: Endpoint0_10Request["params"]["sessionID"] }
-const Endpoint0_10 = (raw: RawClient["server.session"]) => (input: Endpoint0_10Input) =>
- raw["session.revert.clear"]({ params: { sessionID: input.sessionID } }).pipe(Effect.mapError(mapClientError))
+type Endpoint3_12Request = Parameters[0]
+type Endpoint3_12Input = { readonly sessionID: Endpoint3_12Request["params"]["sessionID"] }
+const Endpoint3_12 = (raw: RawClient["server.session"]) => (input: Endpoint3_12Input) =>
+ raw["session.revert.clear"]({ params: { sessionID: input["sessionID"] } }).pipe(Effect.mapError(mapClientError))
-type Endpoint0_11Request = Parameters[0]
-type Endpoint0_11Input = { readonly sessionID: Endpoint0_11Request["params"]["sessionID"] }
-const Endpoint0_11 = (raw: RawClient["server.session"]) => (input: Endpoint0_11Input) =>
- raw["session.revert.commit"]({ params: { sessionID: input.sessionID } }).pipe(Effect.mapError(mapClientError))
+type Endpoint3_13Request = Parameters[0]
+type Endpoint3_13Input = { readonly sessionID: Endpoint3_13Request["params"]["sessionID"] }
+const Endpoint3_13 = (raw: RawClient["server.session"]) => (input: Endpoint3_13Input) =>
+ raw["session.revert.commit"]({ params: { sessionID: input["sessionID"] } }).pipe(Effect.mapError(mapClientError))
-type Endpoint0_12Request = Parameters[0]
-type Endpoint0_12Input = { readonly sessionID: Endpoint0_12Request["params"]["sessionID"] }
-const Endpoint0_12 = (raw: RawClient["server.session"]) => (input: Endpoint0_12Input) =>
- raw["session.context"]({ params: { sessionID: input.sessionID } }).pipe(
+type Endpoint3_14Request = Parameters[0]
+type Endpoint3_14Input = { readonly sessionID: Endpoint3_14Request["params"]["sessionID"] }
+const Endpoint3_14 = (raw: RawClient["server.session"]) => (input: Endpoint3_14Input) =>
+ raw["session.context"]({ params: { sessionID: input["sessionID"] } }).pipe(
Effect.mapError(mapClientError),
Effect.map((value) => value.data),
)
-type Endpoint0_13Request = Parameters[0]
-type Endpoint0_13Input = {
- readonly sessionID: Endpoint0_13Request["params"]["sessionID"]
- readonly after?: Endpoint0_13Request["query"]["after"]
+type Endpoint3_15Request = Parameters[0]
+type Endpoint3_15Input = {
+ readonly sessionID: Endpoint3_15Request["params"]["sessionID"]
+ readonly limit?: Endpoint3_15Request["query"]["limit"]
+ readonly after?: Endpoint3_15Request["query"]["after"]
}
-const Endpoint0_13 = (raw: RawClient["server.session"]) => (input: Endpoint0_13Input) =>
+const Endpoint3_15 = (raw: RawClient["server.session"]) => (input: Endpoint3_15Input) =>
+ raw["session.history"]({
+ params: { sessionID: input["sessionID"] },
+ query: { limit: input["limit"], after: input["after"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint3_16Request = Parameters[0]
+type Endpoint3_16Input = {
+ readonly sessionID: Endpoint3_16Request["params"]["sessionID"]
+ readonly after?: Endpoint3_16Request["query"]["after"]
+}
+const Endpoint3_16 = (raw: RawClient["server.session"]) => (input: Endpoint3_16Input) =>
Stream.unwrap(
- raw["session.events"]({ params: { sessionID: input.sessionID }, query: { after: input.after } }).pipe(
+ raw["session.events"]({ params: { sessionID: input["sessionID"] }, query: { after: input["after"] } }).pipe(
Effect.mapError(mapClientError),
Effect.map((stream) => stream.pipe(Stream.mapError(mapClientError))),
),
)
-type Endpoint0_14Request = Parameters[0]
-type Endpoint0_14Input = { readonly sessionID: Endpoint0_14Request["params"]["sessionID"] }
-const Endpoint0_14 = (raw: RawClient["server.session"]) => (input: Endpoint0_14Input) =>
- raw["session.interrupt"]({ params: { sessionID: input.sessionID } }).pipe(Effect.mapError(mapClientError))
+type Endpoint3_17Request = Parameters[0]
+type Endpoint3_17Input = { readonly sessionID: Endpoint3_17Request["params"]["sessionID"] }
+const Endpoint3_17 = (raw: RawClient["server.session"]) => (input: Endpoint3_17Input) =>
+ raw["session.interrupt"]({ params: { sessionID: input["sessionID"] } }).pipe(Effect.mapError(mapClientError))
-type Endpoint0_15Request = Parameters[0]
-type Endpoint0_15Input = {
- readonly sessionID: Endpoint0_15Request["params"]["sessionID"]
- readonly messageID: Endpoint0_15Request["params"]["messageID"]
+type Endpoint3_18Request = Parameters[0]
+type Endpoint3_18Input = {
+ readonly sessionID: Endpoint3_18Request["params"]["sessionID"]
+ readonly messageID: Endpoint3_18Request["params"]["messageID"]
}
-const Endpoint0_15 = (raw: RawClient["server.session"]) => (input: Endpoint0_15Input) =>
- raw["session.message"]({ params: { sessionID: input.sessionID, messageID: input.messageID } }).pipe(
+const Endpoint3_18 = (raw: RawClient["server.session"]) => (input: Endpoint3_18Input) =>
+ raw["session.message"]({ params: { sessionID: input["sessionID"], messageID: input["messageID"] } }).pipe(
Effect.mapError(mapClientError),
Effect.map((value) => value.data),
)
-const adaptGroup0 = (raw: RawClient["server.session"]) => ({
- list: Endpoint0_0(raw),
- create: Endpoint0_1(raw),
- active: Endpoint0_2(raw),
- get: Endpoint0_3(raw),
- switchAgent: Endpoint0_4(raw),
- switchModel: Endpoint0_5(raw),
- prompt: Endpoint0_6(raw),
- compact: Endpoint0_7(raw),
- wait: Endpoint0_8(raw),
- stage: Endpoint0_9(raw),
- clear: Endpoint0_10(raw),
- commit: Endpoint0_11(raw),
- context: Endpoint0_12(raw),
- events: Endpoint0_13(raw),
- interrupt: Endpoint0_14(raw),
- message: Endpoint0_15(raw),
+const adaptGroup3 = (raw: RawClient["server.session"]) => ({
+ list: Endpoint3_0(raw),
+ create: Endpoint3_1(raw),
+ active: Endpoint3_2(raw),
+ get: Endpoint3_3(raw),
+ fork: Endpoint3_4(raw),
+ switchAgent: Endpoint3_5(raw),
+ switchModel: Endpoint3_6(raw),
+ rename: Endpoint3_7(raw),
+ prompt: Endpoint3_8(raw),
+ compact: Endpoint3_9(raw),
+ wait: Endpoint3_10(raw),
+ stage: Endpoint3_11(raw),
+ clear: Endpoint3_12(raw),
+ commit: Endpoint3_13(raw),
+ context: Endpoint3_14(raw),
+ history: Endpoint3_15(raw),
+ events: Endpoint3_16(raw),
+ interrupt: Endpoint3_17(raw),
+ message: Endpoint3_18(raw),
})
-const adaptClient = (raw: RawClient) => ({ sessions: adaptGroup0(raw["server.session"]) })
+type Endpoint4_0Request = Parameters[0]
+type Endpoint4_0Input = {
+ readonly sessionID: Endpoint4_0Request["params"]["sessionID"]
+ readonly limit?: Endpoint4_0Request["query"]["limit"]
+ readonly order?: Endpoint4_0Request["query"]["order"]
+ readonly cursor?: Endpoint4_0Request["query"]["cursor"]
+}
+const Endpoint4_0 = (raw: RawClient["server.message"]) => (input: Endpoint4_0Input) =>
+ raw["session.messages"]({
+ params: { sessionID: input["sessionID"] },
+ query: { limit: input["limit"], order: input["order"], cursor: input["cursor"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+const adaptGroup4 = (raw: RawClient["server.message"]) => ({ list: Endpoint4_0(raw) })
+
+type Endpoint5_0Request = Parameters[0]
+type Endpoint5_0Input = { readonly location?: Endpoint5_0Request["query"]["location"] }
+const Endpoint5_0 = (raw: RawClient["server.model"]) => (input?: Endpoint5_0Input) =>
+ raw["model.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
+
+const adaptGroup5 = (raw: RawClient["server.model"]) => ({ list: Endpoint5_0(raw) })
+
+type Endpoint6_0Request = Parameters[0]
+type Endpoint6_0Input = { readonly location?: Endpoint6_0Request["query"]["location"] }
+const Endpoint6_0 = (raw: RawClient["server.provider"]) => (input?: Endpoint6_0Input) =>
+ raw["provider.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint6_1Request = Parameters[0]
+type Endpoint6_1Input = {
+ readonly providerID: Endpoint6_1Request["params"]["providerID"]
+ readonly location?: Endpoint6_1Request["query"]["location"]
+}
+const Endpoint6_1 = (raw: RawClient["server.provider"]) => (input: Endpoint6_1Input) =>
+ raw["provider.get"]({ params: { providerID: input["providerID"] }, query: { location: input["location"] } }).pipe(
+ Effect.mapError(mapClientError),
+ )
+
+const adaptGroup6 = (raw: RawClient["server.provider"]) => ({ list: Endpoint6_0(raw), get: Endpoint6_1(raw) })
+
+type Endpoint7_0Request = Parameters[0]
+type Endpoint7_0Input = { readonly location?: Endpoint7_0Request["query"]["location"] }
+const Endpoint7_0 = (raw: RawClient["server.integration"]) => (input?: Endpoint7_0Input) =>
+ raw["integration.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint7_1Request = Parameters[0]
+type Endpoint7_1Input = {
+ readonly integrationID: Endpoint7_1Request["params"]["integrationID"]
+ readonly location?: Endpoint7_1Request["query"]["location"]
+}
+const Endpoint7_1 = (raw: RawClient["server.integration"]) => (input: Endpoint7_1Input) =>
+ raw["integration.get"]({
+ params: { integrationID: input["integrationID"] },
+ query: { location: input["location"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint7_2Request = Parameters[0]
+type Endpoint7_2Input = {
+ readonly integrationID: Endpoint7_2Request["params"]["integrationID"]
+ readonly location?: Endpoint7_2Request["query"]["location"]
+ readonly key: Endpoint7_2Request["payload"]["key"]
+ readonly label?: Endpoint7_2Request["payload"]["label"]
+}
+const Endpoint7_2 = (raw: RawClient["server.integration"]) => (input: Endpoint7_2Input) =>
+ raw["integration.connect.key"]({
+ params: { integrationID: input["integrationID"] },
+ query: { location: input["location"] },
+ payload: { key: input["key"], label: input["label"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint7_3Request = Parameters[0]
+type Endpoint7_3Input = {
+ readonly integrationID: Endpoint7_3Request["params"]["integrationID"]
+ readonly location?: Endpoint7_3Request["query"]["location"]
+ readonly methodID: Endpoint7_3Request["payload"]["methodID"]
+ readonly inputs: Endpoint7_3Request["payload"]["inputs"]
+ readonly label?: Endpoint7_3Request["payload"]["label"]
+}
+const Endpoint7_3 = (raw: RawClient["server.integration"]) => (input: Endpoint7_3Input) =>
+ raw["integration.connect.oauth"]({
+ params: { integrationID: input["integrationID"] },
+ query: { location: input["location"] },
+ payload: { methodID: input["methodID"], inputs: input["inputs"], label: input["label"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint7_4Request = Parameters[0]
+type Endpoint7_4Input = {
+ readonly attemptID: Endpoint7_4Request["params"]["attemptID"]
+ readonly location?: Endpoint7_4Request["query"]["location"]
+}
+const Endpoint7_4 = (raw: RawClient["server.integration"]) => (input: Endpoint7_4Input) =>
+ raw["integration.attempt.status"]({
+ params: { attemptID: input["attemptID"] },
+ query: { location: input["location"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint7_5Request = Parameters[0]
+type Endpoint7_5Input = {
+ readonly attemptID: Endpoint7_5Request["params"]["attemptID"]
+ readonly location?: Endpoint7_5Request["query"]["location"]
+ readonly code?: Endpoint7_5Request["payload"]["code"]
+}
+const Endpoint7_5 = (raw: RawClient["server.integration"]) => (input: Endpoint7_5Input) =>
+ raw["integration.attempt.complete"]({
+ params: { attemptID: input["attemptID"] },
+ query: { location: input["location"] },
+ payload: { code: input["code"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint7_6Request = Parameters[0]
+type Endpoint7_6Input = {
+ readonly attemptID: Endpoint7_6Request["params"]["attemptID"]
+ readonly location?: Endpoint7_6Request["query"]["location"]
+}
+const Endpoint7_6 = (raw: RawClient["server.integration"]) => (input: Endpoint7_6Input) =>
+ raw["integration.attempt.cancel"]({
+ params: { attemptID: input["attemptID"] },
+ query: { location: input["location"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+const adaptGroup7 = (raw: RawClient["server.integration"]) => ({
+ list: Endpoint7_0(raw),
+ get: Endpoint7_1(raw),
+ connectKey: Endpoint7_2(raw),
+ connectOauth: Endpoint7_3(raw),
+ attemptStatus: Endpoint7_4(raw),
+ attemptComplete: Endpoint7_5(raw),
+ attemptCancel: Endpoint7_6(raw),
+})
+
+type Endpoint8_0Request = Parameters[0]
+type Endpoint8_0Input = {
+ readonly credentialID: Endpoint8_0Request["params"]["credentialID"]
+ readonly location?: Endpoint8_0Request["query"]["location"]
+ readonly label: Endpoint8_0Request["payload"]["label"]
+}
+const Endpoint8_0 = (raw: RawClient["server.credential"]) => (input: Endpoint8_0Input) =>
+ raw["credential.update"]({
+ params: { credentialID: input["credentialID"] },
+ query: { location: input["location"] },
+ payload: { label: input["label"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint8_1Request = Parameters[0]
+type Endpoint8_1Input = {
+ readonly credentialID: Endpoint8_1Request["params"]["credentialID"]
+ readonly location?: Endpoint8_1Request["query"]["location"]
+}
+const Endpoint8_1 = (raw: RawClient["server.credential"]) => (input: Endpoint8_1Input) =>
+ raw["credential.remove"]({
+ params: { credentialID: input["credentialID"] },
+ query: { location: input["location"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+const adaptGroup8 = (raw: RawClient["server.credential"]) => ({ update: Endpoint8_0(raw), remove: Endpoint8_1(raw) })
+
+type Endpoint9_0Request = Parameters[0]
+type Endpoint9_0Input = { readonly location?: Endpoint9_0Request["query"]["location"] }
+const Endpoint9_0 = (raw: RawClient["server.permission"]) => (input?: Endpoint9_0Input) =>
+ raw["permission.request.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint9_1Request = Parameters[0]
+type Endpoint9_1Input = { readonly projectID?: Endpoint9_1Request["query"]["projectID"] }
+const Endpoint9_1 = (raw: RawClient["server.permission"]) => (input?: Endpoint9_1Input) =>
+ raw["permission.saved.list"]({ query: { projectID: input?.["projectID"] } }).pipe(
+ Effect.mapError(mapClientError),
+ Effect.map((value) => value.data),
+ )
+
+type Endpoint9_2Request = Parameters[0]
+type Endpoint9_2Input = { readonly id: Endpoint9_2Request["params"]["id"] }
+const Endpoint9_2 = (raw: RawClient["server.permission"]) => (input: Endpoint9_2Input) =>
+ raw["permission.saved.remove"]({ params: { id: input["id"] } }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint9_3Request = Parameters[0]
+type Endpoint9_3Input = {
+ readonly sessionID: Endpoint9_3Request["params"]["sessionID"]
+ readonly id?: Endpoint9_3Request["payload"]["id"]
+ readonly action: Endpoint9_3Request["payload"]["action"]
+ readonly resources: Endpoint9_3Request["payload"]["resources"]
+ readonly save?: Endpoint9_3Request["payload"]["save"]
+ readonly metadata?: Endpoint9_3Request["payload"]["metadata"]
+ readonly source?: Endpoint9_3Request["payload"]["source"]
+ readonly agent?: Endpoint9_3Request["payload"]["agent"]
+}
+const Endpoint9_3 = (raw: RawClient["server.permission"]) => (input: Endpoint9_3Input) =>
+ raw["session.permission.create"]({
+ params: { sessionID: input["sessionID"] },
+ payload: {
+ id: input["id"],
+ action: input["action"],
+ resources: input["resources"],
+ save: input["save"],
+ metadata: input["metadata"],
+ source: input["source"],
+ agent: input["agent"],
+ },
+ }).pipe(
+ Effect.mapError(mapClientError),
+ Effect.map((value) => value.data),
+ )
+
+type Endpoint9_4Request = Parameters[0]
+type Endpoint9_4Input = { readonly sessionID: Endpoint9_4Request["params"]["sessionID"] }
+const Endpoint9_4 = (raw: RawClient["server.permission"]) => (input: Endpoint9_4Input) =>
+ raw["session.permission.list"]({ params: { sessionID: input["sessionID"] } }).pipe(
+ Effect.mapError(mapClientError),
+ Effect.map((value) => value.data),
+ )
+
+type Endpoint9_5Request = Parameters[0]
+type Endpoint9_5Input = {
+ readonly sessionID: Endpoint9_5Request["params"]["sessionID"]
+ readonly requestID: Endpoint9_5Request["params"]["requestID"]
+}
+const Endpoint9_5 = (raw: RawClient["server.permission"]) => (input: Endpoint9_5Input) =>
+ raw["session.permission.get"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] } }).pipe(
+ Effect.mapError(mapClientError),
+ Effect.map((value) => value.data),
+ )
+
+type Endpoint9_6Request = Parameters[0]
+type Endpoint9_6Input = {
+ readonly sessionID: Endpoint9_6Request["params"]["sessionID"]
+ readonly requestID: Endpoint9_6Request["params"]["requestID"]
+ readonly reply: Endpoint9_6Request["payload"]["reply"]
+ readonly message?: Endpoint9_6Request["payload"]["message"]
+}
+const Endpoint9_6 = (raw: RawClient["server.permission"]) => (input: Endpoint9_6Input) =>
+ raw["session.permission.reply"]({
+ params: { sessionID: input["sessionID"], requestID: input["requestID"] },
+ payload: { reply: input["reply"], message: input["message"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+const adaptGroup9 = (raw: RawClient["server.permission"]) => ({
+ listRequests: Endpoint9_0(raw),
+ listSaved: Endpoint9_1(raw),
+ removeSaved: Endpoint9_2(raw),
+ create: Endpoint9_3(raw),
+ list: Endpoint9_4(raw),
+ get: Endpoint9_5(raw),
+ reply: Endpoint9_6(raw),
+})
+
+type Endpoint10_0Request = Parameters[0]
+type Endpoint10_0Input = {
+ readonly location?: Endpoint10_0Request["query"]["location"]
+ readonly path?: Endpoint10_0Request["query"]["path"]
+}
+const Endpoint10_0 = (raw: RawClient["server.fs"]) => (input?: Endpoint10_0Input) =>
+ raw["fs.list"]({ query: { location: input?.["location"], path: input?.["path"] } }).pipe(
+ Effect.mapError(mapClientError),
+ )
+
+type Endpoint10_1Request = Parameters[0]
+type Endpoint10_1Input = {
+ readonly location?: Endpoint10_1Request["query"]["location"]
+ readonly query: Endpoint10_1Request["query"]["query"]
+ readonly type?: Endpoint10_1Request["query"]["type"]
+ readonly limit?: Endpoint10_1Request["query"]["limit"]
+}
+const Endpoint10_1 = (raw: RawClient["server.fs"]) => (input: Endpoint10_1Input) =>
+ raw["fs.find"]({
+ query: { location: input["location"], query: input["query"], type: input["type"], limit: input["limit"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+const adaptGroup10 = (raw: RawClient["server.fs"]) => ({ list: Endpoint10_0(raw), find: Endpoint10_1(raw) })
+
+type Endpoint11_0Request = Parameters[0]
+type Endpoint11_0Input = { readonly location?: Endpoint11_0Request["query"]["location"] }
+const Endpoint11_0 = (raw: RawClient["server.command"]) => (input?: Endpoint11_0Input) =>
+ raw["command.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
+
+const adaptGroup11 = (raw: RawClient["server.command"]) => ({ list: Endpoint11_0(raw) })
+
+type Endpoint12_0Request = Parameters[0]
+type Endpoint12_0Input = { readonly location?: Endpoint12_0Request["query"]["location"] }
+const Endpoint12_0 = (raw: RawClient["server.skill"]) => (input?: Endpoint12_0Input) =>
+ raw["skill.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
+
+const adaptGroup12 = (raw: RawClient["server.skill"]) => ({ list: Endpoint12_0(raw) })
+
+const Endpoint13_0 = (raw: RawClient["server.event"]) => () =>
+ Stream.unwrap(
+ raw["event.subscribe"]({}).pipe(
+ Effect.mapError(mapClientError),
+ Effect.map((stream) => stream.pipe(Stream.mapError(mapClientError))),
+ ),
+ )
+
+const adaptGroup13 = (raw: RawClient["server.event"]) => ({ subscribe: Endpoint13_0(raw) })
+
+type Endpoint14_0Request = Parameters[0]
+type Endpoint14_0Input = { readonly location?: Endpoint14_0Request["query"]["location"] }
+const Endpoint14_0 = (raw: RawClient["server.pty"]) => (input?: Endpoint14_0Input) =>
+ raw["pty.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint14_1Request = Parameters[0]
+type Endpoint14_1Input = {
+ readonly location?: Endpoint14_1Request["query"]["location"]
+ readonly command?: Endpoint14_1Request["payload"]["command"]
+ readonly args?: Endpoint14_1Request["payload"]["args"]
+ readonly cwd?: Endpoint14_1Request["payload"]["cwd"]
+ readonly title?: Endpoint14_1Request["payload"]["title"]
+ readonly env?: Endpoint14_1Request["payload"]["env"]
+}
+const Endpoint14_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint14_1Input) =>
+ raw["pty.create"]({
+ query: { location: input?.["location"] },
+ payload: {
+ command: input?.["command"],
+ args: input?.["args"],
+ cwd: input?.["cwd"],
+ title: input?.["title"],
+ env: input?.["env"],
+ },
+ }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint14_2Request = Parameters[0]
+type Endpoint14_2Input = {
+ readonly ptyID: Endpoint14_2Request["params"]["ptyID"]
+ readonly location?: Endpoint14_2Request["query"]["location"]
+}
+const Endpoint14_2 = (raw: RawClient["server.pty"]) => (input: Endpoint14_2Input) =>
+ raw["pty.get"]({ params: { ptyID: input["ptyID"] }, query: { location: input["location"] } }).pipe(
+ Effect.mapError(mapClientError),
+ )
+
+type Endpoint14_3Request = Parameters[0]
+type Endpoint14_3Input = {
+ readonly ptyID: Endpoint14_3Request["params"]["ptyID"]
+ readonly location?: Endpoint14_3Request["query"]["location"]
+ readonly title?: Endpoint14_3Request["payload"]["title"]
+ readonly size?: Endpoint14_3Request["payload"]["size"]
+}
+const Endpoint14_3 = (raw: RawClient["server.pty"]) => (input: Endpoint14_3Input) =>
+ raw["pty.update"]({
+ params: { ptyID: input["ptyID"] },
+ query: { location: input["location"] },
+ payload: { title: input["title"], size: input["size"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint14_4Request = Parameters[0]
+type Endpoint14_4Input = {
+ readonly ptyID: Endpoint14_4Request["params"]["ptyID"]
+ readonly location?: Endpoint14_4Request["query"]["location"]
+}
+const Endpoint14_4 = (raw: RawClient["server.pty"]) => (input: Endpoint14_4Input) =>
+ raw["pty.remove"]({ params: { ptyID: input["ptyID"] }, query: { location: input["location"] } }).pipe(
+ Effect.mapError(mapClientError),
+ )
+
+const adaptGroup14 = (raw: RawClient["server.pty"]) => ({
+ list: Endpoint14_0(raw),
+ create: Endpoint14_1(raw),
+ get: Endpoint14_2(raw),
+ update: Endpoint14_3(raw),
+ remove: Endpoint14_4(raw),
+})
+
+type Endpoint15_0Request = Parameters[0]
+type Endpoint15_0Input = { readonly location?: Endpoint15_0Request["query"]["location"] }
+const Endpoint15_0 = (raw: RawClient["server.question"]) => (input?: Endpoint15_0Input) =>
+ raw["question.request.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint15_1Request = Parameters[0]
+type Endpoint15_1Input = { readonly sessionID: Endpoint15_1Request["params"]["sessionID"] }
+const Endpoint15_1 = (raw: RawClient["server.question"]) => (input: Endpoint15_1Input) =>
+ raw["session.question.list"]({ params: { sessionID: input["sessionID"] } }).pipe(
+ Effect.mapError(mapClientError),
+ Effect.map((value) => value.data),
+ )
+
+type Endpoint15_2Request = Parameters[0]
+type Endpoint15_2Input = {
+ readonly sessionID: Endpoint15_2Request["params"]["sessionID"]
+ readonly requestID: Endpoint15_2Request["params"]["requestID"]
+ readonly answers: Endpoint15_2Request["payload"]["answers"]
+}
+const Endpoint15_2 = (raw: RawClient["server.question"]) => (input: Endpoint15_2Input) =>
+ raw["session.question.reply"]({
+ params: { sessionID: input["sessionID"], requestID: input["requestID"] },
+ payload: { answers: input["answers"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint15_3Request = Parameters[0]
+type Endpoint15_3Input = {
+ readonly sessionID: Endpoint15_3Request["params"]["sessionID"]
+ readonly requestID: Endpoint15_3Request["params"]["requestID"]
+}
+const Endpoint15_3 = (raw: RawClient["server.question"]) => (input: Endpoint15_3Input) =>
+ raw["session.question.reject"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] } }).pipe(
+ Effect.mapError(mapClientError),
+ )
+
+const adaptGroup15 = (raw: RawClient["server.question"]) => ({
+ listRequests: Endpoint15_0(raw),
+ list: Endpoint15_1(raw),
+ reply: Endpoint15_2(raw),
+ reject: Endpoint15_3(raw),
+})
+
+type Endpoint16_0Request = Parameters[0]
+type Endpoint16_0Input = { readonly location?: Endpoint16_0Request["query"]["location"] }
+const Endpoint16_0 = (raw: RawClient["server.reference"]) => (input?: Endpoint16_0Input) =>
+ raw["reference.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
+
+const adaptGroup16 = (raw: RawClient["server.reference"]) => ({ list: Endpoint16_0(raw) })
+
+type Endpoint17_0Request = Parameters[0]
+type Endpoint17_0Input = {
+ readonly projectID: Endpoint17_0Request["params"]["projectID"]
+ readonly location?: Endpoint17_0Request["query"]["location"]
+ readonly strategy: Endpoint17_0Request["payload"]["strategy"]
+ readonly directory: Endpoint17_0Request["payload"]["directory"]
+ readonly name?: Endpoint17_0Request["payload"]["name"]
+}
+const Endpoint17_0 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint17_0Input) =>
+ raw["projectCopy.create"]({
+ params: { projectID: input["projectID"] },
+ query: { location: input["location"] },
+ payload: { strategy: input["strategy"], directory: input["directory"], name: input["name"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint17_1Request = Parameters[0]
+type Endpoint17_1Input = {
+ readonly projectID: Endpoint17_1Request["params"]["projectID"]
+ readonly location?: Endpoint17_1Request["query"]["location"]
+ readonly directory: Endpoint17_1Request["payload"]["directory"]
+ readonly force: Endpoint17_1Request["payload"]["force"]
+}
+const Endpoint17_1 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint17_1Input) =>
+ raw["projectCopy.remove"]({
+ params: { projectID: input["projectID"] },
+ query: { location: input["location"] },
+ payload: { directory: input["directory"], force: input["force"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+type Endpoint17_2Request = Parameters[0]
+type Endpoint17_2Input = {
+ readonly projectID: Endpoint17_2Request["params"]["projectID"]
+ readonly location?: Endpoint17_2Request["query"]["location"]
+}
+const Endpoint17_2 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint17_2Input) =>
+ raw["projectCopy.refresh"]({
+ params: { projectID: input["projectID"] },
+ query: { location: input["location"] },
+ }).pipe(Effect.mapError(mapClientError))
+
+const adaptGroup17 = (raw: RawClient["server.projectCopy"]) => ({
+ create: Endpoint17_0(raw),
+ remove: Endpoint17_1(raw),
+ refresh: Endpoint17_2(raw),
+})
+
+const adaptClient = (raw: RawClient) => ({
+ health: adaptGroup0(raw["server.health"]),
+ location: adaptGroup1(raw["server.location"]),
+ agents: adaptGroup2(raw["server.agent"]),
+ sessions: adaptGroup3(raw["server.session"]),
+ messages: adaptGroup4(raw["server.message"]),
+ models: adaptGroup5(raw["server.model"]),
+ providers: adaptGroup6(raw["server.provider"]),
+ integrations: adaptGroup7(raw["server.integration"]),
+ credentials: adaptGroup8(raw["server.credential"]),
+ permissions: adaptGroup9(raw["server.permission"]),
+ files: adaptGroup10(raw["server.fs"]),
+ commands: adaptGroup11(raw["server.command"]),
+ skills: adaptGroup12(raw["server.skill"]),
+ events: adaptGroup13(raw["server.event"]),
+ ptys: adaptGroup14(raw["server.pty"]),
+ questions: adaptGroup15(raw["server.question"]),
+ references: adaptGroup16(raw["server.reference"]),
+ projectCopies: adaptGroup17(raw["server.projectCopy"]),
+})
export const make = (options?: { readonly baseUrl?: URL | string }) =>
- HttpApiClient.make(Api, options).pipe(Effect.map(adaptClient))
+ HttpApiClient.make(ClientApi, options).pipe(Effect.map(adaptClient))
diff --git a/packages/client/src/generated/client.ts b/packages/client/src/generated/client.ts
index 2d3cd92ee0..c2e7b05259 100644
--- a/packages/client/src/generated/client.ts
+++ b/packages/client/src/generated/client.ts
@@ -1,4 +1,9 @@
import type {
+ HealthGetOutput,
+ LocationGetInput,
+ LocationGetOutput,
+ AgentsListInput,
+ AgentsListOutput,
SessionsListInput,
SessionsListOutput,
SessionsCreateInput,
@@ -6,10 +11,14 @@ import type {
SessionsActiveOutput,
SessionsGetInput,
SessionsGetOutput,
+ SessionsForkInput,
+ SessionsForkOutput,
SessionsSwitchAgentInput,
SessionsSwitchAgentOutput,
SessionsSwitchModelInput,
SessionsSwitchModelOutput,
+ SessionsRenameInput,
+ SessionsRenameOutput,
SessionsPromptInput,
SessionsPromptOutput,
SessionsCompactInput,
@@ -24,12 +33,89 @@ import type {
SessionsCommitOutput,
SessionsContextInput,
SessionsContextOutput,
+ SessionsHistoryInput,
+ SessionsHistoryOutput,
SessionsEventsInput,
SessionsEventsOutput,
SessionsInterruptInput,
SessionsInterruptOutput,
SessionsMessageInput,
SessionsMessageOutput,
+ MessagesListInput,
+ MessagesListOutput,
+ ModelsListInput,
+ ModelsListOutput,
+ ProvidersListInput,
+ ProvidersListOutput,
+ ProvidersGetInput,
+ ProvidersGetOutput,
+ IntegrationsListInput,
+ IntegrationsListOutput,
+ IntegrationsGetInput,
+ IntegrationsGetOutput,
+ IntegrationsConnectKeyInput,
+ IntegrationsConnectKeyOutput,
+ IntegrationsConnectOauthInput,
+ IntegrationsConnectOauthOutput,
+ IntegrationsAttemptStatusInput,
+ IntegrationsAttemptStatusOutput,
+ IntegrationsAttemptCompleteInput,
+ IntegrationsAttemptCompleteOutput,
+ IntegrationsAttemptCancelInput,
+ IntegrationsAttemptCancelOutput,
+ CredentialsUpdateInput,
+ CredentialsUpdateOutput,
+ CredentialsRemoveInput,
+ CredentialsRemoveOutput,
+ PermissionsListRequestsInput,
+ PermissionsListRequestsOutput,
+ PermissionsListSavedInput,
+ PermissionsListSavedOutput,
+ PermissionsRemoveSavedInput,
+ PermissionsRemoveSavedOutput,
+ PermissionsCreateInput,
+ PermissionsCreateOutput,
+ PermissionsListInput,
+ PermissionsListOutput,
+ PermissionsGetInput,
+ PermissionsGetOutput,
+ PermissionsReplyInput,
+ PermissionsReplyOutput,
+ FilesListInput,
+ FilesListOutput,
+ FilesFindInput,
+ FilesFindOutput,
+ CommandsListInput,
+ CommandsListOutput,
+ SkillsListInput,
+ SkillsListOutput,
+ EventsSubscribeOutput,
+ PtysListInput,
+ PtysListOutput,
+ PtysCreateInput,
+ PtysCreateOutput,
+ PtysGetInput,
+ PtysGetOutput,
+ PtysUpdateInput,
+ PtysUpdateOutput,
+ PtysRemoveInput,
+ PtysRemoveOutput,
+ QuestionsListRequestsInput,
+ QuestionsListRequestsOutput,
+ QuestionsListInput,
+ QuestionsListOutput,
+ QuestionsReplyInput,
+ QuestionsReplyOutput,
+ QuestionsRejectInput,
+ QuestionsRejectOutput,
+ ReferencesListInput,
+ ReferencesListOutput,
+ ProjectCopiesCreateInput,
+ ProjectCopiesCreateOutput,
+ ProjectCopiesRemoveInput,
+ ProjectCopiesRemoveOutput,
+ ProjectCopiesRefreshInput,
+ ProjectCopiesRefreshOutput,
} from "./types"
import { ClientError } from "./client-error"
@@ -165,6 +251,41 @@ export function make(options: ClientOptions) {
})
return {
+ health: {
+ get: (requestOptions?: RequestOptions) =>
+ request(
+ { method: "GET", path: `/api/health`, successStatus: 200, declaredStatuses: [401, 400], empty: false },
+ requestOptions,
+ ),
+ },
+ location: {
+ get: (input?: LocationGetInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/location`,
+ query: { location: input?.["location"] },
+ successStatus: 200,
+ declaredStatuses: [401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ },
+ agents: {
+ list: (input?: AgentsListInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/agent`,
+ query: { location: input?.["location"] },
+ successStatus: 200,
+ declaredStatuses: [401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ },
sessions: {
list: (input?: SessionsListInput, requestOptions?: RequestOptions) =>
request(
@@ -172,14 +293,14 @@ export function make(options: ClientOptions) {
method: "GET",
path: `/api/session`,
query: {
- workspace: input?.workspace,
- limit: input?.limit,
- order: input?.order,
- search: input?.search,
- directory: input?.directory,
- project: input?.project,
- subpath: input?.subpath,
- cursor: input?.cursor,
+ workspace: input?.["workspace"],
+ limit: input?.["limit"],
+ order: input?.["order"],
+ search: input?.["search"],
+ directory: input?.["directory"],
+ project: input?.["project"],
+ subpath: input?.["subpath"],
+ cursor: input?.["cursor"],
},
successStatus: 200,
declaredStatuses: [400, 401],
@@ -192,7 +313,12 @@ export function make(options: ClientOptions) {
{
method: "POST",
path: `/api/session`,
- body: { id: input?.id, agent: input?.agent, model: input?.model, location: input?.location },
+ body: {
+ id: input?.["id"],
+ agent: input?.["agent"],
+ model: input?.["model"],
+ location: input?.["location"],
+ },
successStatus: 200,
declaredStatuses: [401, 400],
empty: false,
@@ -221,12 +347,24 @@ export function make(options: ClientOptions) {
},
requestOptions,
).then((value) => value.data),
+ fork: (input: SessionsForkInput, requestOptions?: RequestOptions) =>
+ request<{ readonly data: SessionsForkOutput }>(
+ {
+ method: "POST",
+ path: `/api/session/${encodeURIComponent(input.sessionID)}/fork`,
+ body: { messageID: input["messageID"] },
+ successStatus: 200,
+ declaredStatuses: [404, 400, 401],
+ empty: false,
+ },
+ requestOptions,
+ ).then((value) => value.data),
switchAgent: (input: SessionsSwitchAgentInput, requestOptions?: RequestOptions) =>
request(
{
method: "POST",
path: `/api/session/${encodeURIComponent(input.sessionID)}/agent`,
- body: { agent: input.agent },
+ body: { agent: input["agent"] },
successStatus: 204,
declaredStatuses: [404, 400, 401],
empty: true,
@@ -238,7 +376,19 @@ export function make(options: ClientOptions) {
{
method: "POST",
path: `/api/session/${encodeURIComponent(input.sessionID)}/model`,
- body: { model: input.model },
+ body: { model: input["model"] },
+ successStatus: 204,
+ declaredStatuses: [404, 400, 401],
+ empty: true,
+ },
+ requestOptions,
+ ),
+ rename: (input: SessionsRenameInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "POST",
+ path: `/api/session/${encodeURIComponent(input.sessionID)}/rename`,
+ body: { title: input["title"] },
successStatus: 204,
declaredStatuses: [404, 400, 401],
empty: true,
@@ -250,7 +400,7 @@ export function make(options: ClientOptions) {
{
method: "POST",
path: `/api/session/${encodeURIComponent(input.sessionID)}/prompt`,
- body: { id: input.id, prompt: input.prompt, delivery: input.delivery, resume: input.resume },
+ body: { id: input["id"], prompt: input["prompt"], delivery: input["delivery"], resume: input["resume"] },
successStatus: 200,
declaredStatuses: [409, 404, 400, 401],
empty: false,
@@ -284,9 +434,9 @@ export function make(options: ClientOptions) {
{
method: "POST",
path: `/api/session/${encodeURIComponent(input.sessionID)}/revert/stage`,
- body: { messageID: input.messageID, files: input.files },
+ body: { messageID: input["messageID"], files: input["files"] },
successStatus: 200,
- declaredStatuses: [404, 500, 400, 401],
+ declaredStatuses: [404, 409, 500, 400, 401],
empty: false,
},
requestOptions,
@@ -297,7 +447,7 @@ export function make(options: ClientOptions) {
method: "POST",
path: `/api/session/${encodeURIComponent(input.sessionID)}/revert/clear`,
successStatus: 204,
- declaredStatuses: [404, 500, 400, 401],
+ declaredStatuses: [404, 409, 500, 400, 401],
empty: true,
},
requestOptions,
@@ -308,7 +458,7 @@ export function make(options: ClientOptions) {
method: "POST",
path: `/api/session/${encodeURIComponent(input.sessionID)}/revert/commit`,
successStatus: 204,
- declaredStatuses: [404, 400, 401],
+ declaredStatuses: [404, 409, 400, 401],
empty: true,
},
requestOptions,
@@ -324,12 +474,24 @@ export function make(options: ClientOptions) {
},
requestOptions,
).then((value) => value.data),
+ history: (input: SessionsHistoryInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/session/${encodeURIComponent(input.sessionID)}/history`,
+ query: { limit: input["limit"], after: input["after"] },
+ successStatus: 200,
+ declaredStatuses: [404, 400, 401],
+ empty: false,
+ },
+ requestOptions,
+ ),
events: (input: SessionsEventsInput, requestOptions?: RequestOptions): AsyncIterable =>
sse(
{
method: "GET",
path: `/api/session/${encodeURIComponent(input.sessionID)}/event`,
- query: { after: input.after },
+ query: { after: input["after"] },
successStatus: 200,
declaredStatuses: [404, 400, 401],
empty: false,
@@ -359,6 +521,500 @@ export function make(options: ClientOptions) {
requestOptions,
).then((value) => value.data),
},
+ messages: {
+ list: (input: MessagesListInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/session/${encodeURIComponent(input.sessionID)}/message`,
+ query: { limit: input["limit"], order: input["order"], cursor: input["cursor"] },
+ successStatus: 200,
+ declaredStatuses: [400, 404, 500, 401],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ },
+ models: {
+ list: (input?: ModelsListInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/model`,
+ query: { location: input?.["location"] },
+ successStatus: 200,
+ declaredStatuses: [503, 401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ },
+ providers: {
+ list: (input?: ProvidersListInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/provider`,
+ query: { location: input?.["location"] },
+ successStatus: 200,
+ declaredStatuses: [503, 401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ get: (input: ProvidersGetInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/provider/${encodeURIComponent(input.providerID)}`,
+ query: { location: input["location"] },
+ successStatus: 200,
+ declaredStatuses: [404, 503, 401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ },
+ integrations: {
+ list: (input?: IntegrationsListInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/integration`,
+ query: { location: input?.["location"] },
+ successStatus: 200,
+ declaredStatuses: [401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ get: (input: IntegrationsGetInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/integration/${encodeURIComponent(input.integrationID)}`,
+ query: { location: input["location"] },
+ successStatus: 200,
+ declaredStatuses: [401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ connectKey: (input: IntegrationsConnectKeyInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "POST",
+ path: `/api/integration/${encodeURIComponent(input.integrationID)}/connect/key`,
+ query: { location: input["location"] },
+ body: { key: input["key"], label: input["label"] },
+ successStatus: 204,
+ declaredStatuses: [400, 401],
+ empty: true,
+ },
+ requestOptions,
+ ),
+ connectOauth: (input: IntegrationsConnectOauthInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "POST",
+ path: `/api/integration/${encodeURIComponent(input.integrationID)}/connect/oauth`,
+ query: { location: input["location"] },
+ body: { methodID: input["methodID"], inputs: input["inputs"], label: input["label"] },
+ successStatus: 200,
+ declaredStatuses: [400, 401],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ attemptStatus: (input: IntegrationsAttemptStatusInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/integration/attempt/${encodeURIComponent(input.attemptID)}`,
+ query: { location: input["location"] },
+ successStatus: 200,
+ declaredStatuses: [401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ attemptComplete: (input: IntegrationsAttemptCompleteInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "POST",
+ path: `/api/integration/attempt/${encodeURIComponent(input.attemptID)}/complete`,
+ query: { location: input["location"] },
+ body: { code: input["code"] },
+ successStatus: 204,
+ declaredStatuses: [400, 401],
+ empty: true,
+ },
+ requestOptions,
+ ),
+ attemptCancel: (input: IntegrationsAttemptCancelInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "DELETE",
+ path: `/api/integration/attempt/${encodeURIComponent(input.attemptID)}`,
+ query: { location: input["location"] },
+ successStatus: 204,
+ declaredStatuses: [401, 400],
+ empty: true,
+ },
+ requestOptions,
+ ),
+ },
+ credentials: {
+ update: (input: CredentialsUpdateInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "PATCH",
+ path: `/api/credential/${encodeURIComponent(input.credentialID)}`,
+ query: { location: input["location"] },
+ body: { label: input["label"] },
+ successStatus: 204,
+ declaredStatuses: [401, 400],
+ empty: true,
+ },
+ requestOptions,
+ ),
+ remove: (input: CredentialsRemoveInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "DELETE",
+ path: `/api/credential/${encodeURIComponent(input.credentialID)}`,
+ query: { location: input["location"] },
+ successStatus: 204,
+ declaredStatuses: [401, 400],
+ empty: true,
+ },
+ requestOptions,
+ ),
+ },
+ permissions: {
+ listRequests: (input?: PermissionsListRequestsInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/permission/request`,
+ query: { location: input?.["location"] },
+ successStatus: 200,
+ declaredStatuses: [401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ listSaved: (input?: PermissionsListSavedInput, requestOptions?: RequestOptions) =>
+ request<{ readonly data: PermissionsListSavedOutput }>(
+ {
+ method: "GET",
+ path: `/api/permission/saved`,
+ query: { projectID: input?.["projectID"] },
+ successStatus: 200,
+ declaredStatuses: [401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ).then((value) => value.data),
+ removeSaved: (input: PermissionsRemoveSavedInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "DELETE",
+ path: `/api/permission/saved/${encodeURIComponent(input.id)}`,
+ successStatus: 204,
+ declaredStatuses: [401, 400],
+ empty: true,
+ },
+ requestOptions,
+ ),
+ create: (input: PermissionsCreateInput, requestOptions?: RequestOptions) =>
+ request<{ readonly data: PermissionsCreateOutput }>(
+ {
+ method: "POST",
+ path: `/api/session/${encodeURIComponent(input.sessionID)}/permission`,
+ body: {
+ id: input["id"],
+ action: input["action"],
+ resources: input["resources"],
+ save: input["save"],
+ metadata: input["metadata"],
+ source: input["source"],
+ agent: input["agent"],
+ },
+ successStatus: 200,
+ declaredStatuses: [404, 400, 401],
+ empty: false,
+ },
+ requestOptions,
+ ).then((value) => value.data),
+ list: (input: PermissionsListInput, requestOptions?: RequestOptions) =>
+ request<{ readonly data: PermissionsListOutput }>(
+ {
+ method: "GET",
+ path: `/api/session/${encodeURIComponent(input.sessionID)}/permission`,
+ successStatus: 200,
+ declaredStatuses: [404, 400, 401],
+ empty: false,
+ },
+ requestOptions,
+ ).then((value) => value.data),
+ get: (input: PermissionsGetInput, requestOptions?: RequestOptions) =>
+ request<{ readonly data: PermissionsGetOutput }>(
+ {
+ method: "GET",
+ path: `/api/session/${encodeURIComponent(input.sessionID)}/permission/${encodeURIComponent(input.requestID)}`,
+ successStatus: 200,
+ declaredStatuses: [404, 400, 401],
+ empty: false,
+ },
+ requestOptions,
+ ).then((value) => value.data),
+ reply: (input: PermissionsReplyInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "POST",
+ path: `/api/session/${encodeURIComponent(input.sessionID)}/permission/${encodeURIComponent(input.requestID)}/reply`,
+ body: { reply: input["reply"], message: input["message"] },
+ successStatus: 204,
+ declaredStatuses: [404, 400, 401],
+ empty: true,
+ },
+ requestOptions,
+ ),
+ },
+ files: {
+ list: (input?: FilesListInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/fs/list`,
+ query: { location: input?.["location"], path: input?.["path"] },
+ successStatus: 200,
+ declaredStatuses: [401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ find: (input: FilesFindInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/fs/find`,
+ query: { location: input["location"], query: input["query"], type: input["type"], limit: input["limit"] },
+ successStatus: 200,
+ declaredStatuses: [401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ },
+ commands: {
+ list: (input?: CommandsListInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/command`,
+ query: { location: input?.["location"] },
+ successStatus: 200,
+ declaredStatuses: [401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ },
+ skills: {
+ list: (input?: SkillsListInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/skill`,
+ query: { location: input?.["location"] },
+ successStatus: 200,
+ declaredStatuses: [401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ },
+ events: {
+ subscribe: (requestOptions?: RequestOptions): AsyncIterable =>
+ sse(
+ { method: "GET", path: `/api/event`, successStatus: 200, declaredStatuses: [401, 400], empty: false },
+ requestOptions,
+ ),
+ },
+ ptys: {
+ list: (input?: PtysListInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/pty`,
+ query: { location: input?.["location"] },
+ successStatus: 200,
+ declaredStatuses: [401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ create: (input?: PtysCreateInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "POST",
+ path: `/api/pty`,
+ query: { location: input?.["location"] },
+ body: {
+ command: input?.["command"],
+ args: input?.["args"],
+ cwd: input?.["cwd"],
+ title: input?.["title"],
+ env: input?.["env"],
+ },
+ successStatus: 200,
+ declaredStatuses: [401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ get: (input: PtysGetInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "GET",
+ path: `/api/pty/${encodeURIComponent(input.ptyID)}`,
+ query: { location: input["location"] },
+ successStatus: 200,
+ declaredStatuses: [404, 401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ update: (input: PtysUpdateInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "PUT",
+ path: `/api/pty/${encodeURIComponent(input.ptyID)}`,
+ query: { location: input["location"] },
+ body: { title: input["title"], size: input["size"] },
+ successStatus: 200,
+ declaredStatuses: [404, 401, 400],
+ empty: false,
+ },
+ requestOptions,
+ ),
+ remove: (input: PtysRemoveInput, requestOptions?: RequestOptions) =>
+ request(
+ {
+ method: "DELETE",
+ path: `/api/pty/${encodeURIComponent(input.ptyID)}`,
+ query: { location: input["location"] },
+ successStatus: 204,
+ declaredStatuses: [404, 401, 400],
+ empty: true,
+ },
+ requestOptions,
+ ),
+ },
+ questions: {
+ listRequests: (input?: QuestionsListRequestsInput, requestOptions?: RequestOptions) =>
+ request