Skip to content

feat(cc): switch action JSON Schema from anyOf to oneOf#94

Open
mvanhorn wants to merge 1 commit intoanipotts:mainfrom
mvanhorn:osc/82-cc-oneof-schema
Open

feat(cc): switch action JSON Schema from anyOf to oneOf#94
mvanhorn wants to merge 1 commit intoanipotts:mainfrom
mvanhorn:osc/82-cc-oneof-schema

Conversation

@mvanhorn
Copy link
Copy Markdown

Resolves #82.

zodToJsonSchema(...) with target: "jsonSchema7" emits an anyOf for the discriminated union, but the file's own comment + tool-surface language already describe the schema as a oneOf. The issue notes:

  1. JSON Schema 2020-12 says discriminated unions SHOULD use oneOf
  2. OpenAPI tooling uses oneOf + discriminator
  3. Some MCP clients treat anyOf permissively whereas oneOf is exclusive

Approach

Post-process the generator output to rename anyOf -> oneOf rather than switching the generator target to openApi3. The post-process keeps every other byte stable, which preserves the existing byte-stability invariant that the ACTION_JSON_SCHEMA is cached at module load and reused across sessions for prompt-cache hits. Switching the target would also alter nullable handling and ref behavior.

Changes

  • plugins/cc/lib/action.ts: extract anyOf from the generator output and re-emit as oneOf via a single object spread.
  • plugins/cc/tests/action.test.ts: update assertions to reference oneOf (the byte-stability test continues to compare JSON.stringify(ACTION_JSON_SCHEMA) across re-imports).

bun test tests/action.test.ts passes (19/19).

Acceptance

  • tools/list inputSchema uses oneOf (not anyOf)
  • Existing tests still pass (19/19)
  • Byte-stability snapshot test continues to pass

Resolves anipotts#82.

`zodToJsonSchema(...)` with `target: "jsonSchema7"` emits an `anyOf` for
the discriminated union, but the file's own comment + tool surface
language already describe the schema as a `oneOf`. Discriminated unions
SHOULD use `oneOf` per JSON Schema 2020-12 + OpenAPI, and some MCP
clients treat `anyOf` permissively (multi-branch match) whereas `oneOf`
is exclusive.

Post-process the generator output to rename `anyOf` -> `oneOf`. This
keeps every other byte of the schema stable (changing the target to
`openApi3` would also alter nullable handling, refs, etc., breaking
the byte-stability invariant).

Tests in `action.test.ts` updated accordingly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[cc] switch JSON Schema generator from anyOf to oneOf for the discriminated union

1 participant