summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/opencode/src/cli/cmd/tui/app.tsx3
-rw-r--r--packages/opencode/src/cli/cmd/tui/context/sdk.tsx19
-rw-r--r--packages/opencode/src/cli/cmd/tui/plugin/api.tsx37
-rw-r--r--packages/opencode/src/cli/cmd/tui/plugin/runtime.ts2
-rw-r--r--packages/opencode/src/cli/cmd/tui/routes/session/index.tsx6
-rw-r--r--packages/opencode/src/cli/cmd/tui/thread.ts15
-rw-r--r--packages/opencode/src/cli/cmd/tui/worker.ts48
-rw-r--r--packages/opencode/test/fixture/tui-plugin.ts9
-rw-r--r--packages/plugin/src/tui.ts2
9 files changed, 51 insertions, 90 deletions
diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx
index a80039dd2..857c76c78 100644
--- a/packages/opencode/src/cli/cmd/tui/app.tsx
+++ b/packages/opencode/src/cli/cmd/tui/app.tsx
@@ -289,9 +289,6 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
toast,
renderer,
})
- onCleanup(() => {
- api.dispose()
- })
const [ready, setReady] = createSignal(false)
TuiPluginRuntime.init(api)
.catch((error) => {
diff --git a/packages/opencode/src/cli/cmd/tui/context/sdk.tsx b/packages/opencode/src/cli/cmd/tui/context/sdk.tsx
index a0f1b3224..348c3ca1d 100644
--- a/packages/opencode/src/cli/cmd/tui/context/sdk.tsx
+++ b/packages/opencode/src/cli/cmd/tui/context/sdk.tsx
@@ -4,8 +4,7 @@ import { createGlobalEmitter } from "@solid-primitives/event-bus"
import { batch, onCleanup, onMount } from "solid-js"
export type EventSource = {
- on: (handler: (event: Event) => void) => () => void
- setWorkspace?: (workspaceID?: string) => void
+ subscribe: (directory: string | undefined, handler: (event: Event) => void) => Promise<() => void>
}
export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
@@ -18,7 +17,6 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
events?: EventSource
}) => {
const abort = new AbortController()
- let workspaceID: string | undefined
let sse: AbortController | undefined
function createSDK() {
@@ -28,7 +26,6 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
directory: props.directory,
fetch: props.fetch,
headers: props.headers,
- experimental_workspaceID: workspaceID,
})
}
@@ -90,9 +87,9 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
})().catch(() => {})
}
- onMount(() => {
+ onMount(async () => {
if (props.events) {
- const unsub = props.events.on(handleEvent)
+ const unsub = await props.events.subscribe(props.directory, handleEvent)
onCleanup(unsub)
} else {
startSSE()
@@ -109,19 +106,9 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
get client() {
return sdk
},
- get workspaceID() {
- return workspaceID
- },
directory: props.directory,
event: emitter,
fetch: props.fetch ?? fetch,
- setWorkspace(next?: string) {
- if (workspaceID === next) return
- workspaceID = next
- sdk = createSDK()
- props.events?.setWorkspace?.(next)
- if (!props.events) startSSE()
- },
url: props.url,
}
},
diff --git a/packages/opencode/src/cli/cmd/tui/plugin/api.tsx b/packages/opencode/src/cli/cmd/tui/plugin/api.tsx
index 529c50cfa..3609f6cc1 100644
--- a/packages/opencode/src/cli/cmd/tui/plugin/api.tsx
+++ b/packages/opencode/src/cli/cmd/tui/plugin/api.tsx
@@ -18,7 +18,7 @@ import { Prompt } from "../component/prompt"
import { Slot as HostSlot } from "./slots"
import type { useToast } from "../ui/toast"
import { Installation } from "@/installation"
-import { createOpencodeClient, type OpencodeClient } from "@opencode-ai/sdk/v2"
+import { type OpencodeClient } from "@opencode-ai/sdk/v2"
type RouteEntry = {
key: symbol
@@ -43,11 +43,6 @@ type Input = {
renderer: TuiPluginApi["renderer"]
}
-type TuiHostPluginApi = TuiPluginApi & {
- map: Map<string | undefined, OpencodeClient>
- dispose: () => void
-}
-
function routeRegister(routes: RouteMap, list: TuiRouteDefinition[], bump: () => void) {
const key = Symbol()
for (const item of list) {
@@ -206,29 +201,7 @@ function appApi(): TuiPluginApi["app"] {
}
}
-export function createTuiApi(input: Input): TuiHostPluginApi {
- const map = new Map<string | undefined, OpencodeClient>()
- const scoped: TuiPluginApi["scopedClient"] = (workspaceID) => {
- const hit = map.get(workspaceID)
- if (hit) return hit
-
- const next = createOpencodeClient({
- baseUrl: input.sdk.url,
- fetch: input.sdk.fetch,
- directory: input.sync.data.path.directory || input.sdk.directory,
- experimental_workspaceID: workspaceID,
- })
- map.set(workspaceID, next)
- return next
- }
- const workspace: TuiPluginApi["workspace"] = {
- current() {
- return input.sdk.workspaceID
- },
- set(workspaceID) {
- input.sdk.setWorkspace(workspaceID)
- },
- }
+export function createTuiApi(input: Input): TuiPluginApi {
const lifecycle: TuiPluginApi["lifecycle"] = {
signal: new AbortController().signal,
onDispose() {
@@ -369,8 +342,6 @@ export function createTuiApi(input: Input): TuiHostPluginApi {
get client() {
return input.sdk.client
},
- scopedClient: scoped,
- workspace,
event: input.sdk.event,
renderer: input.renderer,
slots: {
@@ -422,9 +393,5 @@ export function createTuiApi(input: Input): TuiHostPluginApi {
return input.theme.ready
},
},
- map,
- dispose() {
- map.clear()
- },
}
}
diff --git a/packages/opencode/src/cli/cmd/tui/plugin/runtime.ts b/packages/opencode/src/cli/cmd/tui/plugin/runtime.ts
index b33efdbd3..2f7fd5164 100644
--- a/packages/opencode/src/cli/cmd/tui/plugin/runtime.ts
+++ b/packages/opencode/src/cli/cmd/tui/plugin/runtime.ts
@@ -543,8 +543,6 @@ function pluginApi(runtime: RuntimeState, plugin: PluginEntry, scope: PluginScop
get client() {
return api.client
},
- scopedClient: api.scopedClient,
- workspace: api.workspace,
event,
renderer: api.renderer,
slots,
diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
index afeed6a22..91baca52a 100644
--- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
+++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
@@ -167,12 +167,6 @@ export function Session() {
const scrollAcceleration = createMemo(() => getScrollAcceleration(tuiConfig))
- createEffect(() => {
- if (session()?.workspaceID) {
- sdk.setWorkspace(session()?.workspaceID)
- }
- })
-
createEffect(async () => {
await sync.session
.sync(route.sessionID)
diff --git a/packages/opencode/src/cli/cmd/tui/thread.ts b/packages/opencode/src/cli/cmd/tui/thread.ts
index 3bb56937a..df5c41677 100644
--- a/packages/opencode/src/cli/cmd/tui/thread.ts
+++ b/packages/opencode/src/cli/cmd/tui/thread.ts
@@ -43,9 +43,18 @@ function createWorkerFetch(client: RpcClient): typeof fetch {
function createEventSource(client: RpcClient): EventSource {
return {
- on: (handler) => client.on<Event>("event", handler),
- setWorkspace: (workspaceID) => {
- void client.call("setWorkspace", { workspaceID })
+ subscribe: async (directory, handler) => {
+ const id = await client.call("subscribe", { directory })
+ const unsub = client.on<{ id: string; event: Event }>("event", (e) => {
+ if (e.id === id) {
+ handler(e.event)
+ }
+ })
+
+ return () => {
+ unsub()
+ client.call("unsubscribe", { id })
+ }
},
}
}
diff --git a/packages/opencode/src/cli/cmd/tui/worker.ts b/packages/opencode/src/cli/cmd/tui/worker.ts
index 643676e34..0b9ec82dc 100644
--- a/packages/opencode/src/cli/cmd/tui/worker.ts
+++ b/packages/opencode/src/cli/cmd/tui/worker.ts
@@ -45,20 +45,20 @@ GlobalBus.on("event", (event) => {
let server: Awaited<ReturnType<typeof Server.listen>> | undefined
-const eventStream = {
- abort: undefined as AbortController | undefined,
-}
+const eventStreams = new Map<string, AbortController>()
+
+function startEventStream(directory: string) {
+ const id = crypto.randomUUID()
-const startEventStream = (input: { directory: string; workspaceID?: string }) => {
- if (eventStream.abort) eventStream.abort.abort()
const abort = new AbortController()
- eventStream.abort = abort
const signal = abort.signal
- ;(async () => {
+ eventStreams.set(id, abort)
+
+ async function run() {
while (!signal.aborted) {
const shouldReconnect = await Instance.provide({
- directory: input.directory,
+ directory,
init: InstanceBootstrap,
fn: () =>
new Promise<boolean>((resolve) => {
@@ -77,7 +77,10 @@ const startEventStream = (input: { directory: string; workspaceID?: string }) =>
}
const unsub = Bus.subscribeAll((event) => {
- Rpc.emit("event", event as Event)
+ Rpc.emit("event", {
+ id,
+ event: event as Event,
+ })
if (event.type === Bus.InstanceDisposed.type) {
settle(true)
}
@@ -104,14 +107,24 @@ const startEventStream = (input: { directory: string; workspaceID?: string }) =>
await sleep(250)
}
}
- })().catch((error) => {
+ }
+
+ run().catch((error) => {
Log.Default.error("event stream error", {
error: error instanceof Error ? error.message : error,
})
})
+
+ return id
}
-startEventStream({ directory: process.cwd() })
+function stopEventStream(id: string) {
+ const abortController = eventStreams.get(id)
+ if (!abortController) return
+
+ abortController.abort()
+ eventStreams.delete(id)
+}
export const rpc = {
async fetch(input: { url: string; method: string; headers: Record<string, string>; body?: string }) {
@@ -154,12 +167,19 @@ export const rpc = {
async reload() {
await Config.invalidate(true)
},
- async setWorkspace(input: { workspaceID?: string }) {
- startEventStream({ directory: process.cwd(), workspaceID: input.workspaceID })
+ async subscribe(input: { directory: string | undefined }) {
+ return startEventStream(input.directory || process.cwd())
+ },
+ async unsubscribe(input: { id: string }) {
+ stopEventStream(input.id)
},
async shutdown() {
Log.Default.info("worker shutting down")
- if (eventStream.abort) eventStream.abort.abort()
+
+ for (const id of [...eventStreams.keys()]) {
+ stopEventStream(id)
+ }
+
await Instance.disposeAll()
if (server) await server.stop(true)
},
diff --git a/packages/opencode/test/fixture/tui-plugin.ts b/packages/opencode/test/fixture/tui-plugin.ts
index a9b1ed4ce..7ddcc7733 100644
--- a/packages/opencode/test/fixture/tui-plugin.ts
+++ b/packages/opencode/test/fixture/tui-plugin.ts
@@ -82,8 +82,6 @@ function themeCurrent(): HostPluginApi["theme"]["current"] {
type Opts = {
client?: HostPluginApi["client"] | (() => HostPluginApi["client"])
- scopedClient?: HostPluginApi["scopedClient"]
- workspace?: Partial<HostPluginApi["workspace"]>
renderer?: HostPluginApi["renderer"]
count?: Count
keybind?: Partial<HostPluginApi["keybind"]>
@@ -127,11 +125,6 @@ export function createTuiPluginApi(opts: Opts = {}): HostPluginApi {
? () => opts.client as HostPluginApi["client"]
: fallback
const client = () => read()
- const scopedClient = opts.scopedClient ?? ((_workspaceID?: string) => client())
- const workspace: HostPluginApi["workspace"] = {
- current: opts.workspace?.current ?? (() => undefined),
- set: opts.workspace?.set ?? (() => {}),
- }
let depth = 0
let size: "medium" | "large" | "xlarge" = "medium"
const has = opts.theme?.has ?? (() => false)
@@ -171,8 +164,6 @@ export function createTuiPluginApi(opts: Opts = {}): HostPluginApi {
get client() {
return client()
},
- scopedClient,
- workspace,
event: {
on: () => {
if (count) count.event_add += 1
diff --git a/packages/plugin/src/tui.ts b/packages/plugin/src/tui.ts
index 27b59b8d5..8f8439fab 100644
--- a/packages/plugin/src/tui.ts
+++ b/packages/plugin/src/tui.ts
@@ -484,8 +484,6 @@ export type TuiPluginApi = {
state: TuiState
theme: TuiTheme
client: OpencodeClient
- scopedClient: (workspaceID?: string) => OpencodeClient
- workspace: TuiWorkspace
event: TuiEventBus
renderer: CliRenderer
slots: TuiSlots