Skip to content

Commit aaeff9b

Browse files
committed
refactor: simplify workspace adapter registry
1 parent 34e332c commit aaeff9b

2 files changed

Lines changed: 18 additions & 36 deletions

File tree

packages/opencode/src/control-plane/adapters/index.ts

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,20 @@ import { type WorkspaceAdapter, WorkspaceAdapterError, type WorkspaceAdapterEntr
77
import type { Interface as WorktreeService } from "@/worktree"
88
import { WorktreeAdapterEntry, worktreeAdapter } from "./worktree"
99

10-
export interface AdapterServices {
11-
readonly worktree: WorktreeService
12-
}
13-
14-
const BUILTIN: Record<string, WorkspaceAdapterEntry> = {
15-
worktree: { type: "worktree", ...WorktreeAdapterEntry },
16-
}
10+
const BUILTIN: WorkspaceAdapterEntry[] = [{ type: "worktree", ...WorktreeAdapterEntry }]
1711

18-
const builtinAdapter = (type: string, services: AdapterServices): WorkspaceAdapter | undefined => {
19-
if (type === "worktree") return worktreeAdapter(services.worktree)
20-
}
12+
export const makeBuiltinAdapters = (worktree: WorktreeService) =>
13+
new Map<string, WorkspaceAdapter>([["worktree", worktreeAdapter(worktree)]])
2114

22-
export const makeBuiltinAdapters = (services: AdapterServices) =>
23-
new Map(
24-
Object.keys(BUILTIN).flatMap((type) => {
25-
const adapter = builtinAdapter(type, services)
26-
return adapter ? [[type, adapter] as const] : []
27-
}),
28-
)
29-
30-
const state = new Map<ProjectID, Map<string, WorkspaceAdapter>>()
15+
const plugins = new Map<ProjectID, Map<string, WorkspaceAdapter>>()
3116
const emptyBuiltinAdapters = new Map<string, WorkspaceAdapter>()
3217

3318
export function getAdapter(
3419
projectID: ProjectID,
3520
type: string,
3621
builtin: ReadonlyMap<string, WorkspaceAdapter> = emptyBuiltinAdapters,
3722
): WorkspaceAdapter {
38-
const custom = state.get(projectID)?.get(type)
23+
const custom = plugins.get(projectID)?.get(type)
3924
if (custom) return custom
4025

4126
const adapter = builtin.get(type)
@@ -45,20 +30,12 @@ export function getAdapter(
4530
}
4631

4732
export async function listAdapters(projectID: ProjectID): Promise<WorkspaceAdapterEntry[]> {
48-
const custom = [...(state.get(projectID)?.entries() ?? [])].map(([type, adapter]) => ({
33+
const custom = [...(plugins.get(projectID)?.entries() ?? [])].map(([type, adapter]) => ({
4934
type,
5035
name: adapter.name,
5136
description: adapter.description,
5237
}))
53-
return [...Object.values(BUILTIN), ...custom]
54-
}
55-
56-
// Plugins can be loaded per-project so we need to scope them. If you
57-
// want to install a global one pass `ProjectID.global`
58-
export function registerEffectAdapter(projectID: ProjectID, type: string, adapter: WorkspaceAdapter) {
59-
const adapters = state.get(projectID) ?? new Map<string, WorkspaceAdapter>()
60-
adapters.set(type, adapter)
61-
state.set(projectID, adapters)
38+
return [...BUILTIN, ...custom]
6239
}
6340

6441
const adapterError = (cause: unknown) => new WorkspaceAdapterError({ message: errorMessage(cause), cause })
@@ -92,5 +69,9 @@ function fromPromiseAdapter(adapter: PluginWorkspaceAdapter): WorkspaceAdapter {
9269
}
9370

9471
export function registerAdapter(projectID: ProjectID, type: string, adapter: PluginWorkspaceAdapter) {
95-
registerEffectAdapter(projectID, type, fromPromiseAdapter(adapter))
72+
// Plugins can be loaded per-project so we need to scope them. If you
73+
// want to install a global one pass `ProjectID.global`.
74+
const adapters = plugins.get(projectID) ?? new Map<string, WorkspaceAdapter>()
75+
adapters.set(type, fromPromiseAdapter(adapter))
76+
plugins.set(projectID, adapters)
9677
}

packages/opencode/src/control-plane/workspace.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,12 @@ export const layer = Layer.effect(
176176
const worktree = yield* Worktree.Service
177177
const connections = new Map<WorkspaceID, ConnectionStatus>()
178178
const syncFibers = yield* FiberMap.make<WorkspaceID, void, SyncLoopError>()
179-
const adapters = makeBuiltinAdapters({ worktree })
179+
const builtinAdapters = makeBuiltinAdapters(worktree)
180+
const adapterFor = (space: { projectID: ProjectID; type: string }) =>
181+
getAdapter(space.projectID, space.type, builtinAdapters)
180182

181183
const target = Effect.fn("Workspace.target")(function* (space: Info) {
182-
return yield* getAdapter(space.projectID, space.type, adapters).target(space)
184+
return yield* adapterFor(space).target(space)
183185
})
184186

185187
const setStatus = (id: WorkspaceID, status: ConnectionStatus["status"]) => {
@@ -465,7 +467,7 @@ export const layer = Layer.effect(
465467

466468
const create = Effect.fn("Workspace.create")(function* (input: CreateInput) {
467469
const id = WorkspaceID.ascending(input.id)
468-
const adapter = getAdapter(input.projectID, input.type, adapters)
470+
const adapter = adapterFor(input)
469471
const config = yield* adapter.configure({ ...input, id, name: Slug.create(), directory: null })
470472

471473
const info: Info = {
@@ -730,8 +732,7 @@ export const layer = Layer.effect(
730732
const info = fromRow(row)
731733
yield* Effect.catch(
732734
Effect.gen(function* () {
733-
const adapter = getAdapter(info.projectID, row.type, adapters)
734-
yield* adapter.remove(info)
735+
yield* adapterFor(info).remove(info)
735736
}),
736737
() =>
737738
Effect.sync(() => {

0 commit comments

Comments
 (0)