src/lib/ai/prompts/prompt-renderer.ts

Total Symbols
5
Lines of Code
104
Avg Complexity
2.0
Avg Coverage
100.0%

File Relationships

graph LR renderPromptBase["renderPromptBase"] renderOutputSchema["renderOutputSchema"] renderRules["renderRules"] renderExamples["renderExamples"] renderSystemPrompt["renderSystemPrompt"] renderPromptBase -->|calls| renderOutputSchema renderPromptBase -->|calls| renderRules renderPromptBase -->|calls| renderExamples renderSystemPrompt -->|calls| renderPromptBase click renderPromptBase "../symbols/1d807d7283d93d7a.html" click renderOutputSchema "../symbols/a94ee40c258cb1af.html" click renderRules "../symbols/cc97a1fb4ee38109.html" click renderExamples "../symbols/956dec267f8fa83b.html" click renderSystemPrompt "../symbols/eaffa002075266b5.html"

Symbols by Kind

function 5

All Symbols

Name Kind Visibility Status Lines Signature
renderOutputSchema function exported- 29-40 renderOutputSchema( fields: readonly PromptOutputField[], ): : string
renderRules function - 44-46 renderRules(rules: readonly string[]): : string
renderExamples function - 48-52 renderExamples(examples: readonly PromptExample[]): : string
renderPromptBase function exported- 65-89 renderPromptBase( prompt: StructuredPrompt<TInput, TOutput>, ): : string
renderSystemPrompt function exported- 99-103 renderSystemPrompt( prompt: StructuredPrompt<TInput, TOutput>, ): : string

Full Source

/**
 * Prompt Renderer
 *
 * Utility functions that render a StructuredPrompt's static sections
 * (role, task, schema, rules, examples) into token-efficient text blocks.
 *
 * These helpers are consumed by each prompt's `buildPrompt()` implementation
 * and by session setup code that needs a system-level prompt.
 */

import type {
  PromptOutputField,
  PromptExample,
  StructuredPrompt,
} from "./prompt.interface";

// ── Schema rendering ──────────────────────────────────────────────────────────

/**
 * Renders output schema fields as a compact JSON format spec.
 *
 * @example
 * renderOutputSchema([
 *   { name: "fieldType", type: "string", description: "semantic type" },
 *   { name: "confidence", type: "number", description: "0.0–1.0", range: { min: 0, max: 1 } },
 * ])
 * // → '{"fieldType": <string>, "confidence": <number: 0.0–1.0>}'
 */
export function renderOutputSchema(
  fields: readonly PromptOutputField[],
): string {
  const entries = fields.map((f) => {
    if (f.type === "number" && f.range) {
      return `"${f.name}": <${f.type}: ${f.range.min}–${f.range.max}>`;
    }
    return `"${f.name}": <${f.type}>`;
  });

  return `{${entries.join(", ")}}`;
}

// ── Section renderers ─────────────────────────────────────────────────────────

function renderRules(rules: readonly string[]): string {
  return rules.map((r, i) => `${i + 1}. ${r}`).join("\n");
}

function renderExamples(examples: readonly PromptExample[]): string {
  return examples
    .map((ex) => `Input: ${ex.input}\nOutput: ${ex.output}`)
    .join("\n\n");
}

// ── Main renderers ────────────────────────────────────────────────────────────

/**
 * Renders the static (non-input) sections of a structured prompt into a
 * single text block optimised for token economy.
 *
 * Sections rendered (in order): role → task → output format → rules → examples.
 *
 * Use this inside `buildPrompt()` implementations and then append the
 * per-invocation input context.
 */
export function renderPromptBase<TInput, TOutput>(
  prompt: StructuredPrompt<TInput, TOutput>,
): string {
  const sections: string[] = [];

  sections.push(prompt.persona);
  sections.push(prompt.task);

  if (prompt.outputSchema?.length) {
    const schema = renderOutputSchema(prompt.outputSchema);
    sections.push(
      `Respond ONLY with a JSON object in this exact format — no other text, no markdown, no explanation:\n${schema}`,
    );
  }

  if (prompt.rules.length) {
    sections.push(`Rules:\n${renderRules(prompt.rules)}`);
  }

  if (prompt.examples?.length) {
    sections.push(`Examples:\n${renderExamples(prompt.examples)}`);
  }

  return sections.join("\n\n");
}

/**
 * Renders a system-level prompt from a StructuredPrompt.
 *
 * Useful for APIs that support a separate `systemPrompt` channel
 * (e.g. `LanguageModel.create({ systemPrompt })`).
 *
 * Delegates to `renderPromptBase` — same content, different usage context.
 */
export function renderSystemPrompt<TInput, TOutput>(
  prompt: StructuredPrompt<TInput, TOutput>,
): string {
  return renderPromptBase(prompt);
}