refactor(server): remove dead PtyEnvironment service and simplify route handlers (#57992)

This commit is contained in:
Aiden Cline 2026-10-22 10:48:03 -05:00 • committed by GitHub
parent f8d3f34d3a
commit 080e92d40a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 27 additions and 100 deletions

View file

@ -15,15 +15,7 @@ export const McpHandler = HttpApiBuilder.group(Api, "server.mcp", (handlers) =>
"mcp.list",
Effect.fn(function* () {
const service = yield* Mcp.Service
return yield* response(
service
.servers()
.pipe(
Effect.map((servers) =>
servers.map((info) => ({ name: info.name, status: info.status, integrationID: info.integrationID })),
),
),
)
return yield* response(service.servers())
}),
)
.handle(

View file

@ -1,6 +1,6 @@
import { SessionMessage } from "@opencode/core/session/message"
import { Session } from "@opencode/core/session"
import { Effect, Schema } from "effect"
import { Effect, Option, Schema } from "effect"
import { HttpApiBuilder } from "effect/http-api"
import { Api } from "../api"
import { InvalidCursorError } from "@opencode/protocol/errors"
@ -14,14 +14,14 @@ const Cursor = Schema.Struct({
direction: Schema.Union([Schema.Literal("previous"), Schema.Literal("next")]),
})
const decodeCursor = Schema.decodeUnknownSync(Cursor)
const decodeCursor = Schema.decodeUnknownOption(Schema.fromJsonString(Cursor))
const cursor = {
encode(message: SessionMessage.Info, order: "asc" | "desc", direction: "previous" | "next") {
return Buffer.from(JSON.stringify({ id: message.id, order, direction })).toString("base64url")
},
decode(input: string) {
return decodeCursor(JSON.parse(Buffer.from(input, "base64url").toString("utf8")))
return decodeCursor(Buffer.from(input, "base64url").toString("utf8"))
},
}
@ -34,10 +34,10 @@ export const MessageHandler = HttpApiBuilder.group(Api, "server.message", (handl
Effect.fn(function* (ctx) {
if (ctx.query.cursor && ctx.query.order !== undefined)
return yield* new InvalidCursorError({ message: "Cursor cannot be combined with order" })
const decoded = yield* Effect.try({
try: () => (ctx.query.cursor ? cursor.decode(ctx.query.cursor) : undefined),
catch: () => new InvalidCursorError({ message: "Invalid cursor" }),
})
const decoded = ctx.query.cursor
? Option.getOrUndefined(cursor.decode(ctx.query.cursor)) ??
(yield* new InvalidCursorError({ message: "Invalid cursor" }))
: undefined
const order = decoded?.order ?? ctx.query.order ?? "desc"
const messages = yield* session
.messages({

View file

@ -16,20 +16,15 @@ import {
PTY_CONNECT_TOKEN_HEADER_VALUE,
} from "@opencode/protocol/groups/pty"
import { locationErrors, requestRef, response } from "../location"
import { PtyEnvironment } from "../pty-environment"
import { type Outbound, runPtySocket } from "./pty-socket"
const ticketScope = Effect.gen(function* () {
const location = yield* Location.Service
return { directory: location.directory as string, workspaceID: location.workspaceID }
})
const notFound = (ptyID: Pty.ID) => new PtyNotFoundError({ ptyID, message: `PTY session not found: ${ptyID}` })
export const PtyHandler = HttpApiBuilder.group(Api, "server.pty", (handlers) =>
Effect.gen(function* () {
const locations = yield* LocationServiceMap.Service
const tickets = yield* PtyTicket.Service
const cors = yield* CorsConfig
const environment = yield* PtyEnvironment.Service
return handlers
.handle(
@ -44,16 +39,10 @@ export const PtyHandler = HttpApiBuilder.group(Api, "server.pty", (handlers) =>
Effect.fn(function* (ctx) {
const pty = yield* Pty.Service
const location = yield* Location.Service
const cwd = ctx.payload.cwd || location.directory
return yield* response(
pty.create({
...ctx.payload,
args: ctx.payload.args ? [...ctx.payload.args] : undefined,
cwd,
env: {
...ctx.payload.env,
...(yield* environment.get({ directory: location.directory, cwd })),
},
cwd: ctx.payload.cwd || location.directory,
}),
)
}),
@ -63,16 +52,7 @@ export const PtyHandler = HttpApiBuilder.group(Api, "server.pty", (handlers) =>
Effect.fn(function* (ctx) {
const pty = yield* Pty.Service
return yield* response(
pty.get(ctx.params.ptyID).pipe(
Effect.catchTag(
"Pty.NotFoundError",
() =>
new PtyNotFoundError({
ptyID: ctx.params.ptyID,
message: `PTY session not found: ${ctx.params.ptyID}`,
}),
),
),
pty.get(ctx.params.ptyID).pipe(Effect.catchTag("Pty.NotFoundError", () => notFound(ctx.params.ptyID))),
)
}),
)
@ -82,20 +62,8 @@ export const PtyHandler = HttpApiBuilder.group(Api, "server.pty", (handlers) =>
const pty = yield* Pty.Service
return yield* response(
pty
.update(ctx.params.ptyID, {
...ctx.payload,
size: ctx.payload.size ? { ...ctx.payload.size } : undefined,
})
.pipe(
Effect.catchTag(
"Pty.NotFoundError",
() =>
new PtyNotFoundError({
ptyID: ctx.params.ptyID,
message: `PTY session not found: ${ctx.params.ptyID}`,
}),
),
),
.update(ctx.params.ptyID, ctx.payload)
.pipe(Effect.catchTag("Pty.NotFoundError", () => notFound(ctx.params.ptyID))),
)
}),
)
@ -103,16 +71,9 @@ export const PtyHandler = HttpApiBuilder.group(Api, "server.pty", (handlers) =>
"pty.remove",
Effect.fn(function* (ctx) {
const pty = yield* Pty.Service
yield* pty.remove(ctx.params.ptyID).pipe(
Effect.catchTag(
"Pty.NotFoundError",
() =>
new PtyNotFoundError({
ptyID: ctx.params.ptyID,
message: `PTY session not found: ${ctx.params.ptyID}`,
}),
),
)
yield* pty
.remove(ctx.params.ptyID)
.pipe(Effect.catchTag("Pty.NotFoundError", () => notFound(ctx.params.ptyID)))
return HttpApiSchema.NoContent.make()
}),
)
@ -128,17 +89,15 @@ export const PtyHandler = HttpApiBuilder.group(Api, "server.pty", (handlers) =>
)
return yield* new ForbiddenError({ message: "Invalid PTY connect token request" })
const pty = yield* Pty.Service
yield* pty.get(ctx.params.ptyID).pipe(
Effect.catchTag(
"Pty.NotFoundError",
() =>
new PtyNotFoundError({
ptyID: ctx.params.ptyID,
message: `PTY session not found: ${ctx.params.ptyID}`,
}),
),
const location = yield* Location.Service
yield* pty.get(ctx.params.ptyID).pipe(Effect.catchTag("Pty.NotFoundError", () => notFound(ctx.params.ptyID)))
return yield* response(
tickets.issue({
ptyID: ctx.params.ptyID,
directory: location.directory,
workspaceID: location.workspaceID,
}),
)
return yield* response(tickets.issue({ ptyID: ctx.params.ptyID, ...(yield* ticketScope) }))
}),
)
.handleRaw(

View file

@ -26,10 +26,9 @@ export const WorktreeHandler = HttpApiBuilder.group(Api, "server.worktree", (han
function badRequest<A, R>(effect: Effect.Effect<A, Worktree.Error, R>) {
return effect.pipe(
Effect.catchTag("Project.NotFoundError", missingProject),
Effect.mapError((error) =>
error instanceof ProjectNotFoundError
? error
error._tag === "Project.NotFoundError"
? missingProject(error)
: new WorktreeError({
name: "WorktreeError",
data: {
@ -45,9 +44,7 @@ function badRequest<A, R>(effect: Effect.Effect<A, Worktree.Error, R>) {
}
function missingProject(error: Project.NotFoundError) {
return Effect.fail(
new ProjectNotFoundError({ projectID: error.projectID, message: `Project not found: ${error.projectID}` }),
)
return new ProjectNotFoundError({ projectID: error.projectID, message: `Project not found: ${error.projectID}` })
}
function message(error: Exclude<Worktree.Error, Project.NotFoundError>) {

View file

@ -1,19 +0,0 @@
export * as PtyEnvironment from "./pty-environment"
import { Context, Effect, Layer } from "effect"
import { makeGlobalNode } from "@opencode/util/effect/app-node"
export interface Interface {
readonly get: (input: { directory: string; cwd: string }) => Effect.Effect<Record<string, string>>
}
export class Service extends Context.Service<Service, Interface>()("@opencode/ServerPtyEnvironment") {}
export const layer = Layer.succeed(
Service,
Service.of({
get: () => Effect.succeed({}),
}),
)
export const node = makeGlobalNode({ service: Service, layer, deps: [] })

View file

@ -41,7 +41,6 @@ import { CorsConfig } from "./cors"
import { handlers } from "./handlers"
import { authorizationLayer } from "./middleware/authorization"
import { schemaErrorLayer } from "./middleware/schema-error"
import { PtyEnvironment } from "./pty-environment"
import { ServerPairing } from "./pairing"
import { layer } from "./location"
import { formLocationLayer } from "./middleware/form-location"
@ -69,7 +68,6 @@ const applicationServiceNodes = [
PersistentPty.node,
Credential.node,
WellKnown.node,
PtyEnvironment.node,
ServerPairing.node,
LocationServiceMap.node,
LocationActivity.node,