@json-render/yaml

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

Prompt Generation

yamlPrompt

Generate a YAML-format system prompt from any json-render catalog. Works with catalogs from any renderer.

function yamlPrompt(
  catalog: Catalog,
  options?: YamlPromptOptions
): string
import { yamlPrompt } from "@json-render/yaml";

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

YamlPromptOptions

OptionTypeDefaultDescription
systemstring"You are a UI generator that outputs YAML."Custom system message intro
mode"standalone" | "inline""standalone"Standalone outputs only YAML; inline allows conversational responses with embedded YAML fences
customRulesstring[][]Additional rules appended to the prompt
editModesEditMode[]["merge"]Edit modes to document in the prompt (patch, merge, diff)

AI SDK Transform

createYamlTransform

Creates a TransformStream that intercepts AI SDK stream chunks and converts YAML spec/edit blocks into json-render patch data parts.

function createYamlTransform(
  options?: YamlTransformOptions
): TransformStream<StreamChunk, StreamChunk>

Recognized fence types:

  • ```yaml-spec -- Full YAML spec, parsed progressively
  • ```yaml-edit -- Partial YAML, deep-merged with current spec
  • ```yaml-patch -- RFC 6902 JSON Patch lines
  • ```diff -- Unified diff against serialized spec

pipeYamlRender

Convenience wrapper that pipes an AI SDK stream through the YAML transform. Drop-in replacement for pipeJsonRender from @json-render/core.

function pipeYamlRender<T>(
  stream: ReadableStream<T>,
  options?: YamlTransformOptions
): ReadableStream<T>
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 });

Streaming Parser

createYamlStreamCompiler

Create a streaming YAML compiler that incrementally parses YAML text and emits JSON Patch operations by diffing each successful parse against the previous snapshot.

function createYamlStreamCompiler<T>(
  initial?: Partial<T>
): YamlStreamCompiler<T>
import { createYamlStreamCompiler } from "@json-render/yaml";

const compiler = createYamlStreamCompiler<Spec>();

compiler.push("root: main\n");
compiler.push("elements:\n  main:\n    type: Card\n");

const { result, newPatches } = compiler.flush();

YamlStreamCompiler

MethodReturnsDescription
push(chunk){ result: T; newPatches: JsonPatch[] }Push a chunk of text, returns current result and new patches
flush(){ result: T; newPatches: JsonPatch[] }Flush remaining buffer, return final result
getResult()TGet the current compiled result
getPatches()JsonPatch[]Get all patches applied so far
reset(initial?)voidReset to initial state

Fence Constants

Exported string constants for fence detection in custom parsers:

ConstantValue
YAML_SPEC_FENCE"```yaml-spec"
YAML_EDIT_FENCE"```yaml-edit"
YAML_PATCH_FENCE"```yaml-patch"
DIFF_FENCE"```diff"
FENCE_CLOSE"```"

Re-exports from @json-render/core

diffToPatches

Generate RFC 6902 JSON Patch operations that transform one object into another.

function diffToPatches(
  oldObj: Record<string, unknown>,
  newObj: Record<string, unknown>,
  basePath?: string
): JsonPatch[]

deepMergeSpec

Deep-merge with RFC 7396 semantics: null deletes, arrays replace, objects recurse.

function deepMergeSpec(
  base: Record<string, unknown>,
  patch: Record<string, unknown>
): Record<string, unknown>