mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-16 17:42:30 +00:00
74 lines
2.9 KiB
TypeScript
74 lines
2.9 KiB
TypeScript
import { NodeHttpServer } from "@effect/platform-node"
|
|
import { Session } from "@/session/session"
|
|
import { describe, expect } from "bun:test"
|
|
import { Effect, Layer } from "effect"
|
|
import { HttpClient, HttpClientRequest, HttpRouter } from "effect/unstable/http"
|
|
import { HttpApi, HttpApiBuilder } from "effect/unstable/httpapi"
|
|
import { McpApi, McpPaths } from "../../src/server/routes/instance/httpapi/groups/mcp"
|
|
import { Authorization } from "../../src/server/routes/instance/httpapi/middleware/authorization"
|
|
import { InstanceContextMiddleware } from "../../src/server/routes/instance/httpapi/middleware/instance-context"
|
|
import {
|
|
WorkspaceRouteContext,
|
|
WorkspaceRoutingMiddleware,
|
|
} from "../../src/server/routes/instance/httpapi/middleware/workspace-routing"
|
|
import { testEffect } from "../lib/effect"
|
|
|
|
const TestHttpApi = HttpApi.make("opencode-instance").addHttpApi(McpApi)
|
|
const fakeSession = Layer.mock(Session.Service)({})
|
|
const testMcpHandlers = HttpApiBuilder.group(TestHttpApi, "mcp", (handlers) =>
|
|
Effect.succeed(
|
|
handlers
|
|
.handle("status", () => Effect.die("unexpected MCP status"))
|
|
.handle("add", () => Effect.die("unexpected MCP add"))
|
|
.handle("authStart", () =>
|
|
Effect.succeed({ authorizationUrl: "https://auth.example/start", oauthState: "state-123" }),
|
|
)
|
|
.handle("authCallback", () => Effect.die("unexpected MCP authCallback"))
|
|
.handle("authAuthenticate", () => Effect.die("unexpected MCP authAuthenticate"))
|
|
.handle("authRemove", () => Effect.die("unexpected MCP authRemove"))
|
|
.handle("connect", () => Effect.die("unexpected MCP connect"))
|
|
.handle("disconnect", () => Effect.die("unexpected MCP disconnect")),
|
|
),
|
|
)
|
|
|
|
const passthroughAuthorization = Layer.succeed(
|
|
Authorization,
|
|
Authorization.of((effect) => effect),
|
|
)
|
|
|
|
const passthroughInstanceContext = Layer.succeed(
|
|
InstanceContextMiddleware,
|
|
InstanceContextMiddleware.of((effect) => effect),
|
|
)
|
|
|
|
const testWorkspaceRouting = Layer.succeed(
|
|
WorkspaceRoutingMiddleware,
|
|
WorkspaceRoutingMiddleware.of((effect) =>
|
|
effect.pipe(Effect.provideService(WorkspaceRouteContext, WorkspaceRouteContext.of({ directory: process.cwd() }))),
|
|
),
|
|
)
|
|
|
|
const it = testEffect(
|
|
HttpRouter.serve(
|
|
HttpApiBuilder.layer(TestHttpApi).pipe(
|
|
Layer.provide(testMcpHandlers),
|
|
Layer.provide([passthroughAuthorization, passthroughInstanceContext, testWorkspaceRouting, fakeSession]),
|
|
),
|
|
{ disableListenLog: true, disableLogger: true },
|
|
).pipe(Layer.provideMerge(NodeHttpServer.layerTest)),
|
|
)
|
|
|
|
describe("mcp HttpApi OAuth", () => {
|
|
it.live("preserves oauth state when starting OAuth", () =>
|
|
Effect.gen(function* () {
|
|
const response = yield* HttpClientRequest.post(McpPaths.auth.replace(":name", "demo")).pipe(HttpClient.execute)
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(yield* response.json).toEqual({
|
|
authorizationUrl: "https://auth.example/start",
|
|
oauthState: "state-123",
|
|
})
|
|
}),
|
|
)
|
|
})
|