Просмотр исходного кода

refactor: rename workspace adapters

Kit Langton 3 месяцев назад
Родитель
Сommit
76e2ff4522

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

@@ -187,7 +187,7 @@ Use raw Effect HTTP routes where `HttpApi` does not fit. The goal is deleting Ho
 | `project`                 | `bridged`         | list, current, git init, update                                            |
 | `project`                 | `bridged`         | list, current, git init, update                                            |
 | `file`                    | `bridged` partial | find text/file/symbol, list/content/status                                 |
 | `file`                    | `bridged` partial | find text/file/symbol, list/content/status                                 |
 | `mcp`                     | `bridged`         | status, add, OAuth, connect/disconnect                                     |
 | `mcp`                     | `bridged`         | status, add, OAuth, connect/disconnect                                     |
-| `workspace`               | `bridged`         | adaptor/list/status/create/remove/session-restore                          |
+| `workspace`               | `bridged`         | adapter/list/status/create/remove/session-restore                          |
 | top-level instance routes | `bridged`         | path, vcs, command, agent, skill, lsp, formatter, dispose                  |
 | top-level instance routes | `bridged`         | path, vcs, command, agent, skill, lsp, formatter, dispose                  |
 | experimental JSON routes  | `bridged`         | console, tool, worktree list/mutations, global session list, resource list |
 | experimental JSON routes  | `bridged`         | console, tool, worktree list/mutations, global session list, resource list |
 | `session`                 | `bridged`         | read, lifecycle, prompt, message/part mutations, revert, permission reply  |
 | `session`                 | `bridged`         | read, lifecycle, prompt, message/part mutations, revert, permission reply  |
@@ -279,7 +279,7 @@ This checklist tracks bridge parity only. Checked routes are available through t
 
 
 ### Workspace Routes
 ### Workspace Routes
 
 
-- [x] `GET /experimental/workspace/adaptor` - list workspace adaptors.
+- [x] `GET /experimental/workspace/adapter` - list workspace adapters.
 - [x] `POST /experimental/workspace` - create workspace.
 - [x] `POST /experimental/workspace` - create workspace.
 - [x] `GET /experimental/workspace` - list workspaces.
 - [x] `GET /experimental/workspace` - list workspaces.
 - [x] `GET /experimental/workspace/status` - workspace status.
 - [x] `GET /experimental/workspace/status` - workspace status.

+ 1 - 1
packages/opencode/specs/effect/schema.md

@@ -353,7 +353,7 @@ piecewise.
 - [ ] `src/cli/cmd/tui/event.ts`
 - [ ] `src/cli/cmd/tui/event.ts`
 - [ ] `src/cli/ui.ts`
 - [ ] `src/cli/ui.ts`
 - [ ] `src/command/index.ts`
 - [ ] `src/command/index.ts`
-- [x] `src/control-plane/adaptors/worktree.ts`
+- [x] `src/control-plane/adapters/worktree.ts`
 - [x] `src/control-plane/types.ts`
 - [x] `src/control-plane/types.ts`
 - [x] `src/control-plane/workspace.ts`
 - [x] `src/control-plane/workspace.ts`
 - [ ] `src/file/index.ts`
 - [ ] `src/file/index.ts`

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

@@ -10,7 +10,7 @@ import { errorMessage } from "@/util/error"
 import { useSDK } from "../context/sdk"
 import { useSDK } from "../context/sdk"
 import { useToast } from "../ui/toast"
 import { useToast } from "../ui/toast"
 
 
-type Adaptor = {
+type Adapter = {
   type: string
   type: string
   name: string
   name: string
   description: string
   description: string
@@ -108,26 +108,26 @@ export function DialogWorkspaceCreate(props: { onSelect: (workspaceID: string) =
   const sdk = useSDK()
   const sdk = useSDK()
   const toast = useToast()
   const toast = useToast()
   const [creating, setCreating] = createSignal<string>()
   const [creating, setCreating] = createSignal<string>()
-  const [adaptors, setAdaptors] = createSignal<Adaptor[]>()
+  const [adapters, setAdapters] = createSignal<Adapter[]>()
 
 
   onMount(() => {
   onMount(() => {
     dialog.setSize("medium")
     dialog.setSize("medium")
     void (async () => {
     void (async () => {
       const dir = sync.path.directory || sdk.directory
       const dir = sync.path.directory || sdk.directory
-      const url = new URL("/experimental/workspace/adaptor", sdk.url)
+      const url = new URL("/experimental/workspace/adapter", sdk.url)
       if (dir) url.searchParams.set("directory", dir)
       if (dir) url.searchParams.set("directory", dir)
       const res = await sdk
       const res = await sdk
         .fetch(url)
         .fetch(url)
-        .then((x) => x.json() as Promise<Adaptor[]>)
+        .then((x) => x.json() as Promise<Adapter[]>)
         .catch(() => undefined)
         .catch(() => undefined)
       if (!res) {
       if (!res) {
         toast.show({
         toast.show({
-          message: "Failed to load workspace adaptors",
+          message: "Failed to load workspace adapters",
           variant: "error",
           variant: "error",
         })
         })
         return
         return
       }
       }
-      setAdaptors(res)
+      setAdapters(res)
     })()
     })()
   })
   })
 
 
@@ -142,13 +142,13 @@ export function DialogWorkspaceCreate(props: { onSelect: (workspaceID: string) =
         },
         },
       ]
       ]
     }
     }
-    const list = adaptors()
+    const list = adapters()
     if (!list) {
     if (!list) {
       return [
       return [
         {
         {
           title: "Loading workspaces...",
           title: "Loading workspaces...",
           value: "loading" as const,
           value: "loading" as const,
-          description: "Fetching available workspace adaptors",
+          description: "Fetching available workspace adapters",
         },
         },
       ]
       ]
     }
     }

+ 46 - 0
packages/opencode/src/control-plane/adapters/index.ts

@@ -0,0 +1,46 @@
+import { lazy } from "@/util/lazy"
+import type { ProjectID } from "@/project/schema"
+import type { WorkspaceAdapter, WorkspaceAdapterEntry } from "../types"
+
+const BUILTIN: Record<string, () => Promise<WorkspaceAdapter>> = {
+  worktree: lazy(async () => (await import("./worktree")).WorktreeAdapter),
+}
+
+const state = new Map<ProjectID, Map<string, WorkspaceAdapter>>()
+
+export async function getAdapter(projectID: ProjectID, type: string): Promise<WorkspaceAdapter> {
+  const custom = state.get(projectID)?.get(type)
+  if (custom) return custom
+
+  const builtin = BUILTIN[type]
+  if (builtin) return builtin()
+
+  throw new Error(`Unknown workspace adapter: ${type}`)
+}
+
+export async function listAdapters(projectID: ProjectID): Promise<WorkspaceAdapterEntry[]> {
+  const builtin = await Promise.all(
+    Object.entries(BUILTIN).map(async ([type, init]) => {
+      const adapter = await init()
+      return {
+        type,
+        name: adapter.name,
+        description: adapter.description,
+      }
+    }),
+  )
+  const custom = [...(state.get(projectID)?.entries() ?? [])].map(([type, adapter]) => ({
+    type,
+    name: adapter.name,
+    description: adapter.description,
+  }))
+  return [...builtin, ...custom]
+}
+
+// Plugins can be loaded per-project so we need to scope them. If you
+// want to install a global one pass `ProjectID.global`
+export function registerAdapter(projectID: ProjectID, type: string, adapter: WorkspaceAdapter) {
+  const adapters = state.get(projectID) ?? new Map<string, WorkspaceAdapter>()
+  adapters.set(type, adapter)
+  state.set(projectID, adapters)
+}

+ 2 - 2
packages/opencode/src/control-plane/adaptors/worktree.ts → packages/opencode/src/control-plane/adapters/worktree.ts

@@ -1,7 +1,7 @@
 import { Schema } from "effect"
 import { Schema } from "effect"
 import { AppRuntime } from "@/effect/app-runtime"
 import { AppRuntime } from "@/effect/app-runtime"
 import { Worktree } from "@/worktree"
 import { Worktree } from "@/worktree"
-import { type WorkspaceAdaptor, WorkspaceInfo } from "../types"
+import { type WorkspaceAdapter, WorkspaceInfo } from "../types"
 
 
 const WorktreeConfig = Schema.Struct({
 const WorktreeConfig = Schema.Struct({
   name: WorkspaceInfo.fields.name,
   name: WorkspaceInfo.fields.name,
@@ -10,7 +10,7 @@ const WorktreeConfig = Schema.Struct({
 })
 })
 const decodeWorktreeConfig = Schema.decodeUnknownSync(WorktreeConfig)
 const decodeWorktreeConfig = Schema.decodeUnknownSync(WorktreeConfig)
 
 
-export const WorktreeAdaptor: WorkspaceAdaptor = {
+export const WorktreeAdapter: WorkspaceAdapter = {
   name: "Worktree",
   name: "Worktree",
   description: "Create a git worktree",
   description: "Create a git worktree",
   async configure(info) {
   async configure(info) {

+ 0 - 46
packages/opencode/src/control-plane/adaptors/index.ts

@@ -1,46 +0,0 @@
-import { lazy } from "@/util/lazy"
-import type { ProjectID } from "@/project/schema"
-import type { WorkspaceAdaptor, WorkspaceAdaptorEntry } from "../types"
-
-const BUILTIN: Record<string, () => Promise<WorkspaceAdaptor>> = {
-  worktree: lazy(async () => (await import("./worktree")).WorktreeAdaptor),
-}
-
-const state = new Map<ProjectID, Map<string, WorkspaceAdaptor>>()
-
-export async function getAdaptor(projectID: ProjectID, type: string): Promise<WorkspaceAdaptor> {
-  const custom = state.get(projectID)?.get(type)
-  if (custom) return custom
-
-  const builtin = BUILTIN[type]
-  if (builtin) return builtin()
-
-  throw new Error(`Unknown workspace adaptor: ${type}`)
-}
-
-export async function listAdaptors(projectID: ProjectID): Promise<WorkspaceAdaptorEntry[]> {
-  const builtin = await Promise.all(
-    Object.entries(BUILTIN).map(async ([type, init]) => {
-      const adaptor = await init()
-      return {
-        type,
-        name: adaptor.name,
-        description: adaptor.description,
-      }
-    }),
-  )
-  const custom = [...(state.get(projectID)?.entries() ?? [])].map(([type, adaptor]) => ({
-    type,
-    name: adaptor.name,
-    description: adaptor.description,
-  }))
-  return [...builtin, ...custom]
-}
-
-// Plugins can be loaded per-project so we need to scope them. If you
-// want to install a global one pass `ProjectID.global`
-export function registerAdaptor(projectID: ProjectID, type: string, adaptor: WorkspaceAdaptor) {
-  const adaptors = state.get(projectID) ?? new Map<string, WorkspaceAdaptor>()
-  adaptors.set(type, adaptor)
-  state.set(projectID, adaptors)
-}

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

@@ -17,12 +17,12 @@ export const WorkspaceInfo = Schema.Struct({
   .pipe(withStatics((s) => ({ zod: zod(s) })))
   .pipe(withStatics((s) => ({ zod: zod(s) })))
 export type WorkspaceInfo = DeepMutable<Schema.Schema.Type<typeof WorkspaceInfo>>
 export type WorkspaceInfo = DeepMutable<Schema.Schema.Type<typeof WorkspaceInfo>>
 
 
-export const WorkspaceAdaptorEntry = Schema.Struct({
+export const WorkspaceAdapterEntry = Schema.Struct({
   type: Schema.String,
   type: Schema.String,
   name: Schema.String,
   name: Schema.String,
   description: Schema.String,
   description: Schema.String,
 }).pipe(withStatics((s) => ({ zod: zod(s) })))
 }).pipe(withStatics((s) => ({ zod: zod(s) })))
-export type WorkspaceAdaptorEntry = Schema.Schema.Type<typeof WorkspaceAdaptorEntry>
+export type WorkspaceAdapterEntry = Schema.Schema.Type<typeof WorkspaceAdapterEntry>
 
 
 export type Target =
 export type Target =
   | {
   | {
@@ -35,7 +35,7 @@ export type Target =
       headers?: HeadersInit
       headers?: HeadersInit
     }
     }
 
 
-export type WorkspaceAdaptor = {
+export type WorkspaceAdapter = {
   name: string
   name: string
   description: string
   description: string
   configure(info: WorkspaceInfo): WorkspaceInfo | Promise<WorkspaceInfo>
   configure(info: WorkspaceInfo): WorkspaceInfo | Promise<WorkspaceInfo>

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

@@ -17,7 +17,7 @@ import { Filesystem } from "@/util/filesystem"
 import { ProjectID } from "@/project/schema"
 import { ProjectID } from "@/project/schema"
 import { Slug } from "@opencode-ai/core/util/slug"
 import { Slug } from "@opencode-ai/core/util/slug"
 import { WorkspaceTable } from "./workspace.sql"
 import { WorkspaceTable } from "./workspace.sql"
-import { getAdaptor } from "./adaptors"
+import { getAdapter } from "./adapters"
 import { type WorkspaceInfo, WorkspaceInfo as WorkspaceInfoSchema } from "./types"
 import { type WorkspaceInfo, WorkspaceInfo as WorkspaceInfoSchema } from "./types"
 import { WorkspaceID } from "./schema"
 import { WorkspaceID } from "./schema"
 import { parseSSE } from "./sse"
 import { parseSSE } from "./sse"
@@ -87,9 +87,9 @@ export type CreateInput = Schema.Schema.Type<typeof CreateInput>
 
 
 export const create = fn(CreateInput.zod, async (input) => {
 export const create = fn(CreateInput.zod, async (input) => {
   const id = WorkspaceID.ascending(input.id)
   const id = WorkspaceID.ascending(input.id)
-  const adaptor = await getAdaptor(input.projectID, input.type)
+  const adapter = await getAdapter(input.projectID, input.type)
 
 
-  const config = await adaptor.configure({ ...input, id, name: Slug.create(), directory: null })
+  const config = await adapter.configure({ ...input, id, name: Slug.create(), directory: null })
 
 
   const info: Info = {
   const info: Info = {
     id,
     id,
@@ -123,7 +123,7 @@ export const create = fn(CreateInput.zod, async (input) => {
     OTEL_EXPORTER_OTLP_ENDPOINT: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
     OTEL_EXPORTER_OTLP_ENDPOINT: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
     OTEL_RESOURCE_ATTRIBUTES: process.env.OTEL_RESOURCE_ATTRIBUTES,
     OTEL_RESOURCE_ATTRIBUTES: process.env.OTEL_RESOURCE_ATTRIBUTES,
   }
   }
-  await adaptor.create(config, env)
+  await adapter.create(config, env)
 
 
   startSync(info)
   startSync(info)
 
 
@@ -156,8 +156,8 @@ export const sessionRestore = fn(SessionRestoreInput.zod, async (input) => {
     const space = await get(input.workspaceID)
     const space = await get(input.workspaceID)
     if (!space) throw new Error(`Workspace not found: ${input.workspaceID}`)
     if (!space) throw new Error(`Workspace not found: ${input.workspaceID}`)
 
 
-    const adaptor = await getAdaptor(space.projectID, space.type)
-    const target = await adaptor.target(space)
+    const adapter = await getAdapter(space.projectID, space.type)
+    const target = await adapter.target(space)
 
 
     // Need to switch the workspace of the session
     // Need to switch the workspace of the session
     SyncEvent.run(Session.Event.Updated, {
     SyncEvent.run(Session.Event.Updated, {
@@ -329,10 +329,10 @@ export const remove = fn(WorkspaceID.zod, async (id) => {
 
 
     const info = fromRow(row)
     const info = fromRow(row)
     try {
     try {
-      const adaptor = await getAdaptor(info.projectID, row.type)
-      await adaptor.remove(info)
+      const adapter = await getAdapter(info.projectID, row.type)
+      await adapter.remove(info)
     } catch {
     } catch {
-      log.error("adaptor not available when removing workspace", { type: row.type })
+      log.error("adapter not available when removing workspace", { type: row.type })
     }
     }
     Database.use((db) => db.delete(WorkspaceTable).where(eq(WorkspaceTable.id, id)).run())
     Database.use((db) => db.delete(WorkspaceTable).where(eq(WorkspaceTable.id, id)).run())
     return info
     return info
@@ -501,8 +501,8 @@ async function syncHistory(space: Info, url: URL | string, headers: HeadersInit
 }
 }
 
 
 async function syncWorkspaceLoop(space: Info, signal: AbortSignal) {
 async function syncWorkspaceLoop(space: Info, signal: AbortSignal) {
-  const adaptor = await getAdaptor(space.projectID, space.type)
-  const target = await adaptor.target(space)
+  const adapter = await getAdapter(space.projectID, space.type)
+  const target = await adapter.target(space)
 
 
   if (target.type === "local") return null
   if (target.type === "local") return null
 
 
@@ -568,8 +568,8 @@ async function syncWorkspaceLoop(space: Info, signal: AbortSignal) {
 async function startSync(space: Info) {
 async function startSync(space: Info) {
   if (!Flag.OPENCODE_EXPERIMENTAL_WORKSPACES) return
   if (!Flag.OPENCODE_EXPERIMENTAL_WORKSPACES) return
 
 
-  const adaptor = await getAdaptor(space.projectID, space.type)
-  const target = await adaptor.target(space)
+  const adapter = await getAdapter(space.projectID, space.type)
+  const target = await adapter.target(space)
 
 
   if (target.type === "local") {
   if (target.type === "local") {
     void Filesystem.exists(target.directory).then((exists) => {
     void Filesystem.exists(target.directory).then((exists) => {

+ 5 - 5
packages/opencode/src/plugin/index.ts

@@ -3,7 +3,7 @@ import type {
   PluginInput,
   PluginInput,
   Plugin as PluginInstance,
   Plugin as PluginInstance,
   PluginModule,
   PluginModule,
-  WorkspaceAdaptor as PluginWorkspaceAdaptor,
+  WorkspaceAdapter as PluginWorkspaceAdapter,
 } from "@opencode-ai/plugin"
 } from "@opencode-ai/plugin"
 import { Config } from "@/config/config"
 import { Config } from "@/config/config"
 import { Bus } from "../bus"
 import { Bus } from "../bus"
@@ -23,8 +23,8 @@ import { InstanceState } from "@/effect/instance-state"
 import { errorMessage } from "@/util/error"
 import { errorMessage } from "@/util/error"
 import { PluginLoader } from "./loader"
 import { PluginLoader } from "./loader"
 import { parsePluginSpecifier, readPluginId, readV1Plugin, resolvePluginId } from "./shared"
 import { parsePluginSpecifier, readPluginId, readV1Plugin, resolvePluginId } from "./shared"
-import { registerAdaptor } from "@/control-plane/adaptors"
-import type { WorkspaceAdaptor } from "@/control-plane/types"
+import { registerAdapter } from "@/control-plane/adapters"
+import type { WorkspaceAdapter } from "@/control-plane/types"
 
 
 const log = Log.create({ service: "plugin" })
 const log = Log.create({ service: "plugin" })
 
 
@@ -136,8 +136,8 @@ export const layer = Layer.effect(
           worktree: ctx.worktree,
           worktree: ctx.worktree,
           directory: ctx.directory,
           directory: ctx.directory,
           experimental_workspace: {
           experimental_workspace: {
-            register(type: string, adaptor: PluginWorkspaceAdaptor) {
-              registerAdaptor(ctx.project.id, type, adaptor as WorkspaceAdaptor)
+            register(type: string, adapter: PluginWorkspaceAdapter) {
+              registerAdapter(ctx.project.id, type, adapter as WorkspaceAdapter)
             },
             },
           },
           },
           get serverUrl(): URL {
           get serverUrl(): URL {

+ 9 - 9
packages/opencode/src/server/routes/control/workspace.ts

@@ -1,9 +1,9 @@
 import { Hono } from "hono"
 import { Hono } from "hono"
 import { describeRoute, resolver, validator } from "hono-openapi"
 import { describeRoute, resolver, validator } from "hono-openapi"
 import z from "zod"
 import z from "zod"
-import { listAdaptors } from "@/control-plane/adaptors"
+import { listAdapters } from "@/control-plane/adapters"
 import { Workspace } from "@/control-plane/workspace"
 import { Workspace } from "@/control-plane/workspace"
-import { WorkspaceAdaptorEntry } from "@/control-plane/types"
+import { WorkspaceAdapterEntry } from "@/control-plane/types"
 import { zodObject } from "@/util/effect-zod"
 import { zodObject } from "@/util/effect-zod"
 import { Instance } from "@/project/instance"
 import { Instance } from "@/project/instance"
 import { errors } from "../../error"
 import { errors } from "../../error"
@@ -16,24 +16,24 @@ const log = Log.create({ service: "server.workspace" })
 export const WorkspaceRoutes = lazy(() =>
 export const WorkspaceRoutes = lazy(() =>
   new Hono()
   new Hono()
     .get(
     .get(
-      "/adaptor",
+      "/adapter",
       describeRoute({
       describeRoute({
-        summary: "List workspace adaptors",
-        description: "List all available workspace adaptors for the current project.",
-        operationId: "experimental.workspace.adaptor.list",
+        summary: "List workspace adapters",
+        description: "List all available workspace adapters for the current project.",
+        operationId: "experimental.workspace.adapter.list",
         responses: {
         responses: {
           200: {
           200: {
-            description: "Workspace adaptors",
+            description: "Workspace adapters",
             content: {
             content: {
               "application/json": {
               "application/json": {
-                schema: resolver(z.array(zodObject(WorkspaceAdaptorEntry))),
+                schema: resolver(z.array(zodObject(WorkspaceAdapterEntry))),
               },
               },
             },
             },
           },
           },
         },
         },
       }),
       }),
       async (c) => {
       async (c) => {
-        return c.json(await listAdaptors(Instance.project.id))
+        return c.json(await listAdapters(Instance.project.id))
       },
       },
     )
     )
     .post(
     .post(

+ 7 - 7
packages/opencode/src/server/routes/instance/httpapi/groups/workspace.ts

@@ -1,5 +1,5 @@
 import { Workspace } from "@/control-plane/workspace"
 import { Workspace } from "@/control-plane/workspace"
-import { WorkspaceAdaptorEntry } from "@/control-plane/types"
+import { WorkspaceAdapterEntry } from "@/control-plane/types"
 import { NonNegativeInt } from "@/util/schema"
 import { NonNegativeInt } from "@/util/schema"
 import { Schema, Struct } from "effect"
 import { Schema, Struct } from "effect"
 import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
 import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
@@ -16,7 +16,7 @@ export const SessionRestoreResponse = Schema.Struct({
 })
 })
 
 
 export const WorkspacePaths = {
 export const WorkspacePaths = {
-  adaptors: `${root}/adaptor`,
+  adapters: `${root}/adapter`,
   list: root,
   list: root,
   status: `${root}/status`,
   status: `${root}/status`,
   remove: `${root}/:id`,
   remove: `${root}/:id`,
@@ -27,13 +27,13 @@ export const WorkspaceApi = HttpApi.make("workspace")
   .add(
   .add(
     HttpApiGroup.make("workspace")
     HttpApiGroup.make("workspace")
       .add(
       .add(
-        HttpApiEndpoint.get("adaptors", WorkspacePaths.adaptors, {
-          success: described(Schema.Array(WorkspaceAdaptorEntry), "Workspace adaptors"),
+        HttpApiEndpoint.get("adapters", WorkspacePaths.adapters, {
+          success: described(Schema.Array(WorkspaceAdapterEntry), "Workspace adapters"),
         }).annotateMerge(
         }).annotateMerge(
           OpenApi.annotations({
           OpenApi.annotations({
-            identifier: "experimental.workspace.adaptor.list",
-            summary: "List workspace adaptors",
-            description: "List all available workspace adaptors for the current project.",
+            identifier: "experimental.workspace.adapter.list",
+            summary: "List workspace adapters",
+            description: "List all available workspace adapters for the current project.",
           }),
           }),
         ),
         ),
         HttpApiEndpoint.get("list", WorkspacePaths.list, {
         HttpApiEndpoint.get("list", WorkspacePaths.list, {

+ 4 - 4
packages/opencode/src/server/routes/instance/httpapi/handlers/workspace.ts

@@ -1,4 +1,4 @@
-import { listAdaptors } from "@/control-plane/adaptors"
+import { listAdapters } from "@/control-plane/adapters"
 import { Workspace } from "@/control-plane/workspace"
 import { Workspace } from "@/control-plane/workspace"
 import * as InstanceState from "@/effect/instance-state"
 import * as InstanceState from "@/effect/instance-state"
 import { Instance } from "@/project/instance"
 import { Instance } from "@/project/instance"
@@ -9,9 +9,9 @@ import { CreatePayload, SessionRestorePayload } from "../groups/workspace"
 
 
 export const workspaceHandlers = HttpApiBuilder.group(InstanceHttpApi, "workspace", (handlers) =>
 export const workspaceHandlers = HttpApiBuilder.group(InstanceHttpApi, "workspace", (handlers) =>
   Effect.gen(function* () {
   Effect.gen(function* () {
-    const adaptors = Effect.fn("WorkspaceHttpApi.adaptors")(function* () {
+    const adapters = Effect.fn("WorkspaceHttpApi.adapters")(function* () {
       const instance = yield* InstanceState.context
       const instance = yield* InstanceState.context
-      return yield* Effect.promise(() => listAdaptors(instance.project.id))
+      return yield* Effect.promise(() => listAdapters(instance.project.id))
     })
     })
 
 
     const list = Effect.fn("WorkspaceHttpApi.list")(function* () {
     const list = Effect.fn("WorkspaceHttpApi.list")(function* () {
@@ -56,7 +56,7 @@ export const workspaceHandlers = HttpApiBuilder.group(InstanceHttpApi, "workspac
     })
     })
 
 
     return handlers
     return handlers
-      .handle("adaptors", adaptors)
+      .handle("adapters", adapters)
       .handle("list", list)
       .handle("list", list)
       .handle("create", create)
       .handle("create", create)
       .handle("status", status)
       .handle("status", status)

+ 3 - 3
packages/opencode/src/server/routes/instance/httpapi/middleware/workspace-routing.ts

@@ -1,4 +1,4 @@
-import { getAdaptor } from "@/control-plane/adaptors"
+import { getAdapter } from "@/control-plane/adapters"
 import { WorkspaceID } from "@/control-plane/schema"
 import { WorkspaceID } from "@/control-plane/schema"
 import type { Target } from "@/control-plane/types"
 import type { Target } from "@/control-plane/types"
 import { Workspace } from "@/control-plane/workspace"
 import { Workspace } from "@/control-plane/workspace"
@@ -89,8 +89,8 @@ function missingWorkspaceResponse(id: WorkspaceID): HttpServerResponse.HttpServe
 
 
 function resolveTarget(workspace: Workspace.Info): Effect.Effect<Target> {
 function resolveTarget(workspace: Workspace.Info): Effect.Effect<Target> {
   return Effect.gen(function* () {
   return Effect.gen(function* () {
-    const adaptor = yield* Effect.promise(() => getAdaptor(workspace.projectID, workspace.type))
-    return yield* Effect.promise(() => Promise.resolve(adaptor.target(workspace)))
+    const adapter = yield* Effect.promise(() => getAdapter(workspace.projectID, workspace.type))
+    return yield* Effect.promise(() => Promise.resolve(adapter.target(workspace)))
   })
   })
 }
 }
 
 

+ 3 - 3
packages/opencode/src/server/workspace.ts

@@ -1,6 +1,6 @@
 import type { MiddlewareHandler } from "hono"
 import type { MiddlewareHandler } from "hono"
 import type { UpgradeWebSocket } from "hono/ws"
 import type { UpgradeWebSocket } from "hono/ws"
-import { getAdaptor } from "@/control-plane/adaptors"
+import { getAdapter } from "@/control-plane/adapters"
 import { WorkspaceID } from "@/control-plane/schema"
 import { WorkspaceID } from "@/control-plane/schema"
 import { WorkspaceContext } from "@/control-plane/workspace-context"
 import { WorkspaceContext } from "@/control-plane/workspace-context"
 import { Workspace } from "@/control-plane/workspace"
 import { Workspace } from "@/control-plane/workspace"
@@ -88,8 +88,8 @@ export function WorkspaceRouterMiddleware(upgrade: UpgradeWebSocket): Middleware
       return next()
       return next()
     }
     }
 
 
-    const adaptor = await getAdaptor(workspace.projectID, workspace.type)
-    const target = await adaptor.target(workspace)
+    const adapter = await getAdapter(workspace.projectID, workspace.type)
+    const target = await adapter.target(workspace)
 
 
     if (target.type === "local") {
     if (target.type === "local") {
       return WorkspaceContext.provide({
       return WorkspaceContext.provide({

+ 12 - 12
packages/opencode/test/control-plane/adaptors.test.ts → packages/opencode/test/control-plane/adapters.test.ts

@@ -1,5 +1,5 @@
 import { describe, expect, test } from "bun:test"
 import { describe, expect, test } from "bun:test"
-import { getAdaptor, registerAdaptor } from "../../src/control-plane/adaptors"
+import { getAdapter, registerAdapter } from "../../src/control-plane/adapters"
 import { ProjectID } from "../../src/project/schema"
 import { ProjectID } from "../../src/project/schema"
 import type { WorkspaceInfo } from "../../src/control-plane/types"
 import type { WorkspaceInfo } from "../../src/control-plane/types"
 
 
@@ -15,7 +15,7 @@ function info(projectID: WorkspaceInfo["projectID"], type: string): WorkspaceInf
   }
   }
 }
 }
 
 
-function adaptor(dir: string) {
+function adapter(dir: string) {
   return {
   return {
     name: dir,
     name: dir,
     description: dir,
     description: dir,
@@ -33,19 +33,19 @@ function adaptor(dir: string) {
   }
   }
 }
 }
 
 
-describe("control-plane/adaptors", () => {
-  test("isolates custom adaptors by project", async () => {
+describe("control-plane/adapters", () => {
+  test("isolates custom adapters by project", async () => {
     const type = `demo-${Math.random().toString(36).slice(2)}`
     const type = `demo-${Math.random().toString(36).slice(2)}`
     const one = ProjectID.make(`project-${Math.random().toString(36).slice(2)}`)
     const one = ProjectID.make(`project-${Math.random().toString(36).slice(2)}`)
     const two = ProjectID.make(`project-${Math.random().toString(36).slice(2)}`)
     const two = ProjectID.make(`project-${Math.random().toString(36).slice(2)}`)
-    registerAdaptor(one, type, adaptor("/one"))
-    registerAdaptor(two, type, adaptor("/two"))
+    registerAdapter(one, type, adapter("/one"))
+    registerAdapter(two, type, adapter("/two"))
 
 
-    expect(await (await getAdaptor(one, type)).target(info(one, type))).toEqual({
+    expect(await (await getAdapter(one, type)).target(info(one, type))).toEqual({
       type: "local",
       type: "local",
       directory: "/one",
       directory: "/one",
     })
     })
-    expect(await (await getAdaptor(two, type)).target(info(two, type))).toEqual({
+    expect(await (await getAdapter(two, type)).target(info(two, type))).toEqual({
       type: "local",
       type: "local",
       directory: "/two",
       directory: "/two",
     })
     })
@@ -54,16 +54,16 @@ describe("control-plane/adaptors", () => {
   test("latest install wins within a project", async () => {
   test("latest install wins within a project", async () => {
     const type = `demo-${Math.random().toString(36).slice(2)}`
     const type = `demo-${Math.random().toString(36).slice(2)}`
     const id = ProjectID.make(`project-${Math.random().toString(36).slice(2)}`)
     const id = ProjectID.make(`project-${Math.random().toString(36).slice(2)}`)
-    registerAdaptor(id, type, adaptor("/one"))
+    registerAdapter(id, type, adapter("/one"))
 
 
-    expect(await (await getAdaptor(id, type)).target(info(id, type))).toEqual({
+    expect(await (await getAdapter(id, type)).target(info(id, type))).toEqual({
       type: "local",
       type: "local",
       directory: "/one",
       directory: "/one",
     })
     })
 
 
-    registerAdaptor(id, type, adaptor("/two"))
+    registerAdapter(id, type, adapter("/two"))
 
 
-    expect(await (await getAdaptor(id, type)).target(info(id, type))).toEqual({
+    expect(await (await getAdapter(id, type)).target(info(id, type))).toEqual({
       type: "local",
       type: "local",
       directory: "/two",
       directory: "/two",
     })
     })

+ 2 - 2
packages/opencode/test/plugin/workspace-adaptor.test.ts → packages/opencode/test/plugin/workspace-adapter.test.ts

@@ -31,7 +31,7 @@ afterAll(() => {
 })
 })
 
 
 describe("plugin.workspace", () => {
 describe("plugin.workspace", () => {
-  test("plugin can install a workspace adaptor", async () => {
+  test("plugin can install a workspace adapter", async () => {
     await using tmp = await tmpdir({
     await using tmp = await tmpdir({
       init: async (dir) => {
       init: async (dir) => {
         const type = `plug-${Math.random().toString(36).slice(2)}`
         const type = `plug-${Math.random().toString(36).slice(2)}`
@@ -44,7 +44,7 @@ describe("plugin.workspace", () => {
             "export default async ({ experimental_workspace }) => {",
             "export default async ({ experimental_workspace }) => {",
             `  experimental_workspace.register(${JSON.stringify(type)}, {`,
             `  experimental_workspace.register(${JSON.stringify(type)}, {`,
             '    name: "plug",',
             '    name: "plug",',
-            '    description: "plugin workspace adaptor",',
+            '    description: "plugin workspace adapter",',
             "    configure(input) {",
             "    configure(input) {",
             `      return { ...input, name: "plug", branch: "plug/main", directory: ${JSON.stringify(space)} }`,
             `      return { ...input, name: "plug", branch: "plug/main", directory: ${JSON.stringify(space)} }`,
             "    },",
             "    },",

+ 14 - 14
packages/opencode/test/server/httpapi-workspace.test.ts

@@ -3,8 +3,8 @@ import { mkdir } from "node:fs/promises"
 import path from "node:path"
 import path from "node:path"
 import { Effect } from "effect"
 import { Effect } from "effect"
 import { Flag } from "@opencode-ai/core/flag/flag"
 import { Flag } from "@opencode-ai/core/flag/flag"
-import { registerAdaptor } from "../../src/control-plane/adaptors"
-import type { WorkspaceAdaptor } from "../../src/control-plane/types"
+import { registerAdapter } from "../../src/control-plane/adapters"
+import type { WorkspaceAdapter } from "../../src/control-plane/types"
 import { Workspace } from "../../src/control-plane/workspace"
 import { Workspace } from "../../src/control-plane/workspace"
 import { WorkspacePaths } from "../../src/server/routes/instance/httpapi/groups/workspace"
 import { WorkspacePaths } from "../../src/server/routes/instance/httpapi/groups/workspace"
 import { Session } from "@/session/session"
 import { Session } from "@/session/session"
@@ -37,7 +37,7 @@ function runSession<A, E>(fx: Effect.Effect<A, E, Session.Service>, workspaceID?
   )
   )
 }
 }
 
 
-function localAdaptor(directory: string): WorkspaceAdaptor {
+function localAdapter(directory: string): WorkspaceAdapter {
   return {
   return {
     name: "Local Test",
     name: "Local Test",
     description: "Create a local test workspace",
     description: "Create a local test workspace",
@@ -61,7 +61,7 @@ function localAdaptor(directory: string): WorkspaceAdaptor {
   }
   }
 }
 }
 
 
-function remoteAdaptor(directory: string, url: string, headers?: HeadersInit): WorkspaceAdaptor {
+function remoteAdapter(directory: string, url: string, headers?: HeadersInit): WorkspaceAdapter {
   return {
   return {
     name: "Remote Test",
     name: "Remote Test",
     description: "Create a remote test workspace",
     description: "Create a remote test workspace",
@@ -139,14 +139,14 @@ describe("workspace HttpApi", () => {
   test("serves read endpoints", async () => {
   test("serves read endpoints", async () => {
     await using tmp = await tmpdir({ git: true })
     await using tmp = await tmpdir({ git: true })
 
 
-    const [adaptors, workspaces, status] = await Promise.all([
-      request(WorkspacePaths.adaptors, tmp.path),
+    const [adapters, workspaces, status] = await Promise.all([
+      request(WorkspacePaths.adapters, tmp.path),
       request(WorkspacePaths.list, tmp.path),
       request(WorkspacePaths.list, tmp.path),
       request(WorkspacePaths.status, tmp.path),
       request(WorkspacePaths.status, tmp.path),
     ])
     ])
 
 
-    expect(adaptors.status).toBe(200)
-    expect(await adaptors.json()).toEqual([
+    expect(adapters.status).toBe(200)
+    expect(await adapters.json()).toEqual([
       {
       {
         type: "worktree",
         type: "worktree",
         name: "Worktree",
         name: "Worktree",
@@ -167,7 +167,7 @@ describe("workspace HttpApi", () => {
     await Instance.provide({
     await Instance.provide({
       directory: tmp.path,
       directory: tmp.path,
       fn: async () =>
       fn: async () =>
-        registerAdaptor(Instance.project.id, "local-test", localAdaptor(path.join(tmp.path, ".workspace"))),
+        registerAdapter(Instance.project.id, "local-test", localAdapter(path.join(tmp.path, ".workspace"))),
     })
     })
 
 
     const created = await request(WorkspacePaths.list, tmp.path, {
     const created = await request(WorkspacePaths.list, tmp.path, {
@@ -207,7 +207,7 @@ describe("workspace HttpApi", () => {
     const workspace = await Instance.provide({
     const workspace = await Instance.provide({
       directory: tmp.path,
       directory: tmp.path,
       fn: async () => {
       fn: async () => {
-        registerAdaptor(Instance.project.id, "local-target", localAdaptor(workspaceDir))
+        registerAdapter(Instance.project.id, "local-target", localAdapter(workspaceDir))
         return Workspace.create({
         return Workspace.create({
           type: "local-target",
           type: "local-target",
           branch: null,
           branch: null,
@@ -261,10 +261,10 @@ describe("workspace HttpApi", () => {
     const workspace = await Instance.provide({
     const workspace = await Instance.provide({
       directory: tmp.path,
       directory: tmp.path,
       fn: async () => {
       fn: async () => {
-        registerAdaptor(
+        registerAdapter(
           Instance.project.id,
           Instance.project.id,
           "remote-target",
           "remote-target",
-          remoteAdaptor(path.join(tmp.path, ".remote"), `http://127.0.0.1:${remote.port}/base`, {
+          remoteAdapter(path.join(tmp.path, ".remote"), `http://127.0.0.1:${remote.port}/base`, {
             "x-target-auth": "secret",
             "x-target-auth": "secret",
           }),
           }),
         )
         )
@@ -332,10 +332,10 @@ describe("workspace HttpApi", () => {
     const workspace = await Instance.provide({
     const workspace = await Instance.provide({
       directory: tmp.path,
       directory: tmp.path,
       fn: async () => {
       fn: async () => {
-        registerAdaptor(
+        registerAdapter(
           Instance.project.id,
           Instance.project.id,
           "remote-session-target",
           "remote-session-target",
-          remoteAdaptor(path.join(tmp.path, ".remote-session"), `http://127.0.0.1:${remote.port}/base`),
+          remoteAdapter(path.join(tmp.path, ".remote-session"), `http://127.0.0.1:${remote.port}/base`),
         )
         )
         return Workspace.create({
         return Workspace.create({
           type: "remote-session-target",
           type: "remote-session-target",

+ 6 - 6
packages/opencode/test/workspace/workspace-restore.test.ts

@@ -2,8 +2,8 @@ import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from "bun:
 import fs from "node:fs/promises"
 import fs from "node:fs/promises"
 import path from "node:path"
 import path from "node:path"
 import { GlobalBus } from "../../src/bus/global"
 import { GlobalBus } from "../../src/bus/global"
-import { registerAdaptor } from "../../src/control-plane/adaptors"
-import type { WorkspaceAdaptor } from "../../src/control-plane/types"
+import { registerAdapter } from "../../src/control-plane/adapters"
+import type { WorkspaceAdapter } from "../../src/control-plane/types"
 import { Workspace } from "../../src/control-plane/workspace"
 import { Workspace } from "../../src/control-plane/workspace"
 import { AppRuntime } from "../../src/effect/app-runtime"
 import { AppRuntime } from "../../src/effect/app-runtime"
 import { Flag } from "@opencode-ai/core/flag/flag"
 import { Flag } from "@opencode-ai/core/flag/flag"
@@ -71,7 +71,7 @@ async function user(sessionID: SessionID, text: string) {
   })
   })
 }
 }
 
 
-function remote(dir: string, url: string): WorkspaceAdaptor {
+function remote(dir: string, url: string): WorkspaceAdapter {
   return {
   return {
     name: "remote",
     name: "remote",
     description: "remote",
     description: "remote",
@@ -94,7 +94,7 @@ function remote(dir: string, url: string): WorkspaceAdaptor {
   }
   }
 }
 }
 
 
-function local(dir: string): WorkspaceAdaptor {
+function local(dir: string): WorkspaceAdapter {
   return {
   return {
     name: "local",
     name: "local",
     description: "local",
     description: "local",
@@ -166,7 +166,7 @@ describe("Workspace.sessionRestore", () => {
       const setup = await Instance.provide({
       const setup = await Instance.provide({
         directory: tmp.path,
         directory: tmp.path,
         fn: async () => {
         fn: async () => {
-          registerAdaptor(Instance.project.id, "worktree", remote(dir, "https://workspace.test/base"))
+          registerAdapter(Instance.project.id, "worktree", remote(dir, "https://workspace.test/base"))
           const space = await Workspace.create({
           const space = await Workspace.create({
             type: "worktree",
             type: "worktree",
             branch: null,
             branch: null,
@@ -247,7 +247,7 @@ describe("Workspace.sessionRestore", () => {
       const setup = await Instance.provide({
       const setup = await Instance.provide({
         directory: tmp.path,
         directory: tmp.path,
         fn: async () => {
         fn: async () => {
-          registerAdaptor(Instance.project.id, "local-restore", local(dir))
+          registerAdapter(Instance.project.id, "local-restore", local(dir))
           const space = await Workspace.create({
           const space = await Workspace.create({
             type: "local-restore",
             type: "local-restore",
             branch: null,
             branch: null,

+ 2 - 2
packages/plugin/src/index.ts

@@ -45,7 +45,7 @@ export type WorkspaceTarget =
       headers?: HeadersInit
       headers?: HeadersInit
     }
     }
 
 
-export type WorkspaceAdaptor = {
+export type WorkspaceAdapter = {
   name: string
   name: string
   description: string
   description: string
   configure(config: WorkspaceInfo): WorkspaceInfo | Promise<WorkspaceInfo>
   configure(config: WorkspaceInfo): WorkspaceInfo | Promise<WorkspaceInfo>
@@ -60,7 +60,7 @@ export type PluginInput = {
   directory: string
   directory: string
   worktree: string
   worktree: string
   experimental_workspace: {
   experimental_workspace: {
-    register(type: string, adaptor: WorkspaceAdaptor): void
+    register(type: string, adapter: WorkspaceAdapter): void
   }
   }
   serverUrl: URL
   serverUrl: URL
   $: BunShell
   $: BunShell

+ 9 - 9
packages/sdk/js/src/v2/gen/sdk.gen.ts

@@ -29,7 +29,7 @@ import type {
   ExperimentalConsoleSwitchOrgResponses,
   ExperimentalConsoleSwitchOrgResponses,
   ExperimentalResourceListResponses,
   ExperimentalResourceListResponses,
   ExperimentalSessionListResponses,
   ExperimentalSessionListResponses,
-  ExperimentalWorkspaceAdaptorListResponses,
+  ExperimentalWorkspaceAdapterListResponses,
   ExperimentalWorkspaceCreateErrors,
   ExperimentalWorkspaceCreateErrors,
   ExperimentalWorkspaceCreateResponses,
   ExperimentalWorkspaceCreateResponses,
   ExperimentalWorkspaceListResponses,
   ExperimentalWorkspaceListResponses,
@@ -512,11 +512,11 @@ export class App extends HeyApiClient {
   }
   }
 }
 }
 
 
-export class Adaptor extends HeyApiClient {
+export class Adapter extends HeyApiClient {
   /**
   /**
-   * List workspace adaptors
+   * List workspace adapters
    *
    *
-   * List all available workspace adaptors for the current project.
+   * List all available workspace adapters for the current project.
    */
    */
   public list<ThrowOnError extends boolean = false>(
   public list<ThrowOnError extends boolean = false>(
     parameters?: {
     parameters?: {
@@ -536,8 +536,8 @@ export class Adaptor extends HeyApiClient {
         },
         },
       ],
       ],
     )
     )
-    return (options?.client ?? this.client).get<ExperimentalWorkspaceAdaptorListResponses, unknown, ThrowOnError>({
-      url: "/experimental/workspace/adaptor",
+    return (options?.client ?? this.client).get<ExperimentalWorkspaceAdapterListResponses, unknown, ThrowOnError>({
+      url: "/experimental/workspace/adapter",
       ...options,
       ...options,
       ...params,
       ...params,
     })
     })
@@ -731,9 +731,9 @@ export class Workspace extends HeyApiClient {
     })
     })
   }
   }
 
 
-  private _adaptor?: Adaptor
-  get adaptor(): Adaptor {
-    return (this._adaptor ??= new Adaptor({ client: this.client }))
+  private _adapter?: Adapter
+  get adapter(): Adapter {
+    return (this._adapter ??= new Adapter({ client: this.client }))
   }
   }
 }
 }
 
 

+ 6 - 6
packages/sdk/js/src/v2/gen/types.gen.ts

@@ -2430,19 +2430,19 @@ export type AppLogResponses = {
 
 
 export type AppLogResponse = AppLogResponses[keyof AppLogResponses]
 export type AppLogResponse = AppLogResponses[keyof AppLogResponses]
 
 
-export type ExperimentalWorkspaceAdaptorListData = {
+export type ExperimentalWorkspaceAdapterListData = {
   body?: never
   body?: never
   path?: never
   path?: never
   query?: {
   query?: {
     directory?: string
     directory?: string
     workspace?: string
     workspace?: string
   }
   }
-  url: "/experimental/workspace/adaptor"
+  url: "/experimental/workspace/adapter"
 }
 }
 
 
-export type ExperimentalWorkspaceAdaptorListResponses = {
+export type ExperimentalWorkspaceAdapterListResponses = {
   /**
   /**
-   * Workspace adaptors
+   * Workspace adapters
    */
    */
   200: Array<{
   200: Array<{
     type: string
     type: string
@@ -2451,8 +2451,8 @@ export type ExperimentalWorkspaceAdaptorListResponses = {
   }>
   }>
 }
 }
 
 
-export type ExperimentalWorkspaceAdaptorListResponse =
-  ExperimentalWorkspaceAdaptorListResponses[keyof ExperimentalWorkspaceAdaptorListResponses]
+export type ExperimentalWorkspaceAdapterListResponse =
+  ExperimentalWorkspaceAdapterListResponses[keyof ExperimentalWorkspaceAdapterListResponses]
 
 
 export type ExperimentalWorkspaceListData = {
 export type ExperimentalWorkspaceListData = {
   body?: never
   body?: never

+ 6 - 6
packages/sdk/openapi.json

@@ -415,9 +415,9 @@
         ]
         ]
       }
       }
     },
     },
-    "/experimental/workspace/adaptor": {
+    "/experimental/workspace/adapter": {
       "get": {
       "get": {
-        "operationId": "experimental.workspace.adaptor.list",
+        "operationId": "experimental.workspace.adapter.list",
         "parameters": [
         "parameters": [
           {
           {
             "in": "query",
             "in": "query",
@@ -434,11 +434,11 @@
             }
             }
           }
           }
         ],
         ],
-        "summary": "List workspace adaptors",
-        "description": "List all available workspace adaptors for the current project.",
+        "summary": "List workspace adapters",
+        "description": "List all available workspace adapters for the current project.",
         "responses": {
         "responses": {
           "200": {
           "200": {
-            "description": "Workspace adaptors",
+            "description": "Workspace adapters",
             "content": {
             "content": {
               "application/json": {
               "application/json": {
                 "schema": {
                 "schema": {
@@ -466,7 +466,7 @@
         "x-codeSamples": [
         "x-codeSamples": [
           {
           {
             "lang": "js",
             "lang": "js",
-            "source": "import { createOpencodeClient } from \"@opencode-ai/sdk\n\nconst client = createOpencodeClient()\nawait client.experimental.workspace.adaptor.list({\n  ...\n})"
+            "source": "import { createOpencodeClient } from \"@opencode-ai/sdk\n\nconst client = createOpencodeClient()\nawait client.experimental.workspace.adapter.list({\n  ...\n})"
           }
           }
         ]
         ]
       }
       }