Prepare Effect HttpApi backend parity (#24853)

This commit is contained in:
Kit Langton
2026-04-29 09:34:50 -04:00
committed by GitHub
parent 65ba1f6c13
commit 6015084fa2
98 changed files with 4290 additions and 2766 deletions
@@ -1,4 +1,4 @@
import { afterEach, describe, expect, test } from "bun:test"
import { afterEach, describe, expect, mock, spyOn, test } from "bun:test"
import { mkdir } from "node:fs/promises"
import path from "node:path"
import { Effect } from "effect"
@@ -6,13 +6,14 @@ import { Flag } from "@opencode-ai/core/flag/flag"
import { registerAdaptor } from "../../src/control-plane/adaptors"
import type { WorkspaceAdaptor } from "../../src/control-plane/types"
import { Workspace } from "../../src/control-plane/workspace"
import { WorkspacePaths } from "../../src/server/routes/instance/httpapi/workspace"
import { WorkspacePaths } from "../../src/server/routes/instance/httpapi/groups/workspace"
import { Session } from "@/session/session"
import * as Log from "@opencode-ai/core/util/log"
import { Server } from "../../src/server/server"
import { resetDatabase } from "../fixture/db"
import { tmpdir } from "../fixture/fixture"
import { Instance } from "../../src/project/instance"
import { InstancePaths } from "../../src/server/routes/instance/httpapi/groups/instance"
void Log.init({ print: false })
@@ -54,7 +55,41 @@ function localAdaptor(directory: string): WorkspaceAdaptor {
}
}
function remoteAdaptor(directory: string, url: string): WorkspaceAdaptor {
return {
name: "Remote Test",
description: "Create a remote test workspace",
configure(info) {
return {
...info,
name: "remote-test",
directory,
}
},
async create() {
await mkdir(directory, { recursive: true })
},
async remove() {},
target() {
return {
type: "remote" as const,
url,
}
},
}
}
function eventStreamResponse() {
return new Response(new ReadableStream({ start() {} }), {
status: 200,
headers: {
"content-type": "text/event-stream",
},
})
}
afterEach(async () => {
mock.restore()
Flag.OPENCODE_EXPERIMENTAL_WORKSPACES = originalWorkspaces
Flag.OPENCODE_EXPERIMENTAL_HTTPAPI = originalHttpApi
await Instance.disposeAll()
@@ -125,4 +160,81 @@ describe("workspace HttpApi", () => {
expect(listed.status).toBe(200)
expect(await listed.json()).toEqual([])
})
test("routes local workspace requests through the workspace target directory", async () => {
Flag.OPENCODE_EXPERIMENTAL_WORKSPACES = true
await using tmp = await tmpdir({ git: true })
const workspaceDir = path.join(tmp.path, ".workspace-local")
const workspace = await Instance.provide({
directory: tmp.path,
fn: async () => {
registerAdaptor(Instance.project.id, "local-target", localAdaptor(workspaceDir))
return Workspace.create({
type: "local-target",
branch: null,
extra: null,
projectID: Instance.project.id,
})
},
})
const url = new URL(`http://localhost${InstancePaths.path}`)
url.searchParams.set("workspace", workspace.id)
try {
const response = await request(url.toString(), tmp.path)
expect(response.status).toBe(200)
expect(await response.json()).toMatchObject({ directory: workspaceDir })
} finally {
await Workspace.remove(workspace.id)
}
})
test("proxies remote workspace HTTP requests", async () => {
Flag.OPENCODE_EXPERIMENTAL_WORKSPACES = true
await using tmp = await tmpdir({ git: true })
const proxied: string[] = []
const rawFetch = globalThis.fetch
spyOn(globalThis, "fetch").mockImplementation(
Object.assign(
async (input: URL | RequestInfo, init?: BunFetchRequestInit | RequestInit) => {
const url = new URL(typeof input === "string" || input instanceof URL ? input : input.url)
if (url.pathname === "/base/global/event") return eventStreamResponse()
if (url.pathname === "/base/sync/history") return Response.json([])
proxied.push(url.toString())
return Response.json({ proxied: true, path: url.pathname, workspace: url.searchParams.get("workspace") })
},
{
preconnect: rawFetch.preconnect?.bind(rawFetch),
},
) as typeof globalThis.fetch,
)
const workspace = await Instance.provide({
directory: tmp.path,
fn: async () => {
registerAdaptor(Instance.project.id, "remote-target", remoteAdaptor(path.join(tmp.path, ".remote"), "https://remote.test/base"))
return Workspace.create({
type: "remote-target",
branch: null,
extra: null,
projectID: Instance.project.id,
})
},
})
const url = new URL(`http://localhost${InstancePaths.path}`)
url.searchParams.set("workspace", workspace.id)
try {
const response = await request(url.toString(), tmp.path)
expect(response.status).toBe(200)
expect(await response.json()).toEqual({ proxied: true, path: "/base/path", workspace: null })
expect(proxied).toEqual(["https://remote.test/base/path"])
} finally {
await Workspace.remove(workspace.id)
}
})
})