fix(httpapi): model optional worktree payload as no content (#29246)

This commit is contained in:
Kit Langton
2026-05-25 15:57:12 -04:00
committed by GitHub
parent a99ebd1d65
commit b46cec2a7d
3 changed files with 26 additions and 4 deletions

View File

@@ -5,7 +5,7 @@ import { Session } from "@/session/session"
import { Worktree } from "@/worktree" import { Worktree } from "@/worktree"
import { NonNegativeInt } from "@opencode-ai/core/schema" import { NonNegativeInt } from "@opencode-ai/core/schema"
import { Schema } from "effect" import { Schema } from "effect"
import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from "effect/unstable/httpapi" import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi"
import { Authorization } from "../middleware/authorization" import { Authorization } from "../middleware/authorization"
import { InstanceContextMiddleware } from "../middleware/instance-context" import { InstanceContextMiddleware } from "../middleware/instance-context"
import { import {
@@ -168,7 +168,7 @@ export const ExperimentalApi = HttpApi.make("experimental")
HttpApiEndpoint.post("worktreeCreate", ExperimentalPaths.worktree, { HttpApiEndpoint.post("worktreeCreate", ExperimentalPaths.worktree, {
disableCodecs: true, disableCodecs: true,
query: WorkspaceRoutingQuery, query: WorkspaceRoutingQuery,
payload: Schema.UndefinedOr(Worktree.CreateInput), payload: [HttpApiSchema.NoContent, Worktree.CreateInput],
success: described(Worktree.Info, "Worktree created"), success: described(Worktree.Info, "Worktree created"),
error: WorktreeApiError, error: WorktreeApiError,
}).annotateMerge( }).annotateMerge(

View File

@@ -104,9 +104,9 @@ export const experimentalHandlers = HttpApiBuilder.group(InstanceHttpApi, "exper
}) })
const worktreeCreate = Effect.fn("ExperimentalHttpApi.worktreeCreate")(function* (ctx: { const worktreeCreate = Effect.fn("ExperimentalHttpApi.worktreeCreate")(function* (ctx: {
payload: Worktree.CreateInput | undefined payload: typeof Worktree.CreateInput.Type | void
}) { }) {
return yield* mapWorktreeError(worktreeSvc.create(ctx.payload)) return yield* mapWorktreeError(worktreeSvc.create(ctx.payload ?? undefined))
}) })
const worktreeRemove = Effect.fn("ExperimentalHttpApi.worktreeRemove")(function* (input: { const worktreeRemove = Effect.fn("ExperimentalHttpApi.worktreeRemove")(function* (input: {

View File

@@ -228,6 +228,28 @@ describe("worktree endpoint reproduction", () => {
{ git: true }, { git: true },
) )
worktreeTest(
"direct HttpApi worktree create rejects explicit null payload",
() =>
Effect.gen(function* () {
const test = yield* TestInstance
const server = yield* serverScoped()
const response = yield* request(
server,
`${ExperimentalPaths.worktree}?directory=${encodeURIComponent(test.directory)}`,
{
method: "POST",
headers: { "content-type": "application/json" },
body: "null",
},
)
expect(response.status).toBe(400)
}),
{ git: true },
)
worktreeTest( worktreeTest(
"workspace worktree create does not hang", "workspace worktree create does not hang",
() => () =>