confetti / confetti/confetti-node

schemaToJsonSchema discards helpText/placeholder/values — the only field documentation consumers have

Open Beginner friendly
#36 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
0
Forks
0
Avg merge
1h 51m
Merged PRs (30d)
2

Description

What happens

src/utils/to-json-schema.ts strips the meta keys that carry the human-written documentation:

const metaKeysToStrip = ['label', 'helpText', 'placeholder', 'values']
// ...
for (const key of metaKeysToStrip) delete ctx.jsonSchema[key]

Those are removed because they are not standard JSON Schema keywords — which is correct — but the information is then simply lost, rather than mapped onto the keywords that do exist.

Why it matters

schemaToJsonSchema is exported from the package root, so its output is what consumers hand to an LLM as a tool schema. Building an MCP server on this package, we measured 135 of 340 input fields (40%) carrying any description. Recovering the stripped meta ourselves moved that to 56%.

The fields that lose most are the ones a caller cannot guess:

  • ticket.sendEmailConfirmation is required, and its stripped helpText is the only place that says it sends the invite email. A model setting it true "to be safe" emails real attendees.
  • ticket.ticketBatchId's stripped helpText is "Required for ticket events" — the only statement of that rule.
  • ticket.status serialises as anyOf[string, array-of-enum], so its valid values (attending, invited) exist only in the stripped values meta and are invisible in the schema.
  • contact.phone's format example +46701234567 is stripped.

Suggested fix

Fold the meta into the standard keywords rather than deleting it:

const meta = ctx.zodSchema.meta?.() ?? {}
const extra = [meta.helpText, meta.placeholder && `Example: ${meta.placeholder}`]
  .filter(Boolean).join(' ')
if (!ctx.jsonSchema.description && extra) ctx.jsonSchema.description = extra
if (Array.isArray(meta.values) && meta.values.every(v => typeof v === 'string')) {
  // enum is the standard keyword for exactly this
  ctx.jsonSchema.enum ??= meta.values
}
for (const key of metaKeysToStrip) delete ctx.jsonSchema[key]

label is not worth mapping — of 131 occurrences, nearly all are Title-Case echoes of the field name ("Rsvp Limit"), which add nothing.

This is a few lines in one function and it would improve every consumer at once. We currently reimplement it downstream by walking the Zod shape in parallel with the generated schema, which is strictly worse than doing it here.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/utils/to-json-schema.ts at schemaToJsonSchema and inspect how the Zod metadata is available before metaKeysToStrip is applied. Done means helpText and placeholder information can appear in standard descriptions, string values can become enum values, and the nonstandard metadata keys are still absent from the generated schema.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.