mini migrate to v2 (#35526)
This commit is contained in:
parent
fb75ea2cf6
commit
32cf36de9d
93 changed files with 2244 additions and 2333 deletions
|
|
@ -12,6 +12,7 @@
|
|||
"typecheck": "tsgo --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@effect/platform-node": "catalog:",
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
"@opencode-ai/protocol": "workspace:*",
|
||||
"@opencode-ai/simulation": "workspace:*",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
||||
import { Effect } from "effect"
|
||||
import { HttpApiBuilder } from "effect/unstable/httpapi"
|
||||
import { Api } from "../api"
|
||||
|
||||
export const HealthHandler = HttpApiBuilder.group(Api, "server.health", (handlers) =>
|
||||
handlers.handle("health.get", () => Effect.succeed({ healthy: true as const })),
|
||||
handlers.handle("health.get", () =>
|
||||
Effect.succeed({ healthy: true as const, version: InstallationVersion, pid: process.pid }),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
64
packages/server/src/process.ts
Normal file
64
packages/server/src/process.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
export * as ServerProcess from "./process"
|
||||
|
||||
import { NodeHttpClient, NodeHttpServer } from "@effect/platform-node"
|
||||
import { Credential } from "@opencode-ai/core/credential"
|
||||
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { PermissionSaved } from "@opencode-ai/core/permission/saved"
|
||||
import { Project } from "@opencode-ai/core/project"
|
||||
import { HealthGroup } from "@opencode-ai/protocol/groups/health"
|
||||
import { Context, Effect, Layer, Option } from "effect"
|
||||
import { HttpClient, HttpClientRequest, HttpRouter, HttpServer } from "effect/unstable/http"
|
||||
import { HttpApi, HttpApiClient } from "effect/unstable/httpapi"
|
||||
import { createServer } from "node:http"
|
||||
import { ServerAuth } from "./auth"
|
||||
import { createRoutes } from "./routes"
|
||||
|
||||
export type Options = {
|
||||
readonly hostname: string
|
||||
readonly port: Option.Option<number>
|
||||
readonly password: string
|
||||
}
|
||||
|
||||
const ReadinessApi = HttpApi.make("readiness").add(HealthGroup)
|
||||
|
||||
export const start = Effect.fn("ServerProcess.start")(function* (options: Options) {
|
||||
if (!options.password) return yield* Effect.fail(new Error("Missing server password"))
|
||||
const address = yield* listen(options)
|
||||
yield* Effect.gen(function* () {
|
||||
const client = yield* HttpApiClient.make(ReadinessApi, {
|
||||
baseUrl: HttpServer.formatAddress(address),
|
||||
transformClient: HttpClient.mapRequest((request) =>
|
||||
HttpClientRequest.setHeader(
|
||||
request,
|
||||
"authorization",
|
||||
ServerAuth.header({ username: "opencode", password: options.password }) ?? "",
|
||||
),
|
||||
),
|
||||
})
|
||||
yield* client["server.health"]["health.get"]({})
|
||||
}).pipe(Effect.provide(NodeHttpClient.layerNodeHttp))
|
||||
return address
|
||||
})
|
||||
|
||||
function listen(options: Options) {
|
||||
if (Option.isSome(options.port)) return bind(options.hostname, options.port.value, options.password)
|
||||
const next = (port: number): ReturnType<typeof bind> =>
|
||||
bind(options.hostname, port, options.password).pipe(
|
||||
Effect.catch((error) => (port === 65_535 ? Effect.fail(error) : next(port + 1))),
|
||||
)
|
||||
return next(4096)
|
||||
}
|
||||
|
||||
function bind(hostname: string, port: number, password: string) {
|
||||
const server = createServer()
|
||||
return Layer.build(
|
||||
HttpRouter.serve(createRoutes(password), { disableListenLog: true }).pipe(
|
||||
Layer.provideMerge(NodeHttpServer.layer(() => server, { port, host: hostname })),
|
||||
Layer.provide(AppNodeBuilder.build(LayerNode.group([Credential.node, PermissionSaved.node, Project.node]))),
|
||||
),
|
||||
).pipe(
|
||||
Effect.tap(() => Effect.addFinalizer(() => Effect.sync(() => server.closeAllConnections()))),
|
||||
Effect.map((context) => Context.get(context, HttpServer.HttpServer).address),
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue