Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0b17439f9 | ||
|
|
1261b7d333 | ||
|
|
a3f38e0533 | ||
|
|
681a257df6 | ||
|
|
586207adb4 | ||
|
|
a58dbb3b5c | ||
|
|
131d8e5778 |
@@ -3,6 +3,7 @@
|
|||||||
"module": "index.ts",
|
"module": "index.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "catalog:"
|
"@types/bun": "catalog:"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"name": "@opencode-ai/console-app",
|
"name": "@opencode-ai/console-app",
|
||||||
"version": "1.0.224",
|
"version": "1.0.224",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"typecheck": "tsgo --noEmit",
|
"typecheck": "tsgo --noEmit",
|
||||||
"dev": "vite dev --host 0.0.0.0",
|
"dev": "vite dev --host 0.0.0.0",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"version": "1.0.224",
|
"version": "1.0.224",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-sts": "3.782.0",
|
"@aws-sdk/client-sts": "3.782.0",
|
||||||
"@jsx-email/render": "1.1.1",
|
"@jsx-email/render": "1.1.1",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"typecheck": "tsgo --noEmit"
|
"typecheck": "tsgo --noEmit"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -17,5 +17,6 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "email preview emails/templates"
|
"dev": "email preview emails/templates"
|
||||||
},
|
},
|
||||||
"type": "module"
|
"type": "module",
|
||||||
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/console-resource",
|
"name": "@opencode-ai/console-resource",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cloudflare/workers-types": "catalog:"
|
"@cloudflare/workers-types": "catalog:"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.224",
|
"version": "1.0.224",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"typecheck": "tsgo -b",
|
"typecheck": "tsgo -b",
|
||||||
"predev": "bun ./scripts/predev.ts",
|
"predev": "bun ./scripts/predev.ts",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"version": "1.0.224",
|
"version": "1.0.224",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"typecheck": "tsgo --noEmit",
|
"typecheck": "tsgo --noEmit",
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cloudflare/workers-types": "catalog:",
|
"@cloudflare/workers-types": "catalog:",
|
||||||
"@tsconfig/node22": "22.0.2",
|
"@tsconfig/node22": "22.0.2",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"version": "1.0.224",
|
"version": "1.0.224",
|
||||||
"name": "opencode",
|
"name": "opencode",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"typecheck": "tsgo --noEmit",
|
"typecheck": "tsgo --noEmit",
|
||||||
|
|||||||
@@ -549,6 +549,13 @@ function App() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
sdk.event.on(TuiEvent.SessionSelect.type, (evt) => {
|
||||||
|
route.navigate({
|
||||||
|
type: "session",
|
||||||
|
sessionID: evt.properties.sessionID,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
sdk.event.on(SessionApi.Event.Deleted.type, (evt) => {
|
sdk.event.on(SessionApi.Event.Deleted.type, (evt) => {
|
||||||
if (route.data.type === "session" && route.data.sessionID === evt.properties.info.id) {
|
if (route.data.type === "session" && route.data.sessionID === evt.properties.info.id) {
|
||||||
route.navigate({ type: "home" })
|
route.navigate({ type: "home" })
|
||||||
|
|||||||
@@ -37,4 +37,10 @@ export const TuiEvent = {
|
|||||||
duration: z.number().default(5000).optional().describe("Duration in milliseconds"),
|
duration: z.number().default(5000).optional().describe("Duration in milliseconds"),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
SessionSelect: BusEvent.define(
|
||||||
|
"tui.session.select",
|
||||||
|
z.object({
|
||||||
|
sessionID: z.string().regex(/^ses/).describe("Session ID to navigate to"),
|
||||||
|
}),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ export const LANGUAGE_EXTENSIONS: Record<string, string> = {
|
|||||||
".ini": "ini",
|
".ini": "ini",
|
||||||
".java": "java",
|
".java": "java",
|
||||||
".js": "javascript",
|
".js": "javascript",
|
||||||
|
".kt": "kotlin",
|
||||||
|
".kts": "kotlin",
|
||||||
".jsx": "javascriptreact",
|
".jsx": "javascriptreact",
|
||||||
".json": "json",
|
".json": "json",
|
||||||
".tex": "latex",
|
".tex": "latex",
|
||||||
|
|||||||
@@ -1209,6 +1209,85 @@ export namespace LSPServer {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const KotlinLS: Info = {
|
||||||
|
id: "kotlin-ls",
|
||||||
|
extensions: [".kt", ".kts"],
|
||||||
|
root: NearestRoot(["build.gradle", "build.gradle.kts", "settings.gradle.kts", "pom.xml"]),
|
||||||
|
async spawn(root) {
|
||||||
|
const distPath = path.join(Global.Path.bin, "kotlin-ls")
|
||||||
|
const launcherScript =
|
||||||
|
process.platform === "win32" ? path.join(distPath, "kotlin-lsp.cmd") : path.join(distPath, "kotlin-lsp.sh")
|
||||||
|
const installed = await Bun.file(launcherScript).exists()
|
||||||
|
if (!installed) {
|
||||||
|
if (Flag.OPENCODE_DISABLE_LSP_DOWNLOAD) return
|
||||||
|
log.info("Downloading Kotlin Language Server from GitHub.")
|
||||||
|
|
||||||
|
const releaseResponse = await fetch("https://api.github.com/repos/Kotlin/kotlin-lsp/releases/latest")
|
||||||
|
if (!releaseResponse.ok) {
|
||||||
|
log.error("Failed to fetch kotlin-lsp release info")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const release = await releaseResponse.json()
|
||||||
|
const version = release.name?.replace(/^v/, "")
|
||||||
|
|
||||||
|
if (!version) {
|
||||||
|
log.error("Could not determine Kotlin LSP version from release")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const platform = process.platform
|
||||||
|
const arch = process.arch
|
||||||
|
|
||||||
|
let kotlinArch: string = arch
|
||||||
|
if (arch === "arm64") kotlinArch = "aarch64"
|
||||||
|
else if (arch === "x64") kotlinArch = "x64"
|
||||||
|
|
||||||
|
let kotlinPlatform: string = platform
|
||||||
|
if (platform === "darwin") kotlinPlatform = "mac"
|
||||||
|
else if (platform === "linux") kotlinPlatform = "linux"
|
||||||
|
else if (platform === "win32") kotlinPlatform = "win"
|
||||||
|
|
||||||
|
const supportedCombos = ["mac-x64", "mac-aarch64", "linux-x64", "linux-aarch64", "win-x64", "win-aarch64"]
|
||||||
|
|
||||||
|
const combo = `${kotlinPlatform}-${kotlinArch}`
|
||||||
|
|
||||||
|
if (!supportedCombos.includes(combo)) {
|
||||||
|
log.error(`Platform ${platform}/${arch} is not supported by Kotlin LSP`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const assetName = `kotlin-lsp-${version}-${kotlinPlatform}-${kotlinArch}.zip`
|
||||||
|
const releaseURL = `https://download-cdn.jetbrains.com/kotlin-lsp/${version}/${assetName}`
|
||||||
|
|
||||||
|
await fs.mkdir(distPath, { recursive: true })
|
||||||
|
const archivePath = path.join(distPath, "kotlin-ls.zip")
|
||||||
|
await $`curl -L -o '${archivePath}' '${releaseURL}'`.quiet().nothrow()
|
||||||
|
const ok = await Archive.extractZip(archivePath, distPath)
|
||||||
|
.then(() => true)
|
||||||
|
.catch((error) => {
|
||||||
|
log.error("Failed to extract Kotlin LS archive", { error })
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
if (!ok) return
|
||||||
|
await fs.rm(archivePath, { force: true })
|
||||||
|
if (process.platform !== "win32") {
|
||||||
|
await $`chmod +x ${launcherScript}`.quiet().nothrow()
|
||||||
|
}
|
||||||
|
log.info("Installed Kotlin Language Server", { path: launcherScript })
|
||||||
|
}
|
||||||
|
if (!(await Bun.file(launcherScript).exists())) {
|
||||||
|
log.error(`Failed to locate the Kotlin LS launcher script in the installed directory: ${distPath}.`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
process: spawn(launcherScript, ["--stdio"], {
|
||||||
|
cwd: root,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
export const YamlLS: Info = {
|
export const YamlLS: Info = {
|
||||||
id: "yaml-ls",
|
id: "yaml-ls",
|
||||||
extensions: [".yaml", ".yml"],
|
extensions: [".yaml", ".yml"],
|
||||||
|
|||||||
@@ -39,8 +39,9 @@ export namespace Plugin {
|
|||||||
const lastAtIndex = plugin.lastIndexOf("@")
|
const lastAtIndex = plugin.lastIndexOf("@")
|
||||||
const pkg = lastAtIndex > 0 ? plugin.substring(0, lastAtIndex) : plugin
|
const pkg = lastAtIndex > 0 ? plugin.substring(0, lastAtIndex) : plugin
|
||||||
const version = lastAtIndex > 0 ? plugin.substring(lastAtIndex + 1) : "latest"
|
const version = lastAtIndex > 0 ? plugin.substring(lastAtIndex + 1) : "latest"
|
||||||
|
const builtin = BUILTIN.some((x) => x.startsWith(pkg + "@"))
|
||||||
plugin = await BunProc.install(pkg, version).catch((err) => {
|
plugin = await BunProc.install(pkg, version).catch((err) => {
|
||||||
if (BUILTIN.includes(pkg)) return ""
|
if (builtin) return ""
|
||||||
throw err
|
throw err
|
||||||
})
|
})
|
||||||
if (!plugin) continue
|
if (!plugin) continue
|
||||||
|
|||||||
@@ -974,6 +974,7 @@ export namespace Server {
|
|||||||
return c.json(true)
|
return c.json(true)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
.post(
|
.post(
|
||||||
"/session/:sessionID/share",
|
"/session/:sessionID/share",
|
||||||
describeRoute({
|
describeRoute({
|
||||||
@@ -2600,6 +2601,32 @@ export namespace Server {
|
|||||||
return c.json(true)
|
return c.json(true)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
.post(
|
||||||
|
"/tui/select-session",
|
||||||
|
describeRoute({
|
||||||
|
summary: "Select session",
|
||||||
|
description: "Navigate the TUI to display the specified session.",
|
||||||
|
operationId: "tui.selectSession",
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: "Session selected successfully",
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: resolver(z.boolean()),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...errors(400, 404),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
validator("json", TuiEvent.SessionSelect.properties),
|
||||||
|
async (c) => {
|
||||||
|
const { sessionID } = c.req.valid("json")
|
||||||
|
await Session.get(sessionID)
|
||||||
|
await Bus.publish(TuiEvent.SessionSelect, { sessionID })
|
||||||
|
return c.json(true)
|
||||||
|
},
|
||||||
|
)
|
||||||
.route("/tui/control", TuiRoute)
|
.route("/tui/control", TuiRoute)
|
||||||
.put(
|
.put(
|
||||||
"/auth/:providerID",
|
"/auth/:providerID",
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import { describe, expect, test } from "bun:test"
|
||||||
|
import path from "path"
|
||||||
|
import { Session } from "../../src/session"
|
||||||
|
import { Log } from "../../src/util/log"
|
||||||
|
import { Instance } from "../../src/project/instance"
|
||||||
|
import { Server } from "../../src/server/server"
|
||||||
|
|
||||||
|
const projectRoot = path.join(__dirname, "../..")
|
||||||
|
Log.init({ print: false })
|
||||||
|
|
||||||
|
describe("tui.selectSession endpoint", () => {
|
||||||
|
test("should return 200 when called with valid session", async () => {
|
||||||
|
await Instance.provide({
|
||||||
|
directory: projectRoot,
|
||||||
|
fn: async () => {
|
||||||
|
// #given
|
||||||
|
const session = await Session.create({})
|
||||||
|
|
||||||
|
// #when
|
||||||
|
const app = Server.App()
|
||||||
|
const response = await app.request("/tui/select-session", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ sessionID: session.id }),
|
||||||
|
})
|
||||||
|
|
||||||
|
// #then
|
||||||
|
expect(response.status).toBe(200)
|
||||||
|
const body = await response.json()
|
||||||
|
expect(body).toBe(true)
|
||||||
|
|
||||||
|
await Session.remove(session.id)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should return 404 when session does not exist", async () => {
|
||||||
|
await Instance.provide({
|
||||||
|
directory: projectRoot,
|
||||||
|
fn: async () => {
|
||||||
|
// #given
|
||||||
|
const nonExistentSessionID = "ses_nonexistent123"
|
||||||
|
|
||||||
|
// #when
|
||||||
|
const app = Server.App()
|
||||||
|
const response = await app.request("/tui/select-session", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ sessionID: nonExistentSessionID }),
|
||||||
|
})
|
||||||
|
|
||||||
|
// #then
|
||||||
|
expect(response.status).toBe(404)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should return 400 when session ID format is invalid", async () => {
|
||||||
|
await Instance.provide({
|
||||||
|
directory: projectRoot,
|
||||||
|
fn: async () => {
|
||||||
|
// #given
|
||||||
|
const invalidSessionID = "invalid_session_id"
|
||||||
|
|
||||||
|
// #when
|
||||||
|
const app = Server.App()
|
||||||
|
const response = await app.request("/tui/select-session", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ sessionID: invalidSessionID }),
|
||||||
|
})
|
||||||
|
|
||||||
|
// #then
|
||||||
|
expect(response.status).toBe(400)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
"name": "@opencode-ai/plugin",
|
"name": "@opencode-ai/plugin",
|
||||||
"version": "1.0.224",
|
"version": "1.0.224",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"typecheck": "tsgo --noEmit",
|
"typecheck": "tsgo --noEmit",
|
||||||
"build": "tsc"
|
"build": "tsc"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package",
|
"$schema": "https://json.schemastore.org/package",
|
||||||
"name": "@opencode-ai/script",
|
"name": "@opencode-ai/script",
|
||||||
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "catalog:"
|
"@types/bun": "catalog:"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"name": "@opencode-ai/sdk",
|
"name": "@opencode-ai/sdk",
|
||||||
"version": "1.0.224",
|
"version": "1.0.224",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"typecheck": "tsgo --noEmit",
|
"typecheck": "tsgo --noEmit",
|
||||||
"build": "./script/build.ts"
|
"build": "./script/build.ts"
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import type {
|
|||||||
EventSubscribeResponses,
|
EventSubscribeResponses,
|
||||||
EventTuiCommandExecute,
|
EventTuiCommandExecute,
|
||||||
EventTuiPromptAppend,
|
EventTuiPromptAppend,
|
||||||
|
EventTuiSessionSelect,
|
||||||
EventTuiToastShow,
|
EventTuiToastShow,
|
||||||
FileListResponses,
|
FileListResponses,
|
||||||
FilePartInput,
|
FilePartInput,
|
||||||
@@ -144,6 +145,8 @@ import type {
|
|||||||
TuiOpenThemesResponses,
|
TuiOpenThemesResponses,
|
||||||
TuiPublishErrors,
|
TuiPublishErrors,
|
||||||
TuiPublishResponses,
|
TuiPublishResponses,
|
||||||
|
TuiSelectSessionErrors,
|
||||||
|
TuiSelectSessionResponses,
|
||||||
TuiShowToastResponses,
|
TuiShowToastResponses,
|
||||||
TuiSubmitPromptResponses,
|
TuiSubmitPromptResponses,
|
||||||
VcsGetResponses,
|
VcsGetResponses,
|
||||||
@@ -2688,7 +2691,7 @@ export class Tui extends HeyApiClient {
|
|||||||
public publish<ThrowOnError extends boolean = false>(
|
public publish<ThrowOnError extends boolean = false>(
|
||||||
parameters?: {
|
parameters?: {
|
||||||
directory?: string
|
directory?: string
|
||||||
body?: EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow
|
body?: EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow | EventTuiSessionSelect
|
||||||
},
|
},
|
||||||
options?: Options<never, ThrowOnError>,
|
options?: Options<never, ThrowOnError>,
|
||||||
) {
|
) {
|
||||||
@@ -2705,6 +2708,41 @@ export class Tui extends HeyApiClient {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select session
|
||||||
|
*
|
||||||
|
* Navigate the TUI to display the specified session.
|
||||||
|
*/
|
||||||
|
public selectSession<ThrowOnError extends boolean = false>(
|
||||||
|
parameters?: {
|
||||||
|
directory?: string
|
||||||
|
sessionID?: string
|
||||||
|
},
|
||||||
|
options?: Options<never, ThrowOnError>,
|
||||||
|
) {
|
||||||
|
const params = buildClientParams(
|
||||||
|
[parameters],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
args: [
|
||||||
|
{ in: "query", key: "directory" },
|
||||||
|
{ in: "body", key: "sessionID" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
return (options?.client ?? this.client).post<TuiSelectSessionResponses, TuiSelectSessionErrors, ThrowOnError>({
|
||||||
|
url: "/tui/select-session",
|
||||||
|
...options,
|
||||||
|
...params,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
...options?.headers,
|
||||||
|
...params.headers,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
control = new Control({ client: this.client })
|
control = new Control({ client: this.client })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -592,6 +592,16 @@ export type EventTuiToastShow = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type EventTuiSessionSelect = {
|
||||||
|
type: "tui.session.select"
|
||||||
|
properties: {
|
||||||
|
/**
|
||||||
|
* Session ID to navigate to
|
||||||
|
*/
|
||||||
|
sessionID: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export type EventMcpToolsChanged = {
|
export type EventMcpToolsChanged = {
|
||||||
type: "mcp.tools.changed"
|
type: "mcp.tools.changed"
|
||||||
properties: {
|
properties: {
|
||||||
@@ -776,6 +786,7 @@ export type Event =
|
|||||||
| EventTuiPromptAppend
|
| EventTuiPromptAppend
|
||||||
| EventTuiCommandExecute
|
| EventTuiCommandExecute
|
||||||
| EventTuiToastShow
|
| EventTuiToastShow
|
||||||
|
| EventTuiSessionSelect
|
||||||
| EventMcpToolsChanged
|
| EventMcpToolsChanged
|
||||||
| EventCommandExecuted
|
| EventCommandExecuted
|
||||||
| EventSessionCreated
|
| EventSessionCreated
|
||||||
@@ -4310,7 +4321,7 @@ export type TuiShowToastResponses = {
|
|||||||
export type TuiShowToastResponse = TuiShowToastResponses[keyof TuiShowToastResponses]
|
export type TuiShowToastResponse = TuiShowToastResponses[keyof TuiShowToastResponses]
|
||||||
|
|
||||||
export type TuiPublishData = {
|
export type TuiPublishData = {
|
||||||
body?: EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow
|
body?: EventTuiPromptAppend | EventTuiCommandExecute | EventTuiToastShow | EventTuiSessionSelect
|
||||||
path?: never
|
path?: never
|
||||||
query?: {
|
query?: {
|
||||||
directory?: string
|
directory?: string
|
||||||
@@ -4336,6 +4347,42 @@ export type TuiPublishResponses = {
|
|||||||
|
|
||||||
export type TuiPublishResponse = TuiPublishResponses[keyof TuiPublishResponses]
|
export type TuiPublishResponse = TuiPublishResponses[keyof TuiPublishResponses]
|
||||||
|
|
||||||
|
export type TuiSelectSessionData = {
|
||||||
|
body?: {
|
||||||
|
/**
|
||||||
|
* Session ID to navigate to
|
||||||
|
*/
|
||||||
|
sessionID: string
|
||||||
|
}
|
||||||
|
path?: never
|
||||||
|
query?: {
|
||||||
|
directory?: string
|
||||||
|
}
|
||||||
|
url: "/tui/select-session"
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TuiSelectSessionErrors = {
|
||||||
|
/**
|
||||||
|
* Bad request
|
||||||
|
*/
|
||||||
|
400: BadRequestError
|
||||||
|
/**
|
||||||
|
* Not found
|
||||||
|
*/
|
||||||
|
404: NotFoundError
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TuiSelectSessionError = TuiSelectSessionErrors[keyof TuiSelectSessionErrors]
|
||||||
|
|
||||||
|
export type TuiSelectSessionResponses = {
|
||||||
|
/**
|
||||||
|
* Session selected successfully
|
||||||
|
*/
|
||||||
|
200: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TuiSelectSessionResponse = TuiSelectSessionResponses[keyof TuiSelectSessionResponses]
|
||||||
|
|
||||||
export type TuiControlNextData = {
|
export type TuiControlNextData = {
|
||||||
body?: never
|
body?: never
|
||||||
path?: never
|
path?: never
|
||||||
|
|||||||
@@ -4956,6 +4956,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/components/schemas/Event.tui.toast.show"
|
"$ref": "#/components/schemas/Event.tui.toast.show"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Event.tui.session.select"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -4970,6 +4973,77 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/tui/select-session": {
|
||||||
|
"post": {
|
||||||
|
"operationId": "tui.selectSession",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "directory",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"summary": "Select session",
|
||||||
|
"description": "Navigate the TUI to display the specified session.",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Session selected successfully",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad request",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/BadRequestError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Not found",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/NotFoundError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"sessionID": {
|
||||||
|
"description": "Session ID to navigate to",
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^ses"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["sessionID"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-codeSamples": [
|
||||||
|
{
|
||||||
|
"lang": "js",
|
||||||
|
"source": "import { createOpencodeClient } from \"@opencode-ai/sdk\n\nconst client = createOpencodeClient()\nawait client.tui.selectSession({\n ...\n})"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/tui/control/next": {
|
"/tui/control/next": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "tui.control.next",
|
"operationId": "tui.control.next",
|
||||||
@@ -6794,6 +6868,27 @@
|
|||||||
},
|
},
|
||||||
"required": ["type", "properties"]
|
"required": ["type", "properties"]
|
||||||
},
|
},
|
||||||
|
"Event.tui.session.select": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"const": "tui.session.select"
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"sessionID": {
|
||||||
|
"description": "Session ID to navigate to",
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^ses"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["sessionID"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["type", "properties"]
|
||||||
|
},
|
||||||
"Event.mcp.tools.changed": {
|
"Event.mcp.tools.changed": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -7338,6 +7433,9 @@
|
|||||||
{
|
{
|
||||||
"$ref": "#/components/schemas/Event.tui.toast.show"
|
"$ref": "#/components/schemas/Event.tui.toast.show"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Event.tui.session.select"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"$ref": "#/components/schemas/Event.mcp.tools.changed"
|
"$ref": "#/components/schemas/Event.mcp.tools.changed"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"name": "@opencode-ai/slack",
|
"name": "@opencode-ai/slack",
|
||||||
"version": "1.0.224",
|
"version": "1.0.224",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "bun run src/index.ts",
|
"dev": "bun run src/index.ts",
|
||||||
"typecheck": "tsgo --noEmit"
|
"typecheck": "tsgo --noEmit"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"name": "@opencode-ai/ui",
|
"name": "@opencode-ai/ui",
|
||||||
"version": "1.0.224",
|
"version": "1.0.224",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
"exports": {
|
"exports": {
|
||||||
"./*": "./src/components/*.tsx",
|
"./*": "./src/components/*.tsx",
|
||||||
"./pierre": "./src/pierre/index.ts",
|
"./pierre": "./src/pierre/index.ts",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"version": "1.0.224",
|
"version": "1.0.224",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
"exports": {
|
"exports": {
|
||||||
"./*": "./src/*.ts"
|
"./*": "./src/*.ts"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/web",
|
"name": "@opencode-ai/web",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"license": "MIT",
|
||||||
"version": "1.0.224",
|
"version": "1.0.224",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ You can also check out [awesome-opencode](https://github.com/awesome-opencode/aw
|
|||||||
| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Allow OpenCode agents to lazy load prompts on demand with skill discovery and injection |
|
| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Allow OpenCode agents to lazy load prompts on demand with skill discovery and injection |
|
||||||
| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Persistent memory across sessions using Supermemory |
|
| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Persistent memory across sessions using Supermemory |
|
||||||
| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Interactive plan review with visual annotation and private/offline sharing |
|
| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Interactive plan review with visual annotation and private/offline sharing |
|
||||||
|
| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | Extend opencode /commands into a powerful orchestration system with granular flow control |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ OpenCode comes with several built-in LSP servers for popular languages:
|
|||||||
| gleam | .gleam | `gleam` command available |
|
| gleam | .gleam | `gleam` command available |
|
||||||
| gopls | .go | `go` command available |
|
| gopls | .go | `go` command available |
|
||||||
| jdtls | .java | `Java SDK (version 21+)` installed |
|
| jdtls | .java | `Java SDK (version 21+)` installed |
|
||||||
|
| kotlin-ls | .kt, .kts | Auto-installs for Kotlin projects |
|
||||||
| lua-ls | .lua | Auto-installs for Lua projects |
|
| lua-ls | .lua | Auto-installs for Lua projects |
|
||||||
| nixd | .nix | `nixd` command available |
|
| nixd | .nix | `nixd` command available |
|
||||||
| ocaml-lsp | .ml, .mli | `ocamllsp` command available |
|
| ocaml-lsp | .ml, .mli | `ocamllsp` command available |
|
||||||
|
|||||||
Reference in New Issue
Block a user