refactor(tui): remove legacy sdk client
This commit is contained in:
parent
4c45a5cf23
commit
36f8cb7054
36 changed files with 316 additions and 510 deletions
|
|
@ -1,13 +1,12 @@
|
|||
import type { OpenCodeClient, OpenCodeEvent } from "@opencode-ai/client"
|
||||
import type { OpencodeClient } from "@opencode-ai/sdk/v2"
|
||||
import { createGlobalEmitter } from "@solid-primitives/event-bus"
|
||||
import { onCleanup, onMount } from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { createSimpleContext } from "./helper"
|
||||
import { useLog } from "./log"
|
||||
|
||||
export type SDKConnectionStatus = "connected" | "connecting" | "reconnecting"
|
||||
export type SDKConnectionEvent = {
|
||||
export type ClientConnectionStatus = "connected" | "connecting" | "reconnecting"
|
||||
export type ClientConnectionEvent = {
|
||||
readonly type: "client.connection"
|
||||
readonly created: number
|
||||
readonly data: {
|
||||
|
|
@ -17,27 +16,25 @@ export type SDKConnectionEvent = {
|
|||
}
|
||||
}
|
||||
|
||||
type SDKEventMap = { [Type in OpenCodeEvent["type"]]: Extract<OpenCodeEvent, { type: Type }> }
|
||||
type ClientEventMap = { [Type in OpenCodeEvent["type"]]: Extract<OpenCodeEvent, { type: Type }> }
|
||||
const connectTimeout = 2_000
|
||||
const connectionHistoryLimit = 50
|
||||
|
||||
export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
|
||||
name: "SDK",
|
||||
export const { use: useClient, provider: ClientProvider } = createSimpleContext({
|
||||
name: "Client",
|
||||
init: (props: {
|
||||
client: OpencodeClient
|
||||
api: OpenCodeClient
|
||||
reconnect?: (attempt: number) => Promise<{ client: OpencodeClient; api: OpenCodeClient }>
|
||||
reconnect?: (attempt: number) => Promise<{ api: OpenCodeClient }>
|
||||
// Stops and starts the managed service; present only in service mode.
|
||||
reload?: () => Promise<void>
|
||||
}) => {
|
||||
const log = useLog({ component: "sdk" })
|
||||
const log = useLog({ component: "client" })
|
||||
const abort = new AbortController()
|
||||
const history: SDKConnectionEvent[] = []
|
||||
let client = props.client
|
||||
const history: ClientConnectionEvent[] = []
|
||||
let api = props.api
|
||||
const events = createGlobalEmitter<SDKEventMap>()
|
||||
const events = createGlobalEmitter<ClientEventMap>()
|
||||
const [connection, setConnection] = createStore<{
|
||||
status: SDKConnectionStatus
|
||||
status: ClientConnectionStatus
|
||||
attempt: number
|
||||
error?: string
|
||||
}>({
|
||||
|
|
@ -46,7 +43,7 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
|
|||
})
|
||||
let stream: AbortController | undefined
|
||||
|
||||
function record(status: SDKConnectionEvent["data"]["status"], attempt: number, error?: string) {
|
||||
function record(status: ClientConnectionEvent["data"]["status"], attempt: number, error?: string) {
|
||||
history.push({ type: "client.connection", created: Date.now(), data: { status, attempt, error } })
|
||||
if (history.length > connectionHistoryLimit) history.shift()
|
||||
}
|
||||
|
|
@ -121,7 +118,6 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
|
|||
const next = await props.reconnect(attempt).catch(() => undefined)
|
||||
if (abort.signal.aborted || controller.signal.aborted) return
|
||||
if (next) {
|
||||
client = next.client
|
||||
api = next.api
|
||||
}
|
||||
}
|
||||
|
|
@ -144,9 +140,6 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
|
|||
})
|
||||
|
||||
return {
|
||||
get client() {
|
||||
return client
|
||||
},
|
||||
get api() {
|
||||
return api
|
||||
},
|
||||
|
|
@ -30,7 +30,7 @@ import type {
|
|||
import type { Data } from "@opencode-ai/plugin/v2/tui/context"
|
||||
import { createStore, produce, reconcile } from "solid-js/store"
|
||||
import { createSimpleContext } from "./helper"
|
||||
import { useSDK } from "./sdk"
|
||||
import { useClient } from "./client"
|
||||
import { createSignal, onCleanup } from "solid-js"
|
||||
|
||||
export type DataSessionStatus = "idle" | "running"
|
||||
|
|
@ -110,7 +110,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
location: {},
|
||||
})
|
||||
|
||||
const sdk = useSDK()
|
||||
const client = useClient()
|
||||
const [defaultLocation, setDefaultLocation] = createSignal<LocationRef>({
|
||||
directory: process.cwd(),
|
||||
})
|
||||
|
|
@ -328,7 +328,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
time: { created: event.created },
|
||||
})
|
||||
})
|
||||
void sdk.api.session
|
||||
void client.api.session
|
||||
.message({ sessionID: event.data.sessionID, messageID: messageIDFromEvent(event.id) })
|
||||
.then((item) => {
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
|
|
@ -851,8 +851,8 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
}
|
||||
|
||||
const result = {
|
||||
on: sdk.event.on,
|
||||
listen: sdk.event.listen,
|
||||
on: client.event.on,
|
||||
listen: client.event.listen,
|
||||
session: {
|
||||
list() {
|
||||
return Object.values(store.session.info).toSorted((a, b) => b.time.updated - a.time.updated)
|
||||
|
|
@ -899,7 +899,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
return store.session.pending[sessionID] ?? []
|
||||
},
|
||||
async refresh(sessionID: string) {
|
||||
const pending = await sdk.api.session.pending.list({ sessionID })
|
||||
const pending = await client.api.session.pending.list({ sessionID })
|
||||
setStore("session", "pending", sessionID, reconcile(pending))
|
||||
setStore(
|
||||
"session",
|
||||
|
|
@ -916,7 +916,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
},
|
||||
},
|
||||
async refresh(sessionID: string) {
|
||||
setStore("session", "info", sessionID, await sdk.api.session.get({ sessionID }))
|
||||
setStore("session", "info", sessionID, await client.api.session.get({ sessionID }))
|
||||
registerSession(sessionID)
|
||||
},
|
||||
message: {
|
||||
|
|
@ -929,7 +929,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
return position === undefined ? undefined : messages?.[position]
|
||||
},
|
||||
async refresh(sessionID: string) {
|
||||
const messages = (await sdk.api.message.list({ sessionID, limit: 200, order: "desc" })).data.toReversed()
|
||||
const messages = (await client.api.message.list({ sessionID, limit: 200, order: "desc" })).data.toReversed()
|
||||
messageIndex.set(sessionID, new Map(messages.map((message, index) => [message.id, index])))
|
||||
setStore("session", "message", sessionID, reconcile(messages))
|
||||
},
|
||||
|
|
@ -939,7 +939,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
return store.session.permission[sessionID]
|
||||
},
|
||||
async refresh(sessionID: string) {
|
||||
setStore("session", "permission", sessionID, await sdk.api.permission.list({ sessionID }))
|
||||
setStore("session", "permission", sessionID, await client.api.permission.list({ sessionID }))
|
||||
},
|
||||
},
|
||||
form: {
|
||||
|
|
@ -952,7 +952,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
},
|
||||
async refresh(sessionID: string, ref?: LocationRef) {
|
||||
if (sessionID === "global") {
|
||||
const response = await sdk.api.form.request.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const response = await client.api.form.request.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const location = {
|
||||
directory: response.location.directory,
|
||||
workspaceID: response.location.workspaceID,
|
||||
|
|
@ -966,7 +966,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
])
|
||||
return
|
||||
}
|
||||
setStore("session", "form", sessionID, await sdk.api.form.list({ sessionID }))
|
||||
setStore("session", "form", sessionID, await client.api.form.list({ sessionID }))
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -976,7 +976,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
return store.project.permission[projectID]
|
||||
},
|
||||
async refresh(projectID: string) {
|
||||
setStore("project", "permission", projectID, await sdk.api.permission.saved.list({ projectID }))
|
||||
setStore("project", "permission", projectID, await client.api.permission.saved.list({ projectID }))
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -990,7 +990,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
.find((shell) => shell !== undefined)
|
||||
},
|
||||
async refresh(ref?: LocationRef) {
|
||||
const result = await sdk.api.shell.list({ location: locationQuery(ref) })
|
||||
const result = await client.api.shell.list({ location: locationQuery(ref) })
|
||||
const key = locationKey(result.location)
|
||||
setStore("location", key, {
|
||||
...store.location[key],
|
||||
|
|
@ -1003,7 +1003,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
return defaultLocation()
|
||||
},
|
||||
async refresh(ref?: LocationRef) {
|
||||
const location = await sdk.api.location.get({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const location = await client.api.location.get({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const key = locationKey(location)
|
||||
if (!store.location[key]) setStore("location", key, {})
|
||||
if (!ref) setDefaultLocation({ directory: location.directory, workspaceID: location.workspaceID })
|
||||
|
|
@ -1013,7 +1013,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
return store.location[locationKey(location ?? defaultLocation())]?.agent
|
||||
},
|
||||
async refresh(ref?: LocationRef) {
|
||||
const result = await sdk.api.agent.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const result = await client.api.agent.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const key = locationKey(result.location)
|
||||
setStore("location", key, { ...store.location[key], agent: result.data })
|
||||
},
|
||||
|
|
@ -1023,7 +1023,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
return store.location[locationKey(location ?? defaultLocation())]?.command
|
||||
},
|
||||
async refresh(ref?: LocationRef) {
|
||||
const result = await sdk.api.command.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const result = await client.api.command.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const key = locationKey(result.location)
|
||||
setStore("location", key, { ...store.location[key], command: result.data })
|
||||
},
|
||||
|
|
@ -1033,7 +1033,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
return store.location[locationKey(location ?? defaultLocation())]?.integration
|
||||
},
|
||||
async refresh(ref?: LocationRef) {
|
||||
const result = await sdk.api.integration.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const result = await client.api.integration.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const key = locationKey(result.location)
|
||||
setStore("location", key, { ...store.location[key], integration: result.data })
|
||||
},
|
||||
|
|
@ -1044,7 +1044,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
return store.location[locationKey(location ?? defaultLocation())]?.mcp?.server
|
||||
},
|
||||
async refresh(ref?: LocationRef) {
|
||||
const result = await sdk.api.mcp.list({ location: locationQuery(ref) })
|
||||
const result = await client.api.mcp.list({ location: locationQuery(ref) })
|
||||
const key = locationKey(result.location)
|
||||
setStore("location", key, {
|
||||
...store.location[key],
|
||||
|
|
@ -1057,7 +1057,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
return store.location[locationKey(location ?? defaultLocation())]?.mcp?.resource
|
||||
},
|
||||
async refresh(ref?: LocationRef) {
|
||||
const result = await sdk.api.mcp.resource.catalog({ location: locationQuery(ref) })
|
||||
const result = await client.api.mcp.resource.catalog({ location: locationQuery(ref) })
|
||||
const key = locationKey(result.location)
|
||||
setStore("location", key, {
|
||||
...store.location[key],
|
||||
|
|
@ -1071,7 +1071,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
return store.location[locationKey(location ?? defaultLocation())]?.model
|
||||
},
|
||||
async refresh(ref?: LocationRef) {
|
||||
const result = await sdk.api.model.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const result = await client.api.model.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const key = locationKey(result.location)
|
||||
setStore("location", key, { ...store.location[key], model: result.data })
|
||||
},
|
||||
|
|
@ -1081,7 +1081,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
return store.location[locationKey(location ?? defaultLocation())]?.provider
|
||||
},
|
||||
async refresh(ref?: LocationRef) {
|
||||
const result = await sdk.api.provider.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const result = await client.api.provider.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const key = locationKey(result.location)
|
||||
setStore("location", key, { ...store.location[key], provider: result.data })
|
||||
},
|
||||
|
|
@ -1091,7 +1091,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
return store.location[locationKey(location ?? defaultLocation())]?.reference
|
||||
},
|
||||
async refresh(ref?: LocationRef) {
|
||||
const result = await sdk.api.reference.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const result = await client.api.reference.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const key = locationKey(result.location)
|
||||
setStore("location", key, { ...store.location[key], reference: result.data })
|
||||
},
|
||||
|
|
@ -1101,7 +1101,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
return store.location[locationKey(location ?? defaultLocation())]?.skill
|
||||
},
|
||||
async refresh(ref?: LocationRef) {
|
||||
const result = await sdk.api.skill.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const result = await client.api.skill.list({ location: locationQuery(ref ?? defaultLocation()) })
|
||||
const key = locationKey(result.location)
|
||||
setStore("location", key, { ...store.location[key], skill: result.data })
|
||||
},
|
||||
|
|
@ -1113,7 +1113,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
async function bootstrap() {
|
||||
if (bootstrapping) return bootstrapping
|
||||
bootstrapping = Promise.allSettled([
|
||||
sdk.api.session
|
||||
client.api.session
|
||||
.list({
|
||||
limit: 50,
|
||||
order: "desc",
|
||||
|
|
@ -1130,7 +1130,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
)
|
||||
for (const session of response.data) registerSession(session.id)
|
||||
}),
|
||||
sdk.api.permission.request.list({ location: locationQuery(defaultLocation()) }).then((response) => {
|
||||
client.api.permission.request.list({ location: locationQuery(defaultLocation()) }).then((response) => {
|
||||
const permissions = response.data.reduce<Record<string, PermissionV2Request[]>>(
|
||||
(result, request) => ({
|
||||
...result,
|
||||
|
|
@ -1140,7 +1140,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
)
|
||||
setStore("session", "permission", reconcile(permissions))
|
||||
}),
|
||||
sdk.api.form.request.list({ location: locationQuery(defaultLocation()) }).then((response) => {
|
||||
client.api.form.request.list({ location: locationQuery(defaultLocation()) }).then((response) => {
|
||||
const location = {
|
||||
directory: response.location.directory,
|
||||
workspaceID: response.location.workspaceID,
|
||||
|
|
@ -1193,7 +1193,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
}
|
||||
|
||||
function refreshActive() {
|
||||
void sdk.api.session
|
||||
void client.api.session
|
||||
.active()
|
||||
.then((active) => {
|
||||
setStore(
|
||||
|
|
@ -1206,7 +1206,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
}
|
||||
|
||||
onCleanup(
|
||||
sdk.event.listen(({ details }) => {
|
||||
client.event.listen(({ details }) => {
|
||||
if (details.type === "server.connected") {
|
||||
const messages = connected ? Object.keys(store.session.message) : []
|
||||
const compactions = connected ? Object.keys(store.session.compaction) : []
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { OpenCodeEvent } from "@opencode-ai/client"
|
||||
import { useSDK } from "./sdk"
|
||||
import { useClient } from "./client"
|
||||
|
||||
type EventMetadata = {
|
||||
directory: string | undefined
|
||||
|
|
@ -7,10 +7,10 @@ type EventMetadata = {
|
|||
}
|
||||
|
||||
export function useEvent() {
|
||||
const sdk = useSDK()
|
||||
const client = useClient()
|
||||
|
||||
function subscribe(handler: (event: OpenCodeEvent, metadata: EventMetadata) => void) {
|
||||
return sdk.event.listen(({ details }) => {
|
||||
return client.event.listen(({ details }) => {
|
||||
if (details.type === "server.connected") return
|
||||
handler(details, { directory: details.location?.directory, workspace: details.location?.workspaceID })
|
||||
})
|
||||
|
|
@ -20,7 +20,7 @@ export function useEvent() {
|
|||
type: T,
|
||||
handler: (event: Extract<OpenCodeEvent, { type: T }>, metadata: EventMetadata) => void,
|
||||
) {
|
||||
return sdk.event.on(type, (event) => {
|
||||
return client.event.on(type, (event) => {
|
||||
handler(event, { directory: event.location?.directory, workspace: event.location?.workspaceID })
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { useEvent } from "./event"
|
|||
import path from "path"
|
||||
import { useTuiPaths } from "./runtime"
|
||||
import { useArgs } from "./args"
|
||||
import { useSDK } from "./sdk"
|
||||
import { useClient } from "./client"
|
||||
import { RGBA } from "@opentui/core"
|
||||
import { readJson, writeJsonAtomic } from "../util/persistence"
|
||||
import { useTheme } from "./theme"
|
||||
|
|
@ -52,7 +52,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||
name: "Local",
|
||||
init: () => {
|
||||
const data = useData()
|
||||
const sdk = useSDK()
|
||||
const client = useClient()
|
||||
const toast = useToast()
|
||||
const theme = useTheme().theme
|
||||
const route = useRoute()
|
||||
|
|
@ -493,22 +493,6 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||
|
||||
const session = createSession()
|
||||
|
||||
const mcp = {
|
||||
isEnabled(name: string) {
|
||||
return data.location.mcp.server.list()?.find((item) => item.name === name)?.status.status === "connected"
|
||||
},
|
||||
async toggle(name: string) {
|
||||
const status = data.location.mcp.server.list()?.find((item) => item.name === name)?.status.status
|
||||
if (status === "connected") {
|
||||
// Disable: disconnect the MCP
|
||||
await sdk.client.mcp.disconnect({ name })
|
||||
} else {
|
||||
// Enable/Retry: connect the MCP (handles disabled, failed, and other states)
|
||||
await sdk.client.mcp.connect({ name })
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
createEffect(() => {
|
||||
const value = agent.current()
|
||||
if (!value?.model) return
|
||||
|
|
@ -523,7 +507,6 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||
const result = {
|
||||
model,
|
||||
agent,
|
||||
mcp,
|
||||
session,
|
||||
permission,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { batch } from "solid-js"
|
||||
import { createStore, reconcile } from "solid-js/store"
|
||||
import { createSimpleContext } from "./helper"
|
||||
import { useSDK } from "./sdk"
|
||||
import { useClient } from "./client"
|
||||
|
||||
export const { use: useProject, provider: ProjectProvider } = createSimpleContext({
|
||||
name: "Project",
|
||||
init: () => {
|
||||
const sdk = useSDK()
|
||||
const client = useClient()
|
||||
|
||||
const defaultPath = {
|
||||
home: "",
|
||||
|
|
@ -33,8 +33,8 @@ export const { use: useProject, provider: ProjectProvider } = createSimpleContex
|
|||
async function sync() {
|
||||
const workspace = store.workspace.current
|
||||
const location = { workspace }
|
||||
const current = await sdk.api.location.get({ location })
|
||||
const directories = await sdk.api.project.directories({ projectID: current.project.id, location })
|
||||
const current = await client.api.location.get({ location })
|
||||
const directories = await client.api.project.directories({ projectID: current.project.id, location })
|
||||
batch(() => {
|
||||
setStore(
|
||||
"instance",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue