Polyweave

@polyweave/smart-templates (1.0.6)

Published 2026-07-11 15:32:49 +00:00 by Dvorak

Installation

@polyweave:registry=https://hub.kl1.tenere.ai/api/packages/Polyweave/npm/
npm install @polyweave/smart-templates@1.0.6
"@polyweave/smart-templates": "1.0.6"

About this package

@polyweave/smart-templates

Smart template strings with validation, JSON Schema, and prompt formatting.

Synopsis

import {
  SmartTemplateStringFromTemplate,
  createTemplateNode,
  composeTemplateNodes,
  createPromptFormatter,
  createStructuredFormatter,
  createSmartRepairWrapper,
  createSmartRepairRunner,
  createTemplateRegistryDuplex,
  createTemplateClient,
  createTemplateTreeStoreDuplex,
  createTemplateRestStoreDuplex,
  createTemplateWebSocketStoreDuplex,
  createTemplateCacheDuplex,
  Validator,
  Register,
  AssertValid,
  Is,
  JSONSchema,
  JSONSchemaValidatorConstructor,
  tryRepairJson
} from '@polyweave/smart-templates';

const tmpl = SmartTemplateStringFromTemplate('Hello {{ name }}! The score is {{ score }}%.');
const node = createTemplateNode(tmpl);
console.log(node.render({ name: 'World', score: 95 }));
// Hello World! The score is 95%.

Install

npm install @polyweave/smart-templates

Why

Smart templates provide type-safe variable substitution via {{ var }} or ${var} syntax, combined with a registration-based validator catalog, JSON Schema generation and validation, and composable structural formatting. Every template string is parsed into segments (StringSegment + TemplateHole) with auto-detected variables and schema. TemplateNodes wrap these into reusable render(vars) functions. Formatters build prompt-engineering pipelines with JSON repair and optional LLM-driven smart repair. Use it whenever templates need validation guarantees, schema generation against prompts, or composable formatter pipelines.

API

Template String Subsystem (smartTemplateString.js)

SmartTemplateStringFromTemplate(template: string, path?: []) → SmartTemplateString

Parses a template string (supports {{ }} or ${} delimiters) into an AST of StringSegment and TemplateHole objects. Auto-detects variables and schema from path expressions and JavaScript expressions.

Parameter Type Required Default Description
template string Yes Template string with {{ var }} or ${var} holes
path (string|number)[] No [] Validation path for error reporting

Returns: A SmartTemplateString object:

{
  type: 'SmartTemplateString',
  template: [StringSegment | TemplateHole, ...],
  variables: string[],
  content: string,
  schema: JSONSchema
}

Throws: Error if {{ delimiter has no matching }}.

SmartTemplateString (constructor)

Registered validator/constructor for SmartTemplateString objects. Accepts either a string (delegates to SmartTemplateStringFromTemplate) or an options object { template, variables, content, schema }.

StringSegment (constructor)

A literal text segment. Fields: { type: 'StringSegment', content: string, escaped: boolean }.

TemplateHole (constructor)

A variable substitution hole. Fields: { type: 'TemplateHole', content: string, variables: string[], schema: JSONSchema }.

findVariables(expressionInfo: { type, parts? }) → string[]

Extracts variable names from a parsed expression, filtering out reserved JavaScript tokens.

findSchema(expressionInfo: { type, parts? }) → JSONSchema

Generates a JSON Schema capturing the variables referenced by an expression.

GenericInterpreter(input: object, holes: (StringSegment|TemplateHole)[]) → string

Applies variable substitution: walks the hole array, evaluates TemplateHole expressions against input, concatenates literal content.

TemplateStringInterpreterConstructor(smartTemplate: SmartTemplateString) → (vars: object) → string

Creates a render function from a SmartTemplateString. Validates input against the template schema before rendering.

TemplateVariableValidatorConstructor(smartTemplate: SmartTemplateString) → (input: object, path?) → object

Creates a validator function from the template's schema. Throws via AssertValid if validation fails.

composeSmartTemplates(templates: (SmartTemplateString|string)[], options?: { separator?: string }) → SmartTemplateString

Combines multiple template strings. Merges variables, schemas, and segments. Inserts separator between templates.

deepMerge(target: object, source: object) → object

Deep merge utility used internally for schema merging.


Template Nodes Subsystem (templateNodes.js)

isTemplateNode(value: any) → boolean

Returns true if value is { type: 'TemplateNode', render: function }.

createTemplateNode(input: string | SmartTemplateString | function | TemplateNode, options?: object) → TemplateNode

Creates a renderable template node.

Parameter Type Required Default Description
input string SmartTemplateString function TemplateNode
options object No {} { variables, schema, content } used when input is a function

Throws: Error if input is not a string, SmartTemplateString, function, or TemplateNode.

Returns: { type: 'TemplateNode', content: string | null, variables: string[], schema: JSONSchema, render: (vars) => string }

createTemplateNodeFromSmartTemplate(smartTemplate: SmartTemplateString) → TemplateNode

Wraps a SmartTemplateString as a TemplateNode. The render function is built via TemplateStringInterpreterConstructor.

createTemplateNodeFromFunction(fn: (vars) => string, options?: object) → TemplateNode

Wraps a function as a TemplateNode. Variables and schema are taken from options.variables, options.schema, or fn.variables / fn.schema.

composeTemplateNodes(nodes: TemplateNode[], options?: { separator?: string }) → TemplateNode

Combines multiple TemplateNodes into one. Merges variables and schemas, concatenates rendered output with separator.


Validation Subsystem (validation.js)

Validate(object: any, parent?: ValidationContext, key?: string|number) → ValidationResult

Recursively validates objects through the registered validator catalog. If object.__type names a registered validator, that validator runs. Returns { __valid: boolean, object, comments, path }.

AssertValid(object: any) → void

Throws Error if the object (or its Validate result) has __valid === false.

Throws: Error('Invalid object: ...') with summarized validation comments.

Register(typeName: string, validatorFn: function, constructorFn: function) → ConstructorFn

Registers a type in the validator catalog. Returns a constructor function that can be used to create instances of the type.

Throws: Error if typeName is already registered.

Lookup(typeName: string) → ValidatorFn

Returns the registered validator for typeName.

Throws: Error if typeName is not registered.

Is(constructor: function) → (value: any, fast?: boolean) => boolean

Creates a type guard for a registered constructor. Fast path (fast=true, default) checks __type by name; slow path runs full validation.

Throws: Error if constructor has no __name.

PopType(x: object) → object

Pops the last type off x.__type and reconstructs using the next type's constructor.

Throws: Error if pop fails.

confirmKey(obj: any, prop: string) → boolean

Returns true if obj has own property prop.

confirmKeySet(obj: any, ...props: string[]) → boolean

Returns true if obj has all of the given own properties.

Summarize(object: ValidationResult) → string

Formats validation comments into a human-readable string.

withValidation(fn: function) → (...args) → any

Higher-order function: validates all object arguments, returns validation failures directly if any, otherwise calls fn and validates the result.


JSON Schema Subsystem (jsonSchema.js)

JSONSchema(schema: any, _path?: []) → JSONSchema

Normalizes a schema object. Returns { type: 'object', properties: {} } for null/undefined/non-object input.

JSONSchemaValidatorConstructor(schema: JSONSchema) → (input: any, path?: []) → ValidationResult

Creates a validator function from a JSON Schema. Validates types (object, array, string, number, boolean), required keys for objects, and recursively validates nested schemas. Returns { __valid, object, comments }.


Formatters Subsystem (formatters.js)

createPromptFormatter(options?: object) → (payload: object) → PromptResult

Creates a function that formats LLM prompts from system/user templates.

Parameter Type Required Default Description
options.systemTemplate string No Template string for the system prompt
options.userTemplate string No Template string for the user prompt
options.contextKey string No 'context' Key under which context data is merged into variables

Returns: (payload) → { systemPrompt: string, userPrompt: string, metadata: object, tokenCount: number }

The formatter accepts { variables, context, metadata }. If context is provided, it's merged under contextKey. Token count is estimated as ceil(length / 4).

tryRepairJson(text: string) → string | null

Attempts to repair malformed JSON by:

  1. Finding first structural { or [ and last } or ] (respecting string escapes)
  2. Stripping BOM characters
  3. Removing trailing commas before } or ]
  4. Adding missing closing braces/brackets

Returns null if the input is not a string or is empty after trimming.

createStructuredFormatter(options?: object) → (text: string) → ParseResult

Creates a JSON parser with schema validation and optional repair.

Parameter Type Required Default Description
options.schema JSONSchema No { type: 'object', properties: {} } Schema to validate parsed JSON against
options.tryRepair function No tryRepairJson Custom JSON repair function

Returns: (text: string) → { ok: boolean, value: any | null, error: Error | null, rawText: string, repairedText: string | null, validation?: ValidationResult }

createSmartRepairRunner(adapter: duplex, options?: object) → (payload: object, callback: function) → void

Creates an LLM-powered JSON repair runner. Uses a system prompt template to guide the model in repairing invalid JSON. The adapter must expose source and sink following the push-stream protocol.

Parameter Type Required Default Description
options.systemPromptTemplate string No Custom repair prompt template
options.templateLookup function No Async template resolver: (name, callback)
options.systemPromptTemplateName string No Template name to resolve via templateLookup

The repair runner sends a TEXT frame to the adapter and accumulates response TEXT frames until END is received.

createSmartRepairWrapper(options?: object) → (text: string, done: function) → void

Wraps a structured formatter with smart repair retry logic.

Parameter Type Required Default Description
options.formatter function Yes The structured formatter to wrap
options.smartRepair function Yes The smart repair runner
options.schema JSONSchema No null Schema for repair context
options.maxAttempts number No 1 Max repair attempts before returning failure

Throws: Error('SmartRepairWrapper requires formatter and smartRepair.') if either is missing.


Template Registry Subsystem (templates.js)

createTemplateRegistryDuplex(options?: object) → duplex

Creates a frame-based template registry with optional upstream fallback.

Parameter Type Required Default Description
options.registry Map No new Map() Initial template map
options.templates object No {} Initial templates as plain object
options.upstream duplex No null Upstream registry for cache-miss fallback; must expose source and sink

Frame protocol:

  • Input: META { action: 'template.lookup', name } or META { action: 'template.register', name, template }
  • Output: META { action: 'template.result', name, template } or ERROR { code: 'TEMPLATE_NOT_FOUND' }
  • Upstream fallback: On cache miss, forwards template.lookup to upstream; caches result on return

createTemplateClient(duplex: duplex) → { lookup, register }

Creates a callback-based client for a template registry duplex.

Returns:

  • lookup(name: string, callback: (err: Error | null, template: any) => void) — Look up a template
  • register(name: string, template: any, callback: (err: Error | null, template: any) => void) — Register a template

Template Store Adapters (templateStores.js)

createTemplateTreeStoreDuplex(options?: object) → duplex

Template registry backed by a tree store.

Parameter Type Required Default Description
options.treeStore duplex Yes Tree store with sink and source
options.treeId string No 'templates' Tree identifier
options.basePath string[] No ['templates'] Base path prefix
options.resolvePath function No Custom path resolver: (name, basePath) → path[]

Throws: Error('TemplateTreeStoreDuplex requires a treeStore duplex.') if treeStore is missing. Frame protocol: Lookup uses TREE_QUERY/TREE_RESULT; register uses TREE_UPSERT.

createTemplateRestStoreDuplex(options?: object) → duplex

Template registry backed by a REST API.

Parameter Type Required Default Description
options.request function Yes HTTP request function: (req, callback)
options.baseUrl string No '' Base URL for default request builders
options.buildLookupRequest function No (name) → req Request builder for lookups (default: GET {baseUrl}/templates/{name})
options.buildRegisterRequest function No (name, template) → req Request builder for register (default: PUT {baseUrl}/templates/{name})

Throws: Error('TemplateRestStoreDuplex requires a request function.') if request is missing. Error frames: Emits TEMPLATE_NOT_FOUND on 404, generic error on other 4xx/5xx.

createTemplateWebSocketStoreDuplex(options?: object) → duplex

Template registry backed by a WebSocket connection.

Parameter Type Required Default Description
options.socket WebSocket conditional WebSocket instance with send(); alternative to connect
options.connect function conditional Connection function returning a socket
options.encodeMessage function No JSON.stringify Message serializer
options.decodeMessage function No JSON.parse Message deserializer

Throws: Error('TemplateWebSocketStoreDuplex requires a socket with send().') if no socket found. Message handling: Supports socket.on('message'), socket.addEventListener('message'), and socket.onmessage.

createTemplateCacheDuplex(options?: object) → duplex

Layered template cache with local + remote stores.

Parameter Type Required Default Description
options.local duplex Yes Local (fast) template store
options.remote duplex Yes Remote (authoritative) template store
options.propagateRegister boolean No false If true, register writes propagate to remote

Throws: Error if local or remote is missing. Lookup: Tries local first, falls back to remote, caches remote result locally. Register: Writes to local; optionally propagates to remote.

Tests

npm test

Covers: template string parsing ({{ }} and ${}), variable detection, schema generation, template interpretation, TemplateNode creation and composition, prompt formatting, JSON schema validation, JSON repair, structured formatting, smart repair runner and wrapper, template registry duplex (lookup/register/upstream fallback), template store adapters (tree, REST, WebSocket, cache).

Requirements

  • Node.js 22+
  • ESM only
  • Peer dependency: @polyweave/core

Dependencies

Development Dependencies

ID Version
@rigor/core *

Peer Dependencies

ID Version
@polyweave/core *
@polyweave/errors *

Keywords

polyweave templates prompt validation formatting
Details
npm
2026-07-11 15:32:49 +00:00
464
John Dvorak
SEE LICENSE IN LICENSE
latest
16 KiB
Assets (1)
Versions (4) View all
1.0.6 2026-07-11
1.0.3 2026-07-11
1.0.2 2026-07-11
1.0.1 2026-07-10