diff --git a/packages/opencode/specs/effect/http-api.md b/packages/opencode/specs/effect/http-api.md index 8eda0595db..99b7f1b156 100644 --- a/packages/opencode/specs/effect/http-api.md +++ b/packages/opencode/specs/effect/http-api.md @@ -198,7 +198,7 @@ Use raw Effect HTTP routes where `HttpApi` does not fit. The goal is deleting Ho | `project` | `bridged` | list, current, git init, update | | `file` | `bridged` partial | find text/file/symbol, list/content/status | | `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 | | 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 | @@ -290,7 +290,7 @@ This checklist tracks bridge parity only. Checked routes are available through t ### 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] `GET /experimental/workspace` - list workspaces. - [x] `GET /experimental/workspace/status` - workspace status. diff --git a/packages/opencode/specs/effect/schema.md b/packages/opencode/specs/effect/schema.md index c4f9769224..e755457e61 100644 --- a/packages/opencode/specs/effect/schema.md +++ b/packages/opencode/specs/effect/schema.md @@ -353,7 +353,7 @@ piecewise. - [ ] `src/cli/cmd/tui/event.ts` - [ ] `src/cli/ui.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/workspace.ts` - [ ] `src/file/index.ts` diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-workspace-create.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-workspace-create.tsx index 009bb74d2c..0aa61c313a 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-workspace-create.tsx +++ b/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 { useToast } from "../ui/toast" -type Adaptor = { +type Adapter = { type: string name: string description: string @@ -108,26 +108,26 @@ export function DialogWorkspaceCreate(props: { onSelect: (workspaceID: string) = const sdk = useSDK() const toast = useToast() const [creating, setCreating] = createSignal() - const [adaptors, setAdaptors] = createSignal() + const [adapters, setAdapters] = createSignal() onMount(() => { dialog.setSize("medium") void (async () => { 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) const res = await sdk .fetch(url) - .then((x) => x.json() as Promise) + .then((x) => x.json() as Promise) .catch(() => undefined) if (!res) { toast.show({ - message: "Failed to load workspace adaptors", + message: "Failed to load workspace adapters", variant: "error", }) return } - setAdaptors(res) + setAdapters(res) })() }) @@ -142,13 +142,13 @@ export function DialogWorkspaceCreate(props: { onSelect: (workspaceID: string) = }, ] } - const list = adaptors() + const list = adapters() if (!list) { return [ { title: "Loading workspaces...", value: "loading" as const, - description: "Fetching available workspace adaptors", + description: "Fetching available workspace adapters", }, ] } diff --git a/packages/opencode/src/control-plane/adapters/index.ts b/packages/opencode/src/control-plane/adapters/index.ts new file mode 100644 index 0000000000..963e2a2ed5 --- /dev/null +++ b/packages/opencode/src/control-plane/adapters/index.ts @@ -0,0 +1,45 @@ +import type { ProjectID } from "@/project/schema" +import type { WorkspaceAdapter, WorkspaceAdapterEntry } from "../types" +import { WorktreeAdapter } from "./worktree" + +const BUILTIN: Record = { + worktree: WorktreeAdapter, +} + +const state = new Map>() + +export function getAdapter(projectID: ProjectID, type: string): 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 { + const builtin = await Promise.all( + Object.entries(BUILTIN).map(async ([type, adapter]) => { + 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() + adapters.set(type, adapter) + state.set(projectID, adapters) +} diff --git a/packages/opencode/src/control-plane/adaptors/worktree.ts b/packages/opencode/src/control-plane/adapters/worktree.ts similarity index 92% rename from packages/opencode/src/control-plane/adaptors/worktree.ts rename to packages/opencode/src/control-plane/adapters/worktree.ts index de9618d302..af8f5d8d43 100644 --- a/packages/opencode/src/control-plane/adaptors/worktree.ts +++ b/packages/opencode/src/control-plane/adapters/worktree.ts @@ -1,5 +1,5 @@ import { Schema } from "effect" -import { type WorkspaceAdaptor, WorkspaceInfo } from "../types" +import { type WorkspaceAdapter, WorkspaceInfo } from "../types" const WorktreeConfig = Schema.Struct({ name: WorkspaceInfo.fields.name, @@ -13,7 +13,7 @@ async function loadWorktree() { return { AppRuntime, Worktree } } -export const WorktreeAdaptor: WorkspaceAdaptor = { +export const WorktreeAdapter: WorkspaceAdapter = { name: "Worktree", description: "Create a git worktree", async configure(info) { diff --git a/packages/opencode/src/control-plane/adaptors/index.ts b/packages/opencode/src/control-plane/adaptors/index.ts deleted file mode 100644 index c91f534b5a..0000000000 --- a/packages/opencode/src/control-plane/adaptors/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { ProjectID } from "@/project/schema" -import type { WorkspaceAdaptor, WorkspaceAdaptorEntry } from "../types" -import { WorktreeAdaptor } from "./worktree" - -const BUILTIN: Record = { - worktree: WorktreeAdaptor, -} - -const state = new Map>() - -export function getAdaptor(projectID: ProjectID, type: string): 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 { - const builtin = await Promise.all( - Object.entries(BUILTIN).map(async ([type, adaptor]) => { - 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() - adaptors.set(type, adaptor) - state.set(projectID, adaptors) -} diff --git a/packages/opencode/src/control-plane/types.ts b/packages/opencode/src/control-plane/types.ts index af16c04902..7f3aad7ed1 100644 --- a/packages/opencode/src/control-plane/types.ts +++ b/packages/opencode/src/control-plane/types.ts @@ -17,12 +17,12 @@ export const WorkspaceInfo = Schema.Struct({ .pipe(withStatics((s) => ({ zod: zod(s) }))) export type WorkspaceInfo = DeepMutable> -export const WorkspaceAdaptorEntry = Schema.Struct({ +export const WorkspaceAdapterEntry = Schema.Struct({ type: Schema.String, name: Schema.String, description: Schema.String, }).pipe(withStatics((s) => ({ zod: zod(s) }))) -export type WorkspaceAdaptorEntry = Schema.Schema.Type +export type WorkspaceAdapterEntry = Schema.Schema.Type export type Target = | { @@ -35,7 +35,7 @@ export type Target = headers?: HeadersInit } -export type WorkspaceAdaptor = { +export type WorkspaceAdapter = { name: string description: string configure(info: WorkspaceInfo): WorkspaceInfo | Promise diff --git a/packages/opencode/src/control-plane/workspace.ts b/packages/opencode/src/control-plane/workspace.ts index 7f9d078bb7..7e4b4a6ff4 100644 --- a/packages/opencode/src/control-plane/workspace.ts +++ b/packages/opencode/src/control-plane/workspace.ts @@ -16,7 +16,7 @@ import { Filesystem } from "@/util/filesystem" import { ProjectID } from "@/project/schema" import { Slug } from "@opencode-ai/core/util/slug" import { WorkspaceTable } from "./workspace.sql" -import { getAdaptor } from "./adaptors" +import { getAdapter } from "./adapters" import { type WorkspaceInfo, WorkspaceInfo as WorkspaceInfoSchema } from "./types" import { WorkspaceID } from "./schema" import { Session } from "@/session/session" @@ -335,8 +335,8 @@ export const layer = Layer.effect( }) const syncWorkspaceLoop = Effect.fn("Workspace.syncWorkspaceLoop")(function* (space: Info) { - const adaptor = getAdaptor(space.projectID, space.type) - const target = yield* Effect.promise(() => Promise.resolve(adaptor.target(space))) + const adapter = getAdapter(space.projectID, space.type) + const target = yield* Effect.promise(() => Promise.resolve(adapter.target(space))) if (target.type === "local") return @@ -419,8 +419,8 @@ export const layer = Layer.effect( const startSync = Effect.fn("Workspace.startSync")(function* (space: Info) { if (!Flag.OPENCODE_EXPERIMENTAL_WORKSPACES) return - const adaptor = getAdaptor(space.projectID, space.type) - const target = yield* Effect.promise(() => Promise.resolve(adaptor.target(space))) + const adapter = getAdapter(space.projectID, space.type) + const target = yield* Effect.promise(() => Promise.resolve(adapter.target(space))) if (target.type === "local") { setStatus(space.id, (yield* Effect.promise(() => Filesystem.exists(target.directory))) ? "connected" : "error") @@ -458,9 +458,9 @@ export const layer = Layer.effect( const create = Effect.fn("Workspace.create")(function* (input: CreateInput) { const id = WorkspaceID.ascending(input.id) - const adaptor = getAdaptor(input.projectID, input.type) + const adapter = getAdapter(input.projectID, input.type) const config = yield* Effect.promise(() => - Promise.resolve(adaptor.configure({ ...input, id, name: Slug.create(), directory: null })), + Promise.resolve(adapter.configure({ ...input, id, name: Slug.create(), directory: null })), ) const info: Info = { @@ -496,7 +496,7 @@ export const layer = Layer.effect( OTEL_RESOURCE_ATTRIBUTES: process.env.OTEL_RESOURCE_ATTRIBUTES, } - yield* Effect.promise(() => adaptor.create(config, env)) + yield* Effect.promise(() => adapter.create(config, env)) yield* Effect.all( [ waitEvent({ @@ -531,8 +531,8 @@ export const layer = Layer.effect( workspaceID: input.workspaceID, }) - const adaptor = getAdaptor(space.projectID, space.type) - const target = yield* Effect.promise(() => Promise.resolve(adaptor.target(space))) + const adapter = getAdapter(space.projectID, space.type) + const target = yield* Effect.promise(() => Promise.resolve(adapter.target(space))) yield* sync.run(Session.Event.Updated, { sessionID: input.sessionID, @@ -726,12 +726,12 @@ export const layer = Layer.effect( const info = fromRow(row) yield* Effect.catch( Effect.gen(function* () { - const adaptor = getAdaptor(info.projectID, row.type) - yield* Effect.tryPromise(() => Promise.resolve(adaptor.remove(info))) + const adapter = getAdapter(info.projectID, row.type) + yield* Effect.tryPromise(() => Promise.resolve(adapter.remove(info))) }), () => Effect.sync(() => { - log.error("adaptor not available when removing workspace", { type: row.type }) + log.error("adapter not available when removing workspace", { type: row.type }) }), ) diff --git a/packages/opencode/src/plugin/index.ts b/packages/opencode/src/plugin/index.ts index ac37823c34..95af410ff9 100644 --- a/packages/opencode/src/plugin/index.ts +++ b/packages/opencode/src/plugin/index.ts @@ -3,7 +3,7 @@ import type { PluginInput, Plugin as PluginInstance, PluginModule, - WorkspaceAdaptor as PluginWorkspaceAdaptor, + WorkspaceAdapter as PluginWorkspaceAdapter, } from "@opencode-ai/plugin" import { Config } from "@/config/config" import { Bus } from "../bus" @@ -24,8 +24,8 @@ import { InstanceState } from "@/effect/instance-state" import { errorMessage } from "@/util/error" import { PluginLoader } from "./loader" 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" }) @@ -138,8 +138,8 @@ export const layer = Layer.effect( worktree: ctx.worktree, directory: ctx.directory, 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 { diff --git a/packages/opencode/src/server/routes/control/workspace.ts b/packages/opencode/src/server/routes/control/workspace.ts index 08f926d40d..21a7810ce1 100644 --- a/packages/opencode/src/server/routes/control/workspace.ts +++ b/packages/opencode/src/server/routes/control/workspace.ts @@ -2,10 +2,10 @@ import { Hono } from "hono" import { describeRoute, resolver, validator } from "hono-openapi" import z from "zod" import { Effect } from "effect" -import { listAdaptors } from "@/control-plane/adaptors" +import { listAdapters } from "@/control-plane/adapters" import { Workspace } from "@/control-plane/workspace" import { AppRuntime } from "@/effect/app-runtime" -import { WorkspaceAdaptorEntry } from "@/control-plane/types" +import { WorkspaceAdapterEntry } from "@/control-plane/types" import { zodObject } from "@/util/effect-zod" import { Instance } from "@/project/instance" import { errors } from "../../error" @@ -18,24 +18,24 @@ const log = Log.create({ service: "server.workspace" }) export const WorkspaceRoutes = lazy(() => new Hono() .get( - "/adaptor", + "/adapter", 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: { 200: { - description: "Workspace adaptors", + description: "Workspace adapters", content: { "application/json": { - schema: resolver(z.array(zodObject(WorkspaceAdaptorEntry))), + schema: resolver(z.array(zodObject(WorkspaceAdapterEntry))), }, }, }, }, }), async (c) => { - return c.json(await listAdaptors(Instance.project.id)) + return c.json(await listAdapters(Instance.project.id)) }, ) .post( diff --git a/packages/opencode/src/server/routes/instance/httpapi/groups/workspace.ts b/packages/opencode/src/server/routes/instance/httpapi/groups/workspace.ts index 268e84f2ec..112b8a3298 100644 --- a/packages/opencode/src/server/routes/instance/httpapi/groups/workspace.ts +++ b/packages/opencode/src/server/routes/instance/httpapi/groups/workspace.ts @@ -1,5 +1,5 @@ import { Workspace } from "@/control-plane/workspace" -import { WorkspaceAdaptorEntry } from "@/control-plane/types" +import { WorkspaceAdapterEntry } from "@/control-plane/types" import { NonNegativeInt } from "@/util/schema" import { Schema, Struct } from "effect" import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from "effect/unstable/httpapi" @@ -16,7 +16,7 @@ export const SessionRestoreResponse = Schema.Struct({ }) export const WorkspacePaths = { - adaptors: `${root}/adaptor`, + adapters: `${root}/adapter`, list: root, status: `${root}/status`, remove: `${root}/:id`, @@ -27,13 +27,13 @@ export const WorkspaceApi = HttpApi.make("workspace") .add( HttpApiGroup.make("workspace") .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( 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, { diff --git a/packages/opencode/src/server/routes/instance/httpapi/handlers/workspace.ts b/packages/opencode/src/server/routes/instance/httpapi/handlers/workspace.ts index 4e76a76a30..03e8ee74b7 100644 --- a/packages/opencode/src/server/routes/instance/httpapi/handlers/workspace.ts +++ b/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 * as InstanceState from "@/effect/instance-state" import { Effect } from "effect" @@ -10,9 +10,9 @@ export const workspaceHandlers = HttpApiBuilder.group(InstanceHttpApi, "workspac Effect.gen(function* () { const workspace = yield* Workspace.Service - const adaptors = Effect.fn("WorkspaceHttpApi.adaptors")(function* () { + const adapters = Effect.fn("WorkspaceHttpApi.adapters")(function* () { 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* () { @@ -51,7 +51,7 @@ export const workspaceHandlers = HttpApiBuilder.group(InstanceHttpApi, "workspac }) return handlers - .handle("adaptors", adaptors) + .handle("adapters", adapters) .handle("list", list) .handle("create", create) .handle("status", status) diff --git a/packages/opencode/src/server/routes/instance/httpapi/middleware/workspace-routing.ts b/packages/opencode/src/server/routes/instance/httpapi/middleware/workspace-routing.ts index 30edbc782b..f38c91ccec 100644 --- a/packages/opencode/src/server/routes/instance/httpapi/middleware/workspace-routing.ts +++ b/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 type { Target } from "@/control-plane/types" import { Workspace } from "@/control-plane/workspace" @@ -89,8 +89,8 @@ function missingWorkspaceResponse(id: WorkspaceID): HttpServerResponse.HttpServe function resolveTarget(workspace: Workspace.Info): Effect.Effect { return Effect.gen(function* () { - const adaptor = yield* Effect.sync(() => getAdaptor(workspace.projectID, workspace.type)) - return yield* Effect.promise(() => Promise.resolve(adaptor.target(workspace))) + const adapter = yield* Effect.sync(() => getAdapter(workspace.projectID, workspace.type)) + return yield* Effect.promise(() => Promise.resolve(adapter.target(workspace))) }) } diff --git a/packages/opencode/src/server/workspace.ts b/packages/opencode/src/server/workspace.ts index 667e610abc..f757137483 100644 --- a/packages/opencode/src/server/workspace.ts +++ b/packages/opencode/src/server/workspace.ts @@ -1,6 +1,6 @@ import type { MiddlewareHandler } from "hono" 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 { WorkspaceContext } from "@/control-plane/workspace-context" import { Workspace } from "@/control-plane/workspace" @@ -91,8 +91,8 @@ export function WorkspaceRouterMiddleware(upgrade: UpgradeWebSocket): Middleware return next() } - const adaptor = getAdaptor(workspace.projectID, workspace.type) - const target = await adaptor.target(workspace) + const adapter = getAdapter(workspace.projectID, workspace.type) + const target = await adapter.target(workspace) if (target.type === "local") { return WorkspaceContext.provide({ diff --git a/packages/opencode/test/control-plane/adaptors.test.ts b/packages/opencode/test/control-plane/adapters.test.ts similarity index 68% rename from packages/opencode/test/control-plane/adaptors.test.ts rename to packages/opencode/test/control-plane/adapters.test.ts index a8e490226b..762bb5d57e 100644 --- a/packages/opencode/test/control-plane/adaptors.test.ts +++ b/packages/opencode/test/control-plane/adapters.test.ts @@ -1,5 +1,5 @@ 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 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 { name: 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 one = 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", 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", directory: "/two", }) @@ -54,16 +54,16 @@ describe("control-plane/adaptors", () => { test("latest install wins within a project", async () => { const type = `demo-${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", 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", directory: "/two", }) diff --git a/packages/opencode/test/control-plane/workspace.test.ts b/packages/opencode/test/control-plane/workspace.test.ts index 594789b207..8545aef7f3 100644 --- a/packages/opencode/test/control-plane/workspace.test.ts +++ b/packages/opencode/test/control-plane/workspace.test.ts @@ -23,10 +23,10 @@ import { EventSequenceTable, EventTable } from "@/sync/event.sql" import { resetDatabase } from "../fixture/db" import { provideTmpdirInstance, tmpdir } from "../fixture/fixture" import { testEffect } from "../lib/effect" -import { registerAdaptor } from "../../src/control-plane/adaptors" +import { registerAdapter } from "../../src/control-plane/adapters" import { WorkspaceID } from "../../src/control-plane/schema" import { WorkspaceTable } from "../../src/control-plane/workspace.sql" -import type { Target, WorkspaceAdaptor, WorkspaceInfo } from "../../src/control-plane/types" +import type { Target, WorkspaceAdapter, WorkspaceInfo } from "../../src/control-plane/types" import * as WorkspaceOld from "../../src/control-plane/workspace" import { AppRuntime } from "@/effect/app-runtime" @@ -53,8 +53,8 @@ type RecordedCreate = { from?: WorkspaceInfo } -type RecordedAdaptor = { - adaptor: WorkspaceAdaptor +type RecordedAdapter = { + adapter: WorkspaceAdapter calls: { configure: WorkspaceInfo[] create: RecordedCreate[] @@ -165,13 +165,13 @@ function eventuallyEffect(effect: Effect.Effect, timeout = 1500) { }) } -function recordedAdaptor(input: { +function recordedAdapter(input: { target: (info: WorkspaceInfo) => Target | Promise configure?: (info: WorkspaceInfo) => WorkspaceInfo | Promise create?: (info: WorkspaceInfo, env: Record, from?: WorkspaceInfo) => Promise remove?: (info: WorkspaceInfo) => Promise -}): RecordedAdaptor { - const calls: RecordedAdaptor["calls"] = { +}): RecordedAdapter { + const calls: RecordedAdapter["calls"] = { configure: [], create: [], remove: [], @@ -180,7 +180,7 @@ function recordedAdaptor(input: { return { calls, - adaptor: { + adapter: { name: "recorded", description: "recorded", configure(info) { @@ -207,8 +207,8 @@ function recordedAdaptor(input: { } } -function localAdaptor(dir: string, input?: { createDir?: boolean; remove?: (info: WorkspaceInfo) => Promise }) { - return recordedAdaptor({ +function localAdapter(dir: string, input?: { createDir?: boolean; remove?: (info: WorkspaceInfo) => Promise }) { + return recordedAdapter({ configure(info) { return { ...info, directory: dir } }, @@ -223,8 +223,8 @@ function localAdaptor(dir: string, input?: { createDir?: boolean; remove?: (info }) } -function remoteAdaptor(url: string, input?: { directory?: string | null; headers?: HeadersInit }) { - return recordedAdaptor({ +function remoteAdapter(url: string, input?: { directory?: string | null; headers?: HeadersInit }) { + return recordedAdapter({ configure(info) { return { ...info, directory: input?.directory ?? info.directory } }, @@ -429,7 +429,7 @@ describe("workspace-old CRUD", () => { const workspaceID = WorkspaceID.ascending("wrk_create_local") const type = unique("create-local") const targetDir = path.join(dir, "created-local") - const recorded = recordedAdaptor({ + const recorded = recordedAdapter({ configure(info) { return { ...info, @@ -446,7 +446,7 @@ describe("workspace-old CRUD", () => { return { type: "local", directory: targetDir } }, }) - registerAdaptor(Instance.project.id, type, recorded.adaptor) + registerAdapter(Instance.project.id, type, recorded.adapter) const info = await createWorkspace({ id: workspaceID, @@ -489,17 +489,17 @@ describe("workspace-old CRUD", () => { test("create propagates configure failures and does not insert a workspace", async () => { await withInstance(async () => { const type = unique("configure-failure") - registerAdaptor( + registerAdapter( Instance.project.id, type, - recordedAdaptor({ + recordedAdapter({ configure() { throw new Error("configure exploded") }, target() { return { type: "local", directory: "/unused" } }, - }).adaptor, + }).adapter, ) await expect( @@ -509,10 +509,10 @@ describe("workspace-old CRUD", () => { }) }) - test("create leaves the inserted row when adaptor create fails", async () => { + test("create leaves the inserted row when adapter create fails", async () => { await withInstance(async () => { const type = unique("create-failure") - const recorded = recordedAdaptor({ + const recorded = recordedAdapter({ async create() { throw new Error("create exploded") }, @@ -520,7 +520,7 @@ describe("workspace-old CRUD", () => { return { type: "local", directory: "/unused" } }, }) - registerAdaptor(Instance.project.id, type, recorded.adaptor) + registerAdapter(Instance.project.id, type, recorded.adapter) await expect( createWorkspace({ type, branch: "branch", projectID: Instance.project.id, extra: { x: 1 } }), @@ -538,8 +538,8 @@ describe("workspace-old CRUD", () => { await withInstance(async (dir) => { const type = unique("local-error") const missing = path.join(dir, "missing-local-target") - const recorded = localAdaptor(missing, { createDir: false }) - registerAdaptor(Instance.project.id, type, recorded.adaptor) + const recorded = localAdapter(missing, { createDir: false }) + registerAdapter(Instance.project.id, type, recorded.adapter) const info = await createWorkspace({ type, branch: null, projectID: Instance.project.id, extra: null }) @@ -576,8 +576,8 @@ describe("workspace-old CRUD", () => { Effect.gen(function* () { const workspace = yield* WorkspaceOld.Service const type = unique("remote-create") - const recorded = remoteAdaptor(`${url}/base/?ignored=1#hash`, { directory: dir }) - registerAdaptor(Instance.project.id, type, recorded.adaptor) + const recorded = remoteAdapter(`${url}/base/?ignored=1#hash`, { directory: dir }) + registerAdapter(Instance.project.id, type, recorded.adapter) const info = yield* workspace.create({ type, branch: null, projectID: Instance.project.id, extra: null }) @@ -603,11 +603,11 @@ describe("workspace-old CRUD", () => { }) }) - test("remove deletes the workspace, associated sessions, adaptor resources, and status", async () => { + test("remove deletes the workspace, associated sessions, adapter resources, and status", async () => { await withInstance(async (dir) => { const type = unique("remove-local") - const recorded = localAdaptor(path.join(dir, "remove-local")) - registerAdaptor(Instance.project.id, type, recorded.adaptor) + const recorded = localAdapter(path.join(dir, "remove-local")) + registerAdapter(Instance.project.id, type, recorded.adapter) const info = await createWorkspace({ type, branch: null, projectID: Instance.project.id, extra: null }) const one = await AppRuntime.runPromise(SessionNs.Service.use((svc) => svc.create({}))) const two = await AppRuntime.runPromise(SessionNs.Service.use((svc) => svc.create({}))) @@ -628,21 +628,21 @@ describe("workspace-old CRUD", () => { }) }) - test("remove still deletes the row when the adaptor cannot remove resources", async () => { + test("remove still deletes the row when the adapter cannot remove resources", async () => { await withInstance(async () => { const type = unique("remove-throws") const info = workspaceInfo(Instance.project.id, type, { id: WorkspaceID.ascending("wrk_remove_throws") }) - registerAdaptor( + registerAdapter( Instance.project.id, type, - recordedAdaptor({ + recordedAdapter({ async remove() { throw new Error("remove exploded") }, target() { return { type: "local", directory: "/unused" } }, - }).adaptor, + }).adapter, ) insertWorkspace(info) @@ -661,7 +661,7 @@ describe("workspace-old sync state", () => { const session = await AppRuntime.runPromise(SessionNs.Service.use((svc) => svc.create({}))) attachSessionToWorkspace(session.id, info.id) insertWorkspace(info) - registerAdaptor(Instance.project.id, type, localAdaptor(path.join(dir, "flag-disabled")).adaptor) + registerAdapter(Instance.project.id, type, localAdapter(path.join(dir, "flag-disabled")).adapter) startWorkspaceSyncing(Instance.project.id) await delay(25) @@ -682,8 +682,8 @@ describe("workspace-old sync state", () => { await fs.mkdir(withoutSessionDir, { recursive: true }) insertWorkspace(withSession) insertWorkspace(withoutSession) - registerAdaptor(Instance.project.id, withSessionType, localAdaptor(withSessionDir).adaptor) - registerAdaptor(Instance.project.id, withoutSessionType, localAdaptor(withoutSessionDir).adaptor) + registerAdapter(Instance.project.id, withSessionType, localAdapter(withSessionDir).adapter) + registerAdapter(Instance.project.id, withoutSessionType, localAdapter(withoutSessionDir).adapter) attachSessionToWorkspace( (await AppRuntime.runPromise(SessionNs.Service.use((svc) => svc.create({})))).id, withSession.id, @@ -707,10 +707,10 @@ describe("workspace-old sync state", () => { const type = unique("missing-local") const info = workspaceInfo(Instance.project.id, type) insertWorkspace(info) - registerAdaptor( + registerAdapter( Instance.project.id, type, - localAdaptor(path.join(dir, "missing-target"), { createDir: false }).adaptor, + localAdapter(path.join(dir, "missing-target"), { createDir: false }).adapter, ) attachSessionToWorkspace( (await AppRuntime.runPromise(SessionNs.Service.use((svc) => svc.create({})))).id, @@ -738,7 +738,7 @@ describe("workspace-old sync state", () => { const target = path.join(dir, "dedupe-local") await fs.mkdir(target, { recursive: true }) insertWorkspace(info) - registerAdaptor(Instance.project.id, type, localAdaptor(target).adaptor) + registerAdapter(Instance.project.id, type, localAdapter(target).adapter) attachSessionToWorkspace( (await AppRuntime.runPromise(SessionNs.Service.use((svc) => svc.create({})))).id, info.id, @@ -795,7 +795,7 @@ describe("workspace-old sync state", () => { const type = unique("remote-start") const info = workspaceInfo(Instance.project.id, type) insertWorkspace(info) - registerAdaptor(Instance.project.id, type, remoteAdaptor(`${url}/sync`).adaptor) + registerAdapter(Instance.project.id, type, remoteAdapter(`${url}/sync`).adapter) attachSessionToWorkspace((yield* sessionSvc.create({})).id, info.id) yield* workspace.startWorkspaceSyncing(Instance.project.id) @@ -850,7 +850,7 @@ describe("workspace-old sync state", () => { const type = unique("remote-connect-fail") const info = workspaceInfo(Instance.project.id, type) insertWorkspace(info) - registerAdaptor(Instance.project.id, type, remoteAdaptor(`${url}/failed`).adaptor) + registerAdapter(Instance.project.id, type, remoteAdapter(`${url}/failed`).adapter) attachSessionToWorkspace((yield* sessionSvc.create({})).id, info.id) yield* workspace.startWorkspaceSyncing(Instance.project.id) @@ -890,7 +890,7 @@ describe("workspace-old sync state", () => { const type = unique("remote-history-fail") const info = workspaceInfo(Instance.project.id, type) insertWorkspace(info) - registerAdaptor(Instance.project.id, type, remoteAdaptor(`${url}/history-failed`).adaptor) + registerAdapter(Instance.project.id, type, remoteAdapter(`${url}/history-failed`).adapter) attachSessionToWorkspace((yield* sessionSvc.create({})).id, info.id) yield* workspace.startWorkspaceSyncing(Instance.project.id) @@ -947,7 +947,7 @@ describe("workspace-old sync state", () => { const type = unique("history-replay") const info = workspaceInfo(Instance.project.id, type) insertWorkspace(info) - registerAdaptor(Instance.project.id, type, remoteAdaptor(`${url}/history`).adaptor) + registerAdapter(Instance.project.id, type, remoteAdapter(`${url}/history`).adapter) const session = yield* sessionSvc.create({ title: "before history" }) attachSessionToWorkspace(session.id, info.id) historySessionID = session.id @@ -1014,7 +1014,7 @@ describe("workspace-old sync state", () => { const type = unique("sse-forward") const info = workspaceInfo(Instance.project.id, type) insertWorkspace(info) - registerAdaptor(Instance.project.id, type, remoteAdaptor(`${url}/sse-forward`).adaptor) + registerAdapter(Instance.project.id, type, remoteAdapter(`${url}/sse-forward`).adapter) attachSessionToWorkspace((yield* sessionSvc.create({})).id, info.id) yield* workspace.startWorkspaceSyncing(Instance.project.id) @@ -1095,7 +1095,7 @@ describe("workspace-old sync state", () => { const type = unique("sse-sync") const info = workspaceInfo(Instance.project.id, type) insertWorkspace(info) - registerAdaptor(Instance.project.id, type, remoteAdaptor(`${url}/sse-sync`).adaptor) + registerAdapter(Instance.project.id, type, remoteAdapter(`${url}/sse-sync`).adapter) const session = yield* sessionSvc.create({ title: "before sse" }) attachSessionToWorkspace(session.id, info.id) sseSessionID = session.id @@ -1232,7 +1232,7 @@ describe("workspace-old sessionRestore", () => { const type = unique("restore-missing-session") const info = workspaceInfo(Instance.project.id, type, { directory: dir }) insertWorkspace(info) - registerAdaptor(Instance.project.id, type, localAdaptor(dir).adaptor) + registerAdapter(Instance.project.id, type, localAdapter(dir).adapter) await expect( restoreWorkspaceSession({ workspaceID: info.id, sessionID: SessionID.descending("ses_missing_restore") }), @@ -1273,13 +1273,13 @@ describe("workspace-old sessionRestore", () => { const type = unique("restore-remote") const info = workspaceInfo(Instance.project.id, type, { directory: dir }) insertWorkspace(info) - registerAdaptor( + registerAdapter( Instance.project.id, type, - remoteAdaptor(`${url}/restore/?ignored=1#hash`, { + remoteAdapter(`${url}/restore/?ignored=1#hash`, { directory: dir, headers: { authorization: "Bearer restore" }, - }).adaptor, + }).adapter, ) const session = yield* sessionSvc.create({ title: "restore remote" }) replaceSessionEvents(session.id, 24) @@ -1353,7 +1353,7 @@ describe("workspace-old sessionRestore", () => { const type = unique("restore-null-dir") const info = workspaceInfo(Instance.project.id, type, { directory: null }) insertWorkspace(info) - registerAdaptor(Instance.project.id, type, remoteAdaptor(`${url}/null-dir`, { directory: null }).adaptor) + registerAdapter(Instance.project.id, type, remoteAdapter(`${url}/null-dir`, { directory: null }).adapter) const session = yield* sessionSvc.create({ title: "null dir" }) replaceSessionEvents(session.id, 0) @@ -1397,7 +1397,7 @@ describe("workspace-old sessionRestore", () => { const type = unique("restore-remote-fail") const info = workspaceInfo(Instance.project.id, type, { directory: dir }) insertWorkspace(info) - registerAdaptor(Instance.project.id, type, remoteAdaptor(`${url}/fail`, { directory: dir }).adaptor) + registerAdapter(Instance.project.id, type, remoteAdapter(`${url}/fail`, { directory: dir }).adapter) const session = yield* sessionSvc.create({ title: "restore fail" }) replaceSessionEvents(session.id, 11) @@ -1437,7 +1437,7 @@ describe("workspace-old sessionRestore", () => { const type = unique("restore-local") const info = workspaceInfo(Instance.project.id, type, { directory: dir }) insertWorkspace(info) - registerAdaptor(Instance.project.id, type, localAdaptor(dir).adaptor) + registerAdapter(Instance.project.id, type, localAdapter(dir).adapter) const session = yield* sessionSvc.create({ title: "restore local" }) replaceSessionEvents(session.id, 20) @@ -1488,7 +1488,7 @@ describe("workspace-old sessionRestore", () => { const type = unique("restore-real-events") const info = workspaceInfo(Instance.project.id, type, { directory: dir }) insertWorkspace(info) - registerAdaptor(Instance.project.id, type, remoteAdaptor(`${url}/real`, { directory: dir }).adaptor) + registerAdapter(Instance.project.id, type, remoteAdapter(`${url}/real`, { directory: dir }).adapter) const session = yield* sessionSvc.create({ title: "real events" }) for (let i = 0; i < 3; i++) { const msg = yield* sessionSvc.updateMessage({ diff --git a/packages/opencode/test/plugin/workspace-adaptor.test.ts b/packages/opencode/test/plugin/workspace-adapter.test.ts similarity index 96% rename from packages/opencode/test/plugin/workspace-adaptor.test.ts rename to packages/opencode/test/plugin/workspace-adapter.test.ts index 677c004be4..9abf993d80 100644 --- a/packages/opencode/test/plugin/workspace-adaptor.test.ts +++ b/packages/opencode/test/plugin/workspace-adapter.test.ts @@ -34,7 +34,7 @@ afterAll(() => { }) describe("plugin.workspace", () => { - it.live("plugin can install a workspace adaptor", () => + it.live("plugin can install a workspace adapter", () => provideTmpdirInstance((dir) => Effect.gen(function* () { const type = `plug-${Math.random().toString(36).slice(2)}` @@ -48,7 +48,7 @@ describe("plugin.workspace", () => { "export default async ({ experimental_workspace }) => {", ` experimental_workspace.register(${JSON.stringify(type)}, {`, ' name: "plug",', - ' description: "plugin workspace adaptor",', + ' description: "plugin workspace adapter",', " configure(input) {", ` return { ...input, name: "plug", branch: "plug/main", directory: ${JSON.stringify(space)} }`, " },", diff --git a/packages/opencode/test/server/httpapi-instance-context.test.ts b/packages/opencode/test/server/httpapi-instance-context.test.ts index 28945f0213..9dea20dd66 100644 --- a/packages/opencode/test/server/httpapi-instance-context.test.ts +++ b/packages/opencode/test/server/httpapi-instance-context.test.ts @@ -7,8 +7,8 @@ import { HttpClient, HttpClientRequest, HttpRouter, HttpServerResponse } from "e import * as Socket from "effect/unstable/socket/Socket" import { mkdir } from "node:fs/promises" import path from "node:path" -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 { InstanceRef, WorkspaceRef } from "../../src/effect/instance-ref" import { Instance } from "../../src/project/instance" @@ -49,7 +49,7 @@ const instanceContextTestLayer = instanceRouterMiddleware .combine(workspaceRouterMiddleware) .layer.pipe(Layer.provide(Socket.layerWebSocketConstructorGlobal)) -const localAdaptor = (directory: string): WorkspaceAdaptor => ({ +const localAdapter = (directory: string): WorkspaceAdapter => ({ name: "Local Test", description: "Create a local test workspace", configure: (info) => ({ ...info, name: "local-test", directory }), @@ -63,7 +63,7 @@ const localAdaptor = (directory: string): WorkspaceAdaptor => ({ const createLocalWorkspace = (input: { projectID: Project.Info["id"]; type: string; directory: string }) => Effect.acquireRelease( Effect.gen(function* () { - registerAdaptor(input.projectID, input.type, localAdaptor(input.directory)) + registerAdapter(input.projectID, input.type, localAdapter(input.directory)) const workspace = yield* Workspace.Service return yield* workspace.create({ type: input.type, diff --git a/packages/opencode/test/server/httpapi-session.test.ts b/packages/opencode/test/server/httpapi-session.test.ts index 11e9d8b185..5f2af06f1e 100644 --- a/packages/opencode/test/server/httpapi-session.test.ts +++ b/packages/opencode/test/server/httpapi-session.test.ts @@ -3,8 +3,8 @@ import { mkdir } from "node:fs/promises" import path from "node:path" import { Effect } from "effect" 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 { PermissionID } from "../../src/permission/schema" import { ModelID, ProviderID } from "../../src/provider/schema" @@ -82,7 +82,7 @@ function createTextMessage(directory: string, sessionID: SessionID, text: string ) } -const localAdaptor = (directory: string): WorkspaceAdaptor => ({ +const localAdapter = (directory: string): WorkspaceAdapter => ({ name: "Local Test", description: "Create a local test workspace", configure: (info) => ({ ...info, name: "local-test", directory }), @@ -95,7 +95,7 @@ const localAdaptor = (directory: string): WorkspaceAdaptor => ({ const createLocalWorkspace = (input: { projectID: Project.Info["id"]; type: string; directory: string }) => Effect.gen(function* () { - registerAdaptor(input.projectID, input.type, localAdaptor(input.directory)) + registerAdapter(input.projectID, input.type, localAdapter(input.directory)) return yield* Workspace.Service.use((svc) => svc.create({ type: input.type, diff --git a/packages/opencode/test/server/httpapi-workspace-routing.test.ts b/packages/opencode/test/server/httpapi-workspace-routing.test.ts index 5d92635fbc..b0b276841d 100644 --- a/packages/opencode/test/server/httpapi-workspace-routing.test.ts +++ b/packages/opencode/test/server/httpapi-workspace-routing.test.ts @@ -15,9 +15,9 @@ import * as Socket from "effect/unstable/socket/Socket" import Http from "node:http" import { mkdir } from "node:fs/promises" import path from "node:path" -import { registerAdaptor } from "../../src/control-plane/adaptors" +import { registerAdapter } from "../../src/control-plane/adapters" import { WorkspaceID } from "../../src/control-plane/schema" -import type { WorkspaceAdaptor } from "../../src/control-plane/types" +import type { WorkspaceAdapter } from "../../src/control-plane/types" import { Workspace } from "../../src/control-plane/workspace" import { WorkspaceTable } from "../../src/control-plane/workspace.sql" import { Project } from "../../src/project/project" @@ -82,7 +82,7 @@ const listenAdditionalServer = (handler: TestHandler) => return HttpServer.formatAddress(server.address) }) -const localAdaptor = (directory: string): WorkspaceAdaptor => ({ +const localAdapter = (directory: string): WorkspaceAdapter => ({ name: "Local Test", description: "Create a local test workspace", configure: (info) => ({ ...info, name: "local-test", directory }), @@ -93,7 +93,7 @@ const localAdaptor = (directory: string): WorkspaceAdaptor => ({ target: () => ({ type: "local" as const, directory }), }) -const remoteAdaptor = (directory: string, url: string, headers?: HeadersInit): WorkspaceAdaptor => ({ +const remoteAdapter = (directory: string, url: string, headers?: HeadersInit): WorkspaceAdapter => ({ name: "Remote Test", description: "Create a remote test workspace", configure: (info) => ({ ...info, name: "remote-test", directory }), @@ -116,10 +116,10 @@ const syncResponse = (request: HttpServerRequest.HttpServerRequest) => { return undefined } -const createWorkspace = (input: { projectID: Project.Info["id"]; type: string; adaptor: WorkspaceAdaptor }) => +const createWorkspace = (input: { projectID: Project.Info["id"]; type: string; adapter: WorkspaceAdapter }) => Effect.acquireRelease( Effect.gen(function* () { - registerAdaptor(input.projectID, input.type, input.adaptor) + registerAdapter(input.projectID, input.type, input.adapter) const workspace = yield* Workspace.Service return yield* workspace.create({ type: input.type, @@ -144,14 +144,14 @@ const createRemoteWorkspace = (input: { createWorkspace({ projectID: input.projectID, type: input.type, - adaptor: remoteAdaptor(path.join(input.dir, `.${input.type}`), input.url, input.headers), + adapter: remoteAdapter(path.join(input.dir, `.${input.type}`), input.url, input.headers), }) const createLocalWorkspace = (input: { projectID: Project.Info["id"]; type: string; directory: string }) => createWorkspace({ projectID: input.projectID, type: input.type, - adaptor: localAdaptor(input.directory), + adapter: localAdapter(input.directory), }) const insertRemoteWorkspaceWithoutSync = (input: { @@ -162,7 +162,7 @@ const insertRemoteWorkspaceWithoutSync = (input: { }) => Effect.sync(() => { const id = WorkspaceID.ascending() - registerAdaptor(input.projectID, input.type, remoteAdaptor(path.join(input.dir, `.${input.type}`), input.url)) + registerAdapter(input.projectID, input.type, remoteAdapter(path.join(input.dir, `.${input.type}`), input.url)) Database.use((db) => db.insert(WorkspaceTable).values({ id, type: input.type, project_id: input.projectID }).run()) return id }) @@ -237,7 +237,7 @@ describe("HttpApi workspace routing middleware", () => { { status: 201, headers: { "x-remote": "yes" } }, ) }) - // The adaptor target tells the middleware where to proxy selected remote + // The adapter target tells the middleware where to proxy selected remote // workspace requests. Appending /probe to this base should produce // `${remoteUrl}/base/probe` on the fake remote server above. const workspace = yield* createRemoteWorkspace({ diff --git a/packages/opencode/test/server/httpapi-workspace.test.ts b/packages/opencode/test/server/httpapi-workspace.test.ts index 6a04833e35..e44a5ee3cd 100644 --- a/packages/opencode/test/server/httpapi-workspace.test.ts +++ b/packages/opencode/test/server/httpapi-workspace.test.ts @@ -4,8 +4,8 @@ import { mkdir } from "node:fs/promises" import path from "node:path" import { Effect, Layer } from "effect" 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 { WorkspacePaths } from "../../src/server/routes/instance/httpapi/groups/workspace" import { Session } from "@/session/session" @@ -36,7 +36,7 @@ function request(path: string, directory: string, init: RequestInit = {}) { }) } -function localAdaptor(directory: string): WorkspaceAdaptor { +function localAdapter(directory: string): WorkspaceAdapter { return { name: "Local Test", description: "Create a local test workspace", @@ -60,7 +60,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 { name: "Remote Test", description: "Create a remote test workspace", @@ -137,14 +137,14 @@ describe("workspace HttpApi", () => { Effect.gen(function* () { const dir = yield* tmpdirScoped({ git: true }) - const [adaptors, workspaces, status] = yield* Effect.all([ - request(WorkspacePaths.adaptors, dir), + const [adapters, workspaces, status] = yield* Effect.all([ + request(WorkspacePaths.adapters, dir), request(WorkspacePaths.list, dir), request(WorkspacePaths.status, dir), ]) - expect(adaptors.status).toBe(200) - expect(yield* Effect.promise(() => adaptors.json())).toContainEqual({ + expect(adapters.status).toBe(200) + expect(yield* Effect.promise(() => adapters.json())).toContainEqual({ type: "worktree", name: "Worktree", description: "Create a git worktree", @@ -163,7 +163,7 @@ describe("workspace HttpApi", () => { Flag.OPENCODE_EXPERIMENTAL_WORKSPACES = true const dir = yield* tmpdirScoped({ git: true }) const project = yield* Project.use.fromDirectory(dir) - registerAdaptor(project.project.id, "local-test", localAdaptor(path.join(dir, ".workspace"))) + registerAdapter(project.project.id, "local-test", localAdapter(path.join(dir, ".workspace"))) const created = yield* request(WorkspacePaths.list, dir, { method: "POST", @@ -201,7 +201,7 @@ describe("workspace HttpApi", () => { const dir = yield* tmpdirScoped({ git: true }) const workspaceDir = path.join(dir, ".workspace-local") const project = yield* Project.use.fromDirectory(dir) - registerAdaptor(project.project.id, "local-target", localAdaptor(workspaceDir)) + registerAdapter(project.project.id, "local-target", localAdapter(workspaceDir)) const created = yield* request(WorkspacePaths.list, dir, { method: "POST", headers: { "content-type": "application/json" }, @@ -250,10 +250,10 @@ describe("workspace HttpApi", () => { }) const project = yield* Project.use.fromDirectory(dir) - registerAdaptor( + registerAdapter( project.project.id, "remote-target", - remoteAdaptor(path.join(dir, ".remote"), `http://127.0.0.1:${remote.port}/base`, { + remoteAdapter(path.join(dir, ".remote"), `http://127.0.0.1:${remote.port}/base`, { "x-target-auth": "secret", }), ) @@ -319,10 +319,10 @@ describe("workspace HttpApi", () => { }) const project = yield* Project.use.fromDirectory(dir) - registerAdaptor( + registerAdapter( project.project.id, "remote-session-target", - remoteAdaptor(path.join(dir, ".remote-session"), `http://127.0.0.1:${remote.port}/base`), + remoteAdapter(path.join(dir, ".remote-session"), `http://127.0.0.1:${remote.port}/base`), ) const created = yield* request(WorkspacePaths.list, dir, { method: "POST", diff --git a/packages/plugin/src/index.ts b/packages/plugin/src/index.ts index 71a3278cbb..2e96dd9801 100644 --- a/packages/plugin/src/index.ts +++ b/packages/plugin/src/index.ts @@ -45,7 +45,7 @@ export type WorkspaceTarget = headers?: HeadersInit } -export type WorkspaceAdaptor = { +export type WorkspaceAdapter = { name: string description: string configure(config: WorkspaceInfo): WorkspaceInfo | Promise @@ -60,7 +60,7 @@ export type PluginInput = { directory: string worktree: string experimental_workspace: { - register(type: string, adaptor: WorkspaceAdaptor): void + register(type: string, adapter: WorkspaceAdapter): void } serverUrl: URL $: BunShell diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index 2da7c865d7..67261d7499 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -29,7 +29,7 @@ import type { ExperimentalConsoleSwitchOrgResponses, ExperimentalResourceListResponses, ExperimentalSessionListResponses, - ExperimentalWorkspaceAdaptorListResponses, + ExperimentalWorkspaceAdapterListResponses, ExperimentalWorkspaceCreateErrors, ExperimentalWorkspaceCreateResponses, 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( parameters?: { @@ -536,8 +536,8 @@ export class Adaptor extends HeyApiClient { }, ], ) - return (options?.client ?? this.client).get({ - url: "/experimental/workspace/adaptor", + return (options?.client ?? this.client).get({ + url: "/experimental/workspace/adapter", ...options, ...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 })) } } diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index 9bb1e50aac..b925ec6096 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -2430,19 +2430,19 @@ export type AppLogResponses = { export type AppLogResponse = AppLogResponses[keyof AppLogResponses] -export type ExperimentalWorkspaceAdaptorListData = { +export type ExperimentalWorkspaceAdapterListData = { body?: never path?: never query?: { directory?: string workspace?: string } - url: "/experimental/workspace/adaptor" + url: "/experimental/workspace/adapter" } -export type ExperimentalWorkspaceAdaptorListResponses = { +export type ExperimentalWorkspaceAdapterListResponses = { /** - * Workspace adaptors + * Workspace adapters */ 200: Array<{ type: string @@ -2451,8 +2451,8 @@ export type ExperimentalWorkspaceAdaptorListResponses = { }> } -export type ExperimentalWorkspaceAdaptorListResponse = - ExperimentalWorkspaceAdaptorListResponses[keyof ExperimentalWorkspaceAdaptorListResponses] +export type ExperimentalWorkspaceAdapterListResponse = + ExperimentalWorkspaceAdapterListResponses[keyof ExperimentalWorkspaceAdapterListResponses] export type ExperimentalWorkspaceListData = { body?: never diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index 22e66c7d16..cfd8277a3b 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -415,9 +415,9 @@ ] } }, - "/experimental/workspace/adaptor": { + "/experimental/workspace/adapter": { "get": { - "operationId": "experimental.workspace.adaptor.list", + "operationId": "experimental.workspace.adapter.list", "parameters": [ { "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": { "200": { - "description": "Workspace adaptors", + "description": "Workspace adapters", "content": { "application/json": { "schema": { @@ -466,7 +466,7 @@ "x-codeSamples": [ { "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})" } ] }