From e950ad5306944fe1897949dee9573526206a6860 Mon Sep 17 00:00:00 2001 From: Jeremy Osih Date: Fri, 27 Jun 2025 00:38:14 +0200 Subject: feat(web): add scroll to last message button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add intelligent floating scroll button for long conversations that: - Only appears when scrolling down (direction-aware) - Auto-hides after 3 seconds of inactivity - Stays visible on hover to prevent accidental disappearance - Uses consistent design patterns with repo styling - Includes proper accessibility features 🤖 Generated with [opencode](https://opencode.ai) Co-Authored-By: Jeremy Osih Co-Authored-By: opencode --- packages/web/src/components/Share.tsx | 94 ++++++++++++++++++++++++++++ packages/web/src/components/share.module.css | 35 +++++++++++ 2 files changed, 129 insertions(+) (limited to 'packages') diff --git a/packages/web/src/components/Share.tsx b/packages/web/src/components/Share.tsx index 07b12946b..5510f5a69 100644 --- a/packages/web/src/components/Share.tsx +++ b/packages/web/src/components/Share.tsx @@ -40,6 +40,7 @@ import { IconMagnifyingGlass, IconWrenchScrewdriver, IconDocumentMagnifyingGlass, + IconArrowDown, } from "./icons" import DiffView from "./DiffView" import CodeBlock from "./CodeBlock" @@ -721,6 +722,83 @@ export default function Share(props: { }) }) + const [showScrollButton, setShowScrollButton] = createSignal(false) + const [isButtonHovered, setIsButtonHovered] = createSignal(false) + let scrollTimeout: number | undefined + let lastScrollY = 0 + + const checkScrollNeed = () => { + const currentScrollY = window.scrollY + const isScrollingDown = currentScrollY > lastScrollY + const scrolled = currentScrollY > 200 // Show after scrolling 200px + const isNearBottom = window.innerHeight + currentScrollY >= document.body.scrollHeight - 100 + + // Only show when scrolling down, scrolled enough, and not near bottom + const shouldShow = isScrollingDown && scrolled && !isNearBottom + + // Update last scroll position + lastScrollY = currentScrollY + + if (shouldShow) { + setShowScrollButton(true) + // Clear existing timeout + if (scrollTimeout) { + clearTimeout(scrollTimeout) + } + // Hide button after 3 seconds of no scrolling (unless hovered) + scrollTimeout = window.setTimeout(() => { + if (!isButtonHovered()) { + setShowScrollButton(false) + } + }, 3000) + } else if (!isButtonHovered()) { + // Only hide if not hovered (to prevent disappearing while user is about to click) + setShowScrollButton(false) + if (scrollTimeout) { + clearTimeout(scrollTimeout) + } + } + } + + const handleButtonMouseEnter = () => { + setIsButtonHovered(true) + // Clear timeout when hovering + if (scrollTimeout) { + clearTimeout(scrollTimeout) + } + } + + const handleButtonMouseLeave = () => { + setIsButtonHovered(false) + // Restart timeout when leaving hover + if (showScrollButton()) { + scrollTimeout = window.setTimeout(() => { + if (!isButtonHovered()) { + setShowScrollButton(false) + } + }, 3000) + } + } + + const scrollToBottom = () => { + document.body.scrollIntoView({ behavior: "smooth", block: "end" }) + } + + onMount(() => { + lastScrollY = window.scrollY // Initialize scroll position + checkScrollNeed() + window.addEventListener("scroll", checkScrollNeed) + window.addEventListener("resize", checkScrollNeed) + }) + + onCleanup(() => { + window.removeEventListener("scroll", checkScrollNeed) + window.removeEventListener("resize", checkScrollNeed) + if (scrollTimeout) { + clearTimeout(scrollTimeout) + } + }) + const data = createMemo(() => { const result = { rootDir: undefined as string | undefined, @@ -875,6 +953,7 @@ export default function Share(props: { )} + @@ -1975,6 +2054,21 @@ export default function Share(props: { + + {/* Floating scroll to bottom button */} + + + ) } diff --git a/packages/web/src/components/share.module.css b/packages/web/src/components/share.module.css index 53f082c9b..a52fd1765 100644 --- a/packages/web/src/components/share.module.css +++ b/packages/web/src/components/share.module.css @@ -760,3 +760,38 @@ } } } + +.scrollButton { + position: fixed; + bottom: 2rem; + right: 2rem; + width: 2.5rem; + height: 2.5rem; + border-radius: 0.25rem; + border: 1px solid var(--sl-color-divider); + background-color: var(--sl-color-bg-surface); + color: var(--sl-color-text-secondary); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + transition: all 0.15s ease, opacity 0.5s ease; + z-index: 100; + appearance: none; + opacity: 1; + + &:hover { + color: var(--sl-color-text); + border-color: var(--sl-color-hairline); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + } + + &:active { + transform: translateY(1px); + } + + svg { + display: block; + } +} -- cgit v1.2.3 From 065f0aaddf6612aa30e6977aeb9afa2e3a774c56 Mon Sep 17 00:00:00 2001 From: Jay V Date: Thu, 26 Jun 2025 19:02:42 -0400 Subject: docs: tweak lander --- packages/web/src/components/Lander.astro | 67 ++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 20 deletions(-) (limited to 'packages') diff --git a/packages/web/src/components/Lander.astro b/packages/web/src/components/Lander.astro index ae1b2a5e9..8d4d4efed 100644 --- a/packages/web/src/components/Lander.astro +++ b/packages/web/src/components/Lander.astro @@ -19,8 +19,10 @@ const imageAttrs = { const github = config.social.filter(s => s.icon === 'github')[0]; -const command = "npm i -g"; -const pkg = "opencode-ai"; +const command = "curl -fsSL" +const protocol = "https://" +const url = "opencode.ai/install" +const bash = "| bash" let darkImage: ImageMetadata | undefined; let lightImage: ImageMetadata | undefined; @@ -51,11 +53,14 @@ if (image) {
-
@@ -133,39 +138,43 @@ section.top { section.cta { display: flex; flex-direction: row; - justify-content: space-between; + justify-content: flex-start; + align-items: stretch; border-top: 2px solid var(--sl-color-border); - @media (max-width: 40rem) { + @media (max-width: 50rem) { flex-direction: column; + + & > div.col1 { order: 1; } + & > div.col3 { order: 2; } + & > div.col2 { order: 3; } } & > div { - flex: 1; line-height: 1.4; - padding: calc(var(--padding) / 2) 0.5rem; - - @media (max-width: 40rem) { - padding-bottom: calc(var(--padding) / 2 + 4px); - } + padding: calc(var(--padding) / 2) 1rem; a { font-size: 1rem; } } - & > div.col2 { + & > div.col1, & > div.col3 { + flex: 1 1 auto; + text-align: center; + text-transform: uppercase; + @media (max-width: 50rem) { - flex: 0 0 auto; + padding-bottom: calc(var(--padding) / 2 + 4px); } } - & > div:not(.col2) { - text-align: center; - text-transform: uppercase; + & > div.col2 { + flex: 0 0 auto; } & > div + div { border-left: 2px solid var(--sl-color-border); - @media (max-width: 40rem) { + + @media (max-width: 50rem) { border-left: none; border-top: 2px solid var(--sl-color-border); } @@ -183,6 +192,21 @@ section.cta { code { color: var(--sl-color-text-secondary); font-size: 1.125rem; + + @media (max-width: 24rem) { + font-size: 0.875rem; + } + @media (max-width: 30rem) { + span.protocol { + display: none; + } + } + @media (max-width: 43rem) { + text-align: center; + span:first-child { + display: block; + } + } } code .highlight { color: var(--sl-color-text); @@ -192,6 +216,9 @@ section.cta { .copy { line-height: 1; padding: 0; + @media (max-width: 43rem) { + display: none; + } } .copy svg { width: 1rem; -- cgit v1.2.3 From ebcf11e574d0ebb056248e84f495789e1b211437 Mon Sep 17 00:00:00 2001 From: Jay V Date: Thu, 26 Jun 2025 19:47:58 -0400 Subject: docs: lander tweak --- packages/web/src/components/Lander.astro | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'packages') diff --git a/packages/web/src/components/Lander.astro b/packages/web/src/components/Lander.astro index 8d4d4efed..82c33f3b3 100644 --- a/packages/web/src/components/Lander.astro +++ b/packages/web/src/components/Lander.astro @@ -58,8 +58,7 @@ if (image) {
) }} - {/* System text */} - - {(part) => ( -
-
- - - -
-
-
-
-
- System -
- -
-
-
- )} -
+ {/* Grep tool */} toolData()?.args.path !== data().rootDir ? stripWorkingDirectory( - toolData()?.args.path, - data().rootDir, - ) + toolData()?.args.path, + data().rootDir, + ) : toolData()?.args.path, ) @@ -1737,8 +1670,7 @@ export default function Share(props: { when={ msg.role === "assistant" && part.type === "tool-invocation" && - part.toolInvocation.toolName === - "todowrite" && + part.toolInvocation.toolName === "todowrite" && part } > @@ -1803,8 +1735,7 @@ export default function Share(props: { when={ msg.role === "assistant" && part.type === "tool-invocation" && - part.toolInvocation.toolName === - "webfetch" && + part.toolInvocation.toolName === "webfetch" && part } > @@ -1978,9 +1909,7 @@ export default function Share(props: { > - - - + -- cgit v1.2.3 From 9e2bb6368877fd3f04f970aa8b7944b4abd4aa4d Mon Sep 17 00:00:00 2001 From: Ryan Winchester Date: Fri, 27 Jun 2025 11:15:11 -0300 Subject: feat: add elixir file formatting (#458) --- packages/opencode/src/format/index.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'packages') diff --git a/packages/opencode/src/format/index.ts b/packages/opencode/src/format/index.ts index 9142750b0..750177498 100644 --- a/packages/opencode/src/format/index.ts +++ b/packages/opencode/src/format/index.ts @@ -132,5 +132,32 @@ export namespace Format { } }, }, + { + name: "mix format", + command: ["mix", "format", "$FILE"], + extensions: [ + ".ex", + ".exs", + ".eex", + ".heex", + ".leex", + ".neex", + ".sface", + ], + async enabled() { + try { + const proc = Bun.spawn({ + cmd: ["mix", "--version"], + cwd: App.info().path.cwd, + stdout: "ignore", + stderr: "ignore", + }) + const exit = await proc.exited + return exit === 0 + } catch { + return false + } + }, + }, ] } -- cgit v1.2.3 From d972c27f03c0cc6177a02ec2a7458f27ecc56b93 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 27 Jun 2025 11:29:20 -0400 Subject: lazy load formatters --- package.json | 6 +- packages/opencode/src/app/app.ts | 46 +++---- packages/opencode/src/bus/index.ts | 6 +- packages/opencode/src/cli/bootstrap.ts | 17 +++ packages/opencode/src/cli/cmd/run.ts | 190 ++++++++++++-------------- packages/opencode/src/cli/cmd/tui.ts | 108 +++++++++++++++ packages/opencode/src/config/config.ts | 1 + packages/opencode/src/config/hooks.ts | 54 ++++++++ packages/opencode/src/file/index.ts | 13 ++ packages/opencode/src/file/time.ts | 38 ++++++ packages/opencode/src/format/index.ts | 115 +++++++--------- packages/opencode/src/index.ts | 111 +-------------- packages/opencode/src/session/index.ts | 20 ++- packages/opencode/src/share/share.ts | 13 +- packages/opencode/src/tool/edit.ts | 17 ++- packages/opencode/src/tool/patch.ts | 6 +- packages/opencode/src/tool/read.ts | 4 +- packages/opencode/src/tool/util/file-times.ts | 38 ------ packages/opencode/src/tool/write.ts | 13 +- packages/opencode/src/util/project.ts | 91 ------------ 20 files changed, 440 insertions(+), 467 deletions(-) create mode 100644 packages/opencode/src/cli/bootstrap.ts create mode 100644 packages/opencode/src/cli/cmd/tui.ts create mode 100644 packages/opencode/src/config/hooks.ts create mode 100644 packages/opencode/src/file/index.ts create mode 100644 packages/opencode/src/file/time.ts delete mode 100644 packages/opencode/src/tool/util/file-times.ts delete mode 100644 packages/opencode/src/util/project.ts (limited to 'packages') diff --git a/package.json b/package.json index ed4fcdeda..91515be73 100644 --- a/package.json +++ b/package.json @@ -41,5 +41,9 @@ ], "patchedDependencies": { "ai@4.3.16": "patches/ai@4.3.16.patch" - } + }, + "randomField": "purple-elephant-42", + "mysteriousData": "cosmic-banana-7891", + "quirkyValue": "dancing-octopus-314", + "whimsicalEntry": "flying-penguin-2024" } diff --git a/packages/opencode/src/app/app.ts b/packages/opencode/src/app/app.ts index 44b6d9c75..9b26c05bc 100644 --- a/packages/opencode/src/app/app.ts +++ b/packages/opencode/src/app/app.ts @@ -2,7 +2,6 @@ import "zod-openapi/extend" import { Log } from "../util/log" import { Context } from "../util/context" import { Filesystem } from "../util/filesystem" -import { Project } from "../util/project" import { Global } from "../global" import path from "path" import os from "os" @@ -13,7 +12,6 @@ export namespace App { export const Info = z .object({ - project: z.string(), user: z.string(), hostname: z.string(), git: z.boolean(), @@ -33,11 +31,21 @@ export namespace App { }) export type Info = z.infer - const ctx = Context.create>>("app") + const ctx = Context.create<{ + info: Info + services: Map Promise }> + }>("app") const APP_JSON = "app.json" - async function create(input: { cwd: string }) { + export type Input = { + cwd: string + } + + export async function provide( + input: Input, + cb: (app: App.Info) => Promise, + ) { log.info("creating", { cwd: input.cwd, }) @@ -66,10 +74,8 @@ export namespace App { >() const root = git ?? input.cwd - const project = await Project.getName(root) const info: Info = { - project: project, user: os.userInfo().username, hostname: os.hostname(), time: { @@ -84,12 +90,20 @@ export namespace App { cwd: input.cwd, }, } - const result = { + const app = { services, info, } - return result + return ctx.provide(app, async () => { + const result = await cb(app.info) + for (const [key, entry] of app.services.entries()) { + if (!entry.shutdown) continue + log.info("shutdown", { name: key }) + await entry.shutdown?.(await entry.state) + } + return result + }) } export function state( @@ -115,22 +129,6 @@ export namespace App { return ctx.use().info } - export async function provide( - input: { cwd: string }, - cb: (app: Info) => Promise, - ) { - const app = await create(input) - return ctx.provide(app, async () => { - const result = await cb(app.info) - for (const [key, entry] of app.services.entries()) { - if (!entry.shutdown) continue - log.info("shutdown", { name: key }) - await entry.shutdown?.(await entry.state) - } - return result - }) - } - export async function initialize() { const { info } = ctx.use() info.time.initialized = Date.now() diff --git a/packages/opencode/src/bus/index.ts b/packages/opencode/src/bus/index.ts index 596e6c1c9..8461269a9 100644 --- a/packages/opencode/src/bus/index.ts +++ b/packages/opencode/src/bus/index.ts @@ -49,7 +49,7 @@ export namespace Bus { ) } - export function publish( + export async function publish( def: Definition, properties: z.output, ) { @@ -60,12 +60,14 @@ export namespace Bus { log.info("publishing", { type: def.type, }) + const pending = [] for (const key of [def.type, "*"]) { const match = state().subscriptions.get(key) for (const sub of match ?? []) { - sub(payload) + pending.push(sub(payload)) } } + return Promise.all(pending) } export function subscribe( diff --git a/packages/opencode/src/cli/bootstrap.ts b/packages/opencode/src/cli/bootstrap.ts new file mode 100644 index 000000000..66c8a7570 --- /dev/null +++ b/packages/opencode/src/cli/bootstrap.ts @@ -0,0 +1,17 @@ +import { App } from "../app/app" +import { ConfigHooks } from "../config/hooks" +import { Format } from "../format" +import { Share } from "../share/share" + +export async function bootstrap( + input: App.Input, + cb: (app: App.Info) => Promise, +) { + return App.provide(input, async (app) => { + Share.init() + Format.init() + ConfigHooks.init() + + return cb(app) + }) +} diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index f8f886868..1905aa173 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -1,14 +1,13 @@ import type { Argv } from "yargs" -import { App } from "../../app/app" import { Bus } from "../../bus" import { Provider } from "../../provider/provider" import { Session } from "../../session" -import { Share } from "../../share/share" import { Message } from "../../session/message" import { UI } from "../ui" import { cmd } from "./cmd" import { Flag } from "../../flag/flag" import { Config } from "../../config/config" +import { bootstrap } from "../bootstrap" const TOOL: Record = { todowrite: ["Todo", UI.Style.TEXT_WARNING_BOLD], @@ -56,118 +55,109 @@ export const RunCommand = cmd({ }, handler: async (args) => { const message = args.message.join(" ") - await App.provide( - { - cwd: process.cwd(), - }, - async () => { - await Share.init() - const session = await (async () => { - if (args.continue) { - const first = await Session.list().next() - if (first.done) return - return first.value - } - - if (args.session) return Session.get(args.session) + await bootstrap({ cwd: process.cwd() }, async () => { + const session = await (async () => { + if (args.continue) { + const first = await Session.list().next() + if (first.done) return + return first.value + } - return Session.create() - })() + if (args.session) return Session.get(args.session) - if (!session) { - UI.error("Session not found") - return - } + return Session.create() + })() - const isPiped = !process.stdout.isTTY + if (!session) { + UI.error("Session not found") + return + } - UI.empty() - UI.println(UI.logo()) - UI.empty() - UI.println(UI.Style.TEXT_NORMAL_BOLD + "> ", message) - UI.empty() + const isPiped = !process.stdout.isTTY - const cfg = await Config.get() - if (cfg.autoshare || Flag.OPENCODE_AUTO_SHARE || args.share) { - await Session.share(session.id) - UI.println( - UI.Style.TEXT_INFO_BOLD + - "~ https://opencode.ai/s/" + - session.id.slice(-8), - ) - } - UI.empty() + UI.empty() + UI.println(UI.logo()) + UI.empty() + UI.println(UI.Style.TEXT_NORMAL_BOLD + "> ", message) + UI.empty() - const { providerID, modelID } = args.model - ? Provider.parseModel(args.model) - : await Provider.defaultModel() + const cfg = await Config.get() + if (cfg.autoshare || Flag.OPENCODE_AUTO_SHARE || args.share) { + await Session.share(session.id) UI.println( - UI.Style.TEXT_NORMAL_BOLD + "@ ", - UI.Style.TEXT_NORMAL + `${providerID}/${modelID}`, + UI.Style.TEXT_INFO_BOLD + + "~ https://opencode.ai/s/" + + session.id.slice(-8), ) - UI.empty() + } + UI.empty() - function printEvent(color: string, type: string, title: string) { - UI.println( - color + `|`, - UI.Style.TEXT_NORMAL + - UI.Style.TEXT_DIM + - ` ${type.padEnd(7, " ")}`, - "", - UI.Style.TEXT_NORMAL + title, - ) - } + const { providerID, modelID } = args.model + ? Provider.parseModel(args.model) + : await Provider.defaultModel() + UI.println( + UI.Style.TEXT_NORMAL_BOLD + "@ ", + UI.Style.TEXT_NORMAL + `${providerID}/${modelID}`, + ) + UI.empty() + + function printEvent(color: string, type: string, title: string) { + UI.println( + color + `|`, + UI.Style.TEXT_NORMAL + UI.Style.TEXT_DIM + ` ${type.padEnd(7, " ")}`, + "", + UI.Style.TEXT_NORMAL + title, + ) + } - Bus.subscribe(Message.Event.PartUpdated, async (evt) => { - if (evt.properties.sessionID !== session.id) return - const part = evt.properties.part - const message = await Session.getMessage( - evt.properties.sessionID, - evt.properties.messageID, - ) + Bus.subscribe(Message.Event.PartUpdated, async (evt) => { + if (evt.properties.sessionID !== session.id) return + const part = evt.properties.part + const message = await Session.getMessage( + evt.properties.sessionID, + evt.properties.messageID, + ) - if ( - part.type === "tool-invocation" && - part.toolInvocation.state === "result" - ) { - const metadata = - message.metadata.tool[part.toolInvocation.toolCallId] - const [tool, color] = TOOL[part.toolInvocation.toolName] ?? [ - part.toolInvocation.toolName, - UI.Style.TEXT_INFO_BOLD, - ] - printEvent(color, tool, metadata?.title || "Unknown") - } + if ( + part.type === "tool-invocation" && + part.toolInvocation.state === "result" + ) { + const metadata = message.metadata.tool[part.toolInvocation.toolCallId] + const [tool, color] = TOOL[part.toolInvocation.toolName] ?? [ + part.toolInvocation.toolName, + UI.Style.TEXT_INFO_BOLD, + ] + printEvent(color, tool, metadata?.title || "Unknown") + } - if (part.type === "text") { - if (part.text.includes("\n")) { - UI.empty() - UI.println(part.text) - UI.empty() - return - } - printEvent(UI.Style.TEXT_NORMAL_BOLD, "Text", part.text) + if (part.type === "text") { + if (part.text.includes("\n")) { + UI.empty() + UI.println(part.text) + UI.empty() + return } - }) + printEvent(UI.Style.TEXT_NORMAL_BOLD, "Text", part.text) + } + }) - const result = await Session.chat({ - sessionID: session.id, - providerID, - modelID, - parts: [ - { - type: "text", - text: message, - }, - ], - }) + const result = await Session.chat({ + sessionID: session.id, + providerID, + modelID, + parts: [ + { + type: "text", + text: message, + }, + ], + }) - if (isPiped) { - const match = result.parts.findLast((x) => x.type === "text") - if (match) process.stdout.write(match.text) - } - UI.empty() - }, - ) + if (isPiped) { + const match = result.parts.findLast((x) => x.type === "text") + if (match) process.stdout.write(match.text) + } + UI.empty() + }) }, }) diff --git a/packages/opencode/src/cli/cmd/tui.ts b/packages/opencode/src/cli/cmd/tui.ts new file mode 100644 index 000000000..203cc2998 --- /dev/null +++ b/packages/opencode/src/cli/cmd/tui.ts @@ -0,0 +1,108 @@ +import { Global } from "../../global" +import { Provider } from "../../provider/provider" +import { Server } from "../../server/server" +import { bootstrap } from "../bootstrap" +import { UI } from "../ui" +import { cmd } from "./cmd" +import path from "path" +import fs from "fs/promises" +import { Installation } from "../../installation" +import { Config } from "../../config/config" +import { Bus } from "../../bus" +import { AuthLoginCommand } from "./auth" + +export const TuiCommand = cmd({ + command: "$0 [project]", + describe: "start opencode tui", + builder: (yargs) => + yargs.positional("project", { + type: "string", + describe: "path to start opencode in", + }), + handler: async (args) => { + while (true) { + const cwd = args.project ? path.resolve(args.project) : process.cwd() + try { + process.chdir(cwd) + } catch (e) { + UI.error("Failed to change directory to " + cwd) + return + } + const result = await bootstrap({ cwd }, async (app) => { + const providers = await Provider.list() + if (Object.keys(providers).length === 0) { + return "needs_provider" + } + + const server = Server.listen({ + port: 0, + hostname: "127.0.0.1", + }) + + let cmd = ["go", "run", "./main.go"] + let cwd = Bun.fileURLToPath( + new URL("../../../../tui/cmd/opencode", import.meta.url), + ) + if (Bun.embeddedFiles.length > 0) { + const blob = Bun.embeddedFiles[0] as File + let binaryName = blob.name + if (process.platform === "win32" && !binaryName.endsWith(".exe")) { + binaryName += ".exe" + } + const binary = path.join(Global.Path.cache, "tui", binaryName) + const file = Bun.file(binary) + if (!(await file.exists())) { + await Bun.write(file, blob, { mode: 0o755 }) + await fs.chmod(binary, 0o755) + } + cwd = process.cwd() + cmd = [binary] + } + const proc = Bun.spawn({ + cmd: [...cmd, ...process.argv.slice(2)], + cwd, + stdout: "inherit", + stderr: "inherit", + stdin: "inherit", + env: { + ...process.env, + OPENCODE_SERVER: server.url.toString(), + OPENCODE_APP_INFO: JSON.stringify(app), + }, + onExit: () => { + server.stop() + }, + }) + + ;(async () => { + if (Installation.VERSION === "dev") return + if (Installation.isSnapshot()) return + const config = await Config.global() + if (config.autoupdate === false) return + const latest = await Installation.latest().catch(() => {}) + if (!latest) return + if (Installation.VERSION === latest) return + const method = await Installation.method() + if (method === "unknown") return + await Installation.upgrade(method, latest) + .then(() => { + Bus.publish(Installation.Event.Updated, { version: latest }) + }) + .catch(() => {}) + })() + + await proc.exited + server.stop() + + return "done" + }) + if (result === "done") break + if (result === "needs_provider") { + UI.empty() + UI.println(UI.logo(" ")) + UI.empty() + await AuthLoginCommand.handler(args) + } + } + }, +}) diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index bf3c0ecdf..efb379b52 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -22,6 +22,7 @@ export namespace Config { } } log.info("loaded", result) + return result }) diff --git a/packages/opencode/src/config/hooks.ts b/packages/opencode/src/config/hooks.ts new file mode 100644 index 000000000..ffa2475f7 --- /dev/null +++ b/packages/opencode/src/config/hooks.ts @@ -0,0 +1,54 @@ +import { App } from "../app/app" +import { Bus } from "../bus" +import { File } from "../file" +import { Session } from "../session" +import { Log } from "../util/log" +import { Config } from "./config" +import path from "path" + +export namespace ConfigHooks { + const log = Log.create({ service: "config.hooks" }) + + export function init() { + log.info("init") + const app = App.info() + + Bus.subscribe(File.Event.Edited, async (payload) => { + const cfg = await Config.get() + const ext = path.extname(payload.properties.file) + for (const item of cfg.experimental?.hook?.file_edited?.[ext] ?? []) { + log.info("file_edited", { + file: payload.properties.file, + command: item.command, + }) + Bun.spawn({ + cmd: item.command.map((x) => + x.replace("$FILE", payload.properties.file), + ), + env: item.environment, + cwd: app.path.cwd, + stdout: "ignore", + stderr: "ignore", + }) + } + }) + + Bus.subscribe(Session.Event.Idle, async () => { + const cfg = await Config.get() + if (cfg.experimental?.hook?.session_completed) { + for (const item of cfg.experimental.hook.session_completed) { + log.info("session_completed", { + command: item.command, + }) + Bun.spawn({ + cmd: item.command, + cwd: App.info().path.cwd, + env: item.environment, + stdout: "ignore", + stderr: "ignore", + }) + } + } + }) + } +} diff --git a/packages/opencode/src/file/index.ts b/packages/opencode/src/file/index.ts new file mode 100644 index 000000000..7b5beab4d --- /dev/null +++ b/packages/opencode/src/file/index.ts @@ -0,0 +1,13 @@ +import { z } from "zod" +import { Bus } from "../bus" + +export namespace File { + export const Event = { + Edited: Bus.event( + "file.edited", + z.object({ + file: z.string(), + }), + ), + } +} diff --git a/packages/opencode/src/file/time.ts b/packages/opencode/src/file/time.ts new file mode 100644 index 000000000..531321974 --- /dev/null +++ b/packages/opencode/src/file/time.ts @@ -0,0 +1,38 @@ +import { App } from "../app/app" + +export namespace FileTime { + export const state = App.state("tool.filetimes", () => { + const read: { + [sessionID: string]: { + [path: string]: Date | undefined + } + } = {} + return { + read, + } + }) + + export function read(sessionID: string, file: string) { + const { read } = state() + read[sessionID] = read[sessionID] || {} + read[sessionID][file] = new Date() + } + + export function get(sessionID: string, file: string) { + return state().read[sessionID]?.[file] + } + + export async function assert(sessionID: string, filepath: string) { + const time = get(sessionID, filepath) + if (!time) + throw new Error( + `You must read the file ${filepath} before overwriting it. Use the Read tool first`, + ) + const stats = await Bun.file(filepath).stat() + if (stats.mtime.getTime() > time.getTime()) { + throw new Error( + `File ${filepath} has been modified since it was last read.\nLast modification: ${stats.mtime.toISOString()}\nLast read: ${time.toISOString()}\n\nPlease read the file again before modifying it.`, + ) + } + } +} diff --git a/packages/opencode/src/format/index.ts b/packages/opencode/src/format/index.ts index 750177498..5ce27bc4e 100644 --- a/packages/opencode/src/format/index.ts +++ b/packages/opencode/src/format/index.ts @@ -1,77 +1,68 @@ import { App } from "../app/app" import { BunProc } from "../bun" -import { Config } from "../config/config" +import { Bus } from "../bus" +import { File } from "../file" import { Log } from "../util/log" import path from "path" export namespace Format { const log = Log.create({ service: "format" }) - const state = App.state("format", async () => { - const hooks: Record = {} - for (const item of FORMATTERS) { - if (await item.enabled()) { - for (const ext of item.extensions) { - const list = hooks[ext] ?? [] - list.push({ - command: item.command, - environment: item.environment, - }) - hooks[ext] = list - } - } - } - - const cfg = await Config.get() - for (const [file, items] of Object.entries( - cfg.experimental?.hook?.file_edited ?? {}, - )) { - for (const item of items) { - const list = hooks[file] ?? [] - list.push({ - command: item.command, - environment: item.environment, - }) - hooks[file] = list - } - } + const state = App.state("format", () => { + const enabled: Record = {} return { - hooks, + enabled, } }) - export async function run(file: string) { - log.info("formatting", { file }) - const { hooks } = await state() - const ext = path.extname(file) - const match = hooks[ext] - if (!match) return + async function isEnabled(item: Definition) { + const s = state() + let status = s.enabled[item.name] + if (status === undefined) { + status = await item.enabled() + s.enabled[item.name] = status + } + return status + } - for (const item of match) { - log.info("running", { command: item.command }) - const proc = Bun.spawn({ - cmd: item.command.map((x) => x.replace("$FILE", file)), - cwd: App.info().path.cwd, - env: item.environment, - stdout: "ignore", - stderr: "ignore", - }) - const exit = await proc.exited - if (exit !== 0) - log.error("failed", { - command: item.command, - ...item.environment, - }) + async function getFormatter(ext: string) { + const result = [] + for (const item of FORMATTERS) { + if (!item.extensions.includes(ext)) continue + if (!isEnabled(item)) continue + result.push(item) } + return result } - interface Hook { - command: string[] - environment?: Record + export function init() { + log.info("init") + Bus.subscribe(File.Event.Edited, async (payload) => { + const file = payload.properties.file + log.info("formatting", { file }) + const ext = path.extname(file) + + for (const item of await getFormatter(ext)) { + log.info("running", { command: item.command }) + const proc = Bun.spawn({ + cmd: item.command.map((x) => x.replace("$FILE", file)), + cwd: App.info().path.cwd, + env: item.environment, + stdout: "ignore", + stderr: "ignore", + }) + const exit = await proc.exited + if (exit !== 0) + log.error("failed", { + command: item.command, + ...item.environment, + }) + } + }) } - interface Native { + interface Definition { name: string command: string[] environment?: Record @@ -79,7 +70,7 @@ export namespace Format { enabled(): Promise } - const FORMATTERS: Native[] = [ + const FORMATTERS: Definition[] = [ { name: "prettier", command: [BunProc.which(), "run", "prettier", "--write", "$FILE"], @@ -133,17 +124,9 @@ export namespace Format { }, }, { - name: "mix format", + name: "mix", command: ["mix", "format", "$FILE"], - extensions: [ - ".ex", - ".exs", - ".eex", - ".heex", - ".leex", - ".neex", - ".sface", - ], + extensions: [".ex", ".exs", ".eex", ".heex", ".leex", ".neex", ".sface"], async enabled() { try { const proc = Bun.spawn({ diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts index 25fcf71dd..144d6328b 100644 --- a/packages/opencode/src/index.ts +++ b/packages/opencode/src/index.ts @@ -1,28 +1,19 @@ import "zod-openapi/extend" -import { App } from "./app/app" -import { Server } from "./server/server" -import fs from "fs/promises" -import path from "path" -import { Share } from "./share/share" -import url from "node:url" -import { Global } from "./global" import yargs from "yargs" import { hideBin } from "yargs/helpers" import { RunCommand } from "./cli/cmd/run" import { GenerateCommand } from "./cli/cmd/generate" import { ScrapCommand } from "./cli/cmd/scrap" import { Log } from "./util/log" -import { AuthCommand, AuthLoginCommand } from "./cli/cmd/auth" +import { AuthCommand } from "./cli/cmd/auth" import { UpgradeCommand } from "./cli/cmd/upgrade" import { ModelsCommand } from "./cli/cmd/models" -import { Provider } from "./provider/provider" import { UI } from "./cli/ui" import { Installation } from "./installation" -import { Bus } from "./bus" -import { Config } from "./config/config" import { NamedError } from "./util/error" import { FormatError } from "./cli/error" import { ServeCommand } from "./cli/cmd/serve" +import { TuiCommand } from "./cli/cmd/tui" const cancel = new AbortController() @@ -55,103 +46,7 @@ const cli = yargs(hideBin(process.argv)) }) }) .usage("\n" + UI.logo()) - .command({ - command: "$0 [project]", - describe: "start opencode tui", - builder: (yargs) => - yargs.positional("project", { - type: "string", - describe: "path to start opencode in", - }), - handler: async (args) => { - while (true) { - const cwd = args.project ? path.resolve(args.project) : process.cwd() - try { - process.chdir(cwd) - } catch (e) { - UI.error("Failed to change directory to " + cwd) - return - } - const result = await App.provide({ cwd }, async (app) => { - const providers = await Provider.list() - if (Object.keys(providers).length === 0) { - return "needs_provider" - } - - await Share.init() - const server = Server.listen({ - port: 0, - hostname: "127.0.0.1", - }) - - let cmd = ["go", "run", "./main.go"] - let cwd = url.fileURLToPath( - new URL("../../tui/cmd/opencode", import.meta.url), - ) - if (Bun.embeddedFiles.length > 0) { - const blob = Bun.embeddedFiles[0] as File - let binaryName = blob.name - if (process.platform === "win32" && !binaryName.endsWith(".exe")) { - binaryName += ".exe" - } - const binary = path.join(Global.Path.cache, "tui", binaryName) - const file = Bun.file(binary) - if (!(await file.exists())) { - await Bun.write(file, blob, { mode: 0o755 }) - await fs.chmod(binary, 0o755) - } - cwd = process.cwd() - cmd = [binary] - } - const proc = Bun.spawn({ - cmd: [...cmd, ...process.argv.slice(2)], - signal: cancel.signal, - cwd, - stdout: "inherit", - stderr: "inherit", - stdin: "inherit", - env: { - ...process.env, - OPENCODE_SERVER: server.url.toString(), - OPENCODE_APP_INFO: JSON.stringify(app), - }, - onExit: () => { - server.stop() - }, - }) - - ;(async () => { - if (Installation.VERSION === "dev") return - if (Installation.isSnapshot()) return - const config = await Config.global() - if (config.autoupdate === false) return - const latest = await Installation.latest().catch(() => {}) - if (!latest) return - if (Installation.VERSION === latest) return - const method = await Installation.method() - if (method === "unknown") return - await Installation.upgrade(method, latest) - .then(() => { - Bus.publish(Installation.Event.Updated, { version: latest }) - }) - .catch(() => {}) - })() - - await proc.exited - server.stop() - - return "done" - }) - if (result === "done") break - if (result === "needs_provider") { - UI.empty() - UI.println(UI.logo(" ")) - UI.empty() - await AuthLoginCommand.handler(args) - } - } - }, - }) + .command(TuiCommand) .command(RunCommand) .command(GenerateCommand) .command(ScrapCommand) diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index 0591bb56a..f457ba9c7 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -78,6 +78,12 @@ export namespace Session { info: Info, }), ), + Idle: Bus.event( + "session.idle", + z.object({ + sessionID: z.string(), + }), + ), Error: Bus.event( "session.error", z.object({ @@ -854,18 +860,8 @@ export namespace Session { [Symbol.dispose]() { log.info("unlocking", { sessionID }) state().pending.delete(sessionID) - Config.get().then((cfg) => { - if (cfg.experimental?.hook?.session_completed) { - for (const item of cfg.experimental.hook.session_completed) { - Bun.spawn({ - cmd: item.command, - cwd: App.info().path.cwd, - env: item.environment, - stdout: "ignore", - stderr: "ignore", - }) - } - } + Bus.publish(Event.Idle, { + sessionID, }) }, } diff --git a/packages/opencode/src/share/share.ts b/packages/opencode/src/share/share.ts index f5faee6ed..f498e0f45 100644 --- a/packages/opencode/src/share/share.ts +++ b/packages/opencode/src/share/share.ts @@ -1,4 +1,3 @@ -import { App } from "../app/app" import { Bus } from "../bus" import { Installation } from "../installation" import { Session } from "../session" @@ -11,12 +10,6 @@ export namespace Share { let queue: Promise = Promise.resolve() const pending = new Map() - const state = App.state("share", async () => { - Bus.subscribe(Storage.Event.Write, async (payload) => { - await sync(payload.properties.key, payload.properties.content) - }) - }) - export async function sync(key: string, content: any) { const [root, ...splits] = key.split("/") if (root !== "session") return @@ -52,8 +45,10 @@ export namespace Share { }) } - export async function init() { - await state() + export function init() { + Bus.subscribe(Storage.Event.Write, async (payload) => { + await sync(payload.properties.key, payload.properties.content) + }) } export const URL = diff --git a/packages/opencode/src/tool/edit.ts b/packages/opencode/src/tool/edit.ts index d597635e2..fb02a536c 100644 --- a/packages/opencode/src/tool/edit.ts +++ b/packages/opencode/src/tool/edit.ts @@ -5,13 +5,14 @@ import { z } from "zod" import * as path from "path" import { Tool } from "./tool" -import { FileTimes } from "./util/file-times" import { LSP } from "../lsp" import { createTwoFilesPatch } from "diff" import { Permission } from "../permission" import DESCRIPTION from "./edit.txt" import { App } from "../app/app" -import { Format } from "../format" +import { File } from "../file" +import { Bus } from "../bus" +import { FileTime } from "../file/time" export const EditTool = Tool.define({ id: "edit", @@ -60,7 +61,9 @@ export const EditTool = Tool.define({ if (params.oldString === "") { contentNew = params.newString await Bun.write(filepath, params.newString) - await Format.run(filepath) + await Bus.publish(File.Event.Edited, { + file: filepath, + }) return } @@ -69,7 +72,7 @@ export const EditTool = Tool.define({ if (!stats) throw new Error(`File ${filepath} not found`) if (stats.isDirectory()) throw new Error(`Path is a directory, not a file: ${filepath}`) - await FileTimes.assert(ctx.sessionID, filepath) + await FileTime.assert(ctx.sessionID, filepath) contentOld = await file.text() contentNew = replace( @@ -79,7 +82,9 @@ export const EditTool = Tool.define({ params.replaceAll, ) await file.write(contentNew) - await Format.run(filepath) + await Bus.publish(File.Event.Edited, { + file: filepath, + }) contentNew = await file.text() })() @@ -87,7 +92,7 @@ export const EditTool = Tool.define({ createTwoFilesPatch(filepath, filepath, contentOld, contentNew), ) - FileTimes.read(ctx.sessionID, filepath) + FileTime.read(ctx.sessionID, filepath) let output = "" await LSP.touchFile(filepath, true) diff --git a/packages/opencode/src/tool/patch.ts b/packages/opencode/src/tool/patch.ts index 508814ac4..6266d1639 100644 --- a/packages/opencode/src/tool/patch.ts +++ b/packages/opencode/src/tool/patch.ts @@ -2,7 +2,7 @@ import { z } from "zod" import * as path from "path" import * as fs from "fs/promises" import { Tool } from "./tool" -import { FileTimes } from "./util/file-times" +import { FileTime } from "../file/time" import DESCRIPTION from "./patch.txt" const PatchParams = z.object({ @@ -244,7 +244,7 @@ export const PatchTool = Tool.define({ absPath = path.resolve(process.cwd(), absPath) } - await FileTimes.assert(ctx.sessionID, absPath) + await FileTime.assert(ctx.sessionID, absPath) try { const stats = await fs.stat(absPath) @@ -351,7 +351,7 @@ export const PatchTool = Tool.define({ totalAdditions += additions totalRemovals += removals - FileTimes.read(ctx.sessionID, absPath) + FileTime.read(ctx.sessionID, absPath) } const result = `Patch applied successfully. ${changedFiles.length} files changed, ${totalAdditions} additions, ${totalRemovals} removals` diff --git a/packages/opencode/src/tool/read.ts b/packages/opencode/src/tool/read.ts index 63e5c8efe..3691459db 100644 --- a/packages/opencode/src/tool/read.ts +++ b/packages/opencode/src/tool/read.ts @@ -3,7 +3,7 @@ import * as fs from "fs" import * as path from "path" import { Tool } from "./tool" import { LSP } from "../lsp" -import { FileTimes } from "./util/file-times" +import { FileTime } from "../file/time" import DESCRIPTION from "./read.txt" import { App } from "../app/app" @@ -90,7 +90,7 @@ export const ReadTool = Tool.define({ // just warms the lsp client await LSP.touchFile(filePath, true) - FileTimes.read(ctx.sessionID, filePath) + FileTime.read(ctx.sessionID, filePath) return { output, diff --git a/packages/opencode/src/tool/util/file-times.ts b/packages/opencode/src/tool/util/file-times.ts deleted file mode 100644 index 7eb60aecf..000000000 --- a/packages/opencode/src/tool/util/file-times.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { App } from "../../app/app" - -export namespace FileTimes { - export const state = App.state("tool.filetimes", () => { - const read: { - [sessionID: string]: { - [path: string]: Date | undefined - } - } = {} - return { - read, - } - }) - - export function read(sessionID: string, file: string) { - const { read } = state() - read[sessionID] = read[sessionID] || {} - read[sessionID][file] = new Date() - } - - export function get(sessionID: string, file: string) { - return state().read[sessionID]?.[file] - } - - export async function assert(sessionID: string, filepath: string) { - const time = get(sessionID, filepath) - if (!time) - throw new Error( - `You must read the file ${filepath} before overwriting it. Use the Read tool first`, - ) - const stats = await Bun.file(filepath).stat() - if (stats.mtime.getTime() > time.getTime()) { - throw new Error( - `File ${filepath} has been modified since it was last read.\nLast modification: ${stats.mtime.toISOString()}\nLast read: ${time.toISOString()}\n\nPlease read the file again before modifying it.`, - ) - } - } -} diff --git a/packages/opencode/src/tool/write.ts b/packages/opencode/src/tool/write.ts index 264633ff0..b05158055 100644 --- a/packages/opencode/src/tool/write.ts +++ b/packages/opencode/src/tool/write.ts @@ -1,12 +1,13 @@ import { z } from "zod" import * as path from "path" import { Tool } from "./tool" -import { FileTimes } from "./util/file-times" import { LSP } from "../lsp" import { Permission } from "../permission" import DESCRIPTION from "./write.txt" import { App } from "../app/app" -import { Format } from "../format" +import { Bus } from "../bus" +import { File } from "../file" +import { FileTime } from "../file/time" export const WriteTool = Tool.define({ id: "write", @@ -27,7 +28,7 @@ export const WriteTool = Tool.define({ const file = Bun.file(filepath) const exists = await file.exists() - if (exists) await FileTimes.assert(ctx.sessionID, filepath) + if (exists) await FileTime.assert(ctx.sessionID, filepath) await Permission.ask({ id: "write", @@ -43,8 +44,10 @@ export const WriteTool = Tool.define({ }) await Bun.write(filepath, params.content) - await Format.run(filepath) - FileTimes.read(ctx.sessionID, filepath) + await Bus.publish(File.Event.Edited, { + file: filepath, + }) + FileTime.read(ctx.sessionID, filepath) let output = "" await LSP.touchFile(filepath, true) diff --git a/packages/opencode/src/util/project.ts b/packages/opencode/src/util/project.ts deleted file mode 100644 index 72a9bda52..000000000 --- a/packages/opencode/src/util/project.ts +++ /dev/null @@ -1,91 +0,0 @@ -import path from "path" -import { readdir } from "fs/promises" - -export namespace Project { - export async function getName(rootPath: string): Promise { - try { - const packageJsonPath = path.join(rootPath, "package.json") - const packageJson = await Bun.file(packageJsonPath).json() - if (packageJson.name && typeof packageJson.name === "string") { - return packageJson.name - } - } catch {} - - try { - const cargoTomlPath = path.join(rootPath, "Cargo.toml") - const cargoToml = await Bun.file(cargoTomlPath).text() - const nameMatch = cargoToml.match(/^\s*name\s*=\s*"([^"]+)"/m) - if (nameMatch?.[1]) { - return nameMatch[1] - } - } catch {} - - try { - const pyprojectPath = path.join(rootPath, "pyproject.toml") - const pyproject = await Bun.file(pyprojectPath).text() - const nameMatch = pyproject.match(/^\s*name\s*=\s*"([^"]+)"/m) - if (nameMatch?.[1]) { - return nameMatch[1] - } - } catch {} - - try { - const goModPath = path.join(rootPath, "go.mod") - const goMod = await Bun.file(goModPath).text() - const moduleMatch = goMod.match(/^module\s+(.+)$/m) - if (moduleMatch?.[1]) { - // Extract just the last part of the module path - const parts = moduleMatch[1].trim().split("/") - return parts[parts.length - 1] - } - } catch {} - - try { - const composerPath = path.join(rootPath, "composer.json") - const composer = await Bun.file(composerPath).json() - if (composer.name && typeof composer.name === "string") { - // Composer names are usually vendor/package, extract the package part - const parts = composer.name.split("/") - return parts[parts.length - 1] - } - } catch {} - - try { - const pomPath = path.join(rootPath, "pom.xml") - const pom = await Bun.file(pomPath).text() - const artifactIdMatch = pom.match(/([^<]+)<\/artifactId>/) - if (artifactIdMatch?.[1]) { - return artifactIdMatch[1] - } - } catch {} - - for (const gradleFile of ["build.gradle", "build.gradle.kts"]) { - try { - const gradlePath = path.join(rootPath, gradleFile) - await Bun.file(gradlePath).text() // Check if gradle file exists - // Look for rootProject.name in settings.gradle - const settingsPath = path.join(rootPath, "settings.gradle") - const settings = await Bun.file(settingsPath).text() - const nameMatch = settings.match( - /rootProject\.name\s*=\s*['"]([^'"]+)['"]/, - ) - if (nameMatch?.[1]) { - return nameMatch[1] - } - } catch {} - } - - const dotnetExtensions = [".csproj", ".fsproj", ".vbproj"] - try { - const files = await readdir(rootPath) - for (const file of files) { - if (dotnetExtensions.some((ext) => file.endsWith(ext))) { - // Use the filename without extension as project name - return path.basename(file, path.extname(file)) - } - } - } catch {} - - return path.basename(rootPath) - } -} -- cgit v1.2.3 From 8e0ec6b037f157e1ed10e26982223ed61187854e Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 27 Jun 2025 12:29:13 -0400 Subject: ci: aur --- packages/opencode/script/publish.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'packages') diff --git a/packages/opencode/script/publish.ts b/packages/opencode/script/publish.ts index 2b301080c..20571e44e 100755 --- a/packages/opencode/script/publish.ts +++ b/packages/opencode/script/publish.ts @@ -142,7 +142,7 @@ if (!snapshot) { "# Maintainer: dax", "# Maintainer: adam", "", - "pkgname='opencode-bin'", + "pkgname='${pkg}'", `pkgver=${version.split("-")[0]}`, "options=('!debug' '!strip')", "pkgrel=1", @@ -166,14 +166,17 @@ if (!snapshot) { "", ].join("\n") - await $`rm -rf ./dist/aur-opencode-bin` - - await $`git clone ssh://aur@aur.archlinux.org/opencode-bin.git ./dist/aur-opencode-bin` - await Bun.file("./dist/aur-opencode-bin/PKGBUILD").write(pkgbuild) - await $`cd ./dist/aur-opencode-bin && makepkg --printsrcinfo > .SRCINFO` - await $`cd ./dist/aur-opencode-bin && git add PKGBUILD .SRCINFO` - await $`cd ./dist/aur-opencode-bin && git commit -m "Update to v${version}"` - if (!dry) await $`cd ./dist/aur-opencode-bin && git push` + for (const pkg of ["opencode", "opencode-bin"]) { + await $`rm -rf ./dist/aur-${pkg}` + await $`git clone ssh://aur@aur.archlinux.org/opencode-bin.git ./dist/aur-${pkg}` + await Bun.file(`./dist/aur-${pkg}/PKGBUILD`).write( + pkgbuild.replace("${pkg}", pkg), + ) + await $`cd ./dist/aur-${pkg} && makepkg --printsrcinfo > .SRCINFO` + await $`cd ./dist/aur-${pkg} && git add PKGBUILD .SRCINFO` + await $`cd ./dist/aur-${pkg} && git commit -m "Update to v${version}"` + if (!dry) await $`cd ./dist/aur-${pkg} && git push` + } // Homebrew formula const homebrewFormula = [ -- cgit v1.2.3 From 87d62514dbce9fc0222a99d092c86ea7e6314cbb Mon Sep 17 00:00:00 2001 From: Jay V Date: Fri, 27 Jun 2025 13:25:15 -0400 Subject: docs: share page write tool bug --- packages/web/src/components/Share.tsx | 14 +++++++------- packages/web/src/types/lang-map.d.ts | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) (limited to 'packages') diff --git a/packages/web/src/components/Share.tsx b/packages/web/src/components/Share.tsx index 9b953bd2d..e8879c50a 100644 --- a/packages/web/src/components/Share.tsx +++ b/packages/web/src/components/Share.tsx @@ -85,7 +85,7 @@ function scrollToAnchor(id: string) { el.scrollIntoView({ behavior: "smooth" }) } -function stripWorkingDirectory(filePath: string, workingDir?: string) { +function stripWorkingDirectory(filePath?: string, workingDir?: string) { if (filePath === undefined || workingDir === undefined) return filePath const prefix = workingDir.endsWith("/") ? workingDir : workingDir + "/" @@ -1307,9 +1307,9 @@ export default function Share(props: { const path = createMemo(() => toolData()?.args.path !== data().rootDir ? stripWorkingDirectory( - toolData()?.args.path, - data().rootDir, - ) + toolData()?.args.path, + data().rootDir, + ) : toolData()?.args.path, ) @@ -1470,7 +1470,7 @@ export default function Share(props: { {(_part) => { const filePath = createMemo(() => stripWorkingDirectory( - toolData()?.args.filePath, + toolData()?.args?.filePath, data().rootDir, ), ) @@ -1509,7 +1509,7 @@ export default function Share(props: {
{formatErrorString( - toolData()?.result, + toolData()?.result )}
@@ -1528,7 +1528,7 @@ export default function Share(props: {
diff --git a/packages/web/src/types/lang-map.d.ts b/packages/web/src/types/lang-map.d.ts index e69de29bb..b21d2a005 100644 --- a/packages/web/src/types/lang-map.d.ts +++ b/packages/web/src/types/lang-map.d.ts @@ -0,0 +1,27 @@ +declare module "lang-map" { + /** Returned by calling `map()` */ + export interface MapReturn { + /** All extensions keyed by language name */ + extensions: Record; + /** All languages keyed by file-extension */ + languages: Record; + } + + /** + * Calling `map()` gives you the raw lookup tables: + * + * ```js + * const { extensions, languages } = map(); + * ``` + */ + function map(): MapReturn; + + /** Static method: get extensions for a given language */ + namespace map { + function extensions(language: string): string[]; + /** Static method: get languages for a given extension */ + function languages(extension: string): string[]; + } + + export = map; +} -- cgit v1.2.3 From fa2723f2d0033c5b566abea035062e799a8634c6 Mon Sep 17 00:00:00 2001 From: Jay V Date: Fri, 27 Jun 2025 14:04:09 -0400 Subject: docs: update logo screenshot --- README.md | 8 ++++---- packages/web/public/social-share.png | Bin 17103 -> 17520 bytes .../web/src/assets/lander/screenshot-splash.png | Bin 0 -> 467281 bytes packages/web/src/assets/lander/screenshot.png | Bin 0 -> 552769 bytes packages/web/src/assets/logo-ornate-dark.svg | 18 ++++++++++++++++++ packages/web/src/assets/logo-ornate-light.svg | 18 ++++++++++++++++++ packages/web/src/assets/themes/ayu.png | Bin 449635 -> 0 bytes packages/web/src/assets/themes/everforest.png | Bin 448402 -> 0 bytes packages/web/src/assets/themes/opencode.png | Bin 442445 -> 0 bytes packages/web/src/assets/themes/tokyonight.png | Bin 452738 -> 0 bytes packages/web/src/components/Lander.astro | 2 +- packages/web/src/content/docs/docs/index.mdx | 2 +- packages/web/src/content/docs/index.mdx | 4 ++-- 13 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 packages/web/src/assets/lander/screenshot-splash.png create mode 100644 packages/web/src/assets/lander/screenshot.png create mode 100644 packages/web/src/assets/logo-ornate-dark.svg create mode 100644 packages/web/src/assets/logo-ornate-light.svg delete mode 100644 packages/web/src/assets/themes/ayu.png delete mode 100644 packages/web/src/assets/themes/everforest.png delete mode 100644 packages/web/src/assets/themes/opencode.png delete mode 100644 packages/web/src/assets/themes/tokyonight.png (limited to 'packages') diff --git a/README.md b/README.md index 6cbe9619a..9aa47f988 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@

- - - opencode logo + + + opencode logo

@@ -14,7 +14,7 @@ Build status

-[![opencode Terminal UI](packages/web/src/assets/themes/opencode.png)](https://opencode.ai) +[![opencode Terminal UI](packages/web/src/assets/lander/screenshot.png)](https://opencode.ai) --- diff --git a/packages/web/public/social-share.png b/packages/web/public/social-share.png index 39b86514c..97f67994d 100644 Binary files a/packages/web/public/social-share.png and b/packages/web/public/social-share.png differ diff --git a/packages/web/src/assets/lander/screenshot-splash.png b/packages/web/src/assets/lander/screenshot-splash.png new file mode 100644 index 000000000..e900673ef Binary files /dev/null and b/packages/web/src/assets/lander/screenshot-splash.png differ diff --git a/packages/web/src/assets/lander/screenshot.png b/packages/web/src/assets/lander/screenshot.png new file mode 100644 index 000000000..d49a62b4d Binary files /dev/null and b/packages/web/src/assets/lander/screenshot.png differ diff --git a/packages/web/src/assets/logo-ornate-dark.svg b/packages/web/src/assets/logo-ornate-dark.svg new file mode 100644 index 000000000..b937be0af --- /dev/null +++ b/packages/web/src/assets/logo-ornate-dark.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/packages/web/src/assets/logo-ornate-light.svg b/packages/web/src/assets/logo-ornate-light.svg new file mode 100644 index 000000000..b519ec41a --- /dev/null +++ b/packages/web/src/assets/logo-ornate-light.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/packages/web/src/assets/themes/ayu.png b/packages/web/src/assets/themes/ayu.png deleted file mode 100644 index 0c4af5026..000000000 Binary files a/packages/web/src/assets/themes/ayu.png and /dev/null differ diff --git a/packages/web/src/assets/themes/everforest.png b/packages/web/src/assets/themes/everforest.png deleted file mode 100644 index 611e95530..000000000 Binary files a/packages/web/src/assets/themes/everforest.png and /dev/null differ diff --git a/packages/web/src/assets/themes/opencode.png b/packages/web/src/assets/themes/opencode.png deleted file mode 100644 index cc5c5d007..000000000 Binary files a/packages/web/src/assets/themes/opencode.png and /dev/null differ diff --git a/packages/web/src/assets/themes/tokyonight.png b/packages/web/src/assets/themes/tokyonight.png deleted file mode 100644 index 1d39ba075..000000000 Binary files a/packages/web/src/assets/themes/tokyonight.png and /dev/null differ diff --git a/packages/web/src/components/Lander.astro b/packages/web/src/components/Lander.astro index 82c33f3b3..596bca2d7 100644 --- a/packages/web/src/components/Lander.astro +++ b/packages/web/src/components/Lander.astro @@ -5,7 +5,7 @@ import type { Props } from '@astrojs/starlight/props'; import CopyIcon from "../assets/lander/copy.svg"; import CheckIcon from "../assets/lander/check.svg"; -import Screenshot from "../assets/themes/tokyonight.png"; +import Screenshot from "../assets/lander/screenshot-splash.png"; const { data } = Astro.locals.starlightRoute.entry; const { title = data.title, tagline, image, actions = [] } = data.hero || {}; diff --git a/packages/web/src/content/docs/docs/index.mdx b/packages/web/src/content/docs/docs/index.mdx index 0a8a8fa25..4926450c7 100644 --- a/packages/web/src/content/docs/docs/index.mdx +++ b/packages/web/src/content/docs/docs/index.mdx @@ -13,7 +13,7 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; - Log in with Anthropic to use your Claude Pro or Claude Max account. - Supports 75+ LLM providers through [Models.dev](https://models.dev), including local models. -![opencode TUI with the opencode theme](../../../assets/themes/opencode.png) +![opencode TUI with the opencode theme](../../../assets/lander/screenshot.png) --- diff --git a/packages/web/src/content/docs/index.mdx b/packages/web/src/content/docs/index.mdx index 1f735db21..ea39be9ee 100644 --- a/packages/web/src/content/docs/index.mdx +++ b/packages/web/src/content/docs/index.mdx @@ -6,7 +6,7 @@ hero: title: The AI coding agent built for the terminal. tagline: The AI coding agent built for the terminal. image: - dark: ../../assets/logo-dark.svg - light: ../../assets/logo-light.svg + dark: ../../assets/logo-ornate-dark.svg + light: ../../assets/logo-ornate-light.svg alt: opencode logo --- -- cgit v1.2.3 From e0807d73177aa27a2be3d4910bab48a19c1480f2 Mon Sep 17 00:00:00 2001 From: Wendell Misiedjan Date: Fri, 27 Jun 2025 20:09:35 +0200 Subject: fix: bunproc stdout / stderr parsing, error handling for bun ResolveMessage (#468) --- packages/opencode/src/bun/index.ts | 11 +++++------ packages/opencode/src/index.ts | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 7 deletions(-) (limited to 'packages') diff --git a/packages/opencode/src/bun/index.ts b/packages/opencode/src/bun/index.ts index b48ab16f7..7a7d89cf5 100644 --- a/packages/opencode/src/bun/index.ts +++ b/packages/opencode/src/bun/index.ts @@ -3,6 +3,7 @@ import { Global } from "../global" import { Log } from "../util/log" import path from "path" import { NamedError } from "../util/error" +import { readableStreamToText } from "bun" export namespace BunProc { const log = Log.create({ service: "bun" }) @@ -25,11 +26,9 @@ export namespace BunProc { BUN_BE_BUN: "1", }, }) - const code = await result.exited - // @ts-ignore - const stdout = await result.stdout.text() - // @ts-ignore - const stderr = await result.stderr.text() + const code = await result.exited; + const stdout = result.stdout ? typeof result.stdout === "number" ? result.stdout : await readableStreamToText(result.stdout) : undefined + const stderr = result.stderr ? typeof result.stderr === "number" ? result.stderr : await readableStreamToText(result.stderr) : undefined log.info("done", { code, stdout, @@ -65,7 +64,7 @@ export namespace BunProc { await BunProc.run(["install", "--registry=https://registry.npmjs.org"], { cwd: Global.Path.cache, }).catch((e) => { - new InstallFailedError( + throw new InstallFailedError( { pkg, version }, { cause: e, diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts index 144d6328b..fca13655e 100644 --- a/packages/opencode/src/index.ts +++ b/packages/opencode/src/index.ts @@ -67,19 +67,32 @@ const cli = yargs(hideBin(process.argv)) try { await cli.parse() } catch (e) { - const data: Record = {} + let data: Record = {} if (e instanceof NamedError) { const obj = e.toObject() Object.assign(data, { ...obj.data, }) } + if (e instanceof Error) { Object.assign(data, { name: e.name, message: e.message, cause: e.cause?.toString(), }) + } + + if (e instanceof ResolveMessage) { + Object.assign(data, { + name: e.name, + message: e.message, + code: e.code, + specifier: e.specifier, + referrer: e.referrer, + position: e.position, + importKind: e.importKind, + }); } Log.Default.error("fatal", data) const formatted = FormatError(e) -- cgit v1.2.3 From d076def561d10167d984a4ef071e847d10bd8981 Mon Sep 17 00:00:00 2001 From: Polo123456789 <57022222+Polo123456789@users.noreply.github.com> Date: Fri, 27 Jun 2025 12:11:09 -0600 Subject: feat: Add golang file formatting (#474) --- packages/opencode/src/format/index.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'packages') diff --git a/packages/opencode/src/format/index.ts b/packages/opencode/src/format/index.ts index 5ce27bc4e..2a189380b 100644 --- a/packages/opencode/src/format/index.ts +++ b/packages/opencode/src/format/index.ts @@ -142,5 +142,24 @@ export namespace Format { } }, }, + { + name: "gofmt", + command: ["gofmt", "-w", "$FILE"], + extensions: [".go"], + async enabled() { + try { + const proc = Bun.spawn({ + cmd: ["gofmt", "-h"], + cwd: App.info().path.cwd, + stdout: "ignore", + stderr: "ignore", + }) + const exit = await proc.exited + return exit === 0 + } catch { + return false + } + }, + }, ] } -- cgit v1.2.3 From 0676bcd4fd33b6acb37e248be53b9e6a0352be6b Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 27 Jun 2025 14:35:32 -0400 Subject: temporary patch for input lag on initial run --- packages/opencode/src/cli/cmd/tui.ts | 3 +++ 1 file changed, 3 insertions(+) (limited to 'packages') diff --git a/packages/opencode/src/cli/cmd/tui.ts b/packages/opencode/src/cli/cmd/tui.ts index 203cc2998..b66aca6bd 100644 --- a/packages/opencode/src/cli/cmd/tui.ts +++ b/packages/opencode/src/cli/cmd/tui.ts @@ -102,6 +102,9 @@ export const TuiCommand = cmd({ UI.println(UI.logo(" ")) UI.empty() await AuthLoginCommand.handler(args) + UI.empty() + UI.println("Provider configured - please run again") + return } } }, -- cgit v1.2.3 From be0811ecc30bb8a4fef14111437aacf6fa51fe27 Mon Sep 17 00:00:00 2001 From: adamdottv <2363879+adamdottv@users.noreply.github.com> Date: Fri, 27 Jun 2025 07:46:42 -0500 Subject: chore: rework openapi spec and use stainless sdk --- README.md | 9 +- packages/opencode/AGENTS.md | 3 +- packages/opencode/src/app/app.ts | 2 +- packages/opencode/src/config/config.ts | 8 +- packages/opencode/src/provider/models.ts | 4 +- packages/opencode/src/server/server.ts | 269 +- packages/opencode/src/session/index.ts | 18 +- packages/opencode/src/session/message.ts | 38 +- packages/tui/AGENTS.md | 1 - packages/tui/cmd/opencode/main.go | 17 +- packages/tui/go.mod | 9 +- packages/tui/go.sum | 12 + packages/tui/internal/app/app.go | 235 +- packages/tui/internal/commands/command.go | 8 +- packages/tui/internal/completions/files-folders.go | 15 +- packages/tui/internal/components/chat/message.go | 129 +- packages/tui/internal/components/chat/messages.go | 102 +- .../tui/internal/components/commands/commands.go | 2 +- packages/tui/internal/components/dialog/models.go | 24 +- packages/tui/internal/components/dialog/session.go | 10 +- packages/tui/internal/components/status/status.go | 12 +- packages/tui/internal/config/config.go | 8 - packages/tui/internal/tui/tui.go | 75 +- packages/tui/pkg/client/client.go | 4 - packages/tui/pkg/client/event.go | 13 +- packages/tui/pkg/client/gen/openapi.json | 2042 ---------- packages/tui/pkg/client/generated-client.go | 3952 -------------------- stainless.yml | 105 + 28 files changed, 575 insertions(+), 6551 deletions(-) delete mode 100644 packages/tui/pkg/client/client.go delete mode 100644 packages/tui/pkg/client/gen/openapi.json delete mode 100644 packages/tui/pkg/client/generated-client.go create mode 100644 stainless.yml (limited to 'packages') diff --git a/README.md b/README.md index 9aa47f988..0c9af3444 100644 --- a/README.md +++ b/README.md @@ -54,14 +54,7 @@ $ bun run packages/opencode/src/index.ts #### Development Notes -**API Client Generation**: After making changes to the TypeScript API endpoints in `packages/opencode/src/server/server.ts`, you need to regenerate the Go client and OpenAPI specification: - -```bash -$ cd packages/tui -$ go generate ./pkg/client/ -``` - -This updates the generated Go client code that the TUI uses to communicate with the backend server. +**API Client**: After making changes to the TypeScript API endpoints in `packages/opencode/src/server/server.ts`, you will need the opencode team to generate a new stainless sdk for the clients. ### FAQ diff --git a/packages/opencode/AGENTS.md b/packages/opencode/AGENTS.md index a24ccd7d5..8b3b03dc0 100644 --- a/packages/opencode/AGENTS.md +++ b/packages/opencode/AGENTS.md @@ -7,7 +7,6 @@ - **Typecheck**: `bun run typecheck` (npm run typecheck) - **Test**: `bun test` (runs all tests) - **Single test**: `bun test test/tool/tool.test.ts` (specific test file) -- **API Client Generation**: `cd packages/tui && go generate ./pkg/client/` (after changes to server endpoints) ## Code Style @@ -38,4 +37,4 @@ - **Validation**: All inputs validated with Zod schemas - **Logging**: Use `Log.create({ service: "name" })` pattern - **Storage**: Use `Storage` namespace for persistence -- **API Client**: Go TUI communicates with TypeScript server via generated client. When adding/modifying server endpoints in `packages/opencode/src/server/server.ts`, run `cd packages/tui && go generate ./pkg/client/` to update the Go client code and OpenAPI spec. +- **API Client**: Go TUI communicates with TypeScript server via stainless SDK. When adding/modifying server endpoints in `packages/opencode/src/server/server.ts`, ask the user to generate a new client SDK to proceed with client-side changes. diff --git a/packages/opencode/src/app/app.ts b/packages/opencode/src/app/app.ts index 9b26c05bc..7358b2273 100644 --- a/packages/opencode/src/app/app.ts +++ b/packages/opencode/src/app/app.ts @@ -27,7 +27,7 @@ export namespace App { }), }) .openapi({ - ref: "App.Info", + ref: "App", }) export type Info = z.infer diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index efb379b52..160b5377a 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -40,7 +40,7 @@ export namespace Config { }) .strict() .openapi({ - ref: "Config.McpLocal", + ref: "McpLocalConfig", }) export const McpRemote = z @@ -50,7 +50,7 @@ export namespace Config { }) .strict() .openapi({ - ref: "Config.McpRemote", + ref: "McpRemoteConfig", }) export const Mcp = z.discriminatedUnion("type", [McpLocal, McpRemote]) @@ -124,7 +124,7 @@ export namespace Config { }) .strict() .openapi({ - ref: "Config.Keybinds", + ref: "KeybindsConfig", }) export const Info = z .object({ @@ -197,7 +197,7 @@ export namespace Config { }) .strict() .openapi({ - ref: "Config.Info", + ref: "Config", }) export type Info = z.output diff --git a/packages/opencode/src/provider/models.ts b/packages/opencode/src/provider/models.ts index 5b255ecbd..09c54557a 100644 --- a/packages/opencode/src/provider/models.ts +++ b/packages/opencode/src/provider/models.ts @@ -29,7 +29,7 @@ export namespace ModelsDev { options: z.record(z.any()), }) .openapi({ - ref: "Model.Info", + ref: "Model", }) export type Model = z.infer @@ -43,7 +43,7 @@ export namespace ModelsDev { models: z.record(Model), }) .openapi({ - ref: "Provider.Info", + ref: "Provider", }) export type Provider = z.infer diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index c1aaadebe..34349dedd 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -9,12 +9,10 @@ import { z } from "zod" import { Message } from "../session/message" import { Provider } from "../provider/provider" import { App } from "../app/app" -import { Global } from "../global" import { mapValues } from "remeda" import { NamedError } from "../util/error" import { ModelsDev } from "../provider/models" import { Ripgrep } from "../external/ripgrep" -import { Installation } from "../installation" import { Config } from "../config/config" const ERRORS = { @@ -70,12 +68,12 @@ export namespace Server { }) }) .get( - "/openapi", + "/doc", openAPISpecs(app, { documentation: { info: { title: "opencode", - version: "1.0.0", + version: "0.0.2", description: "opencode api", }, openapi: "3.0.0", @@ -122,8 +120,8 @@ export namespace Server { }) }, ) - .post( - "/app_info", + .get( + "/app", describeRoute({ description: "Get app info", responses: { @@ -142,26 +140,7 @@ export namespace Server { }, ) .post( - "/config_get", - describeRoute({ - description: "Get config info", - responses: { - 200: { - description: "Get config info", - content: { - "application/json": { - schema: resolver(Config.Info), - }, - }, - }, - }, - }), - async (c) => { - return c.json(await Config.get()) - }, - ) - .post( - "/app_initialize", + "/app/init", describeRoute({ description: "Initialize the app", responses: { @@ -180,69 +159,47 @@ export namespace Server { return c.json(true) }, ) - .post( - "/session_initialize", + .get( + "/config", describeRoute({ - description: "Analyze the app and create an AGENTS.md file", + description: "Get config info", responses: { 200: { - description: "200", + description: "Get config info", content: { "application/json": { - schema: resolver(z.boolean()), + schema: resolver(Config.Info), }, }, }, }, }), - zValidator( - "json", - z.object({ - sessionID: z.string(), - providerID: z.string(), - modelID: z.string(), - }), - ), async (c) => { - const body = c.req.valid("json") - await Session.initialize(body) - return c.json(true) + return c.json(await Config.get()) }, ) - .post( - "/path_get", + .get( + "/session", describeRoute({ - description: "Get paths", + description: "List all sessions", responses: { 200: { - description: "200", + description: "List of sessions", content: { "application/json": { - schema: resolver( - z.object({ - root: z.string(), - data: z.string(), - cwd: z.string(), - config: z.string(), - }), - ), + schema: resolver(Session.Info.array()), }, }, }, }, }), async (c) => { - const app = App.info() - return c.json({ - root: app.path.root, - data: app.path.data, - cwd: app.path.cwd, - config: Global.Path.data, - }) + const sessions = await Array.fromAsync(Session.list()) + return c.json(sessions) }, ) .post( - "/session_create", + "/session", describeRoute({ description: "Create a new session", responses: { @@ -262,141 +219,155 @@ export namespace Server { return c.json(session) }, ) - .post( - "/session_share", + .delete( + "/session/:id", describeRoute({ - description: "Share the session", + description: "Delete a session and all its data", responses: { 200: { - description: "Successfully shared session", + description: "Successfully deleted session", content: { "application/json": { - schema: resolver(Session.Info), + schema: resolver(z.boolean()), }, }, }, }, }), zValidator( - "json", + "param", z.object({ - sessionID: z.string(), + id: z.string(), }), ), async (c) => { - const body = c.req.valid("json") - await Session.share(body.sessionID) - const session = await Session.get(body.sessionID) - return c.json(session) + await Session.remove(c.req.valid("param").id) + return c.json(true) }, ) .post( - "/session_unshare", + "/session/:id/init", describeRoute({ - description: "Unshare the session", + description: "Analyze the app and create an AGENTS.md file", responses: { 200: { - description: "Successfully unshared session", + description: "200", content: { "application/json": { - schema: resolver(Session.Info), + schema: resolver(z.boolean()), }, }, }, }, }), + zValidator( + "param", + z.object({ + id: z.string().openapi({ description: "Session ID" }), + }), + ), zValidator( "json", z.object({ - sessionID: z.string(), + providerID: z.string(), + modelID: z.string(), }), ), async (c) => { + const sessionID = c.req.valid("param").id const body = c.req.valid("json") - await Session.unshare(body.sessionID) - const session = await Session.get(body.sessionID) - return c.json(session) + await Session.initialize({ ...body, sessionID }) + return c.json(true) }, ) .post( - "/session_messages", + "/session/:id/abort", describeRoute({ - description: "Get messages for a session", + description: "Abort a session", responses: { 200: { - description: "Successfully created session", + description: "Aborted session", content: { "application/json": { - schema: resolver(Message.Info.array()), + schema: resolver(z.boolean()), }, }, }, }, }), zValidator( - "json", + "param", z.object({ - sessionID: z.string(), + id: z.string(), }), ), async (c) => { - const messages = await Session.messages(c.req.valid("json").sessionID) - return c.json(messages) + return c.json(Session.abort(c.req.valid("param").id)) }, ) .post( - "/session_list", + "/session/:id/share", describeRoute({ - description: "List all sessions", + description: "Share a session", responses: { 200: { - description: "List of sessions", + description: "Successfully shared session", content: { "application/json": { - schema: resolver(Session.Info.array()), + schema: resolver(Session.Info), }, }, }, }, }), + zValidator( + "param", + z.object({ + id: z.string(), + }), + ), async (c) => { - const sessions = await Array.fromAsync(Session.list()) - return c.json(sessions) + const id = c.req.valid("param").id + await Session.share(id) + const session = await Session.get(id) + return c.json(session) }, ) - .post( - "/session_abort", + .delete( + "/session/:id/share", describeRoute({ - description: "Abort a session", + description: "Unshare the session", responses: { 200: { - description: "Aborted session", + description: "Successfully unshared session", content: { "application/json": { - schema: resolver(z.boolean()), + schema: resolver(Session.Info), }, }, }, }, }), zValidator( - "json", + "param", z.object({ - sessionID: z.string(), + id: z.string(), }), ), async (c) => { - const body = c.req.valid("json") - return c.json(Session.abort(body.sessionID)) + const id = c.req.valid("param").id + await Session.unshare(id) + const session = await Session.get(id) + return c.json(session) }, ) .post( - "/session_delete", + "/session/:id/summarize", describeRoute({ - description: "Delete a session and all its data", + description: "Summarize the session", responses: { 200: { - description: "Successfully deleted session", + description: "Summarized session", content: { "application/json": { schema: resolver(z.boolean()), @@ -405,54 +376,59 @@ export namespace Server { }, }, }), + zValidator( + "param", + z.object({ + id: z.string().openapi({ description: "Session ID" }), + }), + ), zValidator( "json", z.object({ - sessionID: z.string(), + providerID: z.string(), + modelID: z.string(), }), ), async (c) => { + const id = c.req.valid("param").id const body = c.req.valid("json") - await Session.remove(body.sessionID) + await Session.summarize({ ...body, sessionID: id }) return c.json(true) }, ) - .post( - "/session_summarize", + .get( + "/session/:id/message", describeRoute({ - description: "Summarize the session", + description: "List messages for a session", responses: { 200: { - description: "Summarize the session", + description: "List of messages", content: { "application/json": { - schema: resolver(z.boolean()), + schema: resolver(Message.Info.array()), }, }, }, }, }), zValidator( - "json", + "param", z.object({ - sessionID: z.string(), - providerID: z.string(), - modelID: z.string(), + id: z.string().openapi({ description: "Session ID" }), }), ), async (c) => { - const body = c.req.valid("json") - await Session.summarize(body) - return c.json(true) + const messages = await Session.messages(c.req.valid("param").id) + return c.json(messages) }, ) .post( - "/session_chat", + "/session/:id/message", describeRoute({ - description: "Chat with a model", + description: "Create and send a new message to a session", responses: { 200: { - description: "Chat with a model", + description: "Created message", content: { "application/json": { schema: resolver(Message.Info), @@ -461,23 +437,29 @@ export namespace Server { }, }, }), + zValidator( + "param", + z.object({ + id: z.string().openapi({ description: "Session ID" }), + }), + ), zValidator( "json", z.object({ - sessionID: z.string(), providerID: z.string(), modelID: z.string(), - parts: Message.Part.array(), + parts: Message.MessagePart.array(), }), ), async (c) => { + const sessionID = c.req.valid("param").id const body = c.req.valid("json") - const msg = await Session.chat(body) + const msg = await Session.chat({ ...body, sessionID }) return c.json(msg) }, ) - .post( - "/provider_list", + .get( + "/config/providers", describeRoute({ description: "List all providers", responses: { @@ -509,8 +491,8 @@ export namespace Server { }) }, ) - .post( - "/file_search", + .get( + "/file", describeRoute({ description: "Search for files", responses: { @@ -525,41 +507,22 @@ export namespace Server { }, }), zValidator( - "json", + "query", z.object({ query: z.string(), }), ), async (c) => { - const body = c.req.valid("json") + const query = c.req.valid("query").query const app = App.info() const result = await Ripgrep.files({ cwd: app.path.cwd, - query: body.query, + query, limit: 10, }) return c.json(result) }, ) - .post( - "installation_info", - describeRoute({ - description: "Get installation info", - responses: { - 200: { - description: "Get installation info", - content: { - "application/json": { - schema: resolver(Installation.Info), - }, - }, - }, - }, - }), - async (c) => { - return c.json(Installation.info()) - }, - ) return result } diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index f457ba9c7..eef43fe58 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -55,14 +55,18 @@ export namespace Session { }), }) .openapi({ - ref: "session.info", + ref: "Session", }) export type Info = z.output - export const ShareInfo = z.object({ - secret: z.string(), - url: z.string(), - }) + export const ShareInfo = z + .object({ + secret: z.string(), + url: z.string(), + }) + .openapi({ + ref: "SessionShare", + }) export type ShareInfo = z.output export const Event = { @@ -273,7 +277,7 @@ export namespace Session { sessionID: string providerID: string modelID: string - parts: Message.Part[] + parts: Message.MessagePart[] system?: string[] tools?: Tool.Info[] }) { @@ -951,7 +955,7 @@ function toUIMessage(msg: Message.Info): UIMessage { throw new Error("not implemented") } -function toParts(parts: Message.Part[]): UIMessage["parts"] { +function toParts(parts: Message.MessagePart[]): UIMessage["parts"] { const result: UIMessage["parts"] = [] for (const part of parts) { switch (part.type) { diff --git a/packages/opencode/src/session/message.ts b/packages/opencode/src/session/message.ts index 03ee332d9..6d16497e4 100644 --- a/packages/opencode/src/session/message.ts +++ b/packages/opencode/src/session/message.ts @@ -18,7 +18,7 @@ export namespace Message { args: z.custom>(), }) .openapi({ - ref: "Message.ToolInvocation.ToolCall", + ref: "ToolCall", }) export type ToolCall = z.infer @@ -31,7 +31,7 @@ export namespace Message { args: z.custom>(), }) .openapi({ - ref: "Message.ToolInvocation.ToolPartialCall", + ref: "ToolPartialCall", }) export type ToolPartialCall = z.infer @@ -45,14 +45,14 @@ export namespace Message { result: z.string(), }) .openapi({ - ref: "Message.ToolInvocation.ToolResult", + ref: "ToolResult", }) export type ToolResult = z.infer export const ToolInvocation = z .discriminatedUnion("state", [ToolCall, ToolPartialCall, ToolResult]) .openapi({ - ref: "Message.ToolInvocation", + ref: "ToolInvocation", }) export type ToolInvocation = z.infer @@ -62,7 +62,7 @@ export namespace Message { text: z.string(), }) .openapi({ - ref: "Message.Part.Text", + ref: "TextPart", }) export type TextPart = z.infer @@ -73,7 +73,7 @@ export namespace Message { providerMetadata: z.record(z.any()).optional(), }) .openapi({ - ref: "Message.Part.Reasoning", + ref: "ReasoningPart", }) export type ReasoningPart = z.infer @@ -83,7 +83,7 @@ export namespace Message { toolInvocation: ToolInvocation, }) .openapi({ - ref: "Message.Part.ToolInvocation", + ref: "ToolInvocationPart", }) export type ToolInvocationPart = z.infer @@ -96,7 +96,7 @@ export namespace Message { providerMetadata: z.record(z.any()).optional(), }) .openapi({ - ref: "Message.Part.SourceUrl", + ref: "SourceUrlPart", }) export type SourceUrlPart = z.infer @@ -108,7 +108,7 @@ export namespace Message { url: z.string(), }) .openapi({ - ref: "Message.Part.File", + ref: "FilePart", }) export type FilePart = z.infer @@ -117,11 +117,11 @@ export namespace Message { type: z.literal("step-start"), }) .openapi({ - ref: "Message.Part.StepStart", + ref: "StepStartPart", }) export type StepStartPart = z.infer - export const Part = z + export const MessagePart = z .discriminatedUnion("type", [ TextPart, ReasoningPart, @@ -131,15 +131,15 @@ export namespace Message { StepStartPart, ]) .openapi({ - ref: "Message.Part", + ref: "MessagePart", }) - export type Part = z.infer + export type MessagePart = z.infer export const Info = z .object({ id: z.string(), role: z.enum(["user", "assistant"]), - parts: z.array(Part), + parts: z.array(MessagePart), metadata: z .object({ time: z.object({ @@ -189,10 +189,10 @@ export namespace Message { }) .optional(), }) - .openapi({ ref: "Message.Metadata" }), + .openapi({ ref: "MessageMetadata" }), }) .openapi({ - ref: "Message.Info", + ref: "Message", }) export type Info = z.infer @@ -205,7 +205,11 @@ export namespace Message { ), PartUpdated: Bus.event( "message.part.updated", - z.object({ part: Part, sessionID: z.string(), messageID: z.string() }), + z.object({ + part: MessagePart, + sessionID: z.string(), + messageID: z.string(), + }), ), } } diff --git a/packages/tui/AGENTS.md b/packages/tui/AGENTS.md index 0000db9b8..753374f92 100644 --- a/packages/tui/AGENTS.md +++ b/packages/tui/AGENTS.md @@ -5,7 +5,6 @@ - **Build**: `go build ./cmd/opencode` (builds main binary) - **Test**: `go test ./...` (runs all tests) - **Single test**: `go test ./internal/theme -run TestLoadThemesFromJSON` (specific test) -- **Generate client**: `go generate ./pkg/client/` (after server endpoint changes) - **Release build**: Uses `.goreleaser.yml` configuration ## Code Style diff --git a/packages/tui/cmd/opencode/main.go b/packages/tui/cmd/opencode/main.go index d2a843d79..aea8256d8 100644 --- a/packages/tui/cmd/opencode/main.go +++ b/packages/tui/cmd/opencode/main.go @@ -9,6 +9,8 @@ import ( "strings" tea "github.com/charmbracelet/bubbletea/v2" + "github.com/sst/opencode-sdk-go" + "github.com/sst/opencode-sdk-go/option" "github.com/sst/opencode/internal/app" "github.com/sst/opencode/internal/tui" "github.com/sst/opencode/pkg/client" @@ -25,7 +27,7 @@ func main() { url := os.Getenv("OPENCODE_SERVER") appInfoStr := os.Getenv("OPENCODE_APP_INFO") - var appInfo client.AppInfo + var appInfo opencode.App err := json.Unmarshal([]byte(appInfoStr), &appInfo) if err != nil { slog.Error("Failed to unmarshal app info", "error", err) @@ -51,7 +53,10 @@ func main() { slog.Debug("TUI launched", "app", appInfo) - httpClient, err := client.NewClientWithResponses(url) + httpClient := opencode.NewClient( + option.WithBaseURL(url), + ) + if err != nil { slog.Error("Failed to create client", "error", err) os.Exit(1) @@ -73,13 +78,7 @@ func main() { tea.WithMouseCellMotion(), ) - eventClient, err := client.NewClient(url) - if err != nil { - slog.Error("Failed to create event client", "error", err) - os.Exit(1) - } - - evts, err := eventClient.Event(ctx) + evts, err := client.Event(httpClient, url, ctx) if err != nil { slog.Error("Failed to subscribe to events", "error", err) os.Exit(1) diff --git a/packages/tui/go.mod b/packages/tui/go.mod index 01b2947ae..434c4dc6d 100644 --- a/packages/tui/go.mod +++ b/packages/tui/go.mod @@ -16,6 +16,8 @@ require ( github.com/muesli/termenv v0.16.0 github.com/oapi-codegen/runtime v1.1.1 github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 + github.com/sst/opencode-sdk-go v0.1.0-alpha.5 + github.com/tidwall/gjson v1.14.4 rsc.io/qr v0.2.0 ) @@ -48,6 +50,9 @@ require ( github.com/sosodev/duration v1.3.1 // indirect github.com/speakeasy-api/openapi-overlay v0.9.0 // indirect github.com/spf13/cobra v1.9.1 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/tidwall/sjson v1.2.5 // indirect github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect golang.org/x/mod v0.24.0 // indirect golang.org/x/tools v0.31.0 // indirect @@ -68,10 +73,10 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/mattn/go-runewidth v0.0.16 github.com/microcosm-cc/bluemonday v1.0.27 // indirect github.com/muesli/cancelreader v0.2.2 // indirect - github.com/rivo/uniseg v0.4.7 // indirect + github.com/rivo/uniseg v0.4.7 github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/spf13/pflag v1.0.6 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect diff --git a/packages/tui/go.sum b/packages/tui/go.sum index 7574855d8..845b7ec24 100644 --- a/packages/tui/go.sum +++ b/packages/tui/go.sum @@ -191,6 +191,8 @@ github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wx github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= +github.com/sst/opencode-sdk-go v0.1.0-alpha.5 h1:iZjdSHLo6jOMjUbDH5JWi+44v76yNbEktsRqG/Qxrco= +github.com/sst/opencode-sdk-go v0.1.0-alpha.5/go.mod h1:uagorfAHZsVy6vf0xY6TlQraM4uCILdZ5tKKhl1oToM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -198,6 +200,16 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= diff --git a/packages/tui/internal/app/app.go b/packages/tui/internal/app/app.go index e8775921a..3bd48f02a 100644 --- a/packages/tui/internal/app/app.go +++ b/packages/tui/internal/app/app.go @@ -11,35 +11,35 @@ import ( "log/slog" tea "github.com/charmbracelet/bubbletea/v2" + "github.com/sst/opencode-sdk-go" "github.com/sst/opencode/internal/commands" "github.com/sst/opencode/internal/components/toast" "github.com/sst/opencode/internal/config" "github.com/sst/opencode/internal/styles" "github.com/sst/opencode/internal/theme" "github.com/sst/opencode/internal/util" - "github.com/sst/opencode/pkg/client" ) var RootPath string type App struct { - Info client.AppInfo + Info opencode.App Version string StatePath string - Config *client.ConfigInfo - Client *client.ClientWithResponses + Config *opencode.Config + Client *opencode.Client State *config.State - Provider *client.ProviderInfo - Model *client.ModelInfo - Session *client.SessionInfo - Messages []client.MessageInfo + Provider *opencode.Provider + Model *opencode.Model + Session *opencode.Session + Messages []opencode.Message Commands commands.CommandRegistry } -type SessionSelectedMsg = *client.SessionInfo +type SessionSelectedMsg = *opencode.Session type ModelSelectedMsg struct { - Provider client.ProviderInfo - Model client.ModelInfo + Provider opencode.Provider + Model opencode.Model } type SessionClearedMsg struct{} type CompactSessionMsg struct{} @@ -51,31 +51,24 @@ type CompletionDialogTriggeredMsg struct { InitialValue string } type OptimisticMessageAddedMsg struct { - Message client.MessageInfo + Message opencode.Message } func New( ctx context.Context, version string, - appInfo client.AppInfo, - httpClient *client.ClientWithResponses, + appInfo opencode.App, + httpClient *opencode.Client, ) (*App, error) { RootPath = appInfo.Path.Root - configResponse, err := httpClient.PostConfigGetWithResponse(ctx) + configInfo, err := httpClient.Config.Get(ctx) if err != nil { return nil, err } - if configResponse.StatusCode() != 200 || configResponse.JSON200 == nil { - return nil, fmt.Errorf("failed to get config: %d", configResponse.StatusCode()) - } - configInfo := configResponse.JSON200 - if configInfo.Keybinds == nil { - leader := "ctrl+x" - keybinds := client.ConfigKeybinds{ - Leader: &leader, - } - configInfo.Keybinds = &keybinds + + if configInfo.Keybinds.Leader == "" { + configInfo.Keybinds.Leader = "ctrl+x" } appStatePath := filepath.Join(appInfo.Path.State, "tui") @@ -85,16 +78,16 @@ func New( config.SaveState(appStatePath, appState) } - if configInfo.Theme != nil { - appState.Theme = *configInfo.Theme + if configInfo.Theme != "" { + appState.Theme = configInfo.Theme } - if configInfo.Model != nil { - splits := strings.Split(*configInfo.Model, "/") + + if configInfo.Model != "" { + splits := strings.Split(configInfo.Model, "/") appState.Provider = splits[0] appState.Model = strings.Join(splits[1:], "/") } - // Load themes from all directories if err := theme.LoadThemesFromDirectories( appInfo.Path.Config, appInfo.Path.Root, @@ -122,8 +115,8 @@ func New( Config: configInfo, State: appState, Client: httpClient, - Session: &client.SessionInfo{}, - Messages: []client.MessageInfo{}, + Session: &opencode.Session{}, + Messages: []opencode.Message{}, Commands: commands.LoadFromConfig(configInfo), } @@ -132,23 +125,19 @@ func New( func (a *App) InitializeProvider() tea.Cmd { return func() tea.Msg { - providersResponse, err := a.Client.PostProviderListWithResponse(context.Background()) + providersResponse, err := a.Client.Config.Providers(context.Background()) if err != nil { slog.Error("Failed to list providers", "error", err) // TODO: notify user return nil } - if providersResponse != nil && providersResponse.StatusCode() != 200 { - slog.Error("failed to retrieve providers", "status", providersResponse.StatusCode(), "message", string(providersResponse.Body)) - return nil - } - providers := []client.ProviderInfo{} - var defaultProvider *client.ProviderInfo - var defaultModel *client.ModelInfo + providers := providersResponse.Providers + var defaultProvider *opencode.Provider + var defaultModel *opencode.Model - var anthropic *client.ProviderInfo - for _, provider := range providersResponse.JSON200.Providers { - if provider.Id == "anthropic" { + var anthropic *opencode.Provider + for _, provider := range providers { + if provider.ID == "anthropic" { anthropic = &provider } } @@ -159,7 +148,7 @@ func (a *App) InitializeProvider() tea.Cmd { defaultModel = getDefaultModel(providersResponse, *anthropic) } - for _, provider := range providersResponse.JSON200.Providers { + for _, provider := range providers { if defaultProvider == nil || defaultModel == nil { defaultProvider = &provider defaultModel = getDefaultModel(providersResponse, provider) @@ -171,14 +160,14 @@ func (a *App) InitializeProvider() tea.Cmd { return nil } - var currentProvider *client.ProviderInfo - var currentModel *client.ModelInfo + var currentProvider *opencode.Provider + var currentModel *opencode.Model for _, provider := range providers { - if provider.Id == a.State.Provider { + if provider.ID == a.State.Provider { currentProvider = &provider for _, model := range provider.Models { - if model.Id == a.State.Model { + if model.ID == a.State.Model { currentModel = &model } } @@ -189,7 +178,6 @@ func (a *App) InitializeProvider() tea.Cmd { currentModel = defaultModel } - // TODO: handle no provider or model setup, yet return ModelSelectedMsg{ Provider: *currentProvider, Model: *currentModel, @@ -197,8 +185,8 @@ func (a *App) InitializeProvider() tea.Cmd { } } -func getDefaultModel(response *client.PostProviderListResponse, provider client.ProviderInfo) *client.ModelInfo { - if match, ok := response.JSON200.Default[provider.Id]; ok { +func getDefaultModel(response *opencode.ConfigProvidersResponse, provider opencode.Provider) *opencode.Model { + if match, ok := response.Default[provider.ID]; ok { model := provider.Models[match] return &model } else { @@ -222,7 +210,7 @@ func (a *App) IsBusy() bool { } lastMessage := a.Messages[len(a.Messages)-1] - return lastMessage.Metadata.Time.Completed == nil + return lastMessage.Metadata.Time.Completed == 0 } func (a *App) SaveState() { @@ -245,19 +233,14 @@ func (a *App) InitializeProject(ctx context.Context) tea.Cmd { cmds = append(cmds, util.CmdHandler(SessionSelectedMsg(session))) go func() { - response, err := a.Client.PostSessionInitialize(ctx, client.PostSessionInitializeJSONRequestBody{ - SessionID: a.Session.Id, - ProviderID: a.Provider.Id, - ModelID: a.Model.Id, + _, err := a.Client.Session.Init(ctx, a.Session.ID, opencode.SessionInitParams{ + ProviderID: opencode.F(a.Provider.ID), + ModelID: opencode.F(a.Model.ID), }) if err != nil { slog.Error("Failed to initialize project", "error", err) // status.Error(err.Error()) } - if response != nil && response.StatusCode != 200 { - slog.Error("Failed to initialize project", "error", response.StatusCode) - // status.Error(fmt.Sprintf("failed to initialize project: %d", response.StatusCode)) - } }() return tea.Batch(cmds...) @@ -265,48 +248,37 @@ func (a *App) InitializeProject(ctx context.Context) tea.Cmd { func (a *App) CompactSession(ctx context.Context) tea.Cmd { go func() { - response, err := a.Client.PostSessionSummarizeWithResponse(ctx, client.PostSessionSummarizeJSONRequestBody{ - SessionID: a.Session.Id, - ProviderID: a.Provider.Id, - ModelID: a.Model.Id, + _, err := a.Client.Session.Summarize(ctx, a.Session.ID, opencode.SessionSummarizeParams{ + ProviderID: opencode.F(a.Provider.ID), + ModelID: opencode.F(a.Model.ID), }) if err != nil { slog.Error("Failed to compact session", "error", err) } - if response != nil && response.StatusCode() != 200 { - slog.Error("Failed to compact session", "error", response.StatusCode) - } }() return nil } func (a *App) MarkProjectInitialized(ctx context.Context) error { - response, err := a.Client.PostAppInitialize(ctx) + _, err := a.Client.App.Init(ctx) if err != nil { slog.Error("Failed to mark project as initialized", "error", err) return err } - if response != nil && response.StatusCode != 200 { - return fmt.Errorf("failed to initialize project: %d", response.StatusCode) - } return nil } -func (a *App) CreateSession(ctx context.Context) (*client.SessionInfo, error) { - resp, err := a.Client.PostSessionCreateWithResponse(ctx) +func (a *App) CreateSession(ctx context.Context) (*opencode.Session, error) { + session, err := a.Client.Session.New(ctx) if err != nil { return nil, err } - if resp != nil && resp.StatusCode() != 200 { - return nil, fmt.Errorf("failed to create session: %d", resp.StatusCode()) - } - session := resp.JSON200 return session, nil } func (a *App) SendChatMessage(ctx context.Context, text string, attachments []Attachment) tea.Cmd { var cmds []tea.Cmd - if a.Session.Id == "" { + if a.Session.ID == "" { session, err := a.CreateSession(ctx) if err != nil { return toast.NewErrorToast(err.Error()) @@ -315,26 +287,18 @@ func (a *App) SendChatMessage(ctx context.Context, text string, attachments []At cmds = append(cmds, util.CmdHandler(SessionSelectedMsg(session))) } - part := client.MessagePart{} - part.FromMessagePartText(client.MessagePartText{ - Type: "text", - Text: text, - }) - parts := []client.MessagePart{part} - - optimisticMessage := client.MessageInfo{ - Id: fmt.Sprintf("optimistic-%d", time.Now().UnixNano()), - Role: client.User, - Parts: parts, - Metadata: client.MessageMetadata{ - SessionID: a.Session.Id, - Time: struct { - Completed *float32 `json:"completed,omitempty"` - Created float32 `json:"created"` - }{ - Created: float32(time.Now().Unix()), + optimisticMessage := opencode.Message{ + ID: fmt.Sprintf("optimistic-%d", time.Now().UnixNano()), + Role: opencode.MessageRoleUser, + Parts: []opencode.MessagePart{{ + Type: opencode.MessagePartTypeText, + Text: text, + }}, + Metadata: opencode.MessageMetadata{ + SessionID: a.Session.ID, + Time: opencode.MessageMetadataTime{ + Created: float64(time.Now().Unix()), }, - Tool: make(map[string]client.MessageMetadata_Tool_AdditionalProperties), }, } @@ -342,22 +306,21 @@ func (a *App) SendChatMessage(ctx context.Context, text string, attachments []At cmds = append(cmds, util.CmdHandler(OptimisticMessageAddedMsg{Message: optimisticMessage})) cmds = append(cmds, func() tea.Msg { - response, err := a.Client.PostSessionChat(ctx, client.PostSessionChatJSONRequestBody{ - SessionID: a.Session.Id, - Parts: parts, - ProviderID: a.Provider.Id, - ModelID: a.Model.Id, + _, err := a.Client.Session.Chat(ctx, a.Session.ID, opencode.SessionChatParams{ + Parts: opencode.F([]opencode.MessagePartUnionParam{ + opencode.TextPartParam{ + Type: opencode.F(opencode.TextPartTypeText), + Text: opencode.F(text), + }, + }), + ProviderID: opencode.F(a.Provider.ID), + ModelID: opencode.F(a.Model.ID), }) if err != nil { errormsg := fmt.Sprintf("failed to send message: %v", err) slog.Error(errormsg) return toast.NewErrorToast(errormsg)() } - if response != nil && response.StatusCode != 200 { - errormsg := fmt.Sprintf("failed to send message: %d", response.StatusCode) - slog.Error(errormsg) - return toast.NewErrorToast(errormsg)() - } return nil }) @@ -367,83 +330,61 @@ func (a *App) SendChatMessage(ctx context.Context, text string, attachments []At } func (a *App) Cancel(ctx context.Context, sessionID string) error { - response, err := a.Client.PostSessionAbort(ctx, client.PostSessionAbortJSONRequestBody{ - SessionID: sessionID, - }) + _, err := a.Client.Session.Abort(ctx, sessionID) if err != nil { slog.Error("Failed to cancel session", "error", err) // status.Error(err.Error()) return err } - if response != nil && response.StatusCode != 200 { - slog.Error("Failed to cancel session", "error", fmt.Sprintf("failed to cancel session: %d", response.StatusCode)) - // status.Error(fmt.Sprintf("failed to cancel session: %d", response.StatusCode)) - return fmt.Errorf("failed to cancel session: %d", response.StatusCode) - } return nil } -func (a *App) ListSessions(ctx context.Context) ([]client.SessionInfo, error) { - resp, err := a.Client.PostSessionListWithResponse(ctx) +func (a *App) ListSessions(ctx context.Context) ([]opencode.Session, error) { + response, err := a.Client.Session.List(ctx) if err != nil { return nil, err } - if resp.StatusCode() != 200 { - return nil, fmt.Errorf("failed to list sessions: %d", resp.StatusCode()) - } - if resp.JSON200 == nil { - return []client.SessionInfo{}, nil + if response == nil { + return []opencode.Session{}, nil } - sessions := *resp.JSON200 - + sessions := *response sort.Slice(sessions, func(i, j int) bool { return sessions[i].Time.Created-sessions[j].Time.Created > 0 }) - return sessions, nil } func (a *App) DeleteSession(ctx context.Context, sessionID string) error { - resp, err := a.Client.PostSessionDeleteWithResponse(ctx, client.PostSessionDeleteJSONRequestBody{ - SessionID: sessionID, - }) + _, err := a.Client.Session.Delete(ctx, sessionID) if err != nil { + slog.Error("Failed to delete session", "error", err) return err } - if resp.StatusCode() != 200 { - return fmt.Errorf("failed to delete session: %d", resp.StatusCode()) - } return nil } -func (a *App) ListMessages(ctx context.Context, sessionId string) ([]client.MessageInfo, error) { - resp, err := a.Client.PostSessionMessagesWithResponse(ctx, client.PostSessionMessagesJSONRequestBody{SessionID: sessionId}) +func (a *App) ListMessages(ctx context.Context, sessionId string) ([]opencode.Message, error) { + response, err := a.Client.Session.Messages(ctx, sessionId) if err != nil { return nil, err } - if resp.StatusCode() != 200 { - return nil, fmt.Errorf("failed to list messages: %d", resp.StatusCode()) - } - if resp.JSON200 == nil { - return []client.MessageInfo{}, nil + if response == nil { + return []opencode.Message{}, nil } - messages := *resp.JSON200 + messages := *response return messages, nil } -func (a *App) ListProviders(ctx context.Context) ([]client.ProviderInfo, error) { - resp, err := a.Client.PostProviderListWithResponse(ctx) +func (a *App) ListProviders(ctx context.Context) ([]opencode.Provider, error) { + response, err := a.Client.Config.Providers(ctx) if err != nil { return nil, err } - if resp.StatusCode() != 200 { - return nil, fmt.Errorf("failed to list sessions: %d", resp.StatusCode()) - } - if resp.JSON200 == nil { - return []client.ProviderInfo{}, nil + if response == nil { + return []opencode.Provider{}, nil } - providers := *resp.JSON200 + providers := *response return providers.Providers, nil } diff --git a/packages/tui/internal/commands/command.go b/packages/tui/internal/commands/command.go index fc27025f6..4ef458832 100644 --- a/packages/tui/internal/commands/command.go +++ b/packages/tui/internal/commands/command.go @@ -6,7 +6,7 @@ import ( "strings" tea "github.com/charmbracelet/bubbletea/v2" - "github.com/sst/opencode/pkg/client" + "github.com/sst/opencode-sdk-go" ) type ExecuteCommandMsg Command @@ -123,7 +123,7 @@ func parseBindings(bindings ...string) []Keybinding { return parsedBindings } -func LoadFromConfig(config *client.ConfigInfo) CommandRegistry { +func LoadFromConfig(config *opencode.Config) CommandRegistry { defaults := []Command{ { Name: AppHelpCommand, @@ -269,10 +269,10 @@ func LoadFromConfig(config *client.ConfigInfo) CommandRegistry { } registry := make(CommandRegistry) keybinds := map[string]string{} - marshalled, _ := json.Marshal(*config.Keybinds) + marshalled, _ := json.Marshal(config.Keybinds) json.Unmarshal(marshalled, &keybinds) for _, command := range defaults { - if keybind, ok := keybinds[string(command.Name)]; ok { + if keybind, ok := keybinds[string(command.Name)]; ok && keybind != "" { command.Keybindings = parseBindings(keybind) } registry[command.Name] = command diff --git a/packages/tui/internal/completions/files-folders.go b/packages/tui/internal/completions/files-folders.go index 491b67aac..6fb4316fc 100644 --- a/packages/tui/internal/completions/files-folders.go +++ b/packages/tui/internal/completions/files-folders.go @@ -3,9 +3,9 @@ package completions import ( "context" + "github.com/sst/opencode-sdk-go" "github.com/sst/opencode/internal/app" "github.com/sst/opencode/internal/components/dialog" - "github.com/sst/opencode/pkg/client" ) type filesAndFoldersContextGroup struct { @@ -29,17 +29,14 @@ func (cg *filesAndFoldersContextGroup) GetEmptyMessage() string { } func (cg *filesAndFoldersContextGroup) getFiles(query string) ([]string, error) { - response, err := cg.app.Client.PostFileSearchWithResponse(context.Background(), client.PostFileSearchJSONRequestBody{ - Query: query, - }) + files, err := cg.app.Client.File.Search( + context.Background(), + opencode.FileSearchParams{Query: opencode.F(query)}, + ) if err != nil { return []string{}, err } - if response.JSON200 == nil { - return []string{}, nil - } - - return *response.JSON200, nil + return *files, nil } func (cg *filesAndFoldersContextGroup) GetChildEntries(query string) ([]dialog.CompletionItemI, error) { diff --git a/packages/tui/internal/components/chat/message.go b/packages/tui/internal/components/chat/message.go index 6fa52c1f4..cf4662d53 100644 --- a/packages/tui/internal/components/chat/message.go +++ b/packages/tui/internal/components/chat/message.go @@ -12,12 +12,13 @@ import ( "github.com/charmbracelet/lipgloss/v2" "github.com/charmbracelet/lipgloss/v2/compat" "github.com/charmbracelet/x/ansi" + "github.com/sst/opencode-sdk-go" "github.com/sst/opencode/internal/app" "github.com/sst/opencode/internal/components/diff" "github.com/sst/opencode/internal/layout" "github.com/sst/opencode/internal/styles" "github.com/sst/opencode/internal/theme" - "github.com/sst/opencode/pkg/client" + "github.com/tidwall/gjson" "golang.org/x/text/cases" "golang.org/x/text/language" ) @@ -209,7 +210,7 @@ func calculatePadding() int { } } -func renderText(message client.MessageInfo, text string, author string) string { +func renderText(message opencode.Message, text string, author string) string { t := theme.CurrentTheme() width := layout.Current.Container.Width padding := calculatePadding() @@ -223,7 +224,7 @@ func renderText(message client.MessageInfo, text string, author string) string { textWidth := max(lipgloss.Width(text), lipgloss.Width(info)) markdownWidth := min(textWidth, width-padding-4) // -4 for the border and padding - if message.Role == client.Assistant { + if message.Role == opencode.MessageRoleAssistant { markdownWidth = width - padding - 4 - 3 } minWidth := max(markdownWidth, (width-4)/2) @@ -235,18 +236,18 @@ func renderText(message client.MessageInfo, text string, author string) string { messageStyle = messageStyle.AlignHorizontal(lipgloss.Right) } content := messageStyle.Render(text) - if message.Role == client.Assistant { + if message.Role == opencode.MessageRoleAssistant { content = toMarkdown(text, markdownWidth, t.BackgroundPanel()) } content = strings.Join([]string{content, info}, "\n") switch message.Role { - case client.User: + case opencode.MessageRoleUser: return renderContentBlock(content, WithAlign(lipgloss.Right), WithBorderColor(t.Secondary()), ) - case client.Assistant: + case opencode.MessageRoleAssistant: return renderContentBlock(content, WithAlign(lipgloss.Left), WithBorderColor(t.Accent()), @@ -256,15 +257,16 @@ func renderText(message client.MessageInfo, text string, author string) string { } func renderToolInvocation( - toolCall client.MessageToolInvocationToolCall, + toolCall opencode.ToolInvocationPart, result *string, - metadata client.MessageMetadata_Tool_AdditionalProperties, + metadata opencode.MessageMetadataTool, showDetails bool, isLast bool, contentOnly bool, + messageMetadata opencode.MessageMetadata, ) string { ignoredTools := []string{"todoread"} - if slices.Contains(ignoredTools, toolCall.ToolName) { + if slices.Contains(ignoredTools, toolCall.ToolInvocation.ToolName) { return "" } @@ -294,8 +296,8 @@ func renderToolInvocation( BorderForeground(t.BackgroundPanel()). BorderStyle(lipgloss.ThickBorder()) - if toolCall.State == "partial-call" { - title := renderToolAction(toolCall.ToolName) + if toolCall.ToolInvocation.State == "partial-call" { + title := renderToolAction(toolCall.ToolInvocation.ToolName) if !showDetails { title = "∟ " + title padding := calculatePadding() @@ -316,8 +318,8 @@ func renderToolInvocation( toolArgs := "" toolArgsMap := make(map[string]any) - if toolCall.Args != nil { - value := *toolCall.Args + if toolCall.ToolInvocation.Args != nil { + value := toolCall.ToolInvocation.Args if m, ok := value.(map[string]any); ok { toolArgsMap = m @@ -339,28 +341,35 @@ func renderToolInvocation( error := "" finished := result != nil && *result != "" - if e, ok := metadata.Get("error"); ok && e.(bool) == true { - if m, ok := metadata.Get("message"); ok { - style = style.BorderLeftForeground(t.Error()) - error = styles.NewStyle(). - Foreground(t.Error()). - Background(t.BackgroundPanel()). - Render(m.(string)) - error = renderContentBlock( - error, - WithFullWidth(), - WithBorderColor(t.Error()), - WithMarginBottom(1), - ) - } + er := messageMetadata.Error.AsUnion() + switch er.(type) { + case nil: + default: + clientError := er.(opencode.UnknownError) + error = clientError.Data.Message + } + + if error != "" { + style = style.BorderLeftForeground(t.Error()) + error = styles.NewStyle(). + Foreground(t.Error()). + Background(t.BackgroundPanel()). + Render(error) + error = renderContentBlock( + error, + WithFullWidth(), + WithBorderColor(t.Error()), + WithMarginBottom(1), + ) } title := "" - switch toolCall.ToolName { + switch toolCall.ToolInvocation.ToolName { case "read": toolArgs = renderArgs(&toolArgsMap, "filePath") title = fmt.Sprintf("READ %s", toolArgs) - if preview, ok := metadata.Get("preview"); ok && toolArgsMap["filePath"] != nil { + preview := metadata.ExtraFields["preview"] + if preview != nil && toolArgsMap["filePath"] != nil { filename := toolArgsMap["filePath"].(string) body = preview.(string) body = renderFile(filename, body, WithTruncate(6)) @@ -368,8 +377,9 @@ func renderToolInvocation( case "edit": if filename, ok := toolArgsMap["filePath"].(string); ok { title = fmt.Sprintf("EDIT %s", relative(filename)) - if d, ok := metadata.Get("diff"); ok { - patch := d.(string) + diffField := metadata.ExtraFields["diff"] + if diffField != nil { + patch := diffField.(string) var formattedDiff string if layout.Current.Viewport.Width < 80 { formattedDiff, _ = diff.FormatUnifiedDiff( @@ -406,7 +416,7 @@ func renderToolInvocation( ) // Add diagnostics at the bottom if they exist - if diagnostics := renderDiagnostics(metadata, filename); diagnostics != "" { + if diagnostics := renderDiagnostics(messageMetadata, filename); diagnostics != "" { body += "\n" + renderContentBlock(diagnostics, WithFullWidth(), WithBorderColor(t.Error())) } } @@ -418,7 +428,7 @@ func renderToolInvocation( body = renderFile(filename, content) // Add diagnostics at the bottom if they exist - if diagnostics := renderDiagnostics(metadata, filename); diagnostics != "" { + if diagnostics := renderDiagnostics(messageMetadata, filename); diagnostics != "" { body += "\n" + renderContentBlock(diagnostics, WithFullWidth(), WithBorderColor(t.Error())) } } @@ -427,9 +437,10 @@ func renderToolInvocation( if description, ok := toolArgsMap["description"].(string); ok { title = fmt.Sprintf("SHELL %s", description) } - if stdout, ok := metadata.Get("stdout"); ok { + stdout := metadata.JSON.ExtraFields["stdout"] + if !stdout.IsNull() { command := toolArgsMap["command"].(string) - stdout := stdout.(string) + stdout := stdout.Raw() body = fmt.Sprintf("```console\n> %s\n%s```", command, stdout) body = toMarkdown(body, innerWidth, t.BackgroundPanel()) body = renderContentBlock(body, WithFullWidth(), WithMarginBottom(1)) @@ -450,12 +461,13 @@ func renderToolInvocation( case "todowrite": title = fmt.Sprintf("PLAN") - if to, ok := metadata.Get("todos"); ok && finished { - todos := to.([]any) - for _, todo := range todos { - t := todo.(map[string]any) - content := t["content"].(string) - switch t["status"].(string) { + todos := metadata.JSON.ExtraFields["todos"] + if !todos.IsNull() && finished { + strTodos := todos.Raw() + todos := gjson.Parse(strTodos) + for _, todo := range todos.Array() { + content := todo.Get("content").String() + switch todo.Get("status").String() { case "completed": body += fmt.Sprintf("- [x] %s\n", content) // case "in-progress": @@ -470,21 +482,22 @@ func renderToolInvocation( case "task": if description, ok := toolArgsMap["description"].(string); ok { title = fmt.Sprintf("TASK %s", description) - if summary, ok := metadata.Get("summary"); ok { - toolcalls := summary.([]any) - // toolcalls := + summary := metadata.JSON.ExtraFields["summary"] + if !summary.IsNull() { + strValue := summary.Raw() + toolcalls := gjson.Parse(strValue).Array() steps := []string{} for _, toolcall := range toolcalls { - call := toolcall.(map[string]any) + call := toolcall.Value().(map[string]any) if toolInvocation, ok := call["toolInvocation"].(map[string]any); ok { data, _ := json.Marshal(toolInvocation) - var toolCall client.MessageToolInvocationToolCall + var toolCall opencode.ToolInvocationPart _ = json.Unmarshal(data, &toolCall) if metadata, ok := call["metadata"].(map[string]any); ok { data, _ = json.Marshal(metadata) - var toolMetadata client.MessageMetadata_Tool_AdditionalProperties + var toolMetadata opencode.MessageMetadataTool _ = json.Unmarshal(data, &toolMetadata) step := renderToolInvocation( @@ -494,6 +507,7 @@ func renderToolInvocation( false, false, true, + messageMetadata, ) steps = append(steps, step) } @@ -505,7 +519,7 @@ func renderToolInvocation( } default: - toolName := renderToolName(toolCall.ToolName) + toolName := renderToolName(toolCall.ToolInvocation.ToolName) title = fmt.Sprintf("%s %s", toolName, toolArgs) if result == nil { empty := "" @@ -537,7 +551,7 @@ func renderToolInvocation( ) } - if body == "" && error == "" { + if body == "" && error == "" && result != nil { body = *result body = truncateHeight(body, 10) body = renderContentBlock(body, WithFullWidth(), WithMarginBottom(1)) @@ -716,31 +730,28 @@ type Diagnostic struct { } // renderDiagnostics formats LSP diagnostics for display in the TUI -func renderDiagnostics(metadata client.MessageMetadata_Tool_AdditionalProperties, filePath string) string { - diagnosticsData, ok := metadata.Get("diagnostics") - if !ok { +func renderDiagnostics(metadata opencode.MessageMetadata, filePath string) string { + diagnosticsData := metadata.JSON.ExtraFields["diagnostics"] + if diagnosticsData.IsNull() { return "" } // diagnosticsData should be a map[string][]Diagnostic - diagnosticsMap, ok := diagnosticsData.(map[string]interface{}) - if !ok { - return "" - } - + strDiagnosticsData := diagnosticsData.Raw() + diagnosticsMap := gjson.Parse(strDiagnosticsData).Value().(map[string]any) fileDiagnostics, ok := diagnosticsMap[filePath] if !ok { return "" } - diagnosticsList, ok := fileDiagnostics.([]interface{}) + diagnosticsList, ok := fileDiagnostics.([]any) if !ok { return "" } var errorDiagnostics []string for _, diagInterface := range diagnosticsList { - diagMap, ok := diagInterface.(map[string]interface{}) + diagMap, ok := diagInterface.(map[string]any) if !ok { continue } diff --git a/packages/tui/internal/components/chat/messages.go b/packages/tui/internal/components/chat/messages.go index da45545c9..e1c7a9d14 100644 --- a/packages/tui/internal/components/chat/messages.go +++ b/packages/tui/internal/components/chat/messages.go @@ -9,13 +9,13 @@ import ( "github.com/charmbracelet/bubbles/v2/viewport" tea "github.com/charmbracelet/bubbletea/v2" "github.com/charmbracelet/lipgloss/v2" + "github.com/sst/opencode-sdk-go" "github.com/sst/opencode/internal/app" "github.com/sst/opencode/internal/components/commands" "github.com/sst/opencode/internal/components/dialog" "github.com/sst/opencode/internal/layout" "github.com/sst/opencode/internal/styles" "github.com/sst/opencode/internal/theme" - "github.com/sst/opencode/pkg/client" ) type MessagesComponent interface { @@ -83,7 +83,7 @@ func (m *messagesComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if m.tail { m.viewport.GotoBottom() } - case client.EventSessionUpdated, client.EventMessageUpdated: + case opencode.EventListResponseEventSessionUpdated, opencode.EventListResponseEventMessageUpdated: m.renderView() if m.tail { m.viewport.GotoBottom() @@ -130,90 +130,97 @@ func (m *messagesComponent) renderView() { lastToolIndex := 0 lastToolIndices := []int{} for i, p := range message.Parts { - part, _ := p.ValueByDiscriminator() - switch part.(type) { - case client.MessagePartText: + switch p.Type { + case opencode.MessagePartTypeText: lastToolIndices = append(lastToolIndices, lastToolIndex) - case client.MessagePartToolInvocation: + case opencode.MessagePartTypeToolInvocation: lastToolIndex = i } } author := "" switch message.Role { - case client.User: + case opencode.MessageRoleUser: author = m.app.Info.User - case client.Assistant: + case opencode.MessageRoleAssistant: author = message.Metadata.Assistant.ModelID } for i, p := range message.Parts { - part, err := p.ValueByDiscriminator() - if err != nil { - continue //TODO: handle error? - } - - switch part.(type) { + switch part := p.AsUnion().(type) { // case client.MessagePartStepStart: // messages = append(messages, "") - case client.MessagePartText: - text := part.(client.MessagePartText) - key := m.cache.GenerateKey(message.Id, text.Text, layout.Current.Viewport.Width) + case opencode.TextPart: + key := m.cache.GenerateKey(message.ID, p.Text, layout.Current.Viewport.Width) content, cached = m.cache.Get(key) if !cached { - content = renderText(message, text.Text, author) + content = renderText(message, p.Text, author) m.cache.Set(key, content) } if previousBlockType != none { blocks = append(blocks, "") } blocks = append(blocks, content) - if message.Role == client.User { + if message.Role == opencode.MessageRoleUser { previousBlockType = userTextBlock - } else if message.Role == client.Assistant { + } else if message.Role == opencode.MessageRoleAssistant { previousBlockType = assistantTextBlock } - case client.MessagePartToolInvocation: + case opencode.ToolInvocationPart: isLastToolInvocation := slices.Contains(lastToolIndices, i) - toolInvocationPart := part.(client.MessagePartToolInvocation) - toolCall, _ := toolInvocationPart.ToolInvocation.AsMessageToolInvocationToolCall() - metadata := client.MessageMetadata_Tool_AdditionalProperties{} - if _, ok := message.Metadata.Tool[toolCall.ToolCallId]; ok { - metadata = message.Metadata.Tool[toolCall.ToolCallId] + metadata := opencode.MessageMetadataTool{} + + toolCallID := part.ToolInvocation.ToolCallID + // var toolCallID string + // var result *string + // switch toolCall := part.ToolInvocation.AsUnion().(type) { + // case opencode.ToolCall: + // toolCallID = toolCall.ToolCallID + // case opencode.ToolPartialCall: + // toolCallID = toolCall.ToolCallID + // case opencode.ToolResult: + // toolCallID = toolCall.ToolCallID + // result = &toolCall.Result + // } + + if _, ok := message.Metadata.Tool[toolCallID]; ok { + metadata = message.Metadata.Tool[toolCallID] } + var result *string - resultPart, resultError := toolInvocationPart.ToolInvocation.AsMessageToolInvocationToolResult() - if resultError == nil { - result = &resultPart.Result + if part.ToolInvocation.Result != "" { + result = &part.ToolInvocation.Result } - if toolCall.State == "result" { - key := m.cache.GenerateKey(message.Id, - toolCall.ToolCallId, + if part.ToolInvocation.State == "result" { + key := m.cache.GenerateKey(message.ID, + part.ToolInvocation.ToolCallID, m.showToolDetails, layout.Current.Viewport.Width, ) content, cached = m.cache.Get(key) if !cached { content = renderToolInvocation( - toolCall, + part, result, metadata, m.showToolDetails, isLastToolInvocation, false, + message.Metadata, ) m.cache.Set(key, content) } } else { // if the tool call isn't finished, don't cache content = renderToolInvocation( - toolCall, + part, result, metadata, m.showToolDetails, isLastToolInvocation, false, + message.Metadata, ) } @@ -226,16 +233,17 @@ func (m *messagesComponent) renderView() { } error := "" - if message.Metadata.Error != nil { - errorValue, _ := message.Metadata.Error.ValueByDiscriminator() - switch errorValue.(type) { - case client.UnknownError: - clientError := errorValue.(client.UnknownError) - error = clientError.Data.Message - error = renderContentBlock(error, WithBorderColor(t.Error()), WithFullWidth(), WithMarginTop(1), WithMarginBottom(1)) - blocks = append(blocks, error) - previousBlockType = errorBlock - } + switch err := message.Metadata.Error.AsUnion().(type) { + case nil: + default: + clientError := err.(opencode.UnknownError) + error = clientError.Data.Message + } + + if error != "" { + error = renderContentBlock(error, WithBorderColor(t.Error()), WithFullWidth(), WithMarginTop(1), WithMarginBottom(1)) + blocks = append(blocks, error) + previousBlockType = errorBlock } } @@ -254,7 +262,7 @@ func (m *messagesComponent) renderView() { } func (m *messagesComponent) header() string { - if m.app.Session.Id == "" { + if m.app.Session.ID == "" { return "" } @@ -264,8 +272,8 @@ func (m *messagesComponent) header() string { muted := styles.NewStyle().Foreground(t.TextMuted()).Background(t.Background()).Render headerLines := []string{} headerLines = append(headerLines, toMarkdown("# "+m.app.Session.Title, width-6, t.Background())) - if m.app.Session.Share != nil && m.app.Session.Share.Url != "" { - headerLines = append(headerLines, muted(m.app.Session.Share.Url)) + if m.app.Session.Share.URL != "" { + headerLines = append(headerLines, muted(m.app.Session.Share.URL)) } else { headerLines = append(headerLines, base("/share")+muted(" to create a shareable link")) } diff --git a/packages/tui/internal/components/commands/commands.go b/packages/tui/internal/components/commands/commands.go index d7f334c35..e20755575 100644 --- a/packages/tui/internal/components/commands/commands.go +++ b/packages/tui/internal/components/commands/commands.go @@ -128,7 +128,7 @@ func (c *commandsComponent) View() string { if c.showKeybinds { for _, kb := range cmd.Keybindings { if kb.RequiresLeader { - keybindStrs = append(keybindStrs, *c.app.Config.Keybinds.Leader+" "+kb.Key) + keybindStrs = append(keybindStrs, c.app.Config.Keybinds.Leader+" "+kb.Key) } else { keybindStrs = append(keybindStrs, kb.Key) } diff --git a/packages/tui/internal/components/dialog/models.go b/packages/tui/internal/components/dialog/models.go index 52ece493f..b43d48156 100644 --- a/packages/tui/internal/components/dialog/models.go +++ b/packages/tui/internal/components/dialog/models.go @@ -10,6 +10,7 @@ import ( "github.com/charmbracelet/bubbles/v2/key" tea "github.com/charmbracelet/bubbletea/v2" "github.com/charmbracelet/lipgloss/v2" + "github.com/sst/opencode-sdk-go" "github.com/sst/opencode/internal/app" "github.com/sst/opencode/internal/components/list" "github.com/sst/opencode/internal/components/modal" @@ -17,7 +18,6 @@ import ( "github.com/sst/opencode/internal/styles" "github.com/sst/opencode/internal/theme" "github.com/sst/opencode/internal/util" - "github.com/sst/opencode/pkg/client" ) const ( @@ -32,8 +32,8 @@ type ModelDialog interface { type modelDialog struct { app *app.App - availableProviders []client.ProviderInfo - provider client.ProviderInfo + availableProviders []opencode.Provider + provider opencode.Provider width int height int hScrollOffset int @@ -69,7 +69,7 @@ var modelKeys = modelKeyMap{ } func (m *modelDialog) Init() tea.Cmd { - m.setupModelsForProvider(m.provider.Id) + m.setupModelsForProvider(m.provider.ID) return nil } @@ -90,7 +90,7 @@ func (m *modelDialog) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case key.Matches(msg, modelKeys.Enter): selectedItem, _ := m.modelList.GetSelectedItem() models := m.models() - var selectedModel client.ModelInfo + var selectedModel opencode.Model for _, model := range models { if model.Name == string(selectedItem) { selectedModel = model @@ -119,8 +119,8 @@ func (m *modelDialog) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, cmd } -func (m *modelDialog) models() []client.ModelInfo { - models := slices.SortedFunc(maps.Values(m.provider.Models), func(a, b client.ModelInfo) int { +func (m *modelDialog) models() []opencode.Model { + models := slices.SortedFunc(maps.Values(m.provider.Models), func(a, b opencode.Model) int { return strings.Compare(a.Name, b.Name) }) return models @@ -139,7 +139,7 @@ func (m *modelDialog) switchProvider(offset int) { m.hScrollOffset = newOffset m.provider = m.availableProviders[m.hScrollOffset] m.modal.SetTitle(fmt.Sprintf("Select %s Model", m.provider.Name)) - m.setupModelsForProvider(m.provider.Id) + m.setupModelsForProvider(m.provider.ID) } func (m *modelDialog) View() string { @@ -175,9 +175,9 @@ func (m *modelDialog) setupModelsForProvider(providerId string) { m.modelList = list.NewStringList(modelNames, numVisibleModels, "No models available", true) m.modelList.SetMaxWidth(maxDialogWidth) - if m.app.Provider != nil && m.app.Model != nil && m.app.Provider.Id == providerId { + if m.app.Provider != nil && m.app.Model != nil && m.app.Provider.ID == providerId { for i, model := range models { - if model.Id == m.app.Model.Id { + if model.ID == m.app.Model.ID { m.modelList.SetSelectedIndex(i) break } @@ -200,7 +200,7 @@ func NewModelDialog(app *app.App) ModelDialog { hScrollOffset := 0 if app.Provider != nil { for i, provider := range availableProviders { - if provider.Id == app.Provider.Id { + if provider.ID == app.Provider.ID { currentProvider = provider hScrollOffset = i break @@ -220,6 +220,6 @@ func NewModelDialog(app *app.App) ModelDialog { ), } - dialog.setupModelsForProvider(currentProvider.Id) + dialog.setupModelsForProvider(currentProvider.ID) return dialog } diff --git a/packages/tui/internal/components/dialog/session.go b/packages/tui/internal/components/dialog/session.go index f38f37bf5..6f18dba0e 100644 --- a/packages/tui/internal/components/dialog/session.go +++ b/packages/tui/internal/components/dialog/session.go @@ -8,6 +8,7 @@ import ( tea "github.com/charmbracelet/bubbletea/v2" "github.com/muesli/reflow/truncate" + "github.com/sst/opencode-sdk-go" "github.com/sst/opencode/internal/app" "github.com/sst/opencode/internal/components/list" "github.com/sst/opencode/internal/components/modal" @@ -16,7 +17,6 @@ import ( "github.com/sst/opencode/internal/styles" "github.com/sst/opencode/internal/theme" "github.com/sst/opencode/internal/util" - "github.com/sst/opencode/pkg/client" ) // SessionDialog interface for the session switching dialog @@ -79,7 +79,7 @@ type sessionDialog struct { width int height int modal *modal.Modal - sessions []client.SessionInfo + sessions []opencode.Session list list.List[sessionItem] app *app.App deleteConfirmation int // -1 means no confirmation, >= 0 means confirming deletion of session at this index @@ -122,7 +122,7 @@ func (s *sessionDialog) Update(msg tea.Msg) (tea.Model, tea.Cmd) { s.updateListItems() return nil }, - s.deleteSession(sessionToDelete.Id), + s.deleteSession(sessionToDelete.ID), ) } else { // First press - enter delete confirmation mode @@ -193,10 +193,10 @@ func (s *sessionDialog) Close() tea.Cmd { func NewSessionDialog(app *app.App) SessionDialog { sessions, _ := app.ListSessions(context.Background()) - var filteredSessions []client.SessionInfo + var filteredSessions []opencode.Session var items []sessionItem for _, sess := range sessions { - if sess.ParentID != nil { + if sess.ParentID != "" { continue } filteredSessions = append(filteredSessions, sess) diff --git a/packages/tui/internal/components/status/status.go b/packages/tui/internal/components/status/status.go index fb5ff8ced..fb44cbcb8 100644 --- a/packages/tui/internal/components/status/status.go +++ b/packages/tui/internal/components/status/status.go @@ -48,7 +48,7 @@ func (m statusComponent) logo() string { Render(open + code + version) } -func formatTokensAndCost(tokens float32, contextWindow float32, cost float32) string { +func formatTokensAndCost(tokens float64, contextWindow float64, cost float64) string { // Format tokens in human-readable format (e.g., 110K, 1.2M) var formattedTokens string switch { @@ -77,7 +77,7 @@ func formatTokensAndCost(tokens float32, contextWindow float32, cost float32) st func (m statusComponent) View() string { t := theme.CurrentTheme() - if m.app.Session.Id == "" { + if m.app.Session.ID == "" { return styles.NewStyle(). Background(t.Background()). Width(m.width). @@ -94,13 +94,13 @@ func (m statusComponent) View() string { Render(m.app.Info.Path.Cwd) sessionInfo := "" - if m.app.Session.Id != "" { - tokens := float32(0) - cost := float32(0) + if m.app.Session.ID != "" { + tokens := float64(0) + cost := float64(0) contextWindow := m.app.Model.Limit.Context for _, message := range m.app.Messages { - if message.Metadata.Assistant != nil { + if message.Metadata.Assistant.Cost > 0 { cost += message.Metadata.Assistant.Cost usage := message.Metadata.Assistant.Tokens if usage.Output > 0 { diff --git a/packages/tui/internal/config/config.go b/packages/tui/internal/config/config.go index 29db8657e..258007a47 100644 --- a/packages/tui/internal/config/config.go +++ b/packages/tui/internal/config/config.go @@ -7,7 +7,6 @@ import ( "os" "github.com/BurntSushi/toml" - "github.com/sst/opencode/pkg/client" ) type State struct { @@ -22,13 +21,6 @@ func NewState() *State { } } -func MergeState(state *State, config *client.ConfigInfo) *client.ConfigInfo { - if config.Theme == nil { - config.Theme = &state.Theme - } - return config -} - // SaveState writes the provided Config struct to the specified TOML file. // It will create the file if it doesn't exist, or overwrite it if it does. func SaveState(filePath string, state *State) error { diff --git a/packages/tui/internal/tui/tui.go b/packages/tui/internal/tui/tui.go index 500ab56d4..89a34e351 100644 --- a/packages/tui/internal/tui/tui.go +++ b/packages/tui/internal/tui/tui.go @@ -12,6 +12,7 @@ import ( tea "github.com/charmbracelet/bubbletea/v2" "github.com/charmbracelet/lipgloss/v2" + "github.com/sst/opencode-sdk-go" "github.com/sst/opencode/internal/app" "github.com/sst/opencode/internal/commands" "github.com/sst/opencode/internal/completions" @@ -24,7 +25,6 @@ import ( "github.com/sst/opencode/internal/styles" "github.com/sst/opencode/internal/theme" "github.com/sst/opencode/internal/util" - "github.com/sst/opencode/pkg/client" ) // InterruptDebounceTimeoutMsg is sent when the interrupt key debounce timeout expires @@ -74,7 +74,7 @@ func (a appModel) Init() tea.Cmd { // Check if we should show the init dialog cmds = append(cmds, func() tea.Msg { - shouldShow := a.app.Info.Git && a.app.Info.Time.Initialized == nil + shouldShow := a.app.Info.Git && a.app.Info.Time.Initialized > 0 return dialog.ShowInitDialogMsg{Show: shouldShow} }) @@ -267,31 +267,31 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { cmds = append(cmds, cmd) case dialog.CompletionDialogCloseMsg: a.showCompletionDialog = false - case client.EventInstallationUpdated: + case opencode.EventListResponseEventInstallationUpdated: return a, toast.NewSuccessToast( "opencode updated to "+msg.Properties.Version+", restart to apply.", toast.WithTitle("New version installed"), ) - case client.EventSessionDeleted: - if a.app.Session != nil && msg.Properties.Info.Id == a.app.Session.Id { - a.app.Session = &client.SessionInfo{} - a.app.Messages = []client.MessageInfo{} + case opencode.EventListResponseEventSessionDeleted: + if a.app.Session != nil && msg.Properties.Info.ID == a.app.Session.ID { + a.app.Session = &opencode.Session{} + a.app.Messages = []opencode.Message{} } return a, toast.NewSuccessToast("Session deleted successfully") - case client.EventSessionUpdated: - if msg.Properties.Info.Id == a.app.Session.Id { + case opencode.EventListResponseEventSessionUpdated: + if msg.Properties.Info.ID == a.app.Session.ID { a.app.Session = &msg.Properties.Info } - case client.EventMessageUpdated: - if msg.Properties.Info.Metadata.SessionID == a.app.Session.Id { + case opencode.EventListResponseEventMessageUpdated: + if msg.Properties.Info.Metadata.SessionID == a.app.Session.ID { exists := false optimisticReplaced := false // First check if this is replacing an optimistic message - if msg.Properties.Info.Role == client.User { + if msg.Properties.Info.Role == opencode.MessageRoleUser { // Look for optimistic messages to replace for i, m := range a.app.Messages { - if strings.HasPrefix(m.Id, "optimistic-") && m.Role == client.User { + if strings.HasPrefix(m.ID, "optimistic-") && m.Role == opencode.MessageRoleUser { // Replace the optimistic message with the real one a.app.Messages[i] = msg.Properties.Info exists = true @@ -304,7 +304,7 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // If not replacing optimistic, check for existing message with same ID if !optimisticReplaced { for i, m := range a.app.Messages { - if m.Id == msg.Properties.Info.Id { + if m.ID == msg.Properties.Info.ID { a.app.Messages[i] = msg.Properties.Info exists = true break @@ -316,11 +316,12 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { a.app.Messages = append(a.app.Messages, msg.Properties.Info) } } - case client.EventSessionError: - unknownError, err := msg.Properties.Error.AsUnknownError() - if err == nil { - slog.Error("Server error", "name", unknownError.Name, "message", unknownError.Data.Message) - return a, toast.NewErrorToast(unknownError.Data.Message, toast.WithTitle(unknownError.Name)) + case opencode.EventListResponseEventSessionError: + switch err := msg.Properties.Error.AsUnion().(type) { + case nil: + case opencode.UnknownError: + slog.Error("Server error", "name", err.Name, "message", err.Data.Message) + return a, toast.NewErrorToast(err.Data.Message, toast.WithTitle(string(err.Name))) } case tea.WindowSizeMsg: msg.Height -= 2 // Make space for the status bar @@ -336,7 +337,7 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } a.layout.SetSize(a.width, a.height) case app.SessionSelectedMsg: - messages, err := a.app.ListMessages(context.Background(), msg.Id) + messages, err := a.app.ListMessages(context.Background(), msg.ID) if err != nil { slog.Error("Failed to list messages", "error", err) return a, toast.NewErrorToast("Failed to open session") @@ -346,8 +347,8 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case app.ModelSelectedMsg: a.app.Provider = &msg.Provider a.app.Model = &msg.Model - a.app.State.Provider = msg.Provider.Id - a.app.State.Model = msg.Model.Id + a.app.State.Provider = msg.Provider.ID + a.app.State.Model = msg.Model.ID a.app.SaveState() case dialog.ThemeSelectedMsg: a.app.State.Theme = msg.ThemeName @@ -499,42 +500,32 @@ func (a appModel) executeCommand(command commands.Command) (tea.Model, tea.Cmd) }) cmds = append(cmds, cmd) case commands.SessionNewCommand: - if a.app.Session.Id == "" { + if a.app.Session.ID == "" { return a, nil } - a.app.Session = &client.SessionInfo{} - a.app.Messages = []client.MessageInfo{} + a.app.Session = &opencode.Session{} + a.app.Messages = []opencode.Message{} cmds = append(cmds, util.CmdHandler(app.SessionClearedMsg{})) case commands.SessionListCommand: sessionDialog := dialog.NewSessionDialog(a.app) a.modal = sessionDialog case commands.SessionShareCommand: - if a.app.Session.Id == "" { + if a.app.Session.ID == "" { return a, nil } - response, err := a.app.Client.PostSessionShareWithResponse( - context.Background(), - client.PostSessionShareJSONRequestBody{ - SessionID: a.app.Session.Id, - }, - ) + _, err := a.app.Client.Session.Share(context.Background(), a.app.Session.ID) if err != nil { slog.Error("Failed to share session", "error", err) return a, toast.NewErrorToast("Failed to share session") } - if response.JSON200 != nil && response.JSON200.Share != nil { - shareUrl := response.JSON200.Share.Url - cmds = append(cmds, tea.SetClipboard(shareUrl)) - cmds = append(cmds, toast.NewSuccessToast("Share URL copied to clipboard!")) - } case commands.SessionInterruptCommand: - if a.app.Session.Id == "" { + if a.app.Session.ID == "" { return a, nil } - a.app.Cancel(context.Background(), a.app.Session.Id) + a.app.Cancel(context.Background(), a.app.Session.ID) return a, nil case commands.SessionCompactCommand: - if a.app.Session.Id == "" { + if a.app.Session.ID == "" { return a, nil } // TODO: block until compaction is complete @@ -642,8 +633,8 @@ func NewModel(app *app.App) tea.Model { messagesContainer := layout.NewContainer(messages) var leaderBinding *key.Binding - if (*app.Config.Keybinds).Leader != nil { - binding := key.NewBinding(key.WithKeys(*app.Config.Keybinds.Leader)) + if app.Config.Keybinds.Leader != "" { + binding := key.NewBinding(key.WithKeys(app.Config.Keybinds.Leader)) leaderBinding = &binding } diff --git a/packages/tui/pkg/client/client.go b/packages/tui/pkg/client/client.go deleted file mode 100644 index 1f53dd1e7..000000000 --- a/packages/tui/pkg/client/client.go +++ /dev/null @@ -1,4 +0,0 @@ -package client - -//go:generate bun run ../../../opencode/src/index.ts generate -//go:generate go tool github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --package=client --generate=types,client,models -o generated-client.go ./gen/openapi.json diff --git a/packages/tui/pkg/client/event.go b/packages/tui/pkg/client/event.go index 1c5dcdc65..96ae679d3 100644 --- a/packages/tui/pkg/client/event.go +++ b/packages/tui/pkg/client/event.go @@ -6,11 +6,13 @@ import ( "encoding/json" "net/http" "strings" + + "github.com/sst/opencode-sdk-go" ) -func (c *Client) Event(ctx context.Context) (<-chan any, error) { +func Event(c *opencode.Client, url string, ctx context.Context) (<-chan any, error) { events := make(chan any) - req, err := http.NewRequestWithContext(ctx, "GET", c.Server+"event", nil) + req, err := http.NewRequestWithContext(ctx, "GET", url+"event", nil) if err != nil { return nil, err } @@ -31,15 +33,12 @@ func (c *Client) Event(ctx context.Context) (<-chan any, error) { if strings.HasPrefix(line, "data: ") { data := strings.TrimPrefix(line, "data: ") - var event Event + var event opencode.EventListResponse if err := json.Unmarshal([]byte(data), &event); err != nil { continue } - val, err := event.ValueByDiscriminator() - if err != nil { - continue - } + val := event.AsUnion() select { case events <- val: diff --git a/packages/tui/pkg/client/gen/openapi.json b/packages/tui/pkg/client/gen/openapi.json deleted file mode 100644 index cb6cd5dca..000000000 --- a/packages/tui/pkg/client/gen/openapi.json +++ /dev/null @@ -1,2042 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "opencode", - "description": "opencode api", - "version": "1.0.0" - }, - "paths": { - "/event": { - "get": { - "responses": { - "200": { - "description": "Event stream", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Event" - } - } - } - } - }, - "operationId": "getEvent", - "parameters": [], - "description": "Get events" - } - }, - "/app_info": { - "post": { - "responses": { - "200": { - "description": "200", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/App.Info" - } - } - } - } - }, - "operationId": "postApp_info", - "parameters": [], - "description": "Get app info" - } - }, - "/config_get": { - "post": { - "responses": { - "200": { - "description": "Get config info", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Config.Info" - } - } - } - } - }, - "operationId": "postConfig_get", - "parameters": [], - "description": "Get config info" - } - }, - "/app_initialize": { - "post": { - "responses": { - "200": { - "description": "Initialize the app", - "content": { - "application/json": { - "schema": { - "type": "boolean" - } - } - } - } - }, - "operationId": "postApp_initialize", - "parameters": [], - "description": "Initialize the app" - } - }, - "/session_initialize": { - "post": { - "responses": { - "200": { - "description": "200", - "content": { - "application/json": { - "schema": { - "type": "boolean" - } - } - } - } - }, - "operationId": "postSession_initialize", - "parameters": [], - "description": "Analyze the app and create an AGENTS.md file", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "sessionID": { - "type": "string" - }, - "providerID": { - "type": "string" - }, - "modelID": { - "type": "string" - } - }, - "required": [ - "sessionID", - "providerID", - "modelID" - ] - } - } - } - } - } - }, - "/path_get": { - "post": { - "responses": { - "200": { - "description": "200", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "root": { - "type": "string" - }, - "data": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "config": { - "type": "string" - } - }, - "required": [ - "root", - "data", - "cwd", - "config" - ] - } - } - } - } - }, - "operationId": "postPath_get", - "parameters": [], - "description": "Get paths" - } - }, - "/session_create": { - "post": { - "responses": { - "200": { - "description": "Successfully created session", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/session.info" - } - } - } - }, - "400": { - "description": "Bad request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - }, - "operationId": "postSession_create", - "parameters": [], - "description": "Create a new session" - } - }, - "/session_share": { - "post": { - "responses": { - "200": { - "description": "Successfully shared session", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/session.info" - } - } - } - } - }, - "operationId": "postSession_share", - "parameters": [], - "description": "Share the session", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "sessionID": { - "type": "string" - } - }, - "required": [ - "sessionID" - ] - } - } - } - } - } - }, - "/session_unshare": { - "post": { - "responses": { - "200": { - "description": "Successfully unshared session", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/session.info" - } - } - } - } - }, - "operationId": "postSession_unshare", - "parameters": [], - "description": "Unshare the session", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "sessionID": { - "type": "string" - } - }, - "required": [ - "sessionID" - ] - } - } - } - } - } - }, - "/session_messages": { - "post": { - "responses": { - "200": { - "description": "Successfully created session", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Message.Info" - } - } - } - } - } - }, - "operationId": "postSession_messages", - "parameters": [], - "description": "Get messages for a session", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "sessionID": { - "type": "string" - } - }, - "required": [ - "sessionID" - ] - } - } - } - } - } - }, - "/session_list": { - "post": { - "responses": { - "200": { - "description": "List of sessions", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/session.info" - } - } - } - } - } - }, - "operationId": "postSession_list", - "parameters": [], - "description": "List all sessions" - } - }, - "/session_abort": { - "post": { - "responses": { - "200": { - "description": "Aborted session", - "content": { - "application/json": { - "schema": { - "type": "boolean" - } - } - } - } - }, - "operationId": "postSession_abort", - "parameters": [], - "description": "Abort a session", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "sessionID": { - "type": "string" - } - }, - "required": [ - "sessionID" - ] - } - } - } - } - } - }, - "/session_delete": { - "post": { - "responses": { - "200": { - "description": "Successfully deleted session", - "content": { - "application/json": { - "schema": { - "type": "boolean" - } - } - } - } - }, - "operationId": "postSession_delete", - "parameters": [], - "description": "Delete a session and all its data", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "sessionID": { - "type": "string" - } - }, - "required": [ - "sessionID" - ] - } - } - } - } - } - }, - "/session_summarize": { - "post": { - "responses": { - "200": { - "description": "Summarize the session", - "content": { - "application/json": { - "schema": { - "type": "boolean" - } - } - } - } - }, - "operationId": "postSession_summarize", - "parameters": [], - "description": "Summarize the session", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "sessionID": { - "type": "string" - }, - "providerID": { - "type": "string" - }, - "modelID": { - "type": "string" - } - }, - "required": [ - "sessionID", - "providerID", - "modelID" - ] - } - } - } - } - } - }, - "/session_chat": { - "post": { - "responses": { - "200": { - "description": "Chat with a model", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Message.Info" - } - } - } - } - }, - "operationId": "postSession_chat", - "parameters": [], - "description": "Chat with a model", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "sessionID": { - "type": "string" - }, - "providerID": { - "type": "string" - }, - "modelID": { - "type": "string" - }, - "parts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Message.Part" - } - } - }, - "required": [ - "sessionID", - "providerID", - "modelID", - "parts" - ] - } - } - } - } - } - }, - "/provider_list": { - "post": { - "responses": { - "200": { - "description": "List of providers", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "providers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Provider.Info" - } - }, - "default": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "providers", - "default" - ] - } - } - } - } - }, - "operationId": "postProvider_list", - "parameters": [], - "description": "List all providers" - } - }, - "/file_search": { - "post": { - "responses": { - "200": { - "description": "Search for files", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "operationId": "postFile_search", - "parameters": [], - "description": "Search for files", - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "query": { - "type": "string" - } - }, - "required": [ - "query" - ] - } - } - } - } - } - }, - "/installation_info": { - "post": { - "responses": { - "200": { - "description": "Get installation info", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InstallationInfo" - } - } - } - } - }, - "operationId": "postInstallation_info", - "parameters": [], - "description": "Get installation info" - } - } - }, - "components": { - "schemas": { - "Event": { - "oneOf": [ - { - "$ref": "#/components/schemas/Event.storage.write" - }, - { - "$ref": "#/components/schemas/Event.installation.updated" - }, - { - "$ref": "#/components/schemas/Event.lsp.client.diagnostics" - }, - { - "$ref": "#/components/schemas/Event.permission.updated" - }, - { - "$ref": "#/components/schemas/Event.message.updated" - }, - { - "$ref": "#/components/schemas/Event.message.part.updated" - }, - { - "$ref": "#/components/schemas/Event.session.updated" - }, - { - "$ref": "#/components/schemas/Event.session.deleted" - }, - { - "$ref": "#/components/schemas/Event.session.error" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "storage.write": "#/components/schemas/Event.storage.write", - "installation.updated": "#/components/schemas/Event.installation.updated", - "lsp.client.diagnostics": "#/components/schemas/Event.lsp.client.diagnostics", - "permission.updated": "#/components/schemas/Event.permission.updated", - "message.updated": "#/components/schemas/Event.message.updated", - "message.part.updated": "#/components/schemas/Event.message.part.updated", - "session.updated": "#/components/schemas/Event.session.updated", - "session.deleted": "#/components/schemas/Event.session.deleted", - "session.error": "#/components/schemas/Event.session.error" - } - } - }, - "Event.storage.write": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "storage.write" - }, - "properties": { - "type": "object", - "properties": { - "key": { - "type": "string" - }, - "content": {} - }, - "required": [ - "key" - ] - } - }, - "required": [ - "type", - "properties" - ] - }, - "Event.installation.updated": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "installation.updated" - }, - "properties": { - "type": "object", - "properties": { - "version": { - "type": "string" - } - }, - "required": [ - "version" - ] - } - }, - "required": [ - "type", - "properties" - ] - }, - "Event.lsp.client.diagnostics": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "lsp.client.diagnostics" - }, - "properties": { - "type": "object", - "properties": { - "serverID": { - "type": "string" - }, - "path": { - "type": "string" - } - }, - "required": [ - "serverID", - "path" - ] - } - }, - "required": [ - "type", - "properties" - ] - }, - "Event.permission.updated": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "permission.updated" - }, - "properties": { - "$ref": "#/components/schemas/permission.info" - } - }, - "required": [ - "type", - "properties" - ] - }, - "permission.info": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "sessionID": { - "type": "string" - }, - "title": { - "type": "string" - }, - "metadata": { - "type": "object", - "additionalProperties": {} - }, - "time": { - "type": "object", - "properties": { - "created": { - "type": "number" - } - }, - "required": [ - "created" - ] - } - }, - "required": [ - "id", - "sessionID", - "title", - "metadata", - "time" - ] - }, - "Event.message.updated": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "message.updated" - }, - "properties": { - "type": "object", - "properties": { - "info": { - "$ref": "#/components/schemas/Message.Info" - } - }, - "required": [ - "info" - ] - } - }, - "required": [ - "type", - "properties" - ] - }, - "Message.Info": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "role": { - "type": "string", - "enum": [ - "user", - "assistant" - ] - }, - "parts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Message.Part" - } - }, - "metadata": { - "$ref": "#/components/schemas/Message.Metadata" - } - }, - "required": [ - "id", - "role", - "parts", - "metadata" - ] - }, - "Message.Part": { - "oneOf": [ - { - "$ref": "#/components/schemas/Message.Part.Text" - }, - { - "$ref": "#/components/schemas/Message.Part.Reasoning" - }, - { - "$ref": "#/components/schemas/Message.Part.ToolInvocation" - }, - { - "$ref": "#/components/schemas/Message.Part.SourceUrl" - }, - { - "$ref": "#/components/schemas/Message.Part.File" - }, - { - "$ref": "#/components/schemas/Message.Part.StepStart" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "text": "#/components/schemas/Message.Part.Text", - "reasoning": "#/components/schemas/Message.Part.Reasoning", - "tool-invocation": "#/components/schemas/Message.Part.ToolInvocation", - "source-url": "#/components/schemas/Message.Part.SourceUrl", - "file": "#/components/schemas/Message.Part.File", - "step-start": "#/components/schemas/Message.Part.StepStart" - } - } - }, - "Message.Part.Text": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "text" - }, - "text": { - "type": "string" - } - }, - "required": [ - "type", - "text" - ] - }, - "Message.Part.Reasoning": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "reasoning" - }, - "text": { - "type": "string" - }, - "providerMetadata": { - "type": "object", - "additionalProperties": {} - } - }, - "required": [ - "type", - "text" - ] - }, - "Message.Part.ToolInvocation": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "tool-invocation" - }, - "toolInvocation": { - "$ref": "#/components/schemas/Message.ToolInvocation" - } - }, - "required": [ - "type", - "toolInvocation" - ] - }, - "Message.ToolInvocation": { - "oneOf": [ - { - "$ref": "#/components/schemas/Message.ToolInvocation.ToolCall" - }, - { - "$ref": "#/components/schemas/Message.ToolInvocation.ToolPartialCall" - }, - { - "$ref": "#/components/schemas/Message.ToolInvocation.ToolResult" - } - ], - "discriminator": { - "propertyName": "state", - "mapping": { - "call": "#/components/schemas/Message.ToolInvocation.ToolCall", - "partial-call": "#/components/schemas/Message.ToolInvocation.ToolPartialCall", - "result": "#/components/schemas/Message.ToolInvocation.ToolResult" - } - } - }, - "Message.ToolInvocation.ToolCall": { - "type": "object", - "properties": { - "state": { - "type": "string", - "const": "call" - }, - "step": { - "type": "number" - }, - "toolCallId": { - "type": "string" - }, - "toolName": { - "type": "string" - }, - "args": {} - }, - "required": [ - "state", - "toolCallId", - "toolName" - ] - }, - "Message.ToolInvocation.ToolPartialCall": { - "type": "object", - "properties": { - "state": { - "type": "string", - "const": "partial-call" - }, - "step": { - "type": "number" - }, - "toolCallId": { - "type": "string" - }, - "toolName": { - "type": "string" - }, - "args": {} - }, - "required": [ - "state", - "toolCallId", - "toolName" - ] - }, - "Message.ToolInvocation.ToolResult": { - "type": "object", - "properties": { - "state": { - "type": "string", - "const": "result" - }, - "step": { - "type": "number" - }, - "toolCallId": { - "type": "string" - }, - "toolName": { - "type": "string" - }, - "args": {}, - "result": { - "type": "string" - } - }, - "required": [ - "state", - "toolCallId", - "toolName", - "result" - ] - }, - "Message.Part.SourceUrl": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "source-url" - }, - "sourceId": { - "type": "string" - }, - "url": { - "type": "string" - }, - "title": { - "type": "string" - }, - "providerMetadata": { - "type": "object", - "additionalProperties": {} - } - }, - "required": [ - "type", - "sourceId", - "url" - ] - }, - "Message.Part.File": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "file" - }, - "mediaType": { - "type": "string" - }, - "filename": { - "type": "string" - }, - "url": { - "type": "string" - } - }, - "required": [ - "type", - "mediaType", - "url" - ] - }, - "Message.Part.StepStart": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "step-start" - } - }, - "required": [ - "type" - ] - }, - "Message.Metadata": { - "type": "object", - "properties": { - "time": { - "type": "object", - "properties": { - "created": { - "type": "number" - }, - "completed": { - "type": "number" - } - }, - "required": [ - "created" - ] - }, - "error": { - "oneOf": [ - { - "$ref": "#/components/schemas/ProviderAuthError" - }, - { - "$ref": "#/components/schemas/UnknownError" - }, - { - "$ref": "#/components/schemas/MessageOutputLengthError" - } - ], - "discriminator": { - "propertyName": "name", - "mapping": { - "ProviderAuthError": "#/components/schemas/ProviderAuthError", - "UnknownError": "#/components/schemas/UnknownError", - "MessageOutputLengthError": "#/components/schemas/MessageOutputLengthError" - } - } - }, - "sessionID": { - "type": "string" - }, - "tool": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "time": { - "type": "object", - "properties": { - "start": { - "type": "number" - }, - "end": { - "type": "number" - } - }, - "required": [ - "start", - "end" - ] - } - }, - "required": [ - "title", - "time" - ], - "additionalProperties": {} - } - }, - "assistant": { - "type": "object", - "properties": { - "system": { - "type": "array", - "items": { - "type": "string" - } - }, - "modelID": { - "type": "string" - }, - "providerID": { - "type": "string" - }, - "path": { - "type": "object", - "properties": { - "cwd": { - "type": "string" - }, - "root": { - "type": "string" - } - }, - "required": [ - "cwd", - "root" - ] - }, - "cost": { - "type": "number" - }, - "summary": { - "type": "boolean" - }, - "tokens": { - "type": "object", - "properties": { - "input": { - "type": "number" - }, - "output": { - "type": "number" - }, - "reasoning": { - "type": "number" - }, - "cache": { - "type": "object", - "properties": { - "read": { - "type": "number" - }, - "write": { - "type": "number" - } - }, - "required": [ - "read", - "write" - ] - } - }, - "required": [ - "input", - "output", - "reasoning", - "cache" - ] - } - }, - "required": [ - "system", - "modelID", - "providerID", - "path", - "cost", - "tokens" - ] - } - }, - "required": [ - "time", - "sessionID", - "tool" - ] - }, - "ProviderAuthError": { - "type": "object", - "properties": { - "name": { - "type": "string", - "const": "ProviderAuthError" - }, - "data": { - "type": "object", - "properties": { - "providerID": { - "type": "string" - }, - "message": { - "type": "string" - } - }, - "required": [ - "providerID", - "message" - ] - } - }, - "required": [ - "name", - "data" - ] - }, - "UnknownError": { - "type": "object", - "properties": { - "name": { - "type": "string", - "const": "UnknownError" - }, - "data": { - "type": "object", - "properties": { - "message": { - "type": "string" - } - }, - "required": [ - "message" - ] - } - }, - "required": [ - "name", - "data" - ] - }, - "MessageOutputLengthError": { - "type": "object", - "properties": { - "name": { - "type": "string", - "const": "MessageOutputLengthError" - }, - "data": { - "type": "object" - } - }, - "required": [ - "name", - "data" - ] - }, - "Event.message.part.updated": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "message.part.updated" - }, - "properties": { - "type": "object", - "properties": { - "part": { - "$ref": "#/components/schemas/Message.Part" - }, - "sessionID": { - "type": "string" - }, - "messageID": { - "type": "string" - } - }, - "required": [ - "part", - "sessionID", - "messageID" - ] - } - }, - "required": [ - "type", - "properties" - ] - }, - "Event.session.updated": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "session.updated" - }, - "properties": { - "type": "object", - "properties": { - "info": { - "$ref": "#/components/schemas/session.info" - } - }, - "required": [ - "info" - ] - } - }, - "required": [ - "type", - "properties" - ] - }, - "session.info": { - "type": "object", - "properties": { - "id": { - "type": "string", - "pattern": "^ses" - }, - "parentID": { - "type": "string", - "pattern": "^ses" - }, - "share": { - "type": "object", - "properties": { - "url": { - "type": "string" - } - }, - "required": [ - "url" - ] - }, - "title": { - "type": "string" - }, - "version": { - "type": "string" - }, - "time": { - "type": "object", - "properties": { - "created": { - "type": "number" - }, - "updated": { - "type": "number" - } - }, - "required": [ - "created", - "updated" - ] - } - }, - "required": [ - "id", - "title", - "version", - "time" - ] - }, - "Event.session.deleted": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "session.deleted" - }, - "properties": { - "type": "object", - "properties": { - "info": { - "$ref": "#/components/schemas/session.info" - } - }, - "required": [ - "info" - ] - } - }, - "required": [ - "type", - "properties" - ] - }, - "Event.session.error": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "session.error" - }, - "properties": { - "type": "object", - "properties": { - "error": { - "oneOf": [ - { - "$ref": "#/components/schemas/ProviderAuthError" - }, - { - "$ref": "#/components/schemas/UnknownError" - }, - { - "$ref": "#/components/schemas/MessageOutputLengthError" - } - ], - "discriminator": { - "propertyName": "name", - "mapping": { - "ProviderAuthError": "#/components/schemas/ProviderAuthError", - "UnknownError": "#/components/schemas/UnknownError", - "MessageOutputLengthError": "#/components/schemas/MessageOutputLengthError" - } - } - } - } - } - }, - "required": [ - "type", - "properties" - ] - }, - "App.Info": { - "type": "object", - "properties": { - "project": { - "type": "string" - }, - "user": { - "type": "string" - }, - "hostname": { - "type": "string" - }, - "git": { - "type": "boolean" - }, - "path": { - "type": "object", - "properties": { - "config": { - "type": "string" - }, - "data": { - "type": "string" - }, - "root": { - "type": "string" - }, - "cwd": { - "type": "string" - }, - "state": { - "type": "string" - } - }, - "required": [ - "config", - "data", - "root", - "cwd", - "state" - ] - }, - "time": { - "type": "object", - "properties": { - "initialized": { - "type": "number" - } - } - } - }, - "required": [ - "project", - "user", - "hostname", - "git", - "path", - "time" - ] - }, - "Config.Info": { - "type": "object", - "properties": { - "$schema": { - "type": "string", - "description": "JSON schema reference for configuration validation" - }, - "theme": { - "type": "string", - "description": "Theme name to use for the interface" - }, - "keybinds": { - "$ref": "#/components/schemas/Config.Keybinds", - "description": "Custom keybind configurations" - }, - "autoshare": { - "type": "boolean", - "description": "Share newly created sessions automatically" - }, - "autoupdate": { - "type": "boolean", - "description": "Automatically update to the latest version" - }, - "disabled_providers": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Disable providers that are loaded automatically" - }, - "model": { - "type": "string", - "description": "Model to use in the format of provider/model, eg anthropic/claude-2" - }, - "provider": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "api": { - "type": "string" - }, - "name": { - "type": "string" - }, - "env": { - "type": "array", - "items": { - "type": "string" - } - }, - "id": { - "type": "string" - }, - "npm": { - "type": "string" - }, - "models": { - "type": "object", - "additionalProperties": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "attachment": { - "type": "boolean" - }, - "reasoning": { - "type": "boolean" - }, - "temperature": { - "type": "boolean" - }, - "tool_call": { - "type": "boolean" - }, - "cost": { - "type": "object", - "properties": { - "input": { - "type": "number" - }, - "output": { - "type": "number" - }, - "cache_read": { - "type": "number" - }, - "cache_write": { - "type": "number" - } - }, - "required": [ - "input", - "output" - ] - }, - "limit": { - "type": "object", - "properties": { - "context": { - "type": "number" - }, - "output": { - "type": "number" - } - }, - "required": [ - "context", - "output" - ] - }, - "id": { - "type": "string" - }, - "options": { - "type": "object", - "additionalProperties": {} - } - } - } - }, - "options": { - "type": "object", - "additionalProperties": {} - } - }, - "required": [ - "models" - ] - }, - "description": "Custom provider configurations and model overrides" - }, - "mcp": { - "type": "object", - "additionalProperties": { - "oneOf": [ - { - "$ref": "#/components/schemas/Config.McpLocal" - }, - { - "$ref": "#/components/schemas/Config.McpRemote" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "local": "#/components/schemas/Config.McpLocal", - "remote": "#/components/schemas/Config.McpRemote" - } - } - }, - "description": "MCP (Model Context Protocol) server configurations" - }, - "experimental": { - "type": "object", - "properties": { - "hook": { - "type": "object", - "properties": { - "file_edited": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "object", - "properties": { - "command": { - "type": "array", - "items": { - "type": "string" - } - }, - "environment": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "command" - ] - } - } - }, - "session_completed": { - "type": "array", - "items": { - "type": "object", - "properties": { - "command": { - "type": "array", - "items": { - "type": "string" - } - }, - "environment": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - }, - "required": [ - "command" - ] - } - } - } - } - } - } - }, - "additionalProperties": false - }, - "Config.Keybinds": { - "type": "object", - "properties": { - "leader": { - "type": "string", - "description": "Leader key for keybind combinations" - }, - "help": { - "type": "string", - "description": "Show help dialog" - }, - "editor_open": { - "type": "string", - "description": "Open external editor" - }, - "session_new": { - "type": "string", - "description": "Create a new session" - }, - "session_list": { - "type": "string", - "description": "List all sessions" - }, - "session_share": { - "type": "string", - "description": "Share current session" - }, - "session_interrupt": { - "type": "string", - "description": "Interrupt current session" - }, - "session_compact": { - "type": "string", - "description": "Toggle compact mode for session" - }, - "tool_details": { - "type": "string", - "description": "Show tool details" - }, - "model_list": { - "type": "string", - "description": "List available models" - }, - "theme_list": { - "type": "string", - "description": "List available themes" - }, - "project_init": { - "type": "string", - "description": "Initialize project configuration" - }, - "input_clear": { - "type": "string", - "description": "Clear input field" - }, - "input_paste": { - "type": "string", - "description": "Paste from clipboard" - }, - "input_submit": { - "type": "string", - "description": "Submit input" - }, - "input_newline": { - "type": "string", - "description": "Insert newline in input" - }, - "history_previous": { - "type": "string", - "description": "Navigate to previous history item" - }, - "history_next": { - "type": "string", - "description": "Navigate to next history item" - }, - "messages_page_up": { - "type": "string", - "description": "Scroll messages up by one page" - }, - "messages_page_down": { - "type": "string", - "description": "Scroll messages down by one page" - }, - "messages_half_page_up": { - "type": "string", - "description": "Scroll messages up by half page" - }, - "messages_half_page_down": { - "type": "string", - "description": "Scroll messages down by half page" - }, - "messages_previous": { - "type": "string", - "description": "Navigate to previous message" - }, - "messages_next": { - "type": "string", - "description": "Navigate to next message" - }, - "messages_first": { - "type": "string", - "description": "Navigate to first message" - }, - "messages_last": { - "type": "string", - "description": "Navigate to last message" - }, - "app_exit": { - "type": "string", - "description": "Exit the application" - } - }, - "additionalProperties": false - }, - "Provider.Info": { - "type": "object", - "properties": { - "api": { - "type": "string" - }, - "name": { - "type": "string" - }, - "env": { - "type": "array", - "items": { - "type": "string" - } - }, - "id": { - "type": "string" - }, - "npm": { - "type": "string" - }, - "models": { - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/Model.Info" - } - } - }, - "required": [ - "name", - "env", - "id", - "models" - ] - }, - "Model.Info": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "attachment": { - "type": "boolean" - }, - "reasoning": { - "type": "boolean" - }, - "temperature": { - "type": "boolean" - }, - "tool_call": { - "type": "boolean" - }, - "cost": { - "type": "object", - "properties": { - "input": { - "type": "number" - }, - "output": { - "type": "number" - }, - "cache_read": { - "type": "number" - }, - "cache_write": { - "type": "number" - } - }, - "required": [ - "input", - "output" - ] - }, - "limit": { - "type": "object", - "properties": { - "context": { - "type": "number" - }, - "output": { - "type": "number" - } - }, - "required": [ - "context", - "output" - ] - }, - "id": { - "type": "string" - }, - "options": { - "type": "object", - "additionalProperties": {} - } - }, - "required": [ - "name", - "attachment", - "reasoning", - "temperature", - "tool_call", - "cost", - "limit", - "id", - "options" - ] - }, - "Config.McpLocal": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "local", - "description": "Type of MCP server connection" - }, - "command": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Command and arguments to run the MCP server" - }, - "environment": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "description": "Environment variables to set when running the MCP server" - } - }, - "required": [ - "type", - "command" - ], - "additionalProperties": false - }, - "Config.McpRemote": { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "remote", - "description": "Type of MCP server connection" - }, - "url": { - "type": "string", - "description": "URL of the remote MCP server" - } - }, - "required": [ - "type", - "url" - ], - "additionalProperties": false - }, - "Error": { - "type": "object", - "properties": { - "data": { - "type": "object", - "additionalProperties": {} - } - }, - "required": [ - "data" - ] - }, - "InstallationInfo": { - "type": "object", - "properties": { - "version": { - "type": "string" - }, - "latest": { - "type": "string" - } - }, - "required": [ - "version", - "latest" - ] - } - } - } -} \ No newline at end of file diff --git a/packages/tui/pkg/client/generated-client.go b/packages/tui/pkg/client/generated-client.go deleted file mode 100644 index aa74d3c17..000000000 --- a/packages/tui/pkg/client/generated-client.go +++ /dev/null @@ -1,3952 +0,0 @@ -// Package client provides primitives to interact with the openapi HTTP API. -// -// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.4.1 DO NOT EDIT. -package client - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "net/url" - "strings" - - "github.com/oapi-codegen/runtime" -) - -// Defines values for MessageInfoRole. -const ( - Assistant MessageInfoRole = "assistant" - User MessageInfoRole = "user" -) - -// AppInfo defines model for App.Info. -type AppInfo struct { - Git bool `json:"git"` - Hostname string `json:"hostname"` - Path struct { - Config string `json:"config"` - Cwd string `json:"cwd"` - Data string `json:"data"` - Root string `json:"root"` - State string `json:"state"` - } `json:"path"` - Project string `json:"project"` - Time struct { - Initialized *float32 `json:"initialized,omitempty"` - } `json:"time"` - User string `json:"user"` -} - -// ConfigInfo defines model for Config.Info. -type ConfigInfo struct { - // Schema JSON schema reference for configuration validation - Schema *string `json:"$schema,omitempty"` - - // Autoshare Share newly created sessions automatically - Autoshare *bool `json:"autoshare,omitempty"` - - // Autoupdate Automatically update to the latest version - Autoupdate *bool `json:"autoupdate,omitempty"` - - // DisabledProviders Disable providers that are loaded automatically - DisabledProviders *[]string `json:"disabled_providers,omitempty"` - Experimental *struct { - Hook *struct { - FileEdited *map[string][]struct { - Command []string `json:"command"` - Environment *map[string]string `json:"environment,omitempty"` - } `json:"file_edited,omitempty"` - SessionCompleted *[]struct { - Command []string `json:"command"` - Environment *map[string]string `json:"environment,omitempty"` - } `json:"session_completed,omitempty"` - } `json:"hook,omitempty"` - } `json:"experimental,omitempty"` - Keybinds *ConfigKeybinds `json:"keybinds,omitempty"` - - // Mcp MCP (Model Context Protocol) server configurations - Mcp *map[string]ConfigInfo_Mcp_AdditionalProperties `json:"mcp,omitempty"` - - // Model Model to use in the format of provider/model, eg anthropic/claude-2 - Model *string `json:"model,omitempty"` - - // Provider Custom provider configurations and model overrides - Provider *map[string]struct { - Api *string `json:"api,omitempty"` - Env *[]string `json:"env,omitempty"` - Id *string `json:"id,omitempty"` - Models map[string]struct { - Attachment *bool `json:"attachment,omitempty"` - Cost *struct { - CacheRead *float32 `json:"cache_read,omitempty"` - CacheWrite *float32 `json:"cache_write,omitempty"` - Input float32 `json:"input"` - Output float32 `json:"output"` - } `json:"cost,omitempty"` - Id *string `json:"id,omitempty"` - Limit *struct { - Context float32 `json:"context"` - Output float32 `json:"output"` - } `json:"limit,omitempty"` - Name *string `json:"name,omitempty"` - Options *map[string]interface{} `json:"options,omitempty"` - Reasoning *bool `json:"reasoning,omitempty"` - Temperature *bool `json:"temperature,omitempty"` - ToolCall *bool `json:"tool_call,omitempty"` - } `json:"models"` - Name *string `json:"name,omitempty"` - Npm *string `json:"npm,omitempty"` - Options *map[string]interface{} `json:"options,omitempty"` - } `json:"provider,omitempty"` - - // Theme Theme name to use for the interface - Theme *string `json:"theme,omitempty"` -} - -// ConfigInfo_Mcp_AdditionalProperties defines model for Config.Info.mcp.AdditionalProperties. -type ConfigInfo_Mcp_AdditionalProperties struct { - union json.RawMessage -} - -// ConfigKeybinds defines model for Config.Keybinds. -type ConfigKeybinds struct { - // AppExit Exit the application - AppExit *string `json:"app_exit,omitempty"` - - // EditorOpen Open external editor - EditorOpen *string `json:"editor_open,omitempty"` - - // Help Show help dialog - Help *string `json:"help,omitempty"` - - // HistoryNext Navigate to next history item - HistoryNext *string `json:"history_next,omitempty"` - - // HistoryPrevious Navigate to previous history item - HistoryPrevious *string `json:"history_previous,omitempty"` - - // InputClear Clear input field - InputClear *string `json:"input_clear,omitempty"` - - // InputNewline Insert newline in input - InputNewline *string `json:"input_newline,omitempty"` - - // InputPaste Paste from clipboard - InputPaste *string `json:"input_paste,omitempty"` - - // InputSubmit Submit input - InputSubmit *string `json:"input_submit,omitempty"` - - // Leader Leader key for keybind combinations - Leader *string `json:"leader,omitempty"` - - // MessagesFirst Navigate to first message - MessagesFirst *string `json:"messages_first,omitempty"` - - // MessagesHalfPageDown Scroll messages down by half page - MessagesHalfPageDown *string `json:"messages_half_page_down,omitempty"` - - // MessagesHalfPageUp Scroll messages up by half page - MessagesHalfPageUp *string `json:"messages_half_page_up,omitempty"` - - // MessagesLast Navigate to last message - MessagesLast *string `json:"messages_last,omitempty"` - - // MessagesNext Navigate to next message - MessagesNext *string `json:"messages_next,omitempty"` - - // MessagesPageDown Scroll messages down by one page - MessagesPageDown *string `json:"messages_page_down,omitempty"` - - // MessagesPageUp Scroll messages up by one page - MessagesPageUp *string `json:"messages_page_up,omitempty"` - - // MessagesPrevious Navigate to previous message - MessagesPrevious *string `json:"messages_previous,omitempty"` - - // ModelList List available models - ModelList *string `json:"model_list,omitempty"` - - // ProjectInit Initialize project configuration - ProjectInit *string `json:"project_init,omitempty"` - - // SessionCompact Toggle compact mode for session - SessionCompact *string `json:"session_compact,omitempty"` - - // SessionInterrupt Interrupt current session - SessionInterrupt *string `json:"session_interrupt,omitempty"` - - // SessionList List all sessions - SessionList *string `json:"session_list,omitempty"` - - // SessionNew Create a new session - SessionNew *string `json:"session_new,omitempty"` - - // SessionShare Share current session - SessionShare *string `json:"session_share,omitempty"` - - // ThemeList List available themes - ThemeList *string `json:"theme_list,omitempty"` - - // ToolDetails Show tool details - ToolDetails *string `json:"tool_details,omitempty"` -} - -// ConfigMcpLocal defines model for Config.McpLocal. -type ConfigMcpLocal struct { - // Command Command and arguments to run the MCP server - Command []string `json:"command"` - - // Environment Environment variables to set when running the MCP server - Environment *map[string]string `json:"environment,omitempty"` - - // Type Type of MCP server connection - Type string `json:"type"` -} - -// ConfigMcpRemote defines model for Config.McpRemote. -type ConfigMcpRemote struct { - // Type Type of MCP server connection - Type string `json:"type"` - - // Url URL of the remote MCP server - Url string `json:"url"` -} - -// Error defines model for Error. -type Error struct { - Data map[string]interface{} `json:"data"` -} - -// Event defines model for Event. -type Event struct { - union json.RawMessage -} - -// EventInstallationUpdated defines model for Event.installation.updated. -type EventInstallationUpdated struct { - Properties struct { - Version string `json:"version"` - } `json:"properties"` - Type string `json:"type"` -} - -// EventLspClientDiagnostics defines model for Event.lsp.client.diagnostics. -type EventLspClientDiagnostics struct { - Properties struct { - Path string `json:"path"` - ServerID string `json:"serverID"` - } `json:"properties"` - Type string `json:"type"` -} - -// EventMessagePartUpdated defines model for Event.message.part.updated. -type EventMessagePartUpdated struct { - Properties struct { - MessageID string `json:"messageID"` - Part MessagePart `json:"part"` - SessionID string `json:"sessionID"` - } `json:"properties"` - Type string `json:"type"` -} - -// EventMessageUpdated defines model for Event.message.updated. -type EventMessageUpdated struct { - Properties struct { - Info MessageInfo `json:"info"` - } `json:"properties"` - Type string `json:"type"` -} - -// EventPermissionUpdated defines model for Event.permission.updated. -type EventPermissionUpdated struct { - Properties PermissionInfo `json:"properties"` - Type string `json:"type"` -} - -// EventSessionDeleted defines model for Event.session.deleted. -type EventSessionDeleted struct { - Properties struct { - Info SessionInfo `json:"info"` - } `json:"properties"` - Type string `json:"type"` -} - -// EventSessionError defines model for Event.session.error. -type EventSessionError struct { - Properties struct { - Error *EventSessionError_Properties_Error `json:"error,omitempty"` - } `json:"properties"` - Type string `json:"type"` -} - -// EventSessionError_Properties_Error defines model for EventSessionError.Properties.Error. -type EventSessionError_Properties_Error struct { - union json.RawMessage -} - -// EventSessionUpdated defines model for Event.session.updated. -type EventSessionUpdated struct { - Properties struct { - Info SessionInfo `json:"info"` - } `json:"properties"` - Type string `json:"type"` -} - -// EventStorageWrite defines model for Event.storage.write. -type EventStorageWrite struct { - Properties struct { - Content *interface{} `json:"content,omitempty"` - Key string `json:"key"` - } `json:"properties"` - Type string `json:"type"` -} - -// InstallationInfo defines model for InstallationInfo. -type InstallationInfo struct { - Latest string `json:"latest"` - Version string `json:"version"` -} - -// MessageInfo defines model for Message.Info. -type MessageInfo struct { - Id string `json:"id"` - Metadata MessageMetadata `json:"metadata"` - Parts []MessagePart `json:"parts"` - Role MessageInfoRole `json:"role"` -} - -// MessageInfoRole defines model for MessageInfo.Role. -type MessageInfoRole string - -// MessageMetadata defines model for Message.Metadata. -type MessageMetadata struct { - Assistant *struct { - Cost float32 `json:"cost"` - ModelID string `json:"modelID"` - Path struct { - Cwd string `json:"cwd"` - Root string `json:"root"` - } `json:"path"` - ProviderID string `json:"providerID"` - Summary *bool `json:"summary,omitempty"` - System []string `json:"system"` - Tokens struct { - Cache struct { - Read float32 `json:"read"` - Write float32 `json:"write"` - } `json:"cache"` - Input float32 `json:"input"` - Output float32 `json:"output"` - Reasoning float32 `json:"reasoning"` - } `json:"tokens"` - } `json:"assistant,omitempty"` - Error *MessageMetadata_Error `json:"error,omitempty"` - SessionID string `json:"sessionID"` - Time struct { - Completed *float32 `json:"completed,omitempty"` - Created float32 `json:"created"` - } `json:"time"` - Tool map[string]MessageMetadata_Tool_AdditionalProperties `json:"tool"` -} - -// MessageMetadata_Error defines model for MessageMetadata.Error. -type MessageMetadata_Error struct { - union json.RawMessage -} - -// MessageMetadata_Tool_AdditionalProperties defines model for Message.Metadata.tool.AdditionalProperties. -type MessageMetadata_Tool_AdditionalProperties struct { - Time struct { - End float32 `json:"end"` - Start float32 `json:"start"` - } `json:"time"` - Title string `json:"title"` - AdditionalProperties map[string]interface{} `json:"-"` -} - -// MessagePart defines model for Message.Part. -type MessagePart struct { - union json.RawMessage -} - -// MessagePartFile defines model for Message.Part.File. -type MessagePartFile struct { - Filename *string `json:"filename,omitempty"` - MediaType string `json:"mediaType"` - Type string `json:"type"` - Url string `json:"url"` -} - -// MessagePartReasoning defines model for Message.Part.Reasoning. -type MessagePartReasoning struct { - ProviderMetadata *map[string]interface{} `json:"providerMetadata,omitempty"` - Text string `json:"text"` - Type string `json:"type"` -} - -// MessagePartSourceUrl defines model for Message.Part.SourceUrl. -type MessagePartSourceUrl struct { - ProviderMetadata *map[string]interface{} `json:"providerMetadata,omitempty"` - SourceId string `json:"sourceId"` - Title *string `json:"title,omitempty"` - Type string `json:"type"` - Url string `json:"url"` -} - -// MessagePartStepStart defines model for Message.Part.StepStart. -type MessagePartStepStart struct { - Type string `json:"type"` -} - -// MessagePartText defines model for Message.Part.Text. -type MessagePartText struct { - Text string `json:"text"` - Type string `json:"type"` -} - -// MessagePartToolInvocation defines model for Message.Part.ToolInvocation. -type MessagePartToolInvocation struct { - ToolInvocation MessageToolInvocation `json:"toolInvocation"` - Type string `json:"type"` -} - -// MessageToolInvocation defines model for Message.ToolInvocation. -type MessageToolInvocation struct { - union json.RawMessage -} - -// MessageToolInvocationToolCall defines model for Message.ToolInvocation.ToolCall. -type MessageToolInvocationToolCall struct { - Args *interface{} `json:"args,omitempty"` - State string `json:"state"` - Step *float32 `json:"step,omitempty"` - ToolCallId string `json:"toolCallId"` - ToolName string `json:"toolName"` -} - -// MessageToolInvocationToolPartialCall defines model for Message.ToolInvocation.ToolPartialCall. -type MessageToolInvocationToolPartialCall struct { - Args *interface{} `json:"args,omitempty"` - State string `json:"state"` - Step *float32 `json:"step,omitempty"` - ToolCallId string `json:"toolCallId"` - ToolName string `json:"toolName"` -} - -// MessageToolInvocationToolResult defines model for Message.ToolInvocation.ToolResult. -type MessageToolInvocationToolResult struct { - Args *interface{} `json:"args,omitempty"` - Result string `json:"result"` - State string `json:"state"` - Step *float32 `json:"step,omitempty"` - ToolCallId string `json:"toolCallId"` - ToolName string `json:"toolName"` -} - -// MessageOutputLengthError defines model for MessageOutputLengthError. -type MessageOutputLengthError struct { - Data map[string]interface{} `json:"data"` - Name string `json:"name"` -} - -// ModelInfo defines model for Model.Info. -type ModelInfo struct { - Attachment bool `json:"attachment"` - Cost struct { - CacheRead *float32 `json:"cache_read,omitempty"` - CacheWrite *float32 `json:"cache_write,omitempty"` - Input float32 `json:"input"` - Output float32 `json:"output"` - } `json:"cost"` - Id string `json:"id"` - Limit struct { - Context float32 `json:"context"` - Output float32 `json:"output"` - } `json:"limit"` - Name string `json:"name"` - Options map[string]interface{} `json:"options"` - Reasoning bool `json:"reasoning"` - Temperature bool `json:"temperature"` - ToolCall bool `json:"tool_call"` -} - -// ProviderInfo defines model for Provider.Info. -type ProviderInfo struct { - Api *string `json:"api,omitempty"` - Env []string `json:"env"` - Id string `json:"id"` - Models map[string]ModelInfo `json:"models"` - Name string `json:"name"` - Npm *string `json:"npm,omitempty"` -} - -// ProviderAuthError defines model for ProviderAuthError. -type ProviderAuthError struct { - Data struct { - Message string `json:"message"` - ProviderID string `json:"providerID"` - } `json:"data"` - Name string `json:"name"` -} - -// UnknownError defines model for UnknownError. -type UnknownError struct { - Data struct { - Message string `json:"message"` - } `json:"data"` - Name string `json:"name"` -} - -// PermissionInfo defines model for permission.info. -type PermissionInfo struct { - Id string `json:"id"` - Metadata map[string]interface{} `json:"metadata"` - SessionID string `json:"sessionID"` - Time struct { - Created float32 `json:"created"` - } `json:"time"` - Title string `json:"title"` -} - -// SessionInfo defines model for session.info. -type SessionInfo struct { - Id string `json:"id"` - ParentID *string `json:"parentID,omitempty"` - Share *struct { - Url string `json:"url"` - } `json:"share,omitempty"` - Time struct { - Created float32 `json:"created"` - Updated float32 `json:"updated"` - } `json:"time"` - Title string `json:"title"` - Version string `json:"version"` -} - -// PostFileSearchJSONBody defines parameters for PostFileSearch. -type PostFileSearchJSONBody struct { - Query string `json:"query"` -} - -// PostSessionAbortJSONBody defines parameters for PostSessionAbort. -type PostSessionAbortJSONBody struct { - SessionID string `json:"sessionID"` -} - -// PostSessionChatJSONBody defines parameters for PostSessionChat. -type PostSessionChatJSONBody struct { - ModelID string `json:"modelID"` - Parts []MessagePart `json:"parts"` - ProviderID string `json:"providerID"` - SessionID string `json:"sessionID"` -} - -// PostSessionDeleteJSONBody defines parameters for PostSessionDelete. -type PostSessionDeleteJSONBody struct { - SessionID string `json:"sessionID"` -} - -// PostSessionInitializeJSONBody defines parameters for PostSessionInitialize. -type PostSessionInitializeJSONBody struct { - ModelID string `json:"modelID"` - ProviderID string `json:"providerID"` - SessionID string `json:"sessionID"` -} - -// PostSessionMessagesJSONBody defines parameters for PostSessionMessages. -type PostSessionMessagesJSONBody struct { - SessionID string `json:"sessionID"` -} - -// PostSessionShareJSONBody defines parameters for PostSessionShare. -type PostSessionShareJSONBody struct { - SessionID string `json:"sessionID"` -} - -// PostSessionSummarizeJSONBody defines parameters for PostSessionSummarize. -type PostSessionSummarizeJSONBody struct { - ModelID string `json:"modelID"` - ProviderID string `json:"providerID"` - SessionID string `json:"sessionID"` -} - -// PostSessionUnshareJSONBody defines parameters for PostSessionUnshare. -type PostSessionUnshareJSONBody struct { - SessionID string `json:"sessionID"` -} - -// PostFileSearchJSONRequestBody defines body for PostFileSearch for application/json ContentType. -type PostFileSearchJSONRequestBody PostFileSearchJSONBody - -// PostSessionAbortJSONRequestBody defines body for PostSessionAbort for application/json ContentType. -type PostSessionAbortJSONRequestBody PostSessionAbortJSONBody - -// PostSessionChatJSONRequestBody defines body for PostSessionChat for application/json ContentType. -type PostSessionChatJSONRequestBody PostSessionChatJSONBody - -// PostSessionDeleteJSONRequestBody defines body for PostSessionDelete for application/json ContentType. -type PostSessionDeleteJSONRequestBody PostSessionDeleteJSONBody - -// PostSessionInitializeJSONRequestBody defines body for PostSessionInitialize for application/json ContentType. -type PostSessionInitializeJSONRequestBody PostSessionInitializeJSONBody - -// PostSessionMessagesJSONRequestBody defines body for PostSessionMessages for application/json ContentType. -type PostSessionMessagesJSONRequestBody PostSessionMessagesJSONBody - -// PostSessionShareJSONRequestBody defines body for PostSessionShare for application/json ContentType. -type PostSessionShareJSONRequestBody PostSessionShareJSONBody - -// PostSessionSummarizeJSONRequestBody defines body for PostSessionSummarize for application/json ContentType. -type PostSessionSummarizeJSONRequestBody PostSessionSummarizeJSONBody - -// PostSessionUnshareJSONRequestBody defines body for PostSessionUnshare for application/json ContentType. -type PostSessionUnshareJSONRequestBody PostSessionUnshareJSONBody - -// Getter for additional properties for MessageMetadata_Tool_AdditionalProperties. Returns the specified -// element and whether it was found -func (a MessageMetadata_Tool_AdditionalProperties) Get(fieldName string) (value interface{}, found bool) { - if a.AdditionalProperties != nil { - value, found = a.AdditionalProperties[fieldName] - } - return -} - -// Setter for additional properties for MessageMetadata_Tool_AdditionalProperties -func (a *MessageMetadata_Tool_AdditionalProperties) Set(fieldName string, value interface{}) { - if a.AdditionalProperties == nil { - a.AdditionalProperties = make(map[string]interface{}) - } - a.AdditionalProperties[fieldName] = value -} - -// Override default JSON handling for MessageMetadata_Tool_AdditionalProperties to handle AdditionalProperties -func (a *MessageMetadata_Tool_AdditionalProperties) UnmarshalJSON(b []byte) error { - object := make(map[string]json.RawMessage) - err := json.Unmarshal(b, &object) - if err != nil { - return err - } - - if raw, found := object["time"]; found { - err = json.Unmarshal(raw, &a.Time) - if err != nil { - return fmt.Errorf("error reading 'time': %w", err) - } - delete(object, "time") - } - - if raw, found := object["title"]; found { - err = json.Unmarshal(raw, &a.Title) - if err != nil { - return fmt.Errorf("error reading 'title': %w", err) - } - delete(object, "title") - } - - if len(object) != 0 { - a.AdditionalProperties = make(map[string]interface{}) - for fieldName, fieldBuf := range object { - var fieldVal interface{} - err := json.Unmarshal(fieldBuf, &fieldVal) - if err != nil { - return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err) - } - a.AdditionalProperties[fieldName] = fieldVal - } - } - return nil -} - -// Override default JSON handling for MessageMetadata_Tool_AdditionalProperties to handle AdditionalProperties -func (a MessageMetadata_Tool_AdditionalProperties) MarshalJSON() ([]byte, error) { - var err error - object := make(map[string]json.RawMessage) - - object["time"], err = json.Marshal(a.Time) - if err != nil { - return nil, fmt.Errorf("error marshaling 'time': %w", err) - } - - object["title"], err = json.Marshal(a.Title) - if err != nil { - return nil, fmt.Errorf("error marshaling 'title': %w", err) - } - - for fieldName, field := range a.AdditionalProperties { - object[fieldName], err = json.Marshal(field) - if err != nil { - return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err) - } - } - return json.Marshal(object) -} - -// AsConfigMcpLocal returns the union data inside the ConfigInfo_Mcp_AdditionalProperties as a ConfigMcpLocal -func (t ConfigInfo_Mcp_AdditionalProperties) AsConfigMcpLocal() (ConfigMcpLocal, error) { - var body ConfigMcpLocal - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromConfigMcpLocal overwrites any union data inside the ConfigInfo_Mcp_AdditionalProperties as the provided ConfigMcpLocal -func (t *ConfigInfo_Mcp_AdditionalProperties) FromConfigMcpLocal(v ConfigMcpLocal) error { - v.Type = "local" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeConfigMcpLocal performs a merge with any union data inside the ConfigInfo_Mcp_AdditionalProperties, using the provided ConfigMcpLocal -func (t *ConfigInfo_Mcp_AdditionalProperties) MergeConfigMcpLocal(v ConfigMcpLocal) error { - v.Type = "local" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsConfigMcpRemote returns the union data inside the ConfigInfo_Mcp_AdditionalProperties as a ConfigMcpRemote -func (t ConfigInfo_Mcp_AdditionalProperties) AsConfigMcpRemote() (ConfigMcpRemote, error) { - var body ConfigMcpRemote - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromConfigMcpRemote overwrites any union data inside the ConfigInfo_Mcp_AdditionalProperties as the provided ConfigMcpRemote -func (t *ConfigInfo_Mcp_AdditionalProperties) FromConfigMcpRemote(v ConfigMcpRemote) error { - v.Type = "remote" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeConfigMcpRemote performs a merge with any union data inside the ConfigInfo_Mcp_AdditionalProperties, using the provided ConfigMcpRemote -func (t *ConfigInfo_Mcp_AdditionalProperties) MergeConfigMcpRemote(v ConfigMcpRemote) error { - v.Type = "remote" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -func (t ConfigInfo_Mcp_AdditionalProperties) Discriminator() (string, error) { - var discriminator struct { - Discriminator string `json:"type"` - } - err := json.Unmarshal(t.union, &discriminator) - return discriminator.Discriminator, err -} - -func (t ConfigInfo_Mcp_AdditionalProperties) ValueByDiscriminator() (interface{}, error) { - discriminator, err := t.Discriminator() - if err != nil { - return nil, err - } - switch discriminator { - case "local": - return t.AsConfigMcpLocal() - case "remote": - return t.AsConfigMcpRemote() - default: - return nil, errors.New("unknown discriminator value: " + discriminator) - } -} - -func (t ConfigInfo_Mcp_AdditionalProperties) MarshalJSON() ([]byte, error) { - b, err := t.union.MarshalJSON() - return b, err -} - -func (t *ConfigInfo_Mcp_AdditionalProperties) UnmarshalJSON(b []byte) error { - err := t.union.UnmarshalJSON(b) - return err -} - -// AsEventStorageWrite returns the union data inside the Event as a EventStorageWrite -func (t Event) AsEventStorageWrite() (EventStorageWrite, error) { - var body EventStorageWrite - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromEventStorageWrite overwrites any union data inside the Event as the provided EventStorageWrite -func (t *Event) FromEventStorageWrite(v EventStorageWrite) error { - v.Type = "storage.write" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeEventStorageWrite performs a merge with any union data inside the Event, using the provided EventStorageWrite -func (t *Event) MergeEventStorageWrite(v EventStorageWrite) error { - v.Type = "storage.write" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsEventInstallationUpdated returns the union data inside the Event as a EventInstallationUpdated -func (t Event) AsEventInstallationUpdated() (EventInstallationUpdated, error) { - var body EventInstallationUpdated - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromEventInstallationUpdated overwrites any union data inside the Event as the provided EventInstallationUpdated -func (t *Event) FromEventInstallationUpdated(v EventInstallationUpdated) error { - v.Type = "installation.updated" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeEventInstallationUpdated performs a merge with any union data inside the Event, using the provided EventInstallationUpdated -func (t *Event) MergeEventInstallationUpdated(v EventInstallationUpdated) error { - v.Type = "installation.updated" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsEventLspClientDiagnostics returns the union data inside the Event as a EventLspClientDiagnostics -func (t Event) AsEventLspClientDiagnostics() (EventLspClientDiagnostics, error) { - var body EventLspClientDiagnostics - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromEventLspClientDiagnostics overwrites any union data inside the Event as the provided EventLspClientDiagnostics -func (t *Event) FromEventLspClientDiagnostics(v EventLspClientDiagnostics) error { - v.Type = "lsp.client.diagnostics" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeEventLspClientDiagnostics performs a merge with any union data inside the Event, using the provided EventLspClientDiagnostics -func (t *Event) MergeEventLspClientDiagnostics(v EventLspClientDiagnostics) error { - v.Type = "lsp.client.diagnostics" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsEventPermissionUpdated returns the union data inside the Event as a EventPermissionUpdated -func (t Event) AsEventPermissionUpdated() (EventPermissionUpdated, error) { - var body EventPermissionUpdated - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromEventPermissionUpdated overwrites any union data inside the Event as the provided EventPermissionUpdated -func (t *Event) FromEventPermissionUpdated(v EventPermissionUpdated) error { - v.Type = "permission.updated" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeEventPermissionUpdated performs a merge with any union data inside the Event, using the provided EventPermissionUpdated -func (t *Event) MergeEventPermissionUpdated(v EventPermissionUpdated) error { - v.Type = "permission.updated" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsEventMessageUpdated returns the union data inside the Event as a EventMessageUpdated -func (t Event) AsEventMessageUpdated() (EventMessageUpdated, error) { - var body EventMessageUpdated - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromEventMessageUpdated overwrites any union data inside the Event as the provided EventMessageUpdated -func (t *Event) FromEventMessageUpdated(v EventMessageUpdated) error { - v.Type = "message.updated" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeEventMessageUpdated performs a merge with any union data inside the Event, using the provided EventMessageUpdated -func (t *Event) MergeEventMessageUpdated(v EventMessageUpdated) error { - v.Type = "message.updated" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsEventMessagePartUpdated returns the union data inside the Event as a EventMessagePartUpdated -func (t Event) AsEventMessagePartUpdated() (EventMessagePartUpdated, error) { - var body EventMessagePartUpdated - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromEventMessagePartUpdated overwrites any union data inside the Event as the provided EventMessagePartUpdated -func (t *Event) FromEventMessagePartUpdated(v EventMessagePartUpdated) error { - v.Type = "message.part.updated" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeEventMessagePartUpdated performs a merge with any union data inside the Event, using the provided EventMessagePartUpdated -func (t *Event) MergeEventMessagePartUpdated(v EventMessagePartUpdated) error { - v.Type = "message.part.updated" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsEventSessionUpdated returns the union data inside the Event as a EventSessionUpdated -func (t Event) AsEventSessionUpdated() (EventSessionUpdated, error) { - var body EventSessionUpdated - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromEventSessionUpdated overwrites any union data inside the Event as the provided EventSessionUpdated -func (t *Event) FromEventSessionUpdated(v EventSessionUpdated) error { - v.Type = "session.updated" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeEventSessionUpdated performs a merge with any union data inside the Event, using the provided EventSessionUpdated -func (t *Event) MergeEventSessionUpdated(v EventSessionUpdated) error { - v.Type = "session.updated" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsEventSessionDeleted returns the union data inside the Event as a EventSessionDeleted -func (t Event) AsEventSessionDeleted() (EventSessionDeleted, error) { - var body EventSessionDeleted - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromEventSessionDeleted overwrites any union data inside the Event as the provided EventSessionDeleted -func (t *Event) FromEventSessionDeleted(v EventSessionDeleted) error { - v.Type = "session.deleted" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeEventSessionDeleted performs a merge with any union data inside the Event, using the provided EventSessionDeleted -func (t *Event) MergeEventSessionDeleted(v EventSessionDeleted) error { - v.Type = "session.deleted" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsEventSessionError returns the union data inside the Event as a EventSessionError -func (t Event) AsEventSessionError() (EventSessionError, error) { - var body EventSessionError - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromEventSessionError overwrites any union data inside the Event as the provided EventSessionError -func (t *Event) FromEventSessionError(v EventSessionError) error { - v.Type = "session.error" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeEventSessionError performs a merge with any union data inside the Event, using the provided EventSessionError -func (t *Event) MergeEventSessionError(v EventSessionError) error { - v.Type = "session.error" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -func (t Event) Discriminator() (string, error) { - var discriminator struct { - Discriminator string `json:"type"` - } - err := json.Unmarshal(t.union, &discriminator) - return discriminator.Discriminator, err -} - -func (t Event) ValueByDiscriminator() (interface{}, error) { - discriminator, err := t.Discriminator() - if err != nil { - return nil, err - } - switch discriminator { - case "installation.updated": - return t.AsEventInstallationUpdated() - case "lsp.client.diagnostics": - return t.AsEventLspClientDiagnostics() - case "message.part.updated": - return t.AsEventMessagePartUpdated() - case "message.updated": - return t.AsEventMessageUpdated() - case "permission.updated": - return t.AsEventPermissionUpdated() - case "session.deleted": - return t.AsEventSessionDeleted() - case "session.error": - return t.AsEventSessionError() - case "session.updated": - return t.AsEventSessionUpdated() - case "storage.write": - return t.AsEventStorageWrite() - default: - return nil, errors.New("unknown discriminator value: " + discriminator) - } -} - -func (t Event) MarshalJSON() ([]byte, error) { - b, err := t.union.MarshalJSON() - return b, err -} - -func (t *Event) UnmarshalJSON(b []byte) error { - err := t.union.UnmarshalJSON(b) - return err -} - -// AsProviderAuthError returns the union data inside the EventSessionError_Properties_Error as a ProviderAuthError -func (t EventSessionError_Properties_Error) AsProviderAuthError() (ProviderAuthError, error) { - var body ProviderAuthError - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromProviderAuthError overwrites any union data inside the EventSessionError_Properties_Error as the provided ProviderAuthError -func (t *EventSessionError_Properties_Error) FromProviderAuthError(v ProviderAuthError) error { - v.Name = "ProviderAuthError" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeProviderAuthError performs a merge with any union data inside the EventSessionError_Properties_Error, using the provided ProviderAuthError -func (t *EventSessionError_Properties_Error) MergeProviderAuthError(v ProviderAuthError) error { - v.Name = "ProviderAuthError" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsUnknownError returns the union data inside the EventSessionError_Properties_Error as a UnknownError -func (t EventSessionError_Properties_Error) AsUnknownError() (UnknownError, error) { - var body UnknownError - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromUnknownError overwrites any union data inside the EventSessionError_Properties_Error as the provided UnknownError -func (t *EventSessionError_Properties_Error) FromUnknownError(v UnknownError) error { - v.Name = "UnknownError" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeUnknownError performs a merge with any union data inside the EventSessionError_Properties_Error, using the provided UnknownError -func (t *EventSessionError_Properties_Error) MergeUnknownError(v UnknownError) error { - v.Name = "UnknownError" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsMessageOutputLengthError returns the union data inside the EventSessionError_Properties_Error as a MessageOutputLengthError -func (t EventSessionError_Properties_Error) AsMessageOutputLengthError() (MessageOutputLengthError, error) { - var body MessageOutputLengthError - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromMessageOutputLengthError overwrites any union data inside the EventSessionError_Properties_Error as the provided MessageOutputLengthError -func (t *EventSessionError_Properties_Error) FromMessageOutputLengthError(v MessageOutputLengthError) error { - v.Name = "MessageOutputLengthError" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeMessageOutputLengthError performs a merge with any union data inside the EventSessionError_Properties_Error, using the provided MessageOutputLengthError -func (t *EventSessionError_Properties_Error) MergeMessageOutputLengthError(v MessageOutputLengthError) error { - v.Name = "MessageOutputLengthError" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -func (t EventSessionError_Properties_Error) Discriminator() (string, error) { - var discriminator struct { - Discriminator string `json:"name"` - } - err := json.Unmarshal(t.union, &discriminator) - return discriminator.Discriminator, err -} - -func (t EventSessionError_Properties_Error) ValueByDiscriminator() (interface{}, error) { - discriminator, err := t.Discriminator() - if err != nil { - return nil, err - } - switch discriminator { - case "MessageOutputLengthError": - return t.AsMessageOutputLengthError() - case "ProviderAuthError": - return t.AsProviderAuthError() - case "UnknownError": - return t.AsUnknownError() - default: - return nil, errors.New("unknown discriminator value: " + discriminator) - } -} - -func (t EventSessionError_Properties_Error) MarshalJSON() ([]byte, error) { - b, err := t.union.MarshalJSON() - return b, err -} - -func (t *EventSessionError_Properties_Error) UnmarshalJSON(b []byte) error { - err := t.union.UnmarshalJSON(b) - return err -} - -// AsProviderAuthError returns the union data inside the MessageMetadata_Error as a ProviderAuthError -func (t MessageMetadata_Error) AsProviderAuthError() (ProviderAuthError, error) { - var body ProviderAuthError - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromProviderAuthError overwrites any union data inside the MessageMetadata_Error as the provided ProviderAuthError -func (t *MessageMetadata_Error) FromProviderAuthError(v ProviderAuthError) error { - v.Name = "ProviderAuthError" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeProviderAuthError performs a merge with any union data inside the MessageMetadata_Error, using the provided ProviderAuthError -func (t *MessageMetadata_Error) MergeProviderAuthError(v ProviderAuthError) error { - v.Name = "ProviderAuthError" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsUnknownError returns the union data inside the MessageMetadata_Error as a UnknownError -func (t MessageMetadata_Error) AsUnknownError() (UnknownError, error) { - var body UnknownError - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromUnknownError overwrites any union data inside the MessageMetadata_Error as the provided UnknownError -func (t *MessageMetadata_Error) FromUnknownError(v UnknownError) error { - v.Name = "UnknownError" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeUnknownError performs a merge with any union data inside the MessageMetadata_Error, using the provided UnknownError -func (t *MessageMetadata_Error) MergeUnknownError(v UnknownError) error { - v.Name = "UnknownError" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsMessageOutputLengthError returns the union data inside the MessageMetadata_Error as a MessageOutputLengthError -func (t MessageMetadata_Error) AsMessageOutputLengthError() (MessageOutputLengthError, error) { - var body MessageOutputLengthError - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromMessageOutputLengthError overwrites any union data inside the MessageMetadata_Error as the provided MessageOutputLengthError -func (t *MessageMetadata_Error) FromMessageOutputLengthError(v MessageOutputLengthError) error { - v.Name = "MessageOutputLengthError" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeMessageOutputLengthError performs a merge with any union data inside the MessageMetadata_Error, using the provided MessageOutputLengthError -func (t *MessageMetadata_Error) MergeMessageOutputLengthError(v MessageOutputLengthError) error { - v.Name = "MessageOutputLengthError" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -func (t MessageMetadata_Error) Discriminator() (string, error) { - var discriminator struct { - Discriminator string `json:"name"` - } - err := json.Unmarshal(t.union, &discriminator) - return discriminator.Discriminator, err -} - -func (t MessageMetadata_Error) ValueByDiscriminator() (interface{}, error) { - discriminator, err := t.Discriminator() - if err != nil { - return nil, err - } - switch discriminator { - case "MessageOutputLengthError": - return t.AsMessageOutputLengthError() - case "ProviderAuthError": - return t.AsProviderAuthError() - case "UnknownError": - return t.AsUnknownError() - default: - return nil, errors.New("unknown discriminator value: " + discriminator) - } -} - -func (t MessageMetadata_Error) MarshalJSON() ([]byte, error) { - b, err := t.union.MarshalJSON() - return b, err -} - -func (t *MessageMetadata_Error) UnmarshalJSON(b []byte) error { - err := t.union.UnmarshalJSON(b) - return err -} - -// AsMessagePartText returns the union data inside the MessagePart as a MessagePartText -func (t MessagePart) AsMessagePartText() (MessagePartText, error) { - var body MessagePartText - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromMessagePartText overwrites any union data inside the MessagePart as the provided MessagePartText -func (t *MessagePart) FromMessagePartText(v MessagePartText) error { - v.Type = "text" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeMessagePartText performs a merge with any union data inside the MessagePart, using the provided MessagePartText -func (t *MessagePart) MergeMessagePartText(v MessagePartText) error { - v.Type = "text" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsMessagePartReasoning returns the union data inside the MessagePart as a MessagePartReasoning -func (t MessagePart) AsMessagePartReasoning() (MessagePartReasoning, error) { - var body MessagePartReasoning - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromMessagePartReasoning overwrites any union data inside the MessagePart as the provided MessagePartReasoning -func (t *MessagePart) FromMessagePartReasoning(v MessagePartReasoning) error { - v.Type = "reasoning" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeMessagePartReasoning performs a merge with any union data inside the MessagePart, using the provided MessagePartReasoning -func (t *MessagePart) MergeMessagePartReasoning(v MessagePartReasoning) error { - v.Type = "reasoning" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsMessagePartToolInvocation returns the union data inside the MessagePart as a MessagePartToolInvocation -func (t MessagePart) AsMessagePartToolInvocation() (MessagePartToolInvocation, error) { - var body MessagePartToolInvocation - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromMessagePartToolInvocation overwrites any union data inside the MessagePart as the provided MessagePartToolInvocation -func (t *MessagePart) FromMessagePartToolInvocation(v MessagePartToolInvocation) error { - v.Type = "tool-invocation" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeMessagePartToolInvocation performs a merge with any union data inside the MessagePart, using the provided MessagePartToolInvocation -func (t *MessagePart) MergeMessagePartToolInvocation(v MessagePartToolInvocation) error { - v.Type = "tool-invocation" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsMessagePartSourceUrl returns the union data inside the MessagePart as a MessagePartSourceUrl -func (t MessagePart) AsMessagePartSourceUrl() (MessagePartSourceUrl, error) { - var body MessagePartSourceUrl - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromMessagePartSourceUrl overwrites any union data inside the MessagePart as the provided MessagePartSourceUrl -func (t *MessagePart) FromMessagePartSourceUrl(v MessagePartSourceUrl) error { - v.Type = "source-url" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeMessagePartSourceUrl performs a merge with any union data inside the MessagePart, using the provided MessagePartSourceUrl -func (t *MessagePart) MergeMessagePartSourceUrl(v MessagePartSourceUrl) error { - v.Type = "source-url" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsMessagePartFile returns the union data inside the MessagePart as a MessagePartFile -func (t MessagePart) AsMessagePartFile() (MessagePartFile, error) { - var body MessagePartFile - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromMessagePartFile overwrites any union data inside the MessagePart as the provided MessagePartFile -func (t *MessagePart) FromMessagePartFile(v MessagePartFile) error { - v.Type = "file" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeMessagePartFile performs a merge with any union data inside the MessagePart, using the provided MessagePartFile -func (t *MessagePart) MergeMessagePartFile(v MessagePartFile) error { - v.Type = "file" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsMessagePartStepStart returns the union data inside the MessagePart as a MessagePartStepStart -func (t MessagePart) AsMessagePartStepStart() (MessagePartStepStart, error) { - var body MessagePartStepStart - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromMessagePartStepStart overwrites any union data inside the MessagePart as the provided MessagePartStepStart -func (t *MessagePart) FromMessagePartStepStart(v MessagePartStepStart) error { - v.Type = "step-start" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeMessagePartStepStart performs a merge with any union data inside the MessagePart, using the provided MessagePartStepStart -func (t *MessagePart) MergeMessagePartStepStart(v MessagePartStepStart) error { - v.Type = "step-start" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -func (t MessagePart) Discriminator() (string, error) { - var discriminator struct { - Discriminator string `json:"type"` - } - err := json.Unmarshal(t.union, &discriminator) - return discriminator.Discriminator, err -} - -func (t MessagePart) ValueByDiscriminator() (interface{}, error) { - discriminator, err := t.Discriminator() - if err != nil { - return nil, err - } - switch discriminator { - case "file": - return t.AsMessagePartFile() - case "reasoning": - return t.AsMessagePartReasoning() - case "source-url": - return t.AsMessagePartSourceUrl() - case "step-start": - return t.AsMessagePartStepStart() - case "text": - return t.AsMessagePartText() - case "tool-invocation": - return t.AsMessagePartToolInvocation() - default: - return nil, errors.New("unknown discriminator value: " + discriminator) - } -} - -func (t MessagePart) MarshalJSON() ([]byte, error) { - b, err := t.union.MarshalJSON() - return b, err -} - -func (t *MessagePart) UnmarshalJSON(b []byte) error { - err := t.union.UnmarshalJSON(b) - return err -} - -// AsMessageToolInvocationToolCall returns the union data inside the MessageToolInvocation as a MessageToolInvocationToolCall -func (t MessageToolInvocation) AsMessageToolInvocationToolCall() (MessageToolInvocationToolCall, error) { - var body MessageToolInvocationToolCall - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromMessageToolInvocationToolCall overwrites any union data inside the MessageToolInvocation as the provided MessageToolInvocationToolCall -func (t *MessageToolInvocation) FromMessageToolInvocationToolCall(v MessageToolInvocationToolCall) error { - v.State = "call" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeMessageToolInvocationToolCall performs a merge with any union data inside the MessageToolInvocation, using the provided MessageToolInvocationToolCall -func (t *MessageToolInvocation) MergeMessageToolInvocationToolCall(v MessageToolInvocationToolCall) error { - v.State = "call" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsMessageToolInvocationToolPartialCall returns the union data inside the MessageToolInvocation as a MessageToolInvocationToolPartialCall -func (t MessageToolInvocation) AsMessageToolInvocationToolPartialCall() (MessageToolInvocationToolPartialCall, error) { - var body MessageToolInvocationToolPartialCall - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromMessageToolInvocationToolPartialCall overwrites any union data inside the MessageToolInvocation as the provided MessageToolInvocationToolPartialCall -func (t *MessageToolInvocation) FromMessageToolInvocationToolPartialCall(v MessageToolInvocationToolPartialCall) error { - v.State = "partial-call" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeMessageToolInvocationToolPartialCall performs a merge with any union data inside the MessageToolInvocation, using the provided MessageToolInvocationToolPartialCall -func (t *MessageToolInvocation) MergeMessageToolInvocationToolPartialCall(v MessageToolInvocationToolPartialCall) error { - v.State = "partial-call" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -// AsMessageToolInvocationToolResult returns the union data inside the MessageToolInvocation as a MessageToolInvocationToolResult -func (t MessageToolInvocation) AsMessageToolInvocationToolResult() (MessageToolInvocationToolResult, error) { - var body MessageToolInvocationToolResult - err := json.Unmarshal(t.union, &body) - return body, err -} - -// FromMessageToolInvocationToolResult overwrites any union data inside the MessageToolInvocation as the provided MessageToolInvocationToolResult -func (t *MessageToolInvocation) FromMessageToolInvocationToolResult(v MessageToolInvocationToolResult) error { - v.State = "result" - b, err := json.Marshal(v) - t.union = b - return err -} - -// MergeMessageToolInvocationToolResult performs a merge with any union data inside the MessageToolInvocation, using the provided MessageToolInvocationToolResult -func (t *MessageToolInvocation) MergeMessageToolInvocationToolResult(v MessageToolInvocationToolResult) error { - v.State = "result" - b, err := json.Marshal(v) - if err != nil { - return err - } - - merged, err := runtime.JSONMerge(t.union, b) - t.union = merged - return err -} - -func (t MessageToolInvocation) Discriminator() (string, error) { - var discriminator struct { - Discriminator string `json:"state"` - } - err := json.Unmarshal(t.union, &discriminator) - return discriminator.Discriminator, err -} - -func (t MessageToolInvocation) ValueByDiscriminator() (interface{}, error) { - discriminator, err := t.Discriminator() - if err != nil { - return nil, err - } - switch discriminator { - case "call": - return t.AsMessageToolInvocationToolCall() - case "partial-call": - return t.AsMessageToolInvocationToolPartialCall() - case "result": - return t.AsMessageToolInvocationToolResult() - default: - return nil, errors.New("unknown discriminator value: " + discriminator) - } -} - -func (t MessageToolInvocation) MarshalJSON() ([]byte, error) { - b, err := t.union.MarshalJSON() - return b, err -} - -func (t *MessageToolInvocation) UnmarshalJSON(b []byte) error { - err := t.union.UnmarshalJSON(b) - return err -} - -// RequestEditorFn is the function signature for the RequestEditor callback function -type RequestEditorFn func(ctx context.Context, req *http.Request) error - -// Doer performs HTTP requests. -// -// The standard http.Client implements this interface. -type HttpRequestDoer interface { - Do(req *http.Request) (*http.Response, error) -} - -// Client which conforms to the OpenAPI3 specification for this service. -type Client struct { - // The endpoint of the server conforming to this interface, with scheme, - // https://api.deepmap.com for example. This can contain a path relative - // to the server, such as https://api.deepmap.com/dev-test, and all the - // paths in the swagger spec will be appended to the server. - Server string - - // Doer for performing requests, typically a *http.Client with any - // customized settings, such as certificate chains. - Client HttpRequestDoer - - // A list of callbacks for modifying requests which are generated before sending over - // the network. - RequestEditors []RequestEditorFn -} - -// ClientOption allows setting custom parameters during construction -type ClientOption func(*Client) error - -// Creates a new Client, with reasonable defaults -func NewClient(server string, opts ...ClientOption) (*Client, error) { - // create a client with sane default values - client := Client{ - Server: server, - } - // mutate client and add all optional params - for _, o := range opts { - if err := o(&client); err != nil { - return nil, err - } - } - // ensure the server URL always has a trailing slash - if !strings.HasSuffix(client.Server, "/") { - client.Server += "/" - } - // create httpClient, if not already present - if client.Client == nil { - client.Client = &http.Client{} - } - return &client, nil -} - -// WithHTTPClient allows overriding the default Doer, which is -// automatically created using http.Client. This is useful for tests. -func WithHTTPClient(doer HttpRequestDoer) ClientOption { - return func(c *Client) error { - c.Client = doer - return nil - } -} - -// WithRequestEditorFn allows setting up a callback function, which will be -// called right before sending the request. This can be used to mutate the request. -func WithRequestEditorFn(fn RequestEditorFn) ClientOption { - return func(c *Client) error { - c.RequestEditors = append(c.RequestEditors, fn) - return nil - } -} - -// The interface specification for the client above. -type ClientInterface interface { - // PostAppInfo request - PostAppInfo(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostAppInitialize request - PostAppInitialize(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostConfigGet request - PostConfigGet(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetEvent request - GetEvent(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostFileSearchWithBody request with any body - PostFileSearchWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - PostFileSearch(ctx context.Context, body PostFileSearchJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostInstallationInfo request - PostInstallationInfo(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostPathGet request - PostPathGet(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostProviderList request - PostProviderList(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostSessionAbortWithBody request with any body - PostSessionAbortWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - PostSessionAbort(ctx context.Context, body PostSessionAbortJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostSessionChatWithBody request with any body - PostSessionChatWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - PostSessionChat(ctx context.Context, body PostSessionChatJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostSessionCreate request - PostSessionCreate(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostSessionDeleteWithBody request with any body - PostSessionDeleteWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - PostSessionDelete(ctx context.Context, body PostSessionDeleteJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostSessionInitializeWithBody request with any body - PostSessionInitializeWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - PostSessionInitialize(ctx context.Context, body PostSessionInitializeJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostSessionList request - PostSessionList(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostSessionMessagesWithBody request with any body - PostSessionMessagesWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - PostSessionMessages(ctx context.Context, body PostSessionMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostSessionShareWithBody request with any body - PostSessionShareWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - PostSessionShare(ctx context.Context, body PostSessionShareJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostSessionSummarizeWithBody request with any body - PostSessionSummarizeWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - PostSessionSummarize(ctx context.Context, body PostSessionSummarizeJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) - - // PostSessionUnshareWithBody request with any body - PostSessionUnshareWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) - - PostSessionUnshare(ctx context.Context, body PostSessionUnshareJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) -} - -func (c *Client) PostAppInfo(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostAppInfoRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostAppInitialize(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostAppInitializeRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostConfigGet(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostConfigGetRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) GetEvent(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetEventRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostFileSearchWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostFileSearchRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostFileSearch(ctx context.Context, body PostFileSearchJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostFileSearchRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostInstallationInfo(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostInstallationInfoRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostPathGet(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostPathGetRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostProviderList(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostProviderListRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionAbortWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionAbortRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionAbort(ctx context.Context, body PostSessionAbortJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionAbortRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionChatWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionChatRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionChat(ctx context.Context, body PostSessionChatJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionChatRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionCreate(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionCreateRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionDeleteWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionDeleteRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionDelete(ctx context.Context, body PostSessionDeleteJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionDeleteRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionInitializeWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionInitializeRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionInitialize(ctx context.Context, body PostSessionInitializeJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionInitializeRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionList(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionListRequest(c.Server) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionMessagesWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionMessagesRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionMessages(ctx context.Context, body PostSessionMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionMessagesRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionShareWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionShareRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionShare(ctx context.Context, body PostSessionShareJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionShareRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionSummarizeWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionSummarizeRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionSummarize(ctx context.Context, body PostSessionSummarizeJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionSummarizeRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionUnshareWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionUnshareRequestWithBody(c.Server, contentType, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -func (c *Client) PostSessionUnshare(ctx context.Context, body PostSessionUnshareJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostSessionUnshareRequest(c.Server, body) - if err != nil { - return nil, err - } - req = req.WithContext(ctx) - if err := c.applyEditors(ctx, req, reqEditors); err != nil { - return nil, err - } - return c.Client.Do(req) -} - -// NewPostAppInfoRequest generates requests for PostAppInfo -func NewPostAppInfoRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/app_info") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewPostAppInitializeRequest generates requests for PostAppInitialize -func NewPostAppInitializeRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/app_initialize") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewPostConfigGetRequest generates requests for PostConfigGet -func NewPostConfigGetRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/config_get") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewGetEventRequest generates requests for GetEvent -func NewGetEventRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/event") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("GET", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewPostFileSearchRequest calls the generic PostFileSearch builder with application/json body -func NewPostFileSearchRequest(server string, body PostFileSearchJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewPostFileSearchRequestWithBody(server, "application/json", bodyReader) -} - -// NewPostFileSearchRequestWithBody generates requests for PostFileSearch with any type of body -func NewPostFileSearchRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/file_search") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewPostInstallationInfoRequest generates requests for PostInstallationInfo -func NewPostInstallationInfoRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/installation_info") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewPostPathGetRequest generates requests for PostPathGet -func NewPostPathGetRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/path_get") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewPostProviderListRequest generates requests for PostProviderList -func NewPostProviderListRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/provider_list") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewPostSessionAbortRequest calls the generic PostSessionAbort builder with application/json body -func NewPostSessionAbortRequest(server string, body PostSessionAbortJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewPostSessionAbortRequestWithBody(server, "application/json", bodyReader) -} - -// NewPostSessionAbortRequestWithBody generates requests for PostSessionAbort with any type of body -func NewPostSessionAbortRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/session_abort") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewPostSessionChatRequest calls the generic PostSessionChat builder with application/json body -func NewPostSessionChatRequest(server string, body PostSessionChatJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewPostSessionChatRequestWithBody(server, "application/json", bodyReader) -} - -// NewPostSessionChatRequestWithBody generates requests for PostSessionChat with any type of body -func NewPostSessionChatRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/session_chat") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewPostSessionCreateRequest generates requests for PostSessionCreate -func NewPostSessionCreateRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/session_create") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewPostSessionDeleteRequest calls the generic PostSessionDelete builder with application/json body -func NewPostSessionDeleteRequest(server string, body PostSessionDeleteJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewPostSessionDeleteRequestWithBody(server, "application/json", bodyReader) -} - -// NewPostSessionDeleteRequestWithBody generates requests for PostSessionDelete with any type of body -func NewPostSessionDeleteRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/session_delete") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewPostSessionInitializeRequest calls the generic PostSessionInitialize builder with application/json body -func NewPostSessionInitializeRequest(server string, body PostSessionInitializeJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewPostSessionInitializeRequestWithBody(server, "application/json", bodyReader) -} - -// NewPostSessionInitializeRequestWithBody generates requests for PostSessionInitialize with any type of body -func NewPostSessionInitializeRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/session_initialize") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewPostSessionListRequest generates requests for PostSessionList -func NewPostSessionListRequest(server string) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/session_list") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), nil) - if err != nil { - return nil, err - } - - return req, nil -} - -// NewPostSessionMessagesRequest calls the generic PostSessionMessages builder with application/json body -func NewPostSessionMessagesRequest(server string, body PostSessionMessagesJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewPostSessionMessagesRequestWithBody(server, "application/json", bodyReader) -} - -// NewPostSessionMessagesRequestWithBody generates requests for PostSessionMessages with any type of body -func NewPostSessionMessagesRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/session_messages") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewPostSessionShareRequest calls the generic PostSessionShare builder with application/json body -func NewPostSessionShareRequest(server string, body PostSessionShareJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewPostSessionShareRequestWithBody(server, "application/json", bodyReader) -} - -// NewPostSessionShareRequestWithBody generates requests for PostSessionShare with any type of body -func NewPostSessionShareRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/session_share") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewPostSessionSummarizeRequest calls the generic PostSessionSummarize builder with application/json body -func NewPostSessionSummarizeRequest(server string, body PostSessionSummarizeJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewPostSessionSummarizeRequestWithBody(server, "application/json", bodyReader) -} - -// NewPostSessionSummarizeRequestWithBody generates requests for PostSessionSummarize with any type of body -func NewPostSessionSummarizeRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/session_summarize") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -// NewPostSessionUnshareRequest calls the generic PostSessionUnshare builder with application/json body -func NewPostSessionUnshareRequest(server string, body PostSessionUnshareJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) - if err != nil { - return nil, err - } - bodyReader = bytes.NewReader(buf) - return NewPostSessionUnshareRequestWithBody(server, "application/json", bodyReader) -} - -// NewPostSessionUnshareRequestWithBody generates requests for PostSessionUnshare with any type of body -func NewPostSessionUnshareRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) { - var err error - - serverURL, err := url.Parse(server) - if err != nil { - return nil, err - } - - operationPath := fmt.Sprintf("/session_unshare") - if operationPath[0] == '/' { - operationPath = "." + operationPath - } - - queryURL, err := serverURL.Parse(operationPath) - if err != nil { - return nil, err - } - - req, err := http.NewRequest("POST", queryURL.String(), body) - if err != nil { - return nil, err - } - - req.Header.Add("Content-Type", contentType) - - return req, nil -} - -func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { - for _, r := range c.RequestEditors { - if err := r(ctx, req); err != nil { - return err - } - } - for _, r := range additionalEditors { - if err := r(ctx, req); err != nil { - return err - } - } - return nil -} - -// ClientWithResponses builds on ClientInterface to offer response payloads -type ClientWithResponses struct { - ClientInterface -} - -// NewClientWithResponses creates a new ClientWithResponses, which wraps -// Client with return type handling -func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) { - client, err := NewClient(server, opts...) - if err != nil { - return nil, err - } - return &ClientWithResponses{client}, nil -} - -// WithBaseURL overrides the baseURL. -func WithBaseURL(baseURL string) ClientOption { - return func(c *Client) error { - newBaseURL, err := url.Parse(baseURL) - if err != nil { - return err - } - c.Server = newBaseURL.String() - return nil - } -} - -// ClientWithResponsesInterface is the interface specification for the client with responses above. -type ClientWithResponsesInterface interface { - // PostAppInfoWithResponse request - PostAppInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostAppInfoResponse, error) - - // PostAppInitializeWithResponse request - PostAppInitializeWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostAppInitializeResponse, error) - - // PostConfigGetWithResponse request - PostConfigGetWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostConfigGetResponse, error) - - // GetEventWithResponse request - GetEventWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetEventResponse, error) - - // PostFileSearchWithBodyWithResponse request with any body - PostFileSearchWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostFileSearchResponse, error) - - PostFileSearchWithResponse(ctx context.Context, body PostFileSearchJSONRequestBody, reqEditors ...RequestEditorFn) (*PostFileSearchResponse, error) - - // PostInstallationInfoWithResponse request - PostInstallationInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostInstallationInfoResponse, error) - - // PostPathGetWithResponse request - PostPathGetWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostPathGetResponse, error) - - // PostProviderListWithResponse request - PostProviderListWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostProviderListResponse, error) - - // PostSessionAbortWithBodyWithResponse request with any body - PostSessionAbortWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionAbortResponse, error) - - PostSessionAbortWithResponse(ctx context.Context, body PostSessionAbortJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionAbortResponse, error) - - // PostSessionChatWithBodyWithResponse request with any body - PostSessionChatWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionChatResponse, error) - - PostSessionChatWithResponse(ctx context.Context, body PostSessionChatJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionChatResponse, error) - - // PostSessionCreateWithResponse request - PostSessionCreateWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostSessionCreateResponse, error) - - // PostSessionDeleteWithBodyWithResponse request with any body - PostSessionDeleteWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionDeleteResponse, error) - - PostSessionDeleteWithResponse(ctx context.Context, body PostSessionDeleteJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionDeleteResponse, error) - - // PostSessionInitializeWithBodyWithResponse request with any body - PostSessionInitializeWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionInitializeResponse, error) - - PostSessionInitializeWithResponse(ctx context.Context, body PostSessionInitializeJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionInitializeResponse, error) - - // PostSessionListWithResponse request - PostSessionListWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostSessionListResponse, error) - - // PostSessionMessagesWithBodyWithResponse request with any body - PostSessionMessagesWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionMessagesResponse, error) - - PostSessionMessagesWithResponse(ctx context.Context, body PostSessionMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionMessagesResponse, error) - - // PostSessionShareWithBodyWithResponse request with any body - PostSessionShareWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionShareResponse, error) - - PostSessionShareWithResponse(ctx context.Context, body PostSessionShareJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionShareResponse, error) - - // PostSessionSummarizeWithBodyWithResponse request with any body - PostSessionSummarizeWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionSummarizeResponse, error) - - PostSessionSummarizeWithResponse(ctx context.Context, body PostSessionSummarizeJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionSummarizeResponse, error) - - // PostSessionUnshareWithBodyWithResponse request with any body - PostSessionUnshareWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionUnshareResponse, error) - - PostSessionUnshareWithResponse(ctx context.Context, body PostSessionUnshareJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionUnshareResponse, error) -} - -type PostAppInfoResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *AppInfo -} - -// Status returns HTTPResponse.Status -func (r PostAppInfoResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostAppInfoResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostAppInitializeResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *bool -} - -// Status returns HTTPResponse.Status -func (r PostAppInitializeResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostAppInitializeResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostConfigGetResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *ConfigInfo -} - -// Status returns HTTPResponse.Status -func (r PostConfigGetResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostConfigGetResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type GetEventResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *Event -} - -// Status returns HTTPResponse.Status -func (r GetEventResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r GetEventResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostFileSearchResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *[]string -} - -// Status returns HTTPResponse.Status -func (r PostFileSearchResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostFileSearchResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostInstallationInfoResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *InstallationInfo -} - -// Status returns HTTPResponse.Status -func (r PostInstallationInfoResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostInstallationInfoResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostPathGetResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *struct { - Config string `json:"config"` - Cwd string `json:"cwd"` - Data string `json:"data"` - Root string `json:"root"` - } -} - -// Status returns HTTPResponse.Status -func (r PostPathGetResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostPathGetResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostProviderListResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *struct { - Default map[string]string `json:"default"` - Providers []ProviderInfo `json:"providers"` - } -} - -// Status returns HTTPResponse.Status -func (r PostProviderListResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostProviderListResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostSessionAbortResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *bool -} - -// Status returns HTTPResponse.Status -func (r PostSessionAbortResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostSessionAbortResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostSessionChatResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *MessageInfo -} - -// Status returns HTTPResponse.Status -func (r PostSessionChatResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostSessionChatResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostSessionCreateResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *SessionInfo - JSON400 *Error -} - -// Status returns HTTPResponse.Status -func (r PostSessionCreateResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostSessionCreateResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostSessionDeleteResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *bool -} - -// Status returns HTTPResponse.Status -func (r PostSessionDeleteResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostSessionDeleteResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostSessionInitializeResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *bool -} - -// Status returns HTTPResponse.Status -func (r PostSessionInitializeResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostSessionInitializeResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostSessionListResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *[]SessionInfo -} - -// Status returns HTTPResponse.Status -func (r PostSessionListResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostSessionListResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostSessionMessagesResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *[]MessageInfo -} - -// Status returns HTTPResponse.Status -func (r PostSessionMessagesResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostSessionMessagesResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostSessionShareResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *SessionInfo -} - -// Status returns HTTPResponse.Status -func (r PostSessionShareResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostSessionShareResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostSessionSummarizeResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *bool -} - -// Status returns HTTPResponse.Status -func (r PostSessionSummarizeResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostSessionSummarizeResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -type PostSessionUnshareResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *SessionInfo -} - -// Status returns HTTPResponse.Status -func (r PostSessionUnshareResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status - } - return http.StatusText(0) -} - -// StatusCode returns HTTPResponse.StatusCode -func (r PostSessionUnshareResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode - } - return 0 -} - -// PostAppInfoWithResponse request returning *PostAppInfoResponse -func (c *ClientWithResponses) PostAppInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostAppInfoResponse, error) { - rsp, err := c.PostAppInfo(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostAppInfoResponse(rsp) -} - -// PostAppInitializeWithResponse request returning *PostAppInitializeResponse -func (c *ClientWithResponses) PostAppInitializeWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostAppInitializeResponse, error) { - rsp, err := c.PostAppInitialize(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostAppInitializeResponse(rsp) -} - -// PostConfigGetWithResponse request returning *PostConfigGetResponse -func (c *ClientWithResponses) PostConfigGetWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostConfigGetResponse, error) { - rsp, err := c.PostConfigGet(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostConfigGetResponse(rsp) -} - -// GetEventWithResponse request returning *GetEventResponse -func (c *ClientWithResponses) GetEventWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetEventResponse, error) { - rsp, err := c.GetEvent(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParseGetEventResponse(rsp) -} - -// PostFileSearchWithBodyWithResponse request with arbitrary body returning *PostFileSearchResponse -func (c *ClientWithResponses) PostFileSearchWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostFileSearchResponse, error) { - rsp, err := c.PostFileSearchWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostFileSearchResponse(rsp) -} - -func (c *ClientWithResponses) PostFileSearchWithResponse(ctx context.Context, body PostFileSearchJSONRequestBody, reqEditors ...RequestEditorFn) (*PostFileSearchResponse, error) { - rsp, err := c.PostFileSearch(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostFileSearchResponse(rsp) -} - -// PostInstallationInfoWithResponse request returning *PostInstallationInfoResponse -func (c *ClientWithResponses) PostInstallationInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostInstallationInfoResponse, error) { - rsp, err := c.PostInstallationInfo(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostInstallationInfoResponse(rsp) -} - -// PostPathGetWithResponse request returning *PostPathGetResponse -func (c *ClientWithResponses) PostPathGetWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostPathGetResponse, error) { - rsp, err := c.PostPathGet(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostPathGetResponse(rsp) -} - -// PostProviderListWithResponse request returning *PostProviderListResponse -func (c *ClientWithResponses) PostProviderListWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostProviderListResponse, error) { - rsp, err := c.PostProviderList(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostProviderListResponse(rsp) -} - -// PostSessionAbortWithBodyWithResponse request with arbitrary body returning *PostSessionAbortResponse -func (c *ClientWithResponses) PostSessionAbortWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionAbortResponse, error) { - rsp, err := c.PostSessionAbortWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionAbortResponse(rsp) -} - -func (c *ClientWithResponses) PostSessionAbortWithResponse(ctx context.Context, body PostSessionAbortJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionAbortResponse, error) { - rsp, err := c.PostSessionAbort(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionAbortResponse(rsp) -} - -// PostSessionChatWithBodyWithResponse request with arbitrary body returning *PostSessionChatResponse -func (c *ClientWithResponses) PostSessionChatWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionChatResponse, error) { - rsp, err := c.PostSessionChatWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionChatResponse(rsp) -} - -func (c *ClientWithResponses) PostSessionChatWithResponse(ctx context.Context, body PostSessionChatJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionChatResponse, error) { - rsp, err := c.PostSessionChat(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionChatResponse(rsp) -} - -// PostSessionCreateWithResponse request returning *PostSessionCreateResponse -func (c *ClientWithResponses) PostSessionCreateWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostSessionCreateResponse, error) { - rsp, err := c.PostSessionCreate(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionCreateResponse(rsp) -} - -// PostSessionDeleteWithBodyWithResponse request with arbitrary body returning *PostSessionDeleteResponse -func (c *ClientWithResponses) PostSessionDeleteWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionDeleteResponse, error) { - rsp, err := c.PostSessionDeleteWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionDeleteResponse(rsp) -} - -func (c *ClientWithResponses) PostSessionDeleteWithResponse(ctx context.Context, body PostSessionDeleteJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionDeleteResponse, error) { - rsp, err := c.PostSessionDelete(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionDeleteResponse(rsp) -} - -// PostSessionInitializeWithBodyWithResponse request with arbitrary body returning *PostSessionInitializeResponse -func (c *ClientWithResponses) PostSessionInitializeWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionInitializeResponse, error) { - rsp, err := c.PostSessionInitializeWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionInitializeResponse(rsp) -} - -func (c *ClientWithResponses) PostSessionInitializeWithResponse(ctx context.Context, body PostSessionInitializeJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionInitializeResponse, error) { - rsp, err := c.PostSessionInitialize(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionInitializeResponse(rsp) -} - -// PostSessionListWithResponse request returning *PostSessionListResponse -func (c *ClientWithResponses) PostSessionListWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostSessionListResponse, error) { - rsp, err := c.PostSessionList(ctx, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionListResponse(rsp) -} - -// PostSessionMessagesWithBodyWithResponse request with arbitrary body returning *PostSessionMessagesResponse -func (c *ClientWithResponses) PostSessionMessagesWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionMessagesResponse, error) { - rsp, err := c.PostSessionMessagesWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionMessagesResponse(rsp) -} - -func (c *ClientWithResponses) PostSessionMessagesWithResponse(ctx context.Context, body PostSessionMessagesJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionMessagesResponse, error) { - rsp, err := c.PostSessionMessages(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionMessagesResponse(rsp) -} - -// PostSessionShareWithBodyWithResponse request with arbitrary body returning *PostSessionShareResponse -func (c *ClientWithResponses) PostSessionShareWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionShareResponse, error) { - rsp, err := c.PostSessionShareWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionShareResponse(rsp) -} - -func (c *ClientWithResponses) PostSessionShareWithResponse(ctx context.Context, body PostSessionShareJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionShareResponse, error) { - rsp, err := c.PostSessionShare(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionShareResponse(rsp) -} - -// PostSessionSummarizeWithBodyWithResponse request with arbitrary body returning *PostSessionSummarizeResponse -func (c *ClientWithResponses) PostSessionSummarizeWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionSummarizeResponse, error) { - rsp, err := c.PostSessionSummarizeWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionSummarizeResponse(rsp) -} - -func (c *ClientWithResponses) PostSessionSummarizeWithResponse(ctx context.Context, body PostSessionSummarizeJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionSummarizeResponse, error) { - rsp, err := c.PostSessionSummarize(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionSummarizeResponse(rsp) -} - -// PostSessionUnshareWithBodyWithResponse request with arbitrary body returning *PostSessionUnshareResponse -func (c *ClientWithResponses) PostSessionUnshareWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionUnshareResponse, error) { - rsp, err := c.PostSessionUnshareWithBody(ctx, contentType, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionUnshareResponse(rsp) -} - -func (c *ClientWithResponses) PostSessionUnshareWithResponse(ctx context.Context, body PostSessionUnshareJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionUnshareResponse, error) { - rsp, err := c.PostSessionUnshare(ctx, body, reqEditors...) - if err != nil { - return nil, err - } - return ParsePostSessionUnshareResponse(rsp) -} - -// ParsePostAppInfoResponse parses an HTTP response from a PostAppInfoWithResponse call -func ParsePostAppInfoResponse(rsp *http.Response) (*PostAppInfoResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostAppInfoResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest AppInfo - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostAppInitializeResponse parses an HTTP response from a PostAppInitializeWithResponse call -func ParsePostAppInitializeResponse(rsp *http.Response) (*PostAppInitializeResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostAppInitializeResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest bool - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostConfigGetResponse parses an HTTP response from a PostConfigGetWithResponse call -func ParsePostConfigGetResponse(rsp *http.Response) (*PostConfigGetResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostConfigGetResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ConfigInfo - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParseGetEventResponse parses an HTTP response from a GetEventWithResponse call -func ParseGetEventResponse(rsp *http.Response) (*GetEventResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &GetEventResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest Event - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostFileSearchResponse parses an HTTP response from a PostFileSearchWithResponse call -func ParsePostFileSearchResponse(rsp *http.Response) (*PostFileSearchResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostFileSearchResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest []string - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostInstallationInfoResponse parses an HTTP response from a PostInstallationInfoWithResponse call -func ParsePostInstallationInfoResponse(rsp *http.Response) (*PostInstallationInfoResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostInstallationInfoResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest InstallationInfo - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostPathGetResponse parses an HTTP response from a PostPathGetWithResponse call -func ParsePostPathGetResponse(rsp *http.Response) (*PostPathGetResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostPathGetResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest struct { - Config string `json:"config"` - Cwd string `json:"cwd"` - Data string `json:"data"` - Root string `json:"root"` - } - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostProviderListResponse parses an HTTP response from a PostProviderListWithResponse call -func ParsePostProviderListResponse(rsp *http.Response) (*PostProviderListResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostProviderListResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest struct { - Default map[string]string `json:"default"` - Providers []ProviderInfo `json:"providers"` - } - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostSessionAbortResponse parses an HTTP response from a PostSessionAbortWithResponse call -func ParsePostSessionAbortResponse(rsp *http.Response) (*PostSessionAbortResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostSessionAbortResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest bool - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostSessionChatResponse parses an HTTP response from a PostSessionChatWithResponse call -func ParsePostSessionChatResponse(rsp *http.Response) (*PostSessionChatResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostSessionChatResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest MessageInfo - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostSessionCreateResponse parses an HTTP response from a PostSessionCreateWithResponse call -func ParsePostSessionCreateResponse(rsp *http.Response) (*PostSessionCreateResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostSessionCreateResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest SessionInfo - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: - var dest Error - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON400 = &dest - - } - - return response, nil -} - -// ParsePostSessionDeleteResponse parses an HTTP response from a PostSessionDeleteWithResponse call -func ParsePostSessionDeleteResponse(rsp *http.Response) (*PostSessionDeleteResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostSessionDeleteResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest bool - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostSessionInitializeResponse parses an HTTP response from a PostSessionInitializeWithResponse call -func ParsePostSessionInitializeResponse(rsp *http.Response) (*PostSessionInitializeResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostSessionInitializeResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest bool - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostSessionListResponse parses an HTTP response from a PostSessionListWithResponse call -func ParsePostSessionListResponse(rsp *http.Response) (*PostSessionListResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostSessionListResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest []SessionInfo - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostSessionMessagesResponse parses an HTTP response from a PostSessionMessagesWithResponse call -func ParsePostSessionMessagesResponse(rsp *http.Response) (*PostSessionMessagesResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostSessionMessagesResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest []MessageInfo - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostSessionShareResponse parses an HTTP response from a PostSessionShareWithResponse call -func ParsePostSessionShareResponse(rsp *http.Response) (*PostSessionShareResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostSessionShareResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest SessionInfo - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostSessionSummarizeResponse parses an HTTP response from a PostSessionSummarizeWithResponse call -func ParsePostSessionSummarizeResponse(rsp *http.Response) (*PostSessionSummarizeResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostSessionSummarizeResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest bool - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} - -// ParsePostSessionUnshareResponse parses an HTTP response from a PostSessionUnshareWithResponse call -func ParsePostSessionUnshareResponse(rsp *http.Response) (*PostSessionUnshareResponse, error) { - bodyBytes, err := io.ReadAll(rsp.Body) - defer func() { _ = rsp.Body.Close() }() - if err != nil { - return nil, err - } - - response := &PostSessionUnshareResponse{ - Body: bodyBytes, - HTTPResponse: rsp, - } - - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest SessionInfo - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - - return response, nil -} diff --git a/stainless.yml b/stainless.yml new file mode 100644 index 000000000..29c631d44 --- /dev/null +++ b/stainless.yml @@ -0,0 +1,105 @@ +# yaml-language-server: $schema=https://app.stainless.com/config.schema.json + +organization: + name: opencode + docs: "https://opencode.ai/docs" + contact: "support@sst.dev" + +targets: + typescript: + package_name: "@opencode-ai/sdk" + production_repo: "sst/opencode-sdk-js" + publish: + npm: true + skip: false + go: + package_name: opencode + production_repo: sst/opencode-sdk-go + skip: false + python: + project_name: opencode-ai + package_name: opencode_ai + production_repo: sst/opencode-sdk-python + publish: + pypi: true + skip: false + +environments: + production: http://localhost:54321 + +resources: + $shared: + models: + unknownError: UnknownError + providerAuthError: ProviderAuthError + + event: + methods: + list: get /event + + app: + models: + app: App + methods: + get: get /app + init: post /app/init + + file: + methods: + search: get /file + + config: + models: + config: Config + keybinds: KeybindsConfig + mcpLocal: McpLocalConfig + mcpRemote: McpRemoteConfig + provider: Provider + model: Model + methods: + get: get /config + providers: get /config/providers + + session: + models: + session: Session + message: Message + toolCall: ToolCall + toolPartialCall: ToolPartialCall + toolResult: ToolResult + textPart: TextPart + reasoningPart: ReasoningPart + toolInvocationPart: ToolInvocationPart + sourceUrlPart: SourceUrlPart + filePart: FilePart + stepStartPart: StepStartPart + messagePart: MessagePart + methods: + list: get /session + create: post /session + delete: delete /session/{id} + init: post /session/{id}/init + abort: post /session/{id}/abort + share: post /session/{id}/share + unshare: delete /session/{id}/share + summarize: post /session/{id}/summarize + messages: get /session/{id}/message + chat: post /session/{id}/message + +settings: + disable_mock_tests: true + license: Apache-2.0 + +security: + - {} + +readme: + example_requests: + default: + type: request + endpoint: get /event + params: {} + headline: + type: request + endpoint: get /event + params: {} -- cgit v1.2.3 From 289797f56dbe7a7b51bc74ef8413da1a41a1b95b Mon Sep 17 00:00:00 2001 From: Jay V Date: Fri, 27 Jun 2025 15:31:10 -0400 Subject: docs: share cleanup title --- packages/web/src/components/Share.tsx | 122 +++++++++++++-------------- packages/web/src/components/share.module.css | 34 ++++++-- 2 files changed, 89 insertions(+), 67 deletions(-) (limited to 'packages') diff --git a/packages/web/src/components/Share.tsx b/packages/web/src/components/Share.tsx index e8879c50a..b48d04662 100644 --- a/packages/web/src/components/Share.tsx +++ b/packages/web/src/components/Share.tsx @@ -859,59 +859,15 @@ export default function Share(props: {

{store.info?.title}

-
    -
  • - Cost - {data().cost !== undefined ? ( - ${data().cost.toFixed(2)} - ) : ( - - )} -
  • -
  • - Input Tokens - {data().tokens.input ? ( - {data().tokens.input} - ) : ( - - )} -
  • -
  • - Output Tokens - {data().tokens.output ? ( - {data().tokens.output} - ) : ( - - )} -
  • -
  • - Reasoning Tokens - {data().tokens.reasoning ? ( - {data().tokens.reasoning} - ) : ( - - )} -
  • -
- -
    -
  • -
    - -
    - {data().rootDir} -
  • -
  • -
    - -
    - - v{store.info?.version} - -
  • -
-
    +
  • +
    + +
    + + v{store.info?.version} + +
  • {Object.values(data().models).length > 0 ? ( {([provider, model]) => ( @@ -1305,12 +1261,12 @@ export default function Share(props: { > {(_part) => { const path = createMemo(() => - toolData()?.args.path !== data().rootDir + toolData()?.args?.path !== data().rootDir ? stripWorkingDirectory( - toolData()?.args.path, + toolData()?.args?.path, data().rootDir, ) - : toolData()?.args.path, + : toolData()?.args?.path, ) return ( @@ -1332,7 +1288,9 @@ export default function Share(props: {
    LS - {path()} + + {path()} +
    @@ -1375,7 +1333,7 @@ export default function Share(props: { {(_part) => { const filePath = createMemo(() => stripWorkingDirectory( - toolData()?.args.filePath, + toolData()?.args?.filePath, data().rootDir, ), ) @@ -1398,7 +1356,9 @@ export default function Share(props: {
    Read - {filePath()} + + {filePath()} +
    @@ -1499,7 +1459,9 @@ export default function Share(props: {
    Write - {filePath()} + + {filePath()} +
    0}> {diagnostics()} @@ -1586,7 +1548,9 @@ export default function Share(props: {
    Edit - {filePath()} + + {filePath()} +
    @@ -1935,13 +1899,47 @@ export default function Share(props: { )} -
    +
    - {getStatusText(connectionStatus())} +

    {getStatusText(connectionStatus())}

    +
      +
    • + Cost + {data().cost !== undefined ? ( + ${data().cost.toFixed(2)} + ) : ( + + )} +
    • +
    • + Input Tokens + {data().tokens.input ? ( + {data().tokens.input} + ) : ( + + )} +
    • +
    • + Output Tokens + {data().tokens.output ? ( + {data().tokens.output} + ) : ( + + )} +
    • +
    • + Reasoning Tokens + {data().tokens.reasoning ? ( + {data().tokens.reasoning} + ) : ( + + )} +
    • +
    diff --git a/packages/web/src/components/share.module.css b/packages/web/src/components/share.module.css index a52fd1765..41b257dad 100644 --- a/packages/web/src/components/share.module.css +++ b/packages/web/src/components/share.module.css @@ -89,7 +89,7 @@ padding: 0; margin: 0; display: flex; - gap: 0.5rem 1rem; + gap: 0.5rem 0.875rem; flex-wrap: wrap; li { @@ -104,8 +104,7 @@ } } - [data-section="stats"][data-section-root], - [data-section="stats"][data-section-models] { + [data-section="stats"] { li { gap: 0.3125rem; @@ -375,7 +374,7 @@ } } } - [data-part-type="connection-status"] { + [data-part-type="summary"] { & > [data-section="decoration"] { span:first-child { flex: 0 0 auto; @@ -405,12 +404,37 @@ } & > [data-section="content"] { - span { + display: flex; + flex-direction: column; + gap: 0.5rem; + + p[data-section="copy"] { display: block; line-height: 18px; font-size: 0.875rem; color: var(--sl-color-text-dimmed); } + + [data-section="stats"] { + list-style-type: none; + padding: 0; + margin: 0; + display: flex; + gap: 0.5rem 0.875rem; + flex-wrap: wrap; + + li { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.75rem; + color: var(--sl-color-text-secondary); + + span[data-placeholder] { + color: var(--sl-color-text-dimmed); + } + } + } } } } -- cgit v1.2.3 From 8b400515ea5ab4637866cd14a30423b7c7dc9b77 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 27 Jun 2025 16:09:33 -0400 Subject: smooth out initial onboarding flow --- packages/opencode/src/cli/cmd/tui.ts | 13 ++++++++----- packages/opencode/src/index.ts | 9 +++++---- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'packages') diff --git a/packages/opencode/src/cli/cmd/tui.ts b/packages/opencode/src/cli/cmd/tui.ts index b66aca6bd..87f6f982e 100644 --- a/packages/opencode/src/cli/cmd/tui.ts +++ b/packages/opencode/src/cli/cmd/tui.ts @@ -9,7 +9,6 @@ import fs from "fs/promises" import { Installation } from "../../installation" import { Config } from "../../config/config" import { Bus } from "../../bus" -import { AuthLoginCommand } from "./auth" export const TuiCommand = cmd({ command: "$0 [project]", @@ -100,11 +99,15 @@ export const TuiCommand = cmd({ if (result === "needs_provider") { UI.empty() UI.println(UI.logo(" ")) + const result = await Bun.spawn({ + cmd: [process.execPath, "auth", "login"], + cwd: process.cwd(), + stdout: "inherit", + stderr: "inherit", + stdin: "inherit", + }).exited + if (result !== 0) return UI.empty() - await AuthLoginCommand.handler(args) - UI.empty() - UI.println("Provider configured - please run again") - return } } }, diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts index fca13655e..8a684ae91 100644 --- a/packages/opencode/src/index.ts +++ b/packages/opencode/src/index.ts @@ -74,15 +74,15 @@ try { ...obj.data, }) } - + if (e instanceof Error) { Object.assign(data, { name: e.name, message: e.message, cause: e.cause?.toString(), }) - } - + } + if (e instanceof ResolveMessage) { Object.assign(data, { name: e.name, @@ -92,7 +92,7 @@ try { referrer: e.referrer, position: e.position, importKind: e.importKind, - }); + }) } Log.Default.error("fatal", data) const formatted = FormatError(e) @@ -101,6 +101,7 @@ try { UI.error( "Unexpected error, check log file at " + Log.file() + " for more details", ) + process.exitCode = 1 } cancel.abort() -- cgit v1.2.3 From 145df084440470bb53655f62b5f5588e2615f1ba Mon Sep 17 00:00:00 2001 From: Jay V Date: Fri, 27 Jun 2025 19:16:33 -0400 Subject: docs: share page format --- packages/web/src/components/Share.tsx | 67 ++++++++++++---------------- packages/web/src/components/share.module.css | 9 +--- 2 files changed, 30 insertions(+), 46 deletions(-) (limited to 'packages') diff --git a/packages/web/src/components/Share.tsx b/packages/web/src/components/Share.tsx index b48d04662..008f863c9 100644 --- a/packages/web/src/components/Share.tsx +++ b/packages/web/src/components/Share.tsx @@ -595,12 +595,17 @@ export default function Share(props: { info: Session.Info messages: Record }) { + let lastScrollY = 0 let hasScrolled = false + let scrollTimeout: number | undefined const id = props.id const params = new URLSearchParams(window.location.search) const debug = params.get("debug") === "true" + const [showScrollButton, setShowScrollButton] = createSignal(false) + const [isButtonHovered, setIsButtonHovered] = createSignal(false) + const anchorId = createMemo(() => { const raw = window.location.hash.slice(1) const [id] = raw.split("-") @@ -716,23 +721,18 @@ export default function Share(props: { }) }) - const [showScrollButton, setShowScrollButton] = createSignal(false) - const [isButtonHovered, setIsButtonHovered] = createSignal(false) - let scrollTimeout: number | undefined - let lastScrollY = 0 - - const checkScrollNeed = () => { + function checkScrollNeed() { const currentScrollY = window.scrollY const isScrollingDown = currentScrollY > lastScrollY const scrolled = currentScrollY > 200 // Show after scrolling 200px const isNearBottom = window.innerHeight + currentScrollY >= document.body.scrollHeight - 100 - + // Only show when scrolling down, scrolled enough, and not near bottom const shouldShow = isScrollingDown && scrolled && !isNearBottom - + // Update last scroll position lastScrollY = currentScrollY - + if (shouldShow) { setShowScrollButton(true) // Clear existing timeout @@ -754,30 +754,6 @@ export default function Share(props: { } } - const handleButtonMouseEnter = () => { - setIsButtonHovered(true) - // Clear timeout when hovering - if (scrollTimeout) { - clearTimeout(scrollTimeout) - } - } - - const handleButtonMouseLeave = () => { - setIsButtonHovered(false) - // Restart timeout when leaving hover - if (showScrollButton()) { - scrollTimeout = window.setTimeout(() => { - if (!isButtonHovered()) { - setShowScrollButton(false) - } - }, 3000) - } - } - - const scrollToBottom = () => { - document.body.scrollIntoView({ behavior: "smooth", block: "end" }) - } - onMount(() => { lastScrollY = window.scrollY // Initialize scroll position checkScrollNeed() @@ -1982,14 +1958,29 @@ export default function Share(props: {
    - {/* Floating scroll to bottom button */}