feat(core): expose workspace adaptors to plugins (#21927)

This commit is contained in:
James Long
2026-04-13 13:33:13 -04:00
committed by GitHub
parent b8801dbd22
commit bf50d1c028
17 changed files with 1745 additions and 43 deletions

View File

@@ -9,6 +9,12 @@ import { setTimeout as sleep } from "node:timers/promises"
import { useSDK } from "../context/sdk"
import { useToast } from "../ui/toast"
type Adaptor = {
type: string
name: string
description: string
}
function scoped(sdk: ReturnType<typeof useSDK>, sync: ReturnType<typeof useSync>, workspaceID: string) {
return createOpencodeClient({
baseUrl: sdk.url,
@@ -63,9 +69,27 @@ export function DialogWorkspaceCreate(props: { onSelect: (workspaceID: string) =
const sdk = useSDK()
const toast = useToast()
const [creating, setCreating] = createSignal<string>()
const [adaptors, setAdaptors] = createSignal<Adaptor[]>()
onMount(() => {
dialog.setSize("medium")
void (async () => {
const dir = sync.path.directory || sdk.directory
const url = new URL("/experimental/workspace/adaptor", sdk.url)
if (dir) url.searchParams.set("directory", dir)
const res = await sdk
.fetch(url)
.then((x) => x.json() as Promise<Adaptor[]>)
.catch(() => undefined)
if (!res) {
toast.show({
message: "Failed to load workspace adaptors",
variant: "error",
})
return
}
setAdaptors(res)
})()
})
const options = createMemo(() => {
@@ -79,13 +103,21 @@ export function DialogWorkspaceCreate(props: { onSelect: (workspaceID: string) =
},
]
}
return [
{
title: "Worktree",
value: "worktree" as const,
description: "Create a local git worktree",
},
]
const list = adaptors()
if (!list) {
return [
{
title: "Loading workspaces...",
value: "loading" as const,
description: "Fetching available workspace adaptors",
},
]
}
return list.map((item) => ({
title: item.name,
value: item.type,
description: item.description,
}))
})
const create = async (type: string) => {
@@ -113,7 +145,7 @@ export function DialogWorkspaceCreate(props: { onSelect: (workspaceID: string) =
skipFilter={true}
options={options()}
onSelect={(option) => {
if (option.value === "creating") return
if (option.value === "creating" || option.value === "loading") return
void create(option.value)
}}
/>