From e57d0c2fee02199c7ee2f38a968a5d06df55b622 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Tue, 28 Apr 2026 09:23:54 -0400 Subject: [PATCH] fix(httpapi): document tui bad request responses Document legacy 400 bad-request responses on TUI Effect HttpApi payload-validation endpoints and cover them with OpenAPI parity tests. --- .../src/server/routes/instance/httpapi/tui.ts | 5 ++++- packages/opencode/test/server/httpapi-tui.test.ts | 13 ++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/server/routes/instance/httpapi/tui.ts b/packages/opencode/src/server/routes/instance/httpapi/tui.ts index c5695cf077..36004ea250 100644 --- a/packages/opencode/src/server/routes/instance/httpapi/tui.ts +++ b/packages/opencode/src/server/routes/instance/httpapi/tui.ts @@ -61,6 +61,7 @@ export const TuiApi = HttpApi.make("tui") HttpApiEndpoint.post("appendPrompt", TuiPaths.appendPrompt, { payload: TuiEvent.PromptAppend.properties, success: Schema.Boolean, + error: HttpApiError.BadRequest, }).annotateMerge( OpenApi.annotations({ identifier: "tui.appendPrompt", @@ -113,6 +114,7 @@ export const TuiApi = HttpApi.make("tui") HttpApiEndpoint.post("executeCommand", TuiPaths.executeCommand, { payload: CommandPayload, success: Schema.Boolean, + error: HttpApiError.BadRequest, }).annotateMerge( OpenApi.annotations({ identifier: "tui.executeCommand", @@ -133,6 +135,7 @@ export const TuiApi = HttpApi.make("tui") HttpApiEndpoint.post("publish", TuiPaths.publish, { payload: TuiPublishPayload, success: Schema.Boolean, + error: HttpApiError.BadRequest, }).annotateMerge( OpenApi.annotations({ identifier: "tui.publish", @@ -143,7 +146,7 @@ export const TuiApi = HttpApi.make("tui") HttpApiEndpoint.post("selectSession", TuiPaths.selectSession, { payload: TuiEvent.SessionSelect.properties, success: Schema.Boolean, - error: HttpApiError.NotFound, + error: [HttpApiError.BadRequest, HttpApiError.NotFound], }).annotateMerge( OpenApi.annotations({ identifier: "tui.selectSession", diff --git a/packages/opencode/test/server/httpapi-tui.test.ts b/packages/opencode/test/server/httpapi-tui.test.ts index f47d11c670..e6364fc88d 100644 --- a/packages/opencode/test/server/httpapi-tui.test.ts +++ b/packages/opencode/test/server/httpapi-tui.test.ts @@ -5,9 +5,11 @@ import { Flag } from "@opencode-ai/core/flag/flag" import { SessionID } from "../../src/session/schema" import { Instance } from "../../src/project/instance" import { InstanceRoutes } from "../../src/server/routes/instance" -import { TuiPaths } from "../../src/server/routes/instance/httpapi/tui" +import { TuiApi, TuiPaths } from "../../src/server/routes/instance/httpapi/tui" import { callTui } from "../../src/server/routes/instance/tui" +import { Server } from "../../src/server/server" import * as Log from "@opencode-ai/core/util/log" +import { OpenApi } from "effect/unstable/httpapi" import { resetDatabase } from "../fixture/db" import { tmpdir } from "../fixture/fixture" @@ -38,6 +40,15 @@ afterEach(async () => { }) describe("tui HttpApi bridge", () => { + test("documents legacy bad request responses", async () => { + const legacy = await Server.openapi() + const effect = OpenApi.fromApi(TuiApi) + for (const path of [TuiPaths.appendPrompt, TuiPaths.executeCommand, TuiPaths.publish, TuiPaths.selectSession]) { + expect(legacy.paths[path].post?.responses?.[400]).toBeDefined() + expect(effect.paths[path].post?.responses?.[400]).toBeDefined() + } + }) + test("serves TUI command and event routes through experimental Effect routes", async () => { await using tmp = await tmpdir({ git: true, config: { formatter: false, lsp: false } }) const headers = { "x-opencode-directory": tmp.path }