11 KiB
OpenAPI Translation Cleanup Plan
Goal
Trim packages/opencode/src/server/routes/instance/httpapi/public.ts until OpenAPI generation is mostly a direct projection of the HttpApi route declarations, without breaking the generated SDK surface.
The main failure mode to eliminate is spec-only behavior: anything that appears in /doc or the SDK but is not accepted by runtime HttpApi validation.
Current Culprit
public.ts exports PublicApi with a large OpenApi.annotations({ transform }) hook. That hook rewrites the generated spec for legacy SDK compatibility.
The highest-risk rewrite is InstanceQueryParameters, which injected directory and workspace into every instance route in OpenAPI even when the runtime query schema did not accept them. This caused the SDK and /doc to advertise calls that could fail with 400 at runtime.
Non-Negotiables
- Do not break the generated JavaScript SDK without an explicit versioned migration plan.
- Runtime route schemas are the source of truth for accepted params, payloads, and responses.
/doc, generated SDK types, and runtime validation must agree for every endpoint.- Prefer endpoint or schema annotations over post-generation spec surgery.
- Remove one category of rewrite at a time, with focused compatibility checks.
PR Checklist
Status legend: [x] done locally, [~] in progress locally, [ ] not started.
Current combined PR scope:
[x]PR 1 drift tests: added OpenAPI/runtime query assertions and a negative fixture intest/server/httpapi-query-schema-drift.test.ts.[x]PR 2 injection removal: removed broaddirectory/workspacepost-generation injection frompublic.tsand replaced it with explicit runtime query schemas on affected routes.[ ]PR 3+ cleanup: leave query override, path pattern, error shape, auth, and component-shape rewrites for later PRs.
PR 1: Add OpenAPI/Runtime Query Drift Tests
[x]Add or extendpackages/opencode/test/server/httpapi-query-schema-drift.test.ts.[x]ImportOpenApi.fromApiandPublicApi.[x]Generate the public spec in-process withOpenApi.fromApi(PublicApi).[x]Add a route inventory for the existing runtime reproducers:session,file,experimental, andinstanceroutes.[x]For each inventory entry, assert every OpenAPI query parameter is declared by the runtime query schema.[x]Add a negative regression fixture that fails on spec-onlydirectory/workspaceparams.[x]Keep this part test-only.
Verification:
[x]bun test --timeout 5000 test/server/httpapi-query-schema-drift.test.tsfrompackages/opencode.[x]bun typecheckfrompackages/opencode.
PR 2: Delete Spec-Only Workspace Query Injection
[x]Editpackages/opencode/src/server/routes/instance/httpapi/public.ts.[x]DeleteInstanceQueryParameters.[x]Delete theisInstanceRouteconstant.[x]Delete the branch that prependsdirectoryandworkspaceto every instance operation.[x]KeepnormalizeParameter(param, route)for parameters that are actually produced byHttpApi.[x]AddWorkspaceRoutingQuery/WorkspaceRoutingQueryFieldsto runtime query schemas for affected routes.[x]Regenerate SDK and inspect diff. Result: nodirectory/workspacerequest-param removals; generated SDK diff is declaration ordering only.
Notes:
- Added
WorkspaceRoutingQueryinmiddleware/workspace-routing.tsas the canonical runtime schema for middleware-consumed query params. - Replaced v2 union-query schemas with plain struct query schemas so
OpenApi.fromApiemits their query params directly. This intentionally exposes the beta/api/sessionpagination/filter params in the SDK; cursor mutual-exclusion rules now live in the handlers, whiledirectory/workspaceremain allowed with cursors for routing.
Expected code shape:
for (const param of operation.parameters ?? []) normalizeParameter(param, `${method.toUpperCase()} ${path}`)
Verification:
[x]bun test --timeout 5000 test/server/httpapi-query-schema-drift.test.tsfrompackages/opencode.[x]bun dev generate > /tmp/opencode-openapi.jsonfrompackages/opencode.[x]./packages/sdk/js/script/build.tsfrom repo root.[x]Inspect SDK diff for removeddirectory/workspaceparams. Result: none after explicit runtime schemas; v2 list/message now also expose their existing beta pagination/filter query params in the SDK.[x]bun typecheckfrompackages/opencode.
PR 3: Replace Broad Query Type Override Sets With Route-Level Helpers
- Edit
packages/opencode/src/server/routes/instance/httpapi/public.ts. - Remove broad name-based assumptions from
QueryNumberParametersandQueryBooleanParametersone field at a time. - Add shared query schema helpers near route group code if needed, for example in
groups/metadata.tsor a newgroups/query.ts. - Prefer route declarations like
Schema.NumberFromString.check(...)and boolean string decoders like the existingQueryBooleaningroups/session.ts. - Keep only route-specific
QueryParameterSchemasentries when SDK compatibility requires a public encoded type that Effect OpenAPI cannot emit yet.
Concrete first targets:
[x]Consolidateroots/archivedonto an explicit shared route schema helper. KeepQueryBooleanParametersuntil route-level schema metadata can preserve the SDK'sboolean | "true" | "false"call shape without a global transform.[x]Replace broadQueryNumberParametersreliance forstart/cursor/limitwith route-specific SDK compatibility schemas. Keep improving route-level constraints where behavior is intentionally stricter.- Keep
GET /find/file limit,GET /session/{sessionID}/diff messageID, andGET /session/{sessionID}/message limitoverrides until their route schemas generate identical SDK types directly.
Verification:
- Focused HTTP tests for changed query fields.
bun dev generate > /tmp/opencode-openapi.jsonfrompackages/opencode../packages/sdk/js/script/build.tsfrom repo root.- Inspect generated SDK request param types before deleting each override.
bun typecheckfrompackages/opencode.
PR 4: Move Path Parameter Patterns Into ID Schemas
- Audit
PathParameterSchemasandpathParameterSchema()inpublic.ts. - Check source schemas in files like
packages/opencode/src/session/schema.ts,packages/opencode/src/permission/schema.ts, and pty schema definitions. - Add or fix OpenAPI-compatible annotations on branded ID schemas so generated path params include the same patterns without
public.tsoverrides. - Delete one path override only after generated OpenAPI is unchanged for that param.
Concrete first targets:
-
[x]sessionID -
[x]messageID -
[x]partID -
[x]permissionID -
[x]ptyID -
[x]Remove ambiguous workspaceidpath overrides once the endpoint source schema emits thewrkpattern.
Verification:
bun dev generate > /tmp/opencode-openapi.jsonfrompackages/opencode../packages/sdk/js/script/build.tsfrom repo root.- Inspect generated path param types and patterns.
bun typecheckfrompackages/opencode.
PR 5: Replace Built-In Error Rewrites With Declared API Errors
- Edit route group files under
packages/opencode/src/server/routes/instance/httpapi/groups/. - Replace SDK-visible
HttpApiError.BadRequest/HttpApiError.NotFoundwith explicit error schemas frompackages/opencode/src/server/routes/instance/httpapi/errors.tsor add new ones there. - Update handlers to fail with the declared API errors at the boundary.
- Remove matching cases from
normalizeLegacyErrorResponses()only after generated OpenAPI remains SDK-compatible. - Do this group by group, starting with one small route group.
Concrete first targets:
groups/config.tsPATCH /configbad request.groups/session.tsendpoints that already translate domain not-found errors.groups/file.tsif any handler currently relies on built-in error shape.
Verification:
- Focused HTTP tests asserting response body shape for changed error paths.
bun dev generate > /tmp/opencode-openapi.jsonfrompackages/opencode../packages/sdk/js/script/build.tsfrom repo root.- Inspect SDK error union diff.
bun typecheckfrompackages/opencode.
PR 6: Remove Auth/Security Spec Rewrites If SDK Can Tolerate It
- Audit
delete operation.security,delete operation.responses?.["401"], anddelete spec.components?.securitySchemesinpublic.ts. - Decide whether SDK should expose auth in generated operation metadata.
- If preserving no-auth SDK surface is required, leave this rewrite and document it as intentional compatibility code.
- If removing it, update SDK generation expectations and docs in the same PR.
Verification:
./packages/sdk/js/script/build.tsfrom repo root.- Inspect generated client call signatures and error unions.
- Do not merge if auth churn changes normal SDK call ergonomics unintentionally.
PR 7: Tackle Component Shape Rewrites One At A Time
- Audit these in
public.ts:normalizeComponentNames,collapseDuplicateComponents,applyLegacySchemaOverrides,normalizeComponentDescriptions,stripOptionalNull,fixSelfReferencingComponents. - For each rewrite, make a tiny PR that removes or narrows only that rewrite.
- If generated SDK type names churn broadly, stop and either keep the rewrite or fix
effect-smolgeneration first.
Concrete first targets:
- Delete cosmetic
normalizeComponentDescriptionsif SDK output does not change materially. - Narrow
applyLegacySchemaOverridesentries that correspond to schemas already fixed at the source. - Keep
stripOptionalNulluntil there is an explicit SDK migration plan, because it likely affects many optional fields.
Verification:
bun dev generate > /tmp/opencode-openapi.jsonfrompackages/opencode../packages/sdk/js/script/build.tsfrom repo root.- Inspect generated SDK type-name and optionality diffs.
Upstream Middleware Query Support
Long-term, WorkspaceRoutingMiddleware should declare the query fields it reads once, and HttpApi should use that declaration for both runtime validation and OpenAPI generation.
Target in effect-smol:
- Extend
HttpApiMiddleware.Serviceconfig with optional query schema support, or add a dedicated middleware query annotation. - Make runtime request decoding include middleware query schemas.
- Make
OpenApi.fromApiemit middleware query params for endpoints using that middleware.
Once available, remove WorkspaceRoutingQueryFields spreads from route groups and declare directory / workspace only on WorkspaceRoutingMiddleware.
Suggested PR Order
- Add drift detection tests only.
- Remove
InstanceQueryParametersspec injection; rely onWorkspaceRoutingQueryFieldsalready present in runtime schemas. - Convert query type overrides into route/schema-level helpers where possible.
- Convert path parameter overrides into schema annotations or upstream fixes.
- Replace built-in error response rewrites with explicit declared API errors by route group.
- Tackle component naming/nullability rewrites only after SDK compatibility snapshots are stable.
Verification Checklist Per PR
- Focused HTTP tests for changed routes.
- OpenAPI drift tests.
bun dev generate > /tmp/opencode-openapi.jsonfrompackages/opencode../packages/sdk/js/script/build.tsfrom repo root.- Inspect generated SDK diff for public API churn.
bun typecheckfrompackages/opencode.