Skip to content

Commit 8c79c58

Browse files
authored
refactor: rename workspace adapters (#25272)
1 parent 97ed9ba commit 8c79c58

25 files changed

Lines changed: 225 additions & 225 deletions

File tree

packages/opencode/specs/effect/http-api.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ Use raw Effect HTTP routes where `HttpApi` does not fit. The goal is deleting Ho
198198
| `project` | `bridged` | list, current, git init, update |
199199
| `file` | `bridged` partial | find text/file/symbol, list/content/status |
200200
| `mcp` | `bridged` | status, add, OAuth, connect/disconnect |
201-
| `workspace` | `bridged` | adaptor/list/status/create/remove/session-restore |
201+
| `workspace` | `bridged` | adapter/list/status/create/remove/session-restore |
202202
| top-level instance routes | `bridged` | path, vcs, command, agent, skill, lsp, formatter, dispose |
203203
| experimental JSON routes | `bridged` | console, tool, worktree list/mutations, global session list, resource list |
204204
| `session` | `bridged` | read, lifecycle, prompt, message/part mutations, revert, permission reply |
@@ -290,7 +290,7 @@ This checklist tracks bridge parity only. Checked routes are available through t
290290

291291
### Workspace Routes
292292

293-
- [x] `GET /experimental/workspace/adaptor` - list workspace adaptors.
293+
- [x] `GET /experimental/workspace/adapter` - list workspace adapters.
294294
- [x] `POST /experimental/workspace` - create workspace.
295295
- [x] `GET /experimental/workspace` - list workspaces.
296296
- [x] `GET /experimental/workspace/status` - workspace status.

packages/opencode/specs/effect/schema.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ piecewise.
353353
- [ ] `src/cli/cmd/tui/event.ts`
354354
- [ ] `src/cli/ui.ts`
355355
- [ ] `src/command/index.ts`
356-
- [x] `src/control-plane/adaptors/worktree.ts`
356+
- [x] `src/control-plane/adapters/worktree.ts`
357357
- [x] `src/control-plane/types.ts`
358358
- [x] `src/control-plane/workspace.ts`
359359
- [ ] `src/file/index.ts`

packages/opencode/src/cli/cmd/tui/component/dialog-workspace-create.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { errorMessage } from "@/util/error"
1010
import { useSDK } from "../context/sdk"
1111
import { useToast } from "../ui/toast"
1212

13-
type Adaptor = {
13+
type Adapter = {
1414
type: string
1515
name: string
1616
description: string
@@ -108,26 +108,26 @@ export function DialogWorkspaceCreate(props: { onSelect: (workspaceID: string) =
108108
const sdk = useSDK()
109109
const toast = useToast()
110110
const [creating, setCreating] = createSignal<string>()
111-
const [adaptors, setAdaptors] = createSignal<Adaptor[]>()
111+
const [adapters, setAdapters] = createSignal<Adapter[]>()
112112

113113
onMount(() => {
114114
dialog.setSize("medium")
115115
void (async () => {
116116
const dir = sync.path.directory || sdk.directory
117-
const url = new URL("/experimental/workspace/adaptor", sdk.url)
117+
const url = new URL("/experimental/workspace/adapter", sdk.url)
118118
if (dir) url.searchParams.set("directory", dir)
119119
const res = await sdk
120120
.fetch(url)
121-
.then((x) => x.json() as Promise<Adaptor[]>)
121+
.then((x) => x.json() as Promise<Adapter[]>)
122122
.catch(() => undefined)
123123
if (!res) {
124124
toast.show({
125-
message: "Failed to load workspace adaptors",
125+
message: "Failed to load workspace adapters",
126126
variant: "error",
127127
})
128128
return
129129
}
130-
setAdaptors(res)
130+
setAdapters(res)
131131
})()
132132
})
133133

@@ -142,13 +142,13 @@ export function DialogWorkspaceCreate(props: { onSelect: (workspaceID: string) =
142142
},
143143
]
144144
}
145-
const list = adaptors()
145+
const list = adapters()
146146
if (!list) {
147147
return [
148148
{
149149
title: "Loading workspaces...",
150150
value: "loading" as const,
151-
description: "Fetching available workspace adaptors",
151+
description: "Fetching available workspace adapters",
152152
},
153153
]
154154
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import type { ProjectID } from "@/project/schema"
2+
import type { WorkspaceAdapter, WorkspaceAdapterEntry } from "../types"
3+
import { WorktreeAdapter } from "./worktree"
4+
5+
const BUILTIN: Record<string, WorkspaceAdapter> = {
6+
worktree: WorktreeAdapter,
7+
}
8+
9+
const state = new Map<ProjectID, Map<string, WorkspaceAdapter>>()
10+
11+
export function getAdapter(projectID: ProjectID, type: string): WorkspaceAdapter {
12+
const custom = state.get(projectID)?.get(type)
13+
if (custom) return custom
14+
15+
const builtin = BUILTIN[type]
16+
if (builtin) return builtin
17+
18+
throw new Error(`Unknown workspace adapter: ${type}`)
19+
}
20+
21+
export async function listAdapters(projectID: ProjectID): Promise<WorkspaceAdapterEntry[]> {
22+
const builtin = await Promise.all(
23+
Object.entries(BUILTIN).map(async ([type, adapter]) => {
24+
return {
25+
type,
26+
name: adapter.name,
27+
description: adapter.description,
28+
}
29+
}),
30+
)
31+
const custom = [...(state.get(projectID)?.entries() ?? [])].map(([type, adapter]) => ({
32+
type,
33+
name: adapter.name,
34+
description: adapter.description,
35+
}))
36+
return [...builtin, ...custom]
37+
}
38+
39+
// Plugins can be loaded per-project so we need to scope them. If you
40+
// want to install a global one pass `ProjectID.global`
41+
export function registerAdapter(projectID: ProjectID, type: string, adapter: WorkspaceAdapter) {
42+
const adapters = state.get(projectID) ?? new Map<string, WorkspaceAdapter>()
43+
adapters.set(type, adapter)
44+
state.set(projectID, adapters)
45+
}

packages/opencode/src/control-plane/adaptors/worktree.ts renamed to packages/opencode/src/control-plane/adapters/worktree.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Schema } from "effect"
2-
import { type WorkspaceAdaptor, WorkspaceInfo } from "../types"
2+
import { type WorkspaceAdapter, WorkspaceInfo } from "../types"
33

44
const WorktreeConfig = Schema.Struct({
55
name: WorkspaceInfo.fields.name,
@@ -13,7 +13,7 @@ async function loadWorktree() {
1313
return { AppRuntime, Worktree }
1414
}
1515

16-
export const WorktreeAdaptor: WorkspaceAdaptor = {
16+
export const WorktreeAdapter: WorkspaceAdapter = {
1717
name: "Worktree",
1818
description: "Create a git worktree",
1919
async configure(info) {

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

Lines changed: 0 additions & 45 deletions
This file was deleted.

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ export const WorkspaceInfo = Schema.Struct({
1717
.pipe(withStatics((s) => ({ zod: zod(s) })))
1818
export type WorkspaceInfo = DeepMutable<Schema.Schema.Type<typeof WorkspaceInfo>>
1919

20-
export const WorkspaceAdaptorEntry = Schema.Struct({
20+
export const WorkspaceAdapterEntry = Schema.Struct({
2121
type: Schema.String,
2222
name: Schema.String,
2323
description: Schema.String,
2424
}).pipe(withStatics((s) => ({ zod: zod(s) })))
25-
export type WorkspaceAdaptorEntry = Schema.Schema.Type<typeof WorkspaceAdaptorEntry>
25+
export type WorkspaceAdapterEntry = Schema.Schema.Type<typeof WorkspaceAdapterEntry>
2626

2727
export type Target =
2828
| {
@@ -35,7 +35,7 @@ export type Target =
3535
headers?: HeadersInit
3636
}
3737

38-
export type WorkspaceAdaptor = {
38+
export type WorkspaceAdapter = {
3939
name: string
4040
description: string
4141
configure(info: WorkspaceInfo): WorkspaceInfo | Promise<WorkspaceInfo>

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

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { Filesystem } from "@/util/filesystem"
1616
import { ProjectID } from "@/project/schema"
1717
import { Slug } from "@opencode-ai/core/util/slug"
1818
import { WorkspaceTable } from "./workspace.sql"
19-
import { getAdaptor } from "./adaptors"
19+
import { getAdapter } from "./adapters"
2020
import { type WorkspaceInfo, WorkspaceInfo as WorkspaceInfoSchema } from "./types"
2121
import { WorkspaceID } from "./schema"
2222
import { Session } from "@/session/session"
@@ -335,8 +335,8 @@ export const layer = Layer.effect(
335335
})
336336

337337
const syncWorkspaceLoop = Effect.fn("Workspace.syncWorkspaceLoop")(function* (space: Info) {
338-
const adaptor = getAdaptor(space.projectID, space.type)
339-
const target = yield* Effect.promise(() => Promise.resolve(adaptor.target(space)))
338+
const adapter = getAdapter(space.projectID, space.type)
339+
const target = yield* Effect.promise(() => Promise.resolve(adapter.target(space)))
340340

341341
if (target.type === "local") return
342342

@@ -419,8 +419,8 @@ export const layer = Layer.effect(
419419
const startSync = Effect.fn("Workspace.startSync")(function* (space: Info) {
420420
if (!Flag.OPENCODE_EXPERIMENTAL_WORKSPACES) return
421421

422-
const adaptor = getAdaptor(space.projectID, space.type)
423-
const target = yield* Effect.promise(() => Promise.resolve(adaptor.target(space)))
422+
const adapter = getAdapter(space.projectID, space.type)
423+
const target = yield* Effect.promise(() => Promise.resolve(adapter.target(space)))
424424

425425
if (target.type === "local") {
426426
setStatus(space.id, (yield* Effect.promise(() => Filesystem.exists(target.directory))) ? "connected" : "error")
@@ -458,9 +458,9 @@ export const layer = Layer.effect(
458458

459459
const create = Effect.fn("Workspace.create")(function* (input: CreateInput) {
460460
const id = WorkspaceID.ascending(input.id)
461-
const adaptor = getAdaptor(input.projectID, input.type)
461+
const adapter = getAdapter(input.projectID, input.type)
462462
const config = yield* Effect.promise(() =>
463-
Promise.resolve(adaptor.configure({ ...input, id, name: Slug.create(), directory: null })),
463+
Promise.resolve(adapter.configure({ ...input, id, name: Slug.create(), directory: null })),
464464
)
465465

466466
const info: Info = {
@@ -496,7 +496,7 @@ export const layer = Layer.effect(
496496
OTEL_RESOURCE_ATTRIBUTES: process.env.OTEL_RESOURCE_ATTRIBUTES,
497497
}
498498

499-
yield* Effect.promise(() => adaptor.create(config, env))
499+
yield* Effect.promise(() => adapter.create(config, env))
500500
yield* Effect.all(
501501
[
502502
waitEvent({
@@ -531,8 +531,8 @@ export const layer = Layer.effect(
531531
workspaceID: input.workspaceID,
532532
})
533533

534-
const adaptor = getAdaptor(space.projectID, space.type)
535-
const target = yield* Effect.promise(() => Promise.resolve(adaptor.target(space)))
534+
const adapter = getAdapter(space.projectID, space.type)
535+
const target = yield* Effect.promise(() => Promise.resolve(adapter.target(space)))
536536

537537
yield* sync.run(Session.Event.Updated, {
538538
sessionID: input.sessionID,
@@ -726,12 +726,12 @@ export const layer = Layer.effect(
726726
const info = fromRow(row)
727727
yield* Effect.catch(
728728
Effect.gen(function* () {
729-
const adaptor = getAdaptor(info.projectID, row.type)
730-
yield* Effect.tryPromise(() => Promise.resolve(adaptor.remove(info)))
729+
const adapter = getAdapter(info.projectID, row.type)
730+
yield* Effect.tryPromise(() => Promise.resolve(adapter.remove(info)))
731731
}),
732732
() =>
733733
Effect.sync(() => {
734-
log.error("adaptor not available when removing workspace", { type: row.type })
734+
log.error("adapter not available when removing workspace", { type: row.type })
735735
}),
736736
)
737737

packages/opencode/src/plugin/index.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type {
33
PluginInput,
44
Plugin as PluginInstance,
55
PluginModule,
6-
WorkspaceAdaptor as PluginWorkspaceAdaptor,
6+
WorkspaceAdapter as PluginWorkspaceAdapter,
77
} from "@opencode-ai/plugin"
88
import { Config } from "@/config/config"
99
import { Bus } from "../bus"
@@ -24,8 +24,8 @@ import { InstanceState } from "@/effect/instance-state"
2424
import { errorMessage } from "@/util/error"
2525
import { PluginLoader } from "./loader"
2626
import { parsePluginSpecifier, readPluginId, readV1Plugin, resolvePluginId } from "./shared"
27-
import { registerAdaptor } from "@/control-plane/adaptors"
28-
import type { WorkspaceAdaptor } from "@/control-plane/types"
27+
import { registerAdapter } from "@/control-plane/adapters"
28+
import type { WorkspaceAdapter } from "@/control-plane/types"
2929

3030
const log = Log.create({ service: "plugin" })
3131

@@ -138,8 +138,8 @@ export const layer = Layer.effect(
138138
worktree: ctx.worktree,
139139
directory: ctx.directory,
140140
experimental_workspace: {
141-
register(type: string, adaptor: PluginWorkspaceAdaptor) {
142-
registerAdaptor(ctx.project.id, type, adaptor as WorkspaceAdaptor)
141+
register(type: string, adapter: PluginWorkspaceAdapter) {
142+
registerAdapter(ctx.project.id, type, adapter as WorkspaceAdapter)
143143
},
144144
},
145145
get serverUrl(): URL {

packages/opencode/src/server/routes/control/workspace.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import { Hono } from "hono"
22
import { describeRoute, resolver, validator } from "hono-openapi"
33
import z from "zod"
44
import { Effect } from "effect"
5-
import { listAdaptors } from "@/control-plane/adaptors"
5+
import { listAdapters } from "@/control-plane/adapters"
66
import { Workspace } from "@/control-plane/workspace"
77
import { AppRuntime } from "@/effect/app-runtime"
8-
import { WorkspaceAdaptorEntry } from "@/control-plane/types"
8+
import { WorkspaceAdapterEntry } from "@/control-plane/types"
99
import { zodObject } from "@/util/effect-zod"
1010
import { Instance } from "@/project/instance"
1111
import { errors } from "../../error"
@@ -18,24 +18,24 @@ const log = Log.create({ service: "server.workspace" })
1818
export const WorkspaceRoutes = lazy(() =>
1919
new Hono()
2020
.get(
21-
"/adaptor",
21+
"/adapter",
2222
describeRoute({
23-
summary: "List workspace adaptors",
24-
description: "List all available workspace adaptors for the current project.",
25-
operationId: "experimental.workspace.adaptor.list",
23+
summary: "List workspace adapters",
24+
description: "List all available workspace adapters for the current project.",
25+
operationId: "experimental.workspace.adapter.list",
2626
responses: {
2727
200: {
28-
description: "Workspace adaptors",
28+
description: "Workspace adapters",
2929
content: {
3030
"application/json": {
31-
schema: resolver(z.array(zodObject(WorkspaceAdaptorEntry))),
31+
schema: resolver(z.array(zodObject(WorkspaceAdapterEntry))),
3232
},
3333
},
3434
},
3535
},
3636
}),
3737
async (c) => {
38-
return c.json(await listAdaptors(Instance.project.id))
38+
return c.json(await listAdapters(Instance.project.id))
3939
},
4040
)
4141
.post(

0 commit comments

Comments
 (0)