Skip to content

feat(devframe): accept Standard Schema for RPC args/return schemas - #155

Open
dvcolomban wants to merge 1 commit into
devframes:mainfrom
dvcolomban:dvcol/valibot
Open

feat(devframe): accept Standard Schema for RPC args/return schemas#155
dvcolomban wants to merge 1 commit into
devframes:mainfrom
dvcolomban:dvcol/valibot

Conversation

@dvcolomban

Copy link
Copy Markdown
Contributor

Summary

  • Widen RpcArgsSchema/RpcReturnSchema from valibot's GenericSchema to StandardSchemaV1 (@standard-schema/spec), so RPC functions can declare args/returns with any Standard-Schema-compliant validator — not just valibot. zod 4 is the immediate motivating case: some consumers already use zod elsewhere in their stack and shouldn't have to pull in valibot just to satisfy devframe's RPC types.
  • GenericSchema's ~standard shape is a structural subtype of StandardSchemaV1 (verified against valibot's own type declarations), so this is a pure widening — every existing valibot-based RPC definition keeps inferring identically, with zero runtime behavior change.
  • Agent-exposed tools (adapters/mcp) now prefer a schema's own ~standard.jsonSchema converter (part of the Standard Schema spec, implemented by zod 4) when generating JSON Schema for MCP, before falling back to @valibot/to-json-schema, then to the existing generic-object fallback. So a zod-typed RPC function now exposes a real JSON Schema to agents instead of silently degrading to { type: 'object', additionalProperties: true }.
  • No new runtime dependency on zod (or any other vendor) — @standard-schema/spec is type-only. adapters/flags.ts (CLI flags) is untouched; it introspects valibot's internal shape and is out of scope here.

Test plan

  • pnpm lint
  • pnpm typecheck (all 20 workspace packages)
  • pnpm build
  • pnpm test (905/905, full suite)
  • Added a non-valibot Standard Schema inference case to rpc/types.test.ts (hand-rolled ~standard implementation, proving the code path is vendor-agnostic rather than zod-shaped)
  • Added to-json-schema.test.ts cases covering the ~standard.jsonSchema converter dispatch and its fallback chain

Consumers using zod (or any other Standard Schema vendor) instead of
valibot can now declare RPC args/returns directly, with the same
compile-time inference behavior as today. RpcArgsSchema/RpcReturnSchema
widen from valibot's GenericSchema to StandardSchemaV1 — a structural
superset, so existing valibot-based code is unaffected.

JSON Schema generation for agent-exposed tools now prefers a schema's
own ~standard.jsonSchema converter (e.g. zod 4) before falling back to
@valibot/to-json-schema, then to the existing generic object fallback.
Copilot AI review requested due to automatic review settings July 31, 2026 14:14
@netlify

netlify Bot commented Jul 31, 2026

Copy link
Copy Markdown

Deploy Preview for devfra ready!

Name Link
🔨 Latest commit bc5b950
🔍 Latest deploy log https://app.netlify.com/projects/devfra/deploys/6a6cadaa31c97e00089f6df8
😎 Deploy Preview https://deploy-preview-155--devfra.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR widens devframe’s RPC schema typing from valibot-only (GenericSchema) to the Standard Schema v1 type (@standard-schema/spec), allowing RPC args/returns to be declared with any Standard-Schema-compliant validator (e.g. zod v4) while improving MCP JSON Schema generation for agent tools.

Changes:

  • Switch RpcArgsSchema / RpcReturnSchema to StandardSchemaV1 and update type inference helpers accordingly.
  • Update MCP adapter JSON Schema generation to prefer ~standard.jsonSchema when available, with a fallback chain.
  • Add tests proving vendor-agnostic Standard Schema inference and covering the JSON Schema dispatch/fallback behavior.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
pnpm-workspace.yaml Adds @standard-schema/spec to the workspace dependency catalog.
pnpm-lock.yaml Locks @standard-schema/spec and wires it into packages/devframe.
packages/devframe/package.json Adds @standard-schema/spec as a dependency for exported/public types.
packages/devframe/src/rpc/types.ts Widens RPC schema types to Standard Schema and updates docs/comments.
packages/devframe/src/rpc/utils.ts Updates args/return type inference to use StandardSchemaV1.InferInput.
packages/devframe/src/rpc/types.test.ts Adds a minimal Standard Schema implementation to assert vendor-agnostic inference.
packages/devframe/src/adapters/mcp/to-json-schema.ts Updates schema conversion to accept Standard Schema and prefer ~standard.jsonSchema.
packages/devframe/src/adapters/mcp/build-server.ts Updates MCP server schema extraction to use the renamed converter functions and Standard Schema types.
packages/devframe/src/adapters/mcp/tests/to-json-schema.test.ts Adds coverage for ~standard.jsonSchema dispatch and fallback behavior.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file
Suppressed comments (1)

packages/devframe/src/adapters/mcp/to-json-schema.ts:67

  • safeToJsonSchema() always calls standard.jsonSchema.input(...). To support correct JSON Schema generation for both RPC args (input) and returns (output), this helper should accept which side to convert and default to input so existing arg call sites remain unchanged.
function safeToJsonSchema(schema: StandardSchemaV1): unknown {
  const standard = schema['~standard'] as StandardSchemaProps
  try {
    if (standard.jsonSchema)
      return standard.jsonSchema.input({ target: 'draft-2020-12' })

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +10 to 14
export function returnToJsonSchema(schema: StandardSchemaV1 | undefined): unknown {
if (!schema)
return undefined
try {
return toJsonSchema(schema as any)
}
catch {
return FALLBACK_OBJECT_SCHEMA
}
return safeToJsonSchema(schema)
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept it identical to match the typing of valibot and prevent any breaking changes but if we want to cleanly support validation I can switch to output

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.

2 participants