mcpField
Y
yaml

yaml

github.com/vercel-labsDevelopment18.8k1.0k installsUpdated 5d ago
Repository

About yaml

@json-render/yaml provides a YAML wire format for @json-render/core, with incremental parsing and edit operations for streamed UI specifications. Developers can generate YAML prompts and transform AI SDK streams into render patches.

Key features

  1. 01YAML prompts from catalogs
  2. 02Incremental YAML stream parsing
  3. 03Patch, merge, and diff editing
  4. 04AI SDK stream transform
  5. 05JSON Patch emission

Use cases

  1. 01Stream a UI specification progressively
  2. 02Apply partial edits to an existing spec
  3. 03Convert YAML fences in an AI SDK stream
  4. 04Compile YAML chunks into render patches

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/vercel-labs/json-render --skill yaml

After installing, type/yamlin Claude Code to confirm it loaded.

Details

From the project README

@json-render/yaml

YAML wire format for @json-render/core. Progressive rendering and surgical edits via streaming YAML.

Key Concepts

  • YAML wire format: Alternative to JSONL that uses code fences (yaml-spec, yaml-edit, yaml-patch, diff)
  • Streaming parser: Incrementally parses YAML, emits JSON Patch operations via diffing
  • Edit modes: Patch (RFC 6902), merge (RFC 7396), and unified diff
  • AI SDK transform: TransformStream that converts YAML fences into json-render patches

Generating YAML Prompts

import { yamlPrompt } from "@json-render/yaml";
import { catalog } from "./catalog";

// Standalone mode (LLM outputs only YAML)
const systemPrompt = yamlPrompt(catalog, {
  mode: "standalone",
  editModes: ["merge"],
  customRules: ["Always use dark theme"],
});

// Inline mode (LLM responds conversationally, wraps YAML in fences)
const chatPrompt = yamlPrompt(catalog, { mode: "inline" });

Options:

  • system (string) — Custom system message intro
  • mode ("standalone" | "inline") — Output mode, default "standalone"
  • customRules (string[]) — Additional rules appended to prompt
  • editModes (EditMode[]) — Edit modes to document, default ["merge"]

AI SDK Transform

Use pipeYamlRender as a drop-in replacement for pipeJsonRender:

import { pipeYamlRender } from "@json-render/yaml";
import { createUIMessageStream, createUIMessageStreamResponse } from "ai";

const stream = createUIMessageStream({
  execute: async ({ writer }) => {
    writer.merge(pipeYamlRender(result.toUIMessageStream()));
  },
});
return createUIMessageStreamResponse({ stream });

For multi-turn edits, pass the previous spec:

pipeYamlRender(result.toUIMessageStream(), {
  previousSpec: currentSpec,
});

The transform recognizes four fence types:

  • yaml-spec — Full spec, parsed progressively line-by-line
  • yaml-edit — Partial YAML deep-merged with current spec (RFC 7396)
  • yaml-patch — RFC 6902 JSON Patch lines; applied to the working spec, so later yaml-edit fences see them
  • diff — Unified diff applied to serialized spec

Streaming Parser (Low-Level)

import { createYamlStreamCompiler } from "@json-render/yaml";

const compiler = createYamlStreamCompiler<Spec>();

// Feed chunks as they arrive from any source
const { result, newPatches } = compiler.push("root: main\n");
compiler.push("elements:\n  main:\n    type: Card\n");

// Flush remaining data at end of stream
const { result: final } = compiler.flush();

// Reset for next stream (optionally with initial state)
compiler.reset({ root: "main", elements: {} });

Methods: push(chunk), flush(), getResult(), getPatches(), reset(initial?)

Edit Modes (from @json-render/core)

The YAML package uses the universal edit mode system from core:

import { buildEditInstructions, buildEditUserPrompt } from "@json-render/core";
import type { EditMode } from "@json-render/core";

// Generate edit instructions for YAML format
const instructions = buildEditInstructions({ modes: ["merge", "patch"] }, "yaml");

// Build user prompt with current spec context
const userPrompt = buildEditUserPrompt({
  prompt: "Change the title to Dashboard",
  currentSpec: spec,
  config: { modes: ["merge"] },
  format: "yaml",
  serializer: (s) => yamlStringify(s, { indent: 2 }).trimEnd(),
});

Fence Constants

For custom parsing, use the exported constants:

import {
  YAML_SPEC_FENCE,   // "```yaml-spec"
  YAML_EDIT_FENCE,   // "```yaml-edit"
  YAML_PATCH_FENCE,  // "```yaml-patch"
  DIFF_FENCE,        // "```diff"
  FENCE_CLOSE,       // "```"
} from "@json-render/yaml";

Key Exports

ExportDescription
yamlPromptGenerate YAML system prompt from catalog
createYamlTransformAI SDK TransformStream for YAML fences
pipeYamlRenderConvenience pipe wrapper (replaces pipeJsonRender)
createYamlStreamCompilerStreaming YAML parser with patch emission
YAML_SPEC_FENCEFence constant for yaml-spec
YAML_EDIT_FENCEFence constant for yaml-edit
YAML_PATCH_FENCEFence constant for yaml-patch
DIFF_FENCEFence constant for diff
FENCE_CLOSEFence close constant
diffToPatchesRe-export: object diff to JSON Patch
deepMergeSpecRe-export: RFC 7396 deep merge

Comments

Markdown supported