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) {
- {command}
- {protocol}{url} {bash}
+ {command} {protocol}{url} {bash}
--
cgit v1.2.3
From b61a841aa8f6f92803df8873ad63efd10397fc0f Mon Sep 17 00:00:00 2001
From: Dax Raad
Date: Thu, 26 Jun 2025 22:12:23 -0400
Subject: add auto formatting and experimental hooks feature
---
opencode.json | 14 +++-
packages/opencode/config.schema.json | 70 ++++++++++++++++
packages/opencode/src/cli/cmd/run.ts | 1 -
packages/opencode/src/config/config.ts | 26 ++++++
packages/opencode/src/format/index.ts | 143 +++++++++++++++++++++++++++++++++
packages/opencode/src/session/index.ts | 11 +++
packages/opencode/src/tool/edit.ts | 5 +-
packages/opencode/src/tool/write.ts | 2 +
8 files changed, 269 insertions(+), 3 deletions(-)
create mode 100644 packages/opencode/src/format/index.ts
(limited to 'packages')
diff --git a/opencode.json b/opencode.json
index 720ece5c1..59748f927 100644
--- a/opencode.json
+++ b/opencode.json
@@ -1,3 +1,15 @@
{
- "$schema": "https://opencode.ai/config.json"
+ "$schema": "https://opencode.ai/config.json",
+ "experimental": {
+ "hook": {
+ "file_edited": {
+ ".json": []
+ },
+ "session_completed": [
+ {
+ "command": ["touch", "./node_modules/foo"]
+ }
+ ]
+ }
+ }
}
diff --git a/packages/opencode/config.schema.json b/packages/opencode/config.schema.json
index 99845c53d..98fadb65b 100644
--- a/packages/opencode/config.schema.json
+++ b/packages/opencode/config.schema.json
@@ -183,6 +183,9 @@
"temperature": {
"type": "boolean"
},
+ "tool_call": {
+ "type": "boolean"
+ },
"cost": {
"type": "object",
"properties": {
@@ -223,6 +226,10 @@
},
"id": {
"type": "string"
+ },
+ "options": {
+ "type": "object",
+ "additionalProperties": {}
}
},
"additionalProperties": false
@@ -295,6 +302,69 @@
]
},
"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"
+ ],
+ "additionalProperties": false
+ }
+ }
+ },
+ "session_completed": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "command": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "environment": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ }
+ },
+ "required": [
+ "command"
+ ],
+ "additionalProperties": false
+ }
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
}
},
"additionalProperties": false,
diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts
index d811a51ef..f8f886868 100644
--- a/packages/opencode/src/cli/cmd/run.ts
+++ b/packages/opencode/src/cli/cmd/run.ts
@@ -171,4 +171,3 @@ export const RunCommand = cmd({
)
},
})
-
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index d53f4dda3..bf3c0ecdf 100644
--- a/packages/opencode/src/config/config.ts
+++ b/packages/opencode/src/config/config.ts
@@ -167,6 +167,32 @@ export namespace Config {
.record(z.string(), Mcp)
.optional()
.describe("MCP (Model Context Protocol) server configurations"),
+ experimental: z
+ .object({
+ hook: z
+ .object({
+ file_edited: z
+ .record(
+ z.string(),
+ z
+ .object({
+ command: z.string().array(),
+ environment: z.record(z.string(), z.string()).optional(),
+ })
+ .array(),
+ )
+ .optional(),
+ session_completed: z
+ .object({
+ command: z.string().array(),
+ environment: z.record(z.string(), z.string()).optional(),
+ })
+ .array()
+ .optional(),
+ })
+ .optional(),
+ })
+ .optional(),
})
.strict()
.openapi({
diff --git a/packages/opencode/src/format/index.ts b/packages/opencode/src/format/index.ts
new file mode 100644
index 000000000..7aef384c1
--- /dev/null
+++ b/packages/opencode/src/format/index.ts
@@ -0,0 +1,143 @@
+import { App } from '../app/app'
+import { BunProc } from '../bun'
+import { Config } from '../config/config'
+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
+ }
+ }
+
+ return {
+ hooks,
+ }
+ })
+
+ 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
+
+ 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,
+ })
+ const exit = await proc.exited
+ if (exit !== 0)
+ log.error('failed', {
+ command: item.command,
+ ...item.environment,
+ })
+ }
+ }
+
+ interface Hook {
+ command: string[]
+ environment?: Record
+ }
+
+ interface Native {
+ name: string
+ command: string[]
+ environment?: Record
+ extensions: string[]
+ enabled(): Promise
+ }
+
+ const FORMATTERS: Native[] = [
+ {
+ name: 'prettier',
+ extensions: [
+ '.js',
+ '.jsx',
+ '.mjs',
+ '.cjs',
+ '.ts',
+ '.tsx',
+ '.mts',
+ '.cts',
+ '.html',
+ '.htm',
+ '.css',
+ '.scss',
+ '.sass',
+ '.less',
+ '.vue',
+ '.svelte',
+ '.json',
+ '.jsonc',
+ '.yaml',
+ '.yml',
+ '.toml',
+ '.xml',
+ '.md',
+ '.mdx',
+ '.php',
+ '.rb',
+ '.java',
+ '.go',
+ '.rs',
+ '.swift',
+ '.kt',
+ '.kts',
+ '.sol',
+ '.graphql',
+ '.gql',
+ ],
+ command: [BunProc.which(), 'run', 'prettier', '--write', '$FILE'],
+ environment: {
+ BUN_BE_BUN: '1',
+ },
+ async enabled() {
+ try {
+ const proc = Bun.spawn({
+ cmd: [BunProc.which(), 'run', 'prettier', '--version'],
+ cwd: App.info().path.cwd,
+ env: {
+ BUN_BE_BUN: '1',
+ },
+ stdout: 'ignore',
+ stderr: 'ignore',
+ })
+ const exit = await proc.exited
+ return exit === 0
+ } catch {
+ return false
+ }
+ },
+ },
+ ]
+}
diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts
index ba8787d8b..9abcb6985 100644
--- a/packages/opencode/src/session/index.ts
+++ b/packages/opencode/src/session/index.ts
@@ -853,6 +853,17 @@ 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,
+ })
+ }
+ }
+ })
},
}
}
diff --git a/packages/opencode/src/tool/edit.ts b/packages/opencode/src/tool/edit.ts
index b451ef556..f1e6535dc 100644
--- a/packages/opencode/src/tool/edit.ts
+++ b/packages/opencode/src/tool/edit.ts
@@ -11,6 +11,7 @@ import { createTwoFilesPatch } from "diff"
import { Permission } from "../permission"
import DESCRIPTION from "./edit.txt"
import { App } from "../app/app"
+import { Format } from "../format"
export const EditTool = Tool.define({
id: "edit",
@@ -59,6 +60,7 @@ export const EditTool = Tool.define({
if (params.oldString === "") {
contentNew = params.newString
await Bun.write(filepath, params.newString)
+ await Format.run(filepath)
return
}
@@ -77,6 +79,7 @@ export const EditTool = Tool.define({
params.replaceAll,
)
await file.write(contentNew)
+ await Format.run(filepath)
})()
const diff = trimDiff(
@@ -473,7 +476,7 @@ export function replace(
if (oldString === newString) {
throw new Error("oldString and newString must be different")
}
-
+
for (const replacer of [
SimpleReplacer,
LineTrimmedReplacer,
diff --git a/packages/opencode/src/tool/write.ts b/packages/opencode/src/tool/write.ts
index 3cc0a0816..264633ff0 100644
--- a/packages/opencode/src/tool/write.ts
+++ b/packages/opencode/src/tool/write.ts
@@ -6,6 +6,7 @@ import { LSP } from "../lsp"
import { Permission } from "../permission"
import DESCRIPTION from "./write.txt"
import { App } from "../app/app"
+import { Format } from "../format"
export const WriteTool = Tool.define({
id: "write",
@@ -42,6 +43,7 @@ export const WriteTool = Tool.define({
})
await Bun.write(filepath, params.content)
+ await Format.run(filepath)
FileTimes.read(ctx.sessionID, filepath)
let output = ""
--
cgit v1.2.3
From f3742ddbb845e78c3bef96a639e285e4c19e3135 Mon Sep 17 00:00:00 2001
From: Dax Raad
Date: Thu, 26 Jun 2025 22:30:44 -0400
Subject: ignore: run prettier
---
opencode.json | 6 +-
packages/function/sst-env.d.ts | 16 +-
packages/opencode/config.schema.json | 34 +-
packages/opencode/src/app/app.ts | 1 -
packages/opencode/src/cli/cmd/auth.ts | 16 +-
packages/opencode/src/cli/cmd/models.ts | 4 +-
packages/opencode/src/cli/cmd/scrap.ts | 11 +-
packages/opencode/src/format/index.ts | 110 +++----
packages/opencode/src/tool/edit.ts | 1 +
packages/opencode/src/util/lazy.ts | 1 -
packages/opencode/src/util/log.ts | 5 +-
packages/opencode/sst-env.d.ts | 2 +-
packages/opencode/test/tool/edit.test.ts | 8 +-
packages/tui/AGENTS.md | 2 +-
packages/tui/internal/theme/themes/ayu.json | 1 -
packages/tui/internal/theme/themes/catppuccin.json | 1 -
packages/tui/internal/theme/themes/cobalt2.json | 2 +-
packages/tui/internal/theme/themes/dracula.json | 2 +-
packages/tui/internal/theme/themes/everforest.json | 1 -
packages/tui/internal/theme/themes/github.json | 2 +-
packages/tui/internal/theme/themes/material.json | 2 +-
packages/tui/internal/theme/themes/monokai.json | 2 +-
packages/tui/internal/theme/themes/opencode.json | 1 -
packages/tui/internal/theme/themes/palenight.json | 2 +-
packages/tui/internal/theme/themes/rosepine.json | 2 +-
packages/tui/internal/theme/themes/solarized.json | 2 +-
.../tui/internal/theme/themes/synthwave84.json | 2 +-
packages/tui/internal/theme/themes/tokyonight.json | 1 -
packages/tui/internal/theme/themes/zenburn.json | 2 +-
packages/tui/pkg/client/gen/openapi.json | 344 ++++-----------------
packages/web/astro.config.mjs | 4 +-
31 files changed, 179 insertions(+), 411 deletions(-)
(limited to 'packages')
diff --git a/opencode.json b/opencode.json
index 59748f927..57b940082 100644
--- a/opencode.json
+++ b/opencode.json
@@ -3,7 +3,11 @@
"experimental": {
"hook": {
"file_edited": {
- ".json": []
+ ".json": [
+ {
+ "command": ["bun", "run", "prettier", "$FILE"]
+ }
+ ]
},
"session_completed": [
{
diff --git a/packages/function/sst-env.d.ts b/packages/function/sst-env.d.ts
index 78b7056c1..fd95edbb4 100644
--- a/packages/function/sst-env.d.ts
+++ b/packages/function/sst-env.d.ts
@@ -6,20 +6,20 @@
import "sst"
declare module "sst" {
export interface Resource {
- "Web": {
- "type": "sst.cloudflare.Astro"
- "url": string
+ Web: {
+ type: "sst.cloudflare.Astro"
+ url: string
}
}
}
-// cloudflare
-import * as cloudflare from "@cloudflare/workers-types";
+// cloudflare
+import * as cloudflare from "@cloudflare/workers-types"
declare module "sst" {
export interface Resource {
- "Api": cloudflare.Service
- "Bucket": cloudflare.R2Bucket
+ Api: cloudflare.Service
+ Bucket: cloudflare.R2Bucket
}
}
import "sst"
-export {}
\ No newline at end of file
+export {}
diff --git a/packages/opencode/config.schema.json b/packages/opencode/config.schema.json
index 98fadb65b..813b1225f 100644
--- a/packages/opencode/config.schema.json
+++ b/packages/opencode/config.schema.json
@@ -202,10 +202,7 @@
"type": "number"
}
},
- "required": [
- "input",
- "output"
- ],
+ "required": ["input", "output"],
"additionalProperties": false
},
"limit": {
@@ -218,10 +215,7 @@
"type": "number"
}
},
- "required": [
- "context",
- "output"
- ],
+ "required": ["context", "output"],
"additionalProperties": false
},
"id": {
@@ -240,9 +234,7 @@
"additionalProperties": {}
}
},
- "required": [
- "models"
- ],
+ "required": ["models"],
"additionalProperties": false
},
"description": "Custom provider configurations and model overrides"
@@ -274,10 +266,7 @@
"description": "Environment variables to set when running the MCP server"
}
},
- "required": [
- "type",
- "command"
- ],
+ "required": ["type", "command"],
"additionalProperties": false
},
{
@@ -293,10 +282,7 @@
"description": "URL of the remote MCP server"
}
},
- "required": [
- "type",
- "url"
- ],
+ "required": ["type", "url"],
"additionalProperties": false
}
]
@@ -329,9 +315,7 @@
}
}
},
- "required": [
- "command"
- ],
+ "required": ["command"],
"additionalProperties": false
}
}
@@ -354,9 +338,7 @@
}
}
},
- "required": [
- "command"
- ],
+ "required": ["command"],
"additionalProperties": false
}
}
@@ -369,4 +351,4 @@
},
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
-}
\ No newline at end of file
+}
diff --git a/packages/opencode/src/app/app.ts b/packages/opencode/src/app/app.ts
index 873554d90..b60702f9a 100644
--- a/packages/opencode/src/app/app.ts
+++ b/packages/opencode/src/app/app.ts
@@ -142,4 +142,3 @@ export namespace App {
.replace(/[^A-Za-z0-9_]/g, "-")
}
}
-
diff --git a/packages/opencode/src/cli/cmd/auth.ts b/packages/opencode/src/cli/cmd/auth.ts
index 05314d69b..9e8da95bd 100644
--- a/packages/opencode/src/cli/cmd/auth.ts
+++ b/packages/opencode/src/cli/cmd/auth.ts
@@ -31,7 +31,7 @@ export const AuthListCommand = cmd({
UI.empty()
const authPath = path.join(Global.Path.data, "auth.json")
const homedir = os.homedir()
- const displayPath = authPath.startsWith(homedir)
+ const displayPath = authPath.startsWith(homedir)
? authPath.replace(homedir, "~")
: authPath
prompts.intro(`Credentials ${UI.Style.TEXT_DIM}${displayPath}`)
@@ -46,14 +46,14 @@ export const AuthListCommand = cmd({
prompts.outro(`${results.length} credentials`)
// Environment variables section
- const activeEnvVars: Array<{ provider: string, envVar: string }> = []
-
+ const activeEnvVars: Array<{ provider: string; envVar: string }> = []
+
for (const [providerID, provider] of Object.entries(database)) {
for (const envVar of provider.env) {
if (process.env[envVar]) {
- activeEnvVars.push({
- provider: provider.name || providerID,
- envVar
+ activeEnvVars.push({
+ provider: provider.name || providerID,
+ envVar,
})
}
}
@@ -62,11 +62,11 @@ export const AuthListCommand = cmd({
if (activeEnvVars.length > 0) {
UI.empty()
prompts.intro("Environment")
-
+
for (const { provider, envVar } of activeEnvVars) {
prompts.log.info(`${provider} ${UI.Style.TEXT_DIM}${envVar}`)
}
-
+
prompts.outro(`${activeEnvVars.length} environment variables`)
}
},
diff --git a/packages/opencode/src/cli/cmd/models.ts b/packages/opencode/src/cli/cmd/models.ts
index 9380cec89..e385a310c 100644
--- a/packages/opencode/src/cli/cmd/models.ts
+++ b/packages/opencode/src/cli/cmd/models.ts
@@ -8,7 +8,7 @@ export const ModelsCommand = cmd({
handler: async () => {
await App.provide({ cwd: process.cwd() }, async () => {
const providers = await Provider.list()
-
+
for (const [providerID, provider] of Object.entries(providers)) {
for (const modelID of Object.keys(provider.info.models)) {
console.log(`${providerID}/${modelID}`)
@@ -16,4 +16,4 @@ export const ModelsCommand = cmd({
}
})
},
-})
\ No newline at end of file
+})
diff --git a/packages/opencode/src/cli/cmd/scrap.ts b/packages/opencode/src/cli/cmd/scrap.ts
index 03b69d4e8..20b0f52a3 100644
--- a/packages/opencode/src/cli/cmd/scrap.ts
+++ b/packages/opencode/src/cli/cmd/scrap.ts
@@ -7,12 +7,9 @@ export const ScrapCommand = cmd({
builder: (yargs) =>
yargs.positional("file", { type: "string", demandOption: true }),
async handler(args) {
- await App.provide(
- { cwd: process.cwd() },
- async () => {
- await LSP.touchFile(args.file, true)
- console.log(await LSP.diagnostics())
- },
- )
+ await App.provide({ cwd: process.cwd() }, async () => {
+ await LSP.touchFile(args.file, true)
+ console.log(await LSP.diagnostics())
+ })
},
})
diff --git a/packages/opencode/src/format/index.ts b/packages/opencode/src/format/index.ts
index 7aef384c1..0a873ce1f 100644
--- a/packages/opencode/src/format/index.ts
+++ b/packages/opencode/src/format/index.ts
@@ -1,13 +1,13 @@
-import { App } from '../app/app'
-import { BunProc } from '../bun'
-import { Config } from '../config/config'
-import { Log } from '../util/log'
-import path from 'path'
+import { App } from "../app/app"
+import { BunProc } from "../bun"
+import { Config } from "../config/config"
+import { Log } from "../util/log"
+import path from "path"
export namespace Format {
- const log = Log.create({ service: 'format' })
+ const log = Log.create({ service: "format" })
- const state = App.state('format', async () => {
+ const state = App.state("format", async () => {
const hooks: Record = {}
for (const item of FORMATTERS) {
if (await item.enabled()) {
@@ -42,22 +42,22 @@ export namespace Format {
})
export async function run(file: string) {
- log.info('formatting', { file })
+ log.info("formatting", { file })
const { hooks } = await state()
const ext = path.extname(file)
const match = hooks[ext]
if (!match) return
for (const item of match) {
- log.info('running', { command: item.command })
+ log.info("running", { command: item.command })
const proc = Bun.spawn({
- cmd: item.command.map((x) => x.replace('$FILE', file)),
+ cmd: item.command.map((x) => x.replace("$FILE", file)),
cwd: App.info().path.cwd,
env: item.environment,
})
const exit = await proc.exited
if (exit !== 0)
- log.error('failed', {
+ log.error("failed", {
command: item.command,
...item.environment,
})
@@ -79,58 +79,58 @@ export namespace Format {
const FORMATTERS: Native[] = [
{
- name: 'prettier',
- extensions: [
- '.js',
- '.jsx',
- '.mjs',
- '.cjs',
- '.ts',
- '.tsx',
- '.mts',
- '.cts',
- '.html',
- '.htm',
- '.css',
- '.scss',
- '.sass',
- '.less',
- '.vue',
- '.svelte',
- '.json',
- '.jsonc',
- '.yaml',
- '.yml',
- '.toml',
- '.xml',
- '.md',
- '.mdx',
- '.php',
- '.rb',
- '.java',
- '.go',
- '.rs',
- '.swift',
- '.kt',
- '.kts',
- '.sol',
- '.graphql',
- '.gql',
- ],
- command: [BunProc.which(), 'run', 'prettier', '--write', '$FILE'],
+ name: "prettier",
+ command: [BunProc.which(), "run", "prettier", "--write", "$FILE"],
environment: {
- BUN_BE_BUN: '1',
+ BUN_BE_BUN: "1",
},
+ extensions: [
+ ".js",
+ ".jsx",
+ ".mjs",
+ ".cjs",
+ ".ts",
+ ".tsx",
+ ".mts",
+ ".cts",
+ ".html",
+ ".htm",
+ ".css",
+ ".scss",
+ ".sass",
+ ".less",
+ ".vue",
+ ".svelte",
+ ".json",
+ ".jsonc",
+ ".yaml",
+ ".yml",
+ ".toml",
+ ".xml",
+ ".md",
+ ".mdx",
+ ".php",
+ ".rb",
+ ".java",
+ ".go",
+ ".rs",
+ ".swift",
+ ".kt",
+ ".kts",
+ ".sol",
+ ".graphql",
+ ".gql",
+ ],
async enabled() {
try {
const proc = Bun.spawn({
- cmd: [BunProc.which(), 'run', 'prettier', '--version'],
+ cmd: [BunProc.which(), "run", "prettier", "--version"],
cwd: App.info().path.cwd,
env: {
- BUN_BE_BUN: '1',
+ BUN_BE_BUN: "1",
},
- stdout: 'ignore',
- stderr: 'ignore',
+ stdout: "ignore",
+ stderr: "ignore",
})
const exit = await proc.exited
return exit === 0
diff --git a/packages/opencode/src/tool/edit.ts b/packages/opencode/src/tool/edit.ts
index f1e6535dc..d597635e2 100644
--- a/packages/opencode/src/tool/edit.ts
+++ b/packages/opencode/src/tool/edit.ts
@@ -80,6 +80,7 @@ export const EditTool = Tool.define({
)
await file.write(contentNew)
await Format.run(filepath)
+ contentNew = await file.text()
})()
const diff = trimDiff(
diff --git a/packages/opencode/src/util/lazy.ts b/packages/opencode/src/util/lazy.ts
index 8b7ded89f..3533bcc81 100644
--- a/packages/opencode/src/util/lazy.ts
+++ b/packages/opencode/src/util/lazy.ts
@@ -8,4 +8,3 @@ export function lazy(fn: () => T) {
return value as T
}
}
-
diff --git a/packages/opencode/src/util/log.ts b/packages/opencode/src/util/log.ts
index 7db81de0c..b73e2dee8 100644
--- a/packages/opencode/src/util/log.ts
+++ b/packages/opencode/src/util/log.ts
@@ -19,7 +19,10 @@ export namespace Log {
await fs.mkdir(dir, { recursive: true })
cleanup(dir)
if (options.print) return
- logpath = path.join(dir, new Date().toISOString().split(".")[0].replace(/:/g, "") + ".log")
+ logpath = path.join(
+ dir,
+ new Date().toISOString().split(".")[0].replace(/:/g, "") + ".log",
+ )
const logfile = Bun.file(logpath)
await fs.truncate(logpath).catch(() => {})
const writer = logfile.writer()
diff --git a/packages/opencode/sst-env.d.ts b/packages/opencode/sst-env.d.ts
index b6a7e9066..0397645b5 100644
--- a/packages/opencode/sst-env.d.ts
+++ b/packages/opencode/sst-env.d.ts
@@ -6,4 +6,4 @@
///
import "sst"
-export {}
\ No newline at end of file
+export {}
diff --git a/packages/opencode/test/tool/edit.test.ts b/packages/opencode/test/tool/edit.test.ts
index f5558eaac..6de4f2a71 100644
--- a/packages/opencode/test/tool/edit.test.ts
+++ b/packages/opencode/test/tool/edit.test.ts
@@ -316,13 +316,13 @@ const testCases: TestCase[] = [
// WhitespaceNormalizedReplacer - test regex special characters that could cause errors
{
content: 'const pattern = "test[123]";',
- find: 'test[123]',
- replace: 'test[456]',
+ find: "test[123]",
+ replace: "test[456]",
},
{
content: 'const regex = "^start.*end$";',
- find: '^start.*end$',
- replace: '^begin.*finish$',
+ find: "^start.*end$",
+ replace: "^begin.*finish$",
},
// EscapeNormalizedReplacer - test single backslash vs double backslash
diff --git a/packages/tui/AGENTS.md b/packages/tui/AGENTS.md
index a757e926b..0000db9b8 100644
--- a/packages/tui/AGENTS.md
+++ b/packages/tui/AGENTS.md
@@ -23,4 +23,4 @@
- **Client**: Generated OpenAPI client communicates with TypeScript server
- **Components**: Reusable UI components in `internal/components/`
- **Themes**: JSON-based theming system with override hierarchy
-- **State**: Centralized app state with message passing
\ No newline at end of file
+- **State**: Centralized app state with message passing
diff --git a/packages/tui/internal/theme/themes/ayu.json b/packages/tui/internal/theme/themes/ayu.json
index 3ea7a5ca3..a42fce4c4 100644
--- a/packages/tui/internal/theme/themes/ayu.json
+++ b/packages/tui/internal/theme/themes/ayu.json
@@ -78,4 +78,3 @@
"syntaxPunctuation": "darkFg"
}
}
-
diff --git a/packages/tui/internal/theme/themes/catppuccin.json b/packages/tui/internal/theme/themes/catppuccin.json
index cc4d99f43..d0fa6a11d 100644
--- a/packages/tui/internal/theme/themes/catppuccin.json
+++ b/packages/tui/internal/theme/themes/catppuccin.json
@@ -110,4 +110,3 @@
"syntaxPunctuation": { "dark": "darkText", "light": "lightText" }
}
}
-
diff --git a/packages/tui/internal/theme/themes/cobalt2.json b/packages/tui/internal/theme/themes/cobalt2.json
index 5b9740e34..2967eae58 100644
--- a/packages/tui/internal/theme/themes/cobalt2.json
+++ b/packages/tui/internal/theme/themes/cobalt2.json
@@ -225,4 +225,4 @@
"light": "#193549"
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/tui/internal/theme/themes/dracula.json b/packages/tui/internal/theme/themes/dracula.json
index d57692fbb..c837a0b58 100644
--- a/packages/tui/internal/theme/themes/dracula.json
+++ b/packages/tui/internal/theme/themes/dracula.json
@@ -216,4 +216,4 @@
"light": "#282a36"
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/tui/internal/theme/themes/everforest.json b/packages/tui/internal/theme/themes/everforest.json
index 19cbb9aca..62dfb31ba 100644
--- a/packages/tui/internal/theme/themes/everforest.json
+++ b/packages/tui/internal/theme/themes/everforest.json
@@ -239,4 +239,3 @@
}
}
}
-
diff --git a/packages/tui/internal/theme/themes/github.json b/packages/tui/internal/theme/themes/github.json
index b27080101..99a80879e 100644
--- a/packages/tui/internal/theme/themes/github.json
+++ b/packages/tui/internal/theme/themes/github.json
@@ -230,4 +230,4 @@
"light": "lightFg"
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/tui/internal/theme/themes/material.json b/packages/tui/internal/theme/themes/material.json
index bdb10a7f1..c3a106808 100644
--- a/packages/tui/internal/theme/themes/material.json
+++ b/packages/tui/internal/theme/themes/material.json
@@ -232,4 +232,4 @@
"light": "lightFg"
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/tui/internal/theme/themes/monokai.json b/packages/tui/internal/theme/themes/monokai.json
index 39a5385e9..09637a1e2 100644
--- a/packages/tui/internal/theme/themes/monokai.json
+++ b/packages/tui/internal/theme/themes/monokai.json
@@ -218,4 +218,4 @@
"light": "#272822"
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/tui/internal/theme/themes/opencode.json b/packages/tui/internal/theme/themes/opencode.json
index bdef5ab3e..8f585a450 100644
--- a/packages/tui/internal/theme/themes/opencode.json
+++ b/packages/tui/internal/theme/themes/opencode.json
@@ -243,4 +243,3 @@
}
}
}
-
diff --git a/packages/tui/internal/theme/themes/palenight.json b/packages/tui/internal/theme/themes/palenight.json
index c786b4c6e..79f7c59e8 100644
--- a/packages/tui/internal/theme/themes/palenight.json
+++ b/packages/tui/internal/theme/themes/palenight.json
@@ -219,4 +219,4 @@
"light": "#292d3e"
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/tui/internal/theme/themes/rosepine.json b/packages/tui/internal/theme/themes/rosepine.json
index 612951d00..444cdbd13 100644
--- a/packages/tui/internal/theme/themes/rosepine.json
+++ b/packages/tui/internal/theme/themes/rosepine.json
@@ -231,4 +231,4 @@
"light": "dawnSubtle"
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/tui/internal/theme/themes/solarized.json b/packages/tui/internal/theme/themes/solarized.json
index 2a8a3698c..e4de11367 100644
--- a/packages/tui/internal/theme/themes/solarized.json
+++ b/packages/tui/internal/theme/themes/solarized.json
@@ -220,4 +220,4 @@
"light": "base00"
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/tui/internal/theme/themes/synthwave84.json b/packages/tui/internal/theme/themes/synthwave84.json
index a886eb942..d25bf3b49 100644
--- a/packages/tui/internal/theme/themes/synthwave84.json
+++ b/packages/tui/internal/theme/themes/synthwave84.json
@@ -223,4 +223,4 @@
"light": "#262335"
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/tui/internal/theme/themes/tokyonight.json b/packages/tui/internal/theme/themes/tokyonight.json
index cfd3c7ce6..1c9503a42 100644
--- a/packages/tui/internal/theme/themes/tokyonight.json
+++ b/packages/tui/internal/theme/themes/tokyonight.json
@@ -241,4 +241,3 @@
}
}
}
-
diff --git a/packages/tui/internal/theme/themes/zenburn.json b/packages/tui/internal/theme/themes/zenburn.json
index 04b338eb5..c4475923b 100644
--- a/packages/tui/internal/theme/themes/zenburn.json
+++ b/packages/tui/internal/theme/themes/zenburn.json
@@ -220,4 +220,4 @@
"light": "#3f3f3f"
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/tui/pkg/client/gen/openapi.json b/packages/tui/pkg/client/gen/openapi.json
index e804accf3..78d499e7f 100644
--- a/packages/tui/pkg/client/gen/openapi.json
+++ b/packages/tui/pkg/client/gen/openapi.json
@@ -115,11 +115,7 @@
"type": "string"
}
},
- "required": [
- "sessionID",
- "providerID",
- "modelID"
- ]
+ "required": ["sessionID", "providerID", "modelID"]
}
}
}
@@ -149,12 +145,7 @@
"type": "string"
}
},
- "required": [
- "root",
- "data",
- "cwd",
- "config"
- ]
+ "required": ["root", "data", "cwd", "config"]
}
}
}
@@ -221,9 +212,7 @@
"type": "string"
}
},
- "required": [
- "sessionID"
- ]
+ "required": ["sessionID"]
}
}
}
@@ -257,9 +246,7 @@
"type": "string"
}
},
- "required": [
- "sessionID"
- ]
+ "required": ["sessionID"]
}
}
}
@@ -296,9 +283,7 @@
"type": "string"
}
},
- "required": [
- "sessionID"
- ]
+ "required": ["sessionID"]
}
}
}
@@ -354,9 +339,7 @@
"type": "string"
}
},
- "required": [
- "sessionID"
- ]
+ "required": ["sessionID"]
}
}
}
@@ -390,9 +373,7 @@
"type": "string"
}
},
- "required": [
- "sessionID"
- ]
+ "required": ["sessionID"]
}
}
}
@@ -432,11 +413,7 @@
"type": "string"
}
},
- "required": [
- "sessionID",
- "providerID",
- "modelID"
- ]
+ "required": ["sessionID", "providerID", "modelID"]
}
}
}
@@ -482,12 +459,7 @@
}
}
},
- "required": [
- "sessionID",
- "providerID",
- "modelID",
- "parts"
- ]
+ "required": ["sessionID", "providerID", "modelID", "parts"]
}
}
}
@@ -517,10 +489,7 @@
}
}
},
- "required": [
- "providers",
- "default"
- ]
+ "required": ["providers", "default"]
}
}
}
@@ -561,9 +530,7 @@
"type": "string"
}
},
- "required": [
- "query"
- ]
+ "required": ["query"]
}
}
}
@@ -652,15 +619,10 @@
},
"content": {}
},
- "required": [
- "key"
- ]
+ "required": ["key"]
}
},
- "required": [
- "type",
- "properties"
- ]
+ "required": ["type", "properties"]
},
"Event.installation.updated": {
"type": "object",
@@ -676,15 +638,10 @@
"type": "string"
}
},
- "required": [
- "version"
- ]
+ "required": ["version"]
}
},
- "required": [
- "type",
- "properties"
- ]
+ "required": ["type", "properties"]
},
"Event.lsp.client.diagnostics": {
"type": "object",
@@ -703,16 +660,10 @@
"type": "string"
}
},
- "required": [
- "serverID",
- "path"
- ]
+ "required": ["serverID", "path"]
}
},
- "required": [
- "type",
- "properties"
- ]
+ "required": ["type", "properties"]
},
"Event.permission.updated": {
"type": "object",
@@ -725,10 +676,7 @@
"$ref": "#/components/schemas/permission.info"
}
},
- "required": [
- "type",
- "properties"
- ]
+ "required": ["type", "properties"]
},
"permission.info": {
"type": "object",
@@ -753,18 +701,10 @@
"type": "number"
}
},
- "required": [
- "created"
- ]
+ "required": ["created"]
}
},
- "required": [
- "id",
- "sessionID",
- "title",
- "metadata",
- "time"
- ]
+ "required": ["id", "sessionID", "title", "metadata", "time"]
},
"Event.message.updated": {
"type": "object",
@@ -780,15 +720,10 @@
"$ref": "#/components/schemas/Message.Info"
}
},
- "required": [
- "info"
- ]
+ "required": ["info"]
}
},
- "required": [
- "type",
- "properties"
- ]
+ "required": ["type", "properties"]
},
"Message.Info": {
"type": "object",
@@ -798,10 +733,7 @@
},
"role": {
"type": "string",
- "enum": [
- "user",
- "assistant"
- ]
+ "enum": ["user", "assistant"]
},
"parts": {
"type": "array",
@@ -813,12 +745,7 @@
"$ref": "#/components/schemas/Message.Metadata"
}
},
- "required": [
- "id",
- "role",
- "parts",
- "metadata"
- ]
+ "required": ["id", "role", "parts", "metadata"]
},
"Message.Part": {
"oneOf": [
@@ -864,10 +791,7 @@
"type": "string"
}
},
- "required": [
- "type",
- "text"
- ]
+ "required": ["type", "text"]
},
"Message.Part.Reasoning": {
"type": "object",
@@ -884,10 +808,7 @@
"additionalProperties": {}
}
},
- "required": [
- "type",
- "text"
- ]
+ "required": ["type", "text"]
},
"Message.Part.ToolInvocation": {
"type": "object",
@@ -900,10 +821,7 @@
"$ref": "#/components/schemas/Message.ToolInvocation"
}
},
- "required": [
- "type",
- "toolInvocation"
- ]
+ "required": ["type", "toolInvocation"]
},
"Message.ToolInvocation": {
"oneOf": [
@@ -944,11 +862,7 @@
},
"args": {}
},
- "required": [
- "state",
- "toolCallId",
- "toolName"
- ]
+ "required": ["state", "toolCallId", "toolName"]
},
"Message.ToolInvocation.ToolPartialCall": {
"type": "object",
@@ -968,11 +882,7 @@
},
"args": {}
},
- "required": [
- "state",
- "toolCallId",
- "toolName"
- ]
+ "required": ["state", "toolCallId", "toolName"]
},
"Message.ToolInvocation.ToolResult": {
"type": "object",
@@ -995,12 +905,7 @@
"type": "string"
}
},
- "required": [
- "state",
- "toolCallId",
- "toolName",
- "result"
- ]
+ "required": ["state", "toolCallId", "toolName", "result"]
},
"Message.Part.SourceUrl": {
"type": "object",
@@ -1023,11 +928,7 @@
"additionalProperties": {}
}
},
- "required": [
- "type",
- "sourceId",
- "url"
- ]
+ "required": ["type", "sourceId", "url"]
},
"Message.Part.File": {
"type": "object",
@@ -1046,11 +947,7 @@
"type": "string"
}
},
- "required": [
- "type",
- "mediaType",
- "url"
- ]
+ "required": ["type", "mediaType", "url"]
},
"Message.Part.StepStart": {
"type": "object",
@@ -1060,9 +957,7 @@
"const": "step-start"
}
},
- "required": [
- "type"
- ]
+ "required": ["type"]
},
"Message.Metadata": {
"type": "object",
@@ -1077,9 +972,7 @@
"type": "number"
}
},
- "required": [
- "created"
- ]
+ "required": ["created"]
},
"error": {
"oneOf": [
@@ -1119,16 +1012,10 @@
"type": "number"
}
},
- "required": [
- "start",
- "end"
- ]
+ "required": ["start", "end"]
}
},
- "required": [
- "title",
- "time"
- ],
+ "required": ["title", "time"],
"additionalProperties": {}
}
},
@@ -1157,10 +1044,7 @@
"type": "string"
}
},
- "required": [
- "cwd",
- "root"
- ]
+ "required": ["cwd", "root"]
},
"cost": {
"type": "number"
@@ -1190,18 +1074,10 @@
"type": "number"
}
},
- "required": [
- "read",
- "write"
- ]
+ "required": ["read", "write"]
}
},
- "required": [
- "input",
- "output",
- "reasoning",
- "cache"
- ]
+ "required": ["input", "output", "reasoning", "cache"]
}
},
"required": [
@@ -1214,11 +1090,7 @@
]
}
},
- "required": [
- "time",
- "sessionID",
- "tool"
- ]
+ "required": ["time", "sessionID", "tool"]
},
"ProviderAuthError": {
"type": "object",
@@ -1237,16 +1109,10 @@
"type": "string"
}
},
- "required": [
- "providerID",
- "message"
- ]
+ "required": ["providerID", "message"]
}
},
- "required": [
- "name",
- "data"
- ]
+ "required": ["name", "data"]
},
"UnknownError": {
"type": "object",
@@ -1262,15 +1128,10 @@
"type": "string"
}
},
- "required": [
- "message"
- ]
+ "required": ["message"]
}
},
- "required": [
- "name",
- "data"
- ]
+ "required": ["name", "data"]
},
"Event.message.part.updated": {
"type": "object",
@@ -1292,17 +1153,10 @@
"type": "string"
}
},
- "required": [
- "part",
- "sessionID",
- "messageID"
- ]
+ "required": ["part", "sessionID", "messageID"]
}
},
- "required": [
- "type",
- "properties"
- ]
+ "required": ["type", "properties"]
},
"Event.session.updated": {
"type": "object",
@@ -1318,15 +1172,10 @@
"$ref": "#/components/schemas/session.info"
}
},
- "required": [
- "info"
- ]
+ "required": ["info"]
}
},
- "required": [
- "type",
- "properties"
- ]
+ "required": ["type", "properties"]
},
"session.info": {
"type": "object",
@@ -1346,9 +1195,7 @@
"type": "string"
}
},
- "required": [
- "url"
- ]
+ "required": ["url"]
},
"title": {
"type": "string"
@@ -1366,18 +1213,10 @@
"type": "number"
}
},
- "required": [
- "created",
- "updated"
- ]
+ "required": ["created", "updated"]
}
},
- "required": [
- "id",
- "title",
- "version",
- "time"
- ]
+ "required": ["id", "title", "version", "time"]
},
"Event.session.deleted": {
"type": "object",
@@ -1393,15 +1232,10 @@
"$ref": "#/components/schemas/session.info"
}
},
- "required": [
- "info"
- ]
+ "required": ["info"]
}
},
- "required": [
- "type",
- "properties"
- ]
+ "required": ["type", "properties"]
},
"Event.session.error": {
"type": "object",
@@ -1433,10 +1267,7 @@
}
}
},
- "required": [
- "type",
- "properties"
- ]
+ "required": ["type", "properties"]
},
"App.Info": {
"type": "object",
@@ -1466,13 +1297,7 @@
"type": "string"
}
},
- "required": [
- "config",
- "data",
- "root",
- "cwd",
- "state"
- ]
+ "required": ["config", "data", "root", "cwd", "state"]
},
"time": {
"type": "object",
@@ -1483,12 +1308,7 @@
}
}
},
- "required": [
- "user",
- "git",
- "path",
- "time"
- ]
+ "required": ["user", "git", "path", "time"]
},
"Config.Info": {
"type": "object",
@@ -1583,10 +1403,7 @@
"type": "number"
}
},
- "required": [
- "input",
- "output"
- ]
+ "required": ["input", "output"]
},
"limit": {
"type": "object",
@@ -1598,10 +1415,7 @@
"type": "number"
}
},
- "required": [
- "context",
- "output"
- ]
+ "required": ["context", "output"]
},
"id": {
"type": "string"
@@ -1618,9 +1432,7 @@
"additionalProperties": {}
}
},
- "required": [
- "models"
- ]
+ "required": ["models"]
},
"description": "Custom provider configurations and model overrides"
},
@@ -1790,12 +1602,7 @@
}
}
},
- "required": [
- "name",
- "env",
- "id",
- "models"
- ]
+ "required": ["name", "env", "id", "models"]
},
"Model.Info": {
"type": "object",
@@ -1831,10 +1638,7 @@
"type": "number"
}
},
- "required": [
- "input",
- "output"
- ]
+ "required": ["input", "output"]
},
"limit": {
"type": "object",
@@ -1846,10 +1650,7 @@
"type": "number"
}
},
- "required": [
- "context",
- "output"
- ]
+ "required": ["context", "output"]
},
"id": {
"type": "string"
@@ -1894,10 +1695,7 @@
"description": "Environment variables to set when running the MCP server"
}
},
- "required": [
- "type",
- "command"
- ],
+ "required": ["type", "command"],
"additionalProperties": false
},
"Config.McpRemote": {
@@ -1913,10 +1711,7 @@
"description": "URL of the remote MCP server"
}
},
- "required": [
- "type",
- "url"
- ],
+ "required": ["type", "url"],
"additionalProperties": false
},
"Error": {
@@ -1927,9 +1722,7 @@
"additionalProperties": {}
}
},
- "required": [
- "data"
- ]
+ "required": ["data"]
},
"InstallationInfo": {
"type": "object",
@@ -1941,11 +1734,8 @@
"type": "string"
}
},
- "required": [
- "version",
- "latest"
- ]
+ "required": ["version", "latest"]
}
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/web/astro.config.mjs b/packages/web/astro.config.mjs
index e1b3496d0..9099c6df3 100644
--- a/packages/web/astro.config.mjs
+++ b/packages/web/astro.config.mjs
@@ -32,9 +32,7 @@ export default defineConfig({
starlight({
title: "opencode",
expressiveCode: { themes: ["github-light", "github-dark"] },
- social: [
- { icon: "github", label: "GitHub", href: config.github },
- ],
+ social: [{ icon: "github", label: "GitHub", href: config.github }],
head: [
{
tag: "link",
--
cgit v1.2.3
From 9ead2f3dfb8a04e876c2ef70cbb6657ac14ac00e Mon Sep 17 00:00:00 2001
From: adamdottv <2363879+adamdottv@users.noreply.github.com>
Date: Fri, 27 Jun 2025 05:47:14 -0500
Subject: fix: don't use prettier for langs it doesn't format
---
packages/opencode/src/format/index.ts | 9 ---------
1 file changed, 9 deletions(-)
(limited to 'packages')
diff --git a/packages/opencode/src/format/index.ts b/packages/opencode/src/format/index.ts
index 0a873ce1f..7dfcb3e0c 100644
--- a/packages/opencode/src/format/index.ts
+++ b/packages/opencode/src/format/index.ts
@@ -109,15 +109,6 @@ export namespace Format {
".xml",
".md",
".mdx",
- ".php",
- ".rb",
- ".java",
- ".go",
- ".rs",
- ".swift",
- ".kt",
- ".kts",
- ".sol",
".graphql",
".gql",
],
--
cgit v1.2.3
From d840d43e8f424fa399afec98a87c4f8433feb9e5 Mon Sep 17 00:00:00 2001
From: adamdottv <2363879+adamdottv@users.noreply.github.com>
Date: Fri, 27 Jun 2025 06:19:27 -0500
Subject: ignore: more metadata in app info
---
bun.lock | 2 +-
packages/opencode/src/app/app.ts | 10 +-
packages/opencode/src/util/project.ts | 91 ++++++
packages/tui/cmd/opencode/main.go | 3 +-
packages/tui/pkg/client/gen/openapi.json | 439 +++++++++++++++++++++++-----
packages/tui/pkg/client/generated-client.go | 90 +++++-
6 files changed, 558 insertions(+), 77 deletions(-)
create mode 100644 packages/opencode/src/util/project.ts
(limited to 'packages')
diff --git a/bun.lock b/bun.lock
index 7ee9c838d..1dabf9a68 100644
--- a/bun.lock
+++ b/bun.lock
@@ -19,7 +19,7 @@
},
"packages/opencode": {
"name": "opencode",
- "version": "0.0.0",
+ "version": "0.0.5",
"bin": {
"opencode": "./bin/opencode",
},
diff --git a/packages/opencode/src/app/app.ts b/packages/opencode/src/app/app.ts
index b60702f9a..44b6d9c75 100644
--- a/packages/opencode/src/app/app.ts
+++ b/packages/opencode/src/app/app.ts
@@ -2,6 +2,7 @@ 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"
@@ -12,7 +13,9 @@ export namespace App {
export const Info = z
.object({
+ project: z.string(),
user: z.string(),
+ hostname: z.string(),
git: z.boolean(),
path: z.object({
config: z.string(),
@@ -62,8 +65,13 @@ 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: {
initialized: state.initialized,
},
@@ -72,7 +80,7 @@ export namespace App {
config: Global.Path.config,
state: Global.Path.state,
data,
- root: git ?? input.cwd,
+ root,
cwd: input.cwd,
},
}
diff --git a/packages/opencode/src/util/project.ts b/packages/opencode/src/util/project.ts
new file mode 100644
index 000000000..72a9bda52
--- /dev/null
+++ b/packages/opencode/src/util/project.ts
@@ -0,0 +1,91 @@
+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)
+ }
+}
diff --git a/packages/tui/cmd/opencode/main.go b/packages/tui/cmd/opencode/main.go
index cb898b5f9..d2a843d79 100644
--- a/packages/tui/cmd/opencode/main.go
+++ b/packages/tui/cmd/opencode/main.go
@@ -49,6 +49,8 @@ func main() {
logger := slog.New(slog.NewTextHandler(file, &slog.HandlerOptions{Level: slog.LevelDebug}))
slog.SetDefault(logger)
+ slog.Debug("TUI launched", "app", appInfo)
+
httpClient, err := client.NewClientWithResponses(url)
if err != nil {
slog.Error("Failed to create client", "error", err)
@@ -66,7 +68,6 @@ func main() {
program := tea.NewProgram(
tui.NewModel(app_),
- // tea.WithColorProfile(colorprofile.ANSI),
tea.WithAltScreen(),
tea.WithKeyboardEnhancements(),
tea.WithMouseCellMotion(),
diff --git a/packages/tui/pkg/client/gen/openapi.json b/packages/tui/pkg/client/gen/openapi.json
index 78d499e7f..cb6cd5dca 100644
--- a/packages/tui/pkg/client/gen/openapi.json
+++ b/packages/tui/pkg/client/gen/openapi.json
@@ -115,7 +115,11 @@
"type": "string"
}
},
- "required": ["sessionID", "providerID", "modelID"]
+ "required": [
+ "sessionID",
+ "providerID",
+ "modelID"
+ ]
}
}
}
@@ -145,7 +149,12 @@
"type": "string"
}
},
- "required": ["root", "data", "cwd", "config"]
+ "required": [
+ "root",
+ "data",
+ "cwd",
+ "config"
+ ]
}
}
}
@@ -212,7 +221,9 @@
"type": "string"
}
},
- "required": ["sessionID"]
+ "required": [
+ "sessionID"
+ ]
}
}
}
@@ -246,7 +257,9 @@
"type": "string"
}
},
- "required": ["sessionID"]
+ "required": [
+ "sessionID"
+ ]
}
}
}
@@ -283,7 +296,9 @@
"type": "string"
}
},
- "required": ["sessionID"]
+ "required": [
+ "sessionID"
+ ]
}
}
}
@@ -339,7 +354,9 @@
"type": "string"
}
},
- "required": ["sessionID"]
+ "required": [
+ "sessionID"
+ ]
}
}
}
@@ -373,7 +390,9 @@
"type": "string"
}
},
- "required": ["sessionID"]
+ "required": [
+ "sessionID"
+ ]
}
}
}
@@ -413,7 +432,11 @@
"type": "string"
}
},
- "required": ["sessionID", "providerID", "modelID"]
+ "required": [
+ "sessionID",
+ "providerID",
+ "modelID"
+ ]
}
}
}
@@ -459,7 +482,12 @@
}
}
},
- "required": ["sessionID", "providerID", "modelID", "parts"]
+ "required": [
+ "sessionID",
+ "providerID",
+ "modelID",
+ "parts"
+ ]
}
}
}
@@ -489,7 +517,10 @@
}
}
},
- "required": ["providers", "default"]
+ "required": [
+ "providers",
+ "default"
+ ]
}
}
}
@@ -530,7 +561,9 @@
"type": "string"
}
},
- "required": ["query"]
+ "required": [
+ "query"
+ ]
}
}
}
@@ -619,10 +652,15 @@
},
"content": {}
},
- "required": ["key"]
+ "required": [
+ "key"
+ ]
}
},
- "required": ["type", "properties"]
+ "required": [
+ "type",
+ "properties"
+ ]
},
"Event.installation.updated": {
"type": "object",
@@ -638,10 +676,15 @@
"type": "string"
}
},
- "required": ["version"]
+ "required": [
+ "version"
+ ]
}
},
- "required": ["type", "properties"]
+ "required": [
+ "type",
+ "properties"
+ ]
},
"Event.lsp.client.diagnostics": {
"type": "object",
@@ -660,10 +703,16 @@
"type": "string"
}
},
- "required": ["serverID", "path"]
+ "required": [
+ "serverID",
+ "path"
+ ]
}
},
- "required": ["type", "properties"]
+ "required": [
+ "type",
+ "properties"
+ ]
},
"Event.permission.updated": {
"type": "object",
@@ -676,7 +725,10 @@
"$ref": "#/components/schemas/permission.info"
}
},
- "required": ["type", "properties"]
+ "required": [
+ "type",
+ "properties"
+ ]
},
"permission.info": {
"type": "object",
@@ -701,10 +753,18 @@
"type": "number"
}
},
- "required": ["created"]
+ "required": [
+ "created"
+ ]
}
},
- "required": ["id", "sessionID", "title", "metadata", "time"]
+ "required": [
+ "id",
+ "sessionID",
+ "title",
+ "metadata",
+ "time"
+ ]
},
"Event.message.updated": {
"type": "object",
@@ -720,10 +780,15 @@
"$ref": "#/components/schemas/Message.Info"
}
},
- "required": ["info"]
+ "required": [
+ "info"
+ ]
}
},
- "required": ["type", "properties"]
+ "required": [
+ "type",
+ "properties"
+ ]
},
"Message.Info": {
"type": "object",
@@ -733,7 +798,10 @@
},
"role": {
"type": "string",
- "enum": ["user", "assistant"]
+ "enum": [
+ "user",
+ "assistant"
+ ]
},
"parts": {
"type": "array",
@@ -745,7 +813,12 @@
"$ref": "#/components/schemas/Message.Metadata"
}
},
- "required": ["id", "role", "parts", "metadata"]
+ "required": [
+ "id",
+ "role",
+ "parts",
+ "metadata"
+ ]
},
"Message.Part": {
"oneOf": [
@@ -791,7 +864,10 @@
"type": "string"
}
},
- "required": ["type", "text"]
+ "required": [
+ "type",
+ "text"
+ ]
},
"Message.Part.Reasoning": {
"type": "object",
@@ -808,7 +884,10 @@
"additionalProperties": {}
}
},
- "required": ["type", "text"]
+ "required": [
+ "type",
+ "text"
+ ]
},
"Message.Part.ToolInvocation": {
"type": "object",
@@ -821,7 +900,10 @@
"$ref": "#/components/schemas/Message.ToolInvocation"
}
},
- "required": ["type", "toolInvocation"]
+ "required": [
+ "type",
+ "toolInvocation"
+ ]
},
"Message.ToolInvocation": {
"oneOf": [
@@ -862,7 +944,11 @@
},
"args": {}
},
- "required": ["state", "toolCallId", "toolName"]
+ "required": [
+ "state",
+ "toolCallId",
+ "toolName"
+ ]
},
"Message.ToolInvocation.ToolPartialCall": {
"type": "object",
@@ -882,7 +968,11 @@
},
"args": {}
},
- "required": ["state", "toolCallId", "toolName"]
+ "required": [
+ "state",
+ "toolCallId",
+ "toolName"
+ ]
},
"Message.ToolInvocation.ToolResult": {
"type": "object",
@@ -905,7 +995,12 @@
"type": "string"
}
},
- "required": ["state", "toolCallId", "toolName", "result"]
+ "required": [
+ "state",
+ "toolCallId",
+ "toolName",
+ "result"
+ ]
},
"Message.Part.SourceUrl": {
"type": "object",
@@ -928,7 +1023,11 @@
"additionalProperties": {}
}
},
- "required": ["type", "sourceId", "url"]
+ "required": [
+ "type",
+ "sourceId",
+ "url"
+ ]
},
"Message.Part.File": {
"type": "object",
@@ -947,7 +1046,11 @@
"type": "string"
}
},
- "required": ["type", "mediaType", "url"]
+ "required": [
+ "type",
+ "mediaType",
+ "url"
+ ]
},
"Message.Part.StepStart": {
"type": "object",
@@ -957,7 +1060,9 @@
"const": "step-start"
}
},
- "required": ["type"]
+ "required": [
+ "type"
+ ]
},
"Message.Metadata": {
"type": "object",
@@ -972,7 +1077,9 @@
"type": "number"
}
},
- "required": ["created"]
+ "required": [
+ "created"
+ ]
},
"error": {
"oneOf": [
@@ -981,13 +1088,17 @@
},
{
"$ref": "#/components/schemas/UnknownError"
+ },
+ {
+ "$ref": "#/components/schemas/MessageOutputLengthError"
}
],
"discriminator": {
"propertyName": "name",
"mapping": {
"ProviderAuthError": "#/components/schemas/ProviderAuthError",
- "UnknownError": "#/components/schemas/UnknownError"
+ "UnknownError": "#/components/schemas/UnknownError",
+ "MessageOutputLengthError": "#/components/schemas/MessageOutputLengthError"
}
}
},
@@ -1012,10 +1123,16 @@
"type": "number"
}
},
- "required": ["start", "end"]
+ "required": [
+ "start",
+ "end"
+ ]
}
},
- "required": ["title", "time"],
+ "required": [
+ "title",
+ "time"
+ ],
"additionalProperties": {}
}
},
@@ -1044,7 +1161,10 @@
"type": "string"
}
},
- "required": ["cwd", "root"]
+ "required": [
+ "cwd",
+ "root"
+ ]
},
"cost": {
"type": "number"
@@ -1074,10 +1194,18 @@
"type": "number"
}
},
- "required": ["read", "write"]
+ "required": [
+ "read",
+ "write"
+ ]
}
},
- "required": ["input", "output", "reasoning", "cache"]
+ "required": [
+ "input",
+ "output",
+ "reasoning",
+ "cache"
+ ]
}
},
"required": [
@@ -1090,7 +1218,11 @@
]
}
},
- "required": ["time", "sessionID", "tool"]
+ "required": [
+ "time",
+ "sessionID",
+ "tool"
+ ]
},
"ProviderAuthError": {
"type": "object",
@@ -1109,10 +1241,16 @@
"type": "string"
}
},
- "required": ["providerID", "message"]
+ "required": [
+ "providerID",
+ "message"
+ ]
}
},
- "required": ["name", "data"]
+ "required": [
+ "name",
+ "data"
+ ]
},
"UnknownError": {
"type": "object",
@@ -1128,10 +1266,31 @@
"type": "string"
}
},
- "required": ["message"]
+ "required": [
+ "message"
+ ]
+ }
+ },
+ "required": [
+ "name",
+ "data"
+ ]
+ },
+ "MessageOutputLengthError": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "const": "MessageOutputLengthError"
+ },
+ "data": {
+ "type": "object"
}
},
- "required": ["name", "data"]
+ "required": [
+ "name",
+ "data"
+ ]
},
"Event.message.part.updated": {
"type": "object",
@@ -1153,10 +1312,17 @@
"type": "string"
}
},
- "required": ["part", "sessionID", "messageID"]
+ "required": [
+ "part",
+ "sessionID",
+ "messageID"
+ ]
}
},
- "required": ["type", "properties"]
+ "required": [
+ "type",
+ "properties"
+ ]
},
"Event.session.updated": {
"type": "object",
@@ -1172,10 +1338,15 @@
"$ref": "#/components/schemas/session.info"
}
},
- "required": ["info"]
+ "required": [
+ "info"
+ ]
}
},
- "required": ["type", "properties"]
+ "required": [
+ "type",
+ "properties"
+ ]
},
"session.info": {
"type": "object",
@@ -1195,7 +1366,9 @@
"type": "string"
}
},
- "required": ["url"]
+ "required": [
+ "url"
+ ]
},
"title": {
"type": "string"
@@ -1213,10 +1386,18 @@
"type": "number"
}
},
- "required": ["created", "updated"]
+ "required": [
+ "created",
+ "updated"
+ ]
}
},
- "required": ["id", "title", "version", "time"]
+ "required": [
+ "id",
+ "title",
+ "version",
+ "time"
+ ]
},
"Event.session.deleted": {
"type": "object",
@@ -1232,10 +1413,15 @@
"$ref": "#/components/schemas/session.info"
}
},
- "required": ["info"]
+ "required": [
+ "info"
+ ]
}
},
- "required": ["type", "properties"]
+ "required": [
+ "type",
+ "properties"
+ ]
},
"Event.session.error": {
"type": "object",
@@ -1254,27 +1440,40 @@
},
{
"$ref": "#/components/schemas/UnknownError"
+ },
+ {
+ "$ref": "#/components/schemas/MessageOutputLengthError"
}
],
"discriminator": {
"propertyName": "name",
"mapping": {
"ProviderAuthError": "#/components/schemas/ProviderAuthError",
- "UnknownError": "#/components/schemas/UnknownError"
+ "UnknownError": "#/components/schemas/UnknownError",
+ "MessageOutputLengthError": "#/components/schemas/MessageOutputLengthError"
}
}
}
}
}
},
- "required": ["type", "properties"]
+ "required": [
+ "type",
+ "properties"
+ ]
},
"App.Info": {
"type": "object",
"properties": {
+ "project": {
+ "type": "string"
+ },
"user": {
"type": "string"
},
+ "hostname": {
+ "type": "string"
+ },
"git": {
"type": "boolean"
},
@@ -1297,7 +1496,13 @@
"type": "string"
}
},
- "required": ["config", "data", "root", "cwd", "state"]
+ "required": [
+ "config",
+ "data",
+ "root",
+ "cwd",
+ "state"
+ ]
},
"time": {
"type": "object",
@@ -1308,7 +1513,14 @@
}
}
},
- "required": ["user", "git", "path", "time"]
+ "required": [
+ "project",
+ "user",
+ "hostname",
+ "git",
+ "path",
+ "time"
+ ]
},
"Config.Info": {
"type": "object",
@@ -1403,7 +1615,10 @@
"type": "number"
}
},
- "required": ["input", "output"]
+ "required": [
+ "input",
+ "output"
+ ]
},
"limit": {
"type": "object",
@@ -1415,7 +1630,10 @@
"type": "number"
}
},
- "required": ["context", "output"]
+ "required": [
+ "context",
+ "output"
+ ]
},
"id": {
"type": "string"
@@ -1432,7 +1650,9 @@
"additionalProperties": {}
}
},
- "required": ["models"]
+ "required": [
+ "models"
+ ]
},
"description": "Custom provider configurations and model overrides"
},
@@ -1456,6 +1676,65 @@
}
},
"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
@@ -1602,7 +1881,12 @@
}
}
},
- "required": ["name", "env", "id", "models"]
+ "required": [
+ "name",
+ "env",
+ "id",
+ "models"
+ ]
},
"Model.Info": {
"type": "object",
@@ -1638,7 +1922,10 @@
"type": "number"
}
},
- "required": ["input", "output"]
+ "required": [
+ "input",
+ "output"
+ ]
},
"limit": {
"type": "object",
@@ -1650,7 +1937,10 @@
"type": "number"
}
},
- "required": ["context", "output"]
+ "required": [
+ "context",
+ "output"
+ ]
},
"id": {
"type": "string"
@@ -1695,7 +1985,10 @@
"description": "Environment variables to set when running the MCP server"
}
},
- "required": ["type", "command"],
+ "required": [
+ "type",
+ "command"
+ ],
"additionalProperties": false
},
"Config.McpRemote": {
@@ -1711,7 +2004,10 @@
"description": "URL of the remote MCP server"
}
},
- "required": ["type", "url"],
+ "required": [
+ "type",
+ "url"
+ ],
"additionalProperties": false
},
"Error": {
@@ -1722,7 +2018,9 @@
"additionalProperties": {}
}
},
- "required": ["data"]
+ "required": [
+ "data"
+ ]
},
"InstallationInfo": {
"type": "object",
@@ -1734,8 +2032,11 @@
"type": "string"
}
},
- "required": ["version", "latest"]
+ "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
index 4ef9b77e3..aa74d3c17 100644
--- a/packages/tui/pkg/client/generated-client.go
+++ b/packages/tui/pkg/client/generated-client.go
@@ -25,15 +25,17 @@ const (
// AppInfo defines model for App.Info.
type AppInfo struct {
- Git bool `json:"git"`
- Path 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"`
- Time struct {
+ Project string `json:"project"`
+ Time struct {
Initialized *float32 `json:"initialized,omitempty"`
} `json:"time"`
User string `json:"user"`
@@ -51,8 +53,20 @@ type ConfigInfo struct {
Autoupdate *bool `json:"autoupdate,omitempty"`
// DisabledProviders Disable providers that are loaded automatically
- DisabledProviders *[]string `json:"disabled_providers,omitempty"`
- Keybinds *ConfigKeybinds `json:"keybinds,omitempty"`
+ 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"`
@@ -434,6 +448,12 @@ type MessageToolInvocationToolResult struct {
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"`
@@ -1110,6 +1130,34 @@ func (t *EventSessionError_Properties_Error) MergeUnknownError(v UnknownError) e
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"`
@@ -1124,6 +1172,8 @@ func (t EventSessionError_Properties_Error) ValueByDiscriminator() (interface{},
return nil, err
}
switch discriminator {
+ case "MessageOutputLengthError":
+ return t.AsMessageOutputLengthError()
case "ProviderAuthError":
return t.AsProviderAuthError()
case "UnknownError":
@@ -1199,6 +1249,34 @@ func (t *MessageMetadata_Error) MergeUnknownError(v UnknownError) error {
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"`
@@ -1213,6 +1291,8 @@ func (t MessageMetadata_Error) ValueByDiscriminator() (interface{}, error) {
return nil, err
}
switch discriminator {
+ case "MessageOutputLengthError":
+ return t.AsMessageOutputLengthError()
case "ProviderAuthError":
return t.AsProviderAuthError()
case "UnknownError":
--
cgit v1.2.3
From 9f07f89384907e57c42317b63d8316701bba8f25 Mon Sep 17 00:00:00 2001
From: Dax Raad
Date: Fri, 27 Jun 2025 07:29:41 -0400
Subject: fix formatting output going into tui
---
packages/opencode/src/format/index.ts | 2 ++
packages/opencode/src/session/index.ts | 3 +++
2 files changed, 5 insertions(+)
(limited to 'packages')
diff --git a/packages/opencode/src/format/index.ts b/packages/opencode/src/format/index.ts
index 7dfcb3e0c..9142750b0 100644
--- a/packages/opencode/src/format/index.ts
+++ b/packages/opencode/src/format/index.ts
@@ -54,6 +54,8 @@ export namespace Format {
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)
diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts
index 9abcb6985..0591bb56a 100644
--- a/packages/opencode/src/session/index.ts
+++ b/packages/opencode/src/session/index.ts
@@ -537,6 +537,7 @@ export namespace Session {
// return step
// },
toolCallStreaming: true,
+ maxTokens: model.info.limit.output || undefined,
abortSignal: abort.signal,
maxSteps: 1000,
providerOptions: model.info.options,
@@ -860,6 +861,8 @@ export namespace Session {
cmd: item.command,
cwd: App.info().path.cwd,
env: item.environment,
+ stdout: "ignore",
+ stderr: "ignore",
})
}
}
--
cgit v1.2.3
From 8455029de18b39c524fe7808b9d01b67c8e90a76 Mon Sep 17 00:00:00 2001
From: adamdottv <2363879+adamdottv@users.noreply.github.com>
Date: Fri, 27 Jun 2025 06:30:40 -0500
Subject: fix(tui): min width on user messages
---
packages/tui/internal/components/chat/message.go | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
(limited to 'packages')
diff --git a/packages/tui/internal/components/chat/message.go b/packages/tui/internal/components/chat/message.go
index f547907ee..6fa52c1f4 100644
--- a/packages/tui/internal/components/chat/message.go
+++ b/packages/tui/internal/components/chat/message.go
@@ -226,11 +226,18 @@ func renderText(message client.MessageInfo, text string, author string) string {
if message.Role == client.Assistant {
markdownWidth = width - padding - 4 - 3
}
- if message.Role == client.User {
- text = strings.ReplaceAll(text, "<", "\\<")
- text = strings.ReplaceAll(text, ">", "\\>")
+ minWidth := max(markdownWidth, (width-4)/2)
+ messageStyle := styles.NewStyle().
+ Width(minWidth).
+ Background(t.BackgroundPanel()).
+ Foreground(t.Text())
+ if textWidth < minWidth {
+ messageStyle = messageStyle.AlignHorizontal(lipgloss.Right)
+ }
+ content := messageStyle.Render(text)
+ if message.Role == client.Assistant {
+ content = toMarkdown(text, markdownWidth, t.BackgroundPanel())
}
- content := toMarkdown(text, markdownWidth, t.BackgroundPanel())
content = strings.Join([]string{content, info}, "\n")
switch message.Role {
@@ -409,7 +416,7 @@ func renderToolInvocation(
title = fmt.Sprintf("WRITE %s", relative(filename))
if content, ok := toolArgsMap["content"].(string); ok {
body = renderFile(filename, content)
-
+
// Add diagnostics at the bottom if they exist
if diagnostics := renderDiagnostics(metadata, filename); diagnostics != "" {
body += "\n" + renderContentBlock(diagnostics, WithFullWidth(), WithBorderColor(t.Error()))
@@ -753,7 +760,7 @@ func renderDiagnostics(metadata client.MessageMetadata_Tool_AdditionalProperties
continue
}
- line := diag.Range.Start.Line + 1 // 1-based
+ line := diag.Range.Start.Line + 1 // 1-based
column := diag.Range.Start.Character + 1 // 1-based
errorDiagnostics = append(errorDiagnostics, fmt.Sprintf("Error [%d:%d] %s", line, column, diag.Message))
}
--
cgit v1.2.3
From 49053b66a92e7d1095d7934ff86a6764ed765266 Mon Sep 17 00:00:00 2001
From: adamdottv <2363879+adamdottv@users.noreply.github.com>
Date: Fri, 27 Jun 2025 06:48:34 -0500
Subject: fix(web): remove system prompts from share page
---
packages/web/src/components/Share.tsx | 91 ++++-------------------------------
1 file changed, 10 insertions(+), 81 deletions(-)
(limited to 'packages')
diff --git a/packages/web/src/components/Share.tsx b/packages/web/src/components/Share.tsx
index 5510f5a69..9b953bd2d 100644
--- a/packages/web/src/components/Share.tsx
+++ b/packages/web/src/components/Share.tsx
@@ -23,7 +23,6 @@ import {
} from "./icons/custom"
import {
IconFolder,
- IconCpuChip,
IconHashtag,
IconSparkles,
IconGlobeAlt,
@@ -103,10 +102,7 @@ function stripWorkingDirectory(filePath: string, workingDir?: string) {
}
function getShikiLang(filename: string) {
- const ext = filename
- .split('.')
- .pop()
- ?.toLowerCase() ?? ''
+ const ext = filename.split(".").pop()?.toLowerCase() ?? ""
// map.languages(ext) returns an array of matching Linguist language names (e.g. ['TypeScript'])
const langs = map.languages(ext)
@@ -114,12 +110,10 @@ function getShikiLang(filename: string) {
// Overrride any specific language mappings
const overrides: Record = {
- "conf": "shellscript"
+ conf: "shellscript",
}
- return type
- ? overrides[type] ?? type
- : 'plaintext'
+ return type ? (overrides[type] ?? type) : "plaintext"
}
function formatDuration(ms: number): string {
@@ -1087,13 +1081,6 @@ export default function Share(props: {
}
>
{(assistant) => {
- const system = createMemo(() => {
- const prompts = assistant().system || []
- return prompts.filter(
- (p: string) =>
- !p.startsWith("You are Claude"),
- )
- })
return (
{assistant().modelID}
-
0}>
-
-
- setShowResults((e) => !e)
- }
- />
-
-
-
-
-
)
}}
- {/* System text */}
-
- {(part) => (
-
- )}
-
+
{/* 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 @@
-
-
-
+
+
+
@@ -14,7 +14,7 @@
-[](https://opencode.ai)
+[](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.
-
+
---
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 */}
+ document.body.scrollIntoView({ behavior: "smooth", block: "end" })
+ }
+ onMouseEnter={() => {
+ setIsButtonHovered(true)
+ if (scrollTimeout) {
+ clearTimeout(scrollTimeout)
+ }
+ }}
+ onMouseLeave={() => {
+ setIsButtonHovered(false)
+ if (showScrollButton()) {
+ scrollTimeout = window.setTimeout(() => {
+ if (!isButtonHovered()) {
+ setShowScrollButton(false)
+ }
+ }, 3000)
+ }
+ }}
title="Scroll to bottom"
aria-label="Scroll to bottom"
>
diff --git a/packages/web/src/components/share.module.css b/packages/web/src/components/share.module.css
index 41b257dad..dafbdd8a2 100644
--- a/packages/web/src/components/share.module.css
+++ b/packages/web/src/components/share.module.css
@@ -785,7 +785,7 @@
}
}
-.scrollButton {
+.scroll-button {
position: fixed;
bottom: 2rem;
right: 2rem;
@@ -799,18 +799,11 @@
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);
}
--
cgit v1.2.3