@edv4h/alchemy-core

Core types, refiners, material utilities, and transform helpers. Zero runtime dependencies beyond Zod.

Types

MaterialPart

Discriminated union of all material types. Built-in types:

TypeKey Fields
TextMaterialPart{ type: "text"; text: string }
ImageMaterialPart{ type: "image"; source: { kind: "url"; url } | { kind: "base64"; mediaType; data } }
AudioMaterialPart{ type: "audio"; source: { kind: "url"; url } | { kind: "base64"; mediaType; data } }
DocumentMaterialPart{ type: "document"; source: { kind: "url"; url } | { kind: "text"; text; metadata? } }
VideoMaterialPart{ type: "video"; source: { kind: "url"; url } | { kind: "base64"; mediaType; data } }
DataMaterialPart{ type: "data"; format: "csv"|"json"|"tsv"; content: string; label?: string }

MaterialInput

Wire-format for API requests. Same structure as MaterialPart but used for client-to-server communication. Convert with toMaterialParts().

Transmuter

Interface for LLM provider adapters.

ts
interface Transmuter {
  transmute(
    materials: MaterialPart[],
    options: TransmutationOptions,
  ): Promise<TransmutationResult>;

  stream(
    materials: MaterialPart[],
    options: TransmutationOptions,
  ): AsyncGenerator<string>;
}

TransmutationOptions

PropertyTypeDescription
roleDefinitionstring?System prompt / role definition
temperaturenumber?Sampling temperature (0–2)
signalAbortSignal?Cancellation signal
languagestring?Output language instruction

TransmutationResult

PropertyTypeDescription
textstringRaw text output from LLM
usage{ promptTokens: number; completionTokens: number }?Token usage

Refiner<TOutput>

PropertyTypeDescription
refine(raw: string) => TOutputParse raw LLM output
formatInstructions() => string?Instructions appended to prompt

Recipe<TInput, TOutput>

PropertyTypeDescription
idstringUnique recipe identifier
namestring?Display name
spell(material: TInput) => SpellOutput | Promise<SpellOutput>Prompt instruction function
refinerRefiner<TOutput>Output parser/validator
roleDefinitionstring?System prompt / role definition
temperaturenumber?Sampling temperature (0–2)
transformsMaterialTransform[]?Recipe-specific transforms
requiredMaterialsMaterialRequirement[]?Declarative material type requirements
validateMaterials((parts: MaterialPart[]) => MaterialValidationResult | Promise<MaterialValidationResult>)?Custom validation function (sync or async)
judgeMaterials((evaluations: MaterialEvaluationEntry[]) => MaterialJudgement)?Aggregate quality evaluation to decide transmute eligibility

Validation

MaterialPartType

Union of all material part type strings: "text" | "image" | "audio" | "document" | "video" | "data"

MaterialRequirement

PropertyTypeDescription
typeMaterialPartTypeRequired material type
minnumber?Minimum count (default: 1)
maxnumber?Maximum count (undefined = unlimited)
labelstring?Display label for error messages
evaluate((parts: MaterialPart[]) => MaterialEvaluation | Promise<MaterialEvaluation>)?Quality scoring function (0–1 score)

MaterialValidationResult

PropertyTypeDescription
validbooleanWhether validation passed
messagestring?Human-readable message
issuesMaterialValidationIssue[]?Detailed issue list (type × count check)
evaluationsMaterialEvaluationEntry[]?Per-material quality scores
judgementMaterialJudgement?Aggregate transmute eligibility

MaterialValidationIssue

PropertyTypeDescription
typeMaterialPartTypeMaterial type that failed
labelstring?Label from the requirement
requirement{ min: number; max?: number }The requirement that was violated
actualnumberActual count of this type
kind"too_few" | "too_many"Type of violation

MaterialEvaluation

Quality score returned by evaluate on a MaterialRequirement.

PropertyTypeDescription
scorenumberQuality score between 0 (worst) and 1 (best)
messagestring?Explanation (e.g. "Response rate is low")

MaterialEvaluationEntry

Entry passed to judgeMaterials, grouping a requirement's type/label with its evaluation result.

PropertyTypeDescription
typeMaterialPartTypeMaterial type
labelstring?Label from the requirement
evaluationMaterialEvaluationThe evaluation result

MaterialJudgement

Result of judgeMaterials, deciding whether transmutation should proceed.

PropertyTypeDescription
canTransmutebooleanWhether to allow transmutation
warningstring?Warning even when canTransmute is true
messagestring?Reason when canTransmute is false

validateMaterialRequirements(requirements, parts)

Validate material parts against declarative requirements.

ts
function validateMaterialRequirements(
  requirements: MaterialRequirement[],
  parts: MaterialPart[],
): MaterialValidationResult;

runMaterialValidation(recipe, parts)

Run the validation pipeline: declarative check → evaluate → judgeMaterials → custom validateMaterials. Each stage runs only when configured, and is skipped if a previous stage fails.

ts
async function runMaterialValidation(
  recipe: {
    requiredMaterials?: MaterialRequirement[];
    validateMaterials?: (parts: MaterialPart[]) => MaterialValidationResult | Promise<MaterialValidationResult>;
    judgeMaterials?: (evaluations: MaterialEvaluationEntry[]) => MaterialJudgement;
  },
  parts: MaterialPart[],
): Promise<MaterialValidationResult>;

Validation stages (each runs only when configured, and is skipped if a previous stage fails):

  1. Declarative check — validates requiredMaterials counts by type (if requiredMaterials is set)
  2. Evaluate — runs each requirement's evaluate() in parallel, producing quality scores (only for requirements with evaluate)
  3. Judge — passes evaluations to judgeMaterials() for transmute eligibility (only if evaluations exist and judgeMaterials is set)
  4. Custom check — runs validateMaterials() as a final filter (if provided)

Refiners

TextRefiner

Trims whitespace from the raw output. Returns string.

JsonRefiner<T>

Validates output against a Zod schema.

ts
new JsonRefiner(schema: ZodType<T>)

// Behavior:
// 1. Strips markdown code fences (```json ... ```)
// 2. Parses JSON
// 3. Validates against schema
// 4. Returns typed T
// 5. formatInstructions() returns JSON schema description

Material Utilities

FunctionDescription
normalizeSpellOutput(output)Converts string/single part to MaterialPart[]
extractText(parts)Extracts text parts from materials
isTextOnly(parts)Returns true if all parts are text
extractAllText(parts)Extracts all extractable text including documents
toMaterialParts(inputs)Converts MaterialInput[] to MaterialPart[]

Transforms

FunctionDescription
truncateText(maxLength)Truncates text parts to max length
prependText(text)Adds text at the beginning of materials
filterByType(...types)Keeps only specified material types
dataToText()Converts data parts to text representation

Errors

ClassDescription
AlchemyErrorBase error class
TransmuteErrorLLM API call failure
RefineErrorOutput parsing/validation failure
TransformErrorMaterial transform failure
MaterialValidationErrorMaterial validation failure (has result: MaterialValidationResult property)

@edv4h/alchemy-node

Node.js-specific implementations. Depends on @edv4h/alchemy-core and openai.

Alchemist

Main orchestrator class.

Constructor

ts
new Alchemist(config: AlchemistConfig)

interface AlchemistConfig {
  transmuter: Transmuter;
  transforms?: MaterialTransform[];
  validateMaterials?: boolean; // Auto-validate before transmute/stream (default: false)
}

Methods

transmute<TInput, TOutput>(recipe, material, options?)

Execute a recipe with materials and return the parsed output.

ParameterTypeDescription
recipeRecipe<TInput, TOutput>The recipe to execute
materialTInputInput material
optionsTransmutationOptions?Override options (roleDefinition, temperature, language)

Returns: Promise<TOutput>

stream<TInput>(recipe, material, options?)

Stream the response progressively.

Returns: AsyncGenerator<string>

generate<TInput, TOutput>(recipe, material, count, options?)

Generate multiple variations of the same recipe in parallel.

ParameterTypeDescription
recipeRecipe<TInput, TOutput>The recipe to execute
materialTInputInput material
countnumberNumber of variations to generate
optionsTransmutationOptions?Override options

Returns: Promise<Record<string, TOutput | { error: Error }>> — Keys are variation-1, variation-2, etc. Uses Promise.allSettled internally.


OpenAITransmuter

OpenAI Chat Completions API transmuter.

ts
new OpenAITransmuter(config?: OpenAITransmuterConfig)

interface OpenAITransmuterConfig {
  apiKey?: string;       // Defaults to OPENAI_API_KEY env var
  defaultModel?: string; // Defaults to "gpt-4o-mini"
  baseURL?: string;      // Custom API endpoint
}

Material type mapping:

Material TypeOpenAI Format
textText content
imageImage URL or base64
documentText content or placeholder
dataFormatted text with label
audio / videoPlaceholder text

AnthropicTransmuter

Anthropic Messages API transmuter.

ts
new AnthropicTransmuter(config?: AnthropicTransmuterConfig)

interface AnthropicTransmuterConfig {
  apiKey?: string;       // Defaults to ANTHROPIC_API_KEY env var
  defaultModel?: string; // Defaults to "claude-sonnet-4-20250514"
}

Material type mapping:

Material TypeAnthropic Format
textText content
imageImage (base64 or URL)
documentText content or placeholder
dataFormatted text with label
audio / videoPlaceholder text

GoogleTransmuter

Google Generative AI (Gemini) transmuter.

ts
new GoogleTransmuter(config?: GoogleTransmuterConfig)

interface GoogleTransmuterConfig {
  apiKey?: string;       // Defaults to GOOGLE_API_KEY env var
  defaultModel?: string; // Defaults to "gemini-2.0-flash"
}

Material type mapping:

Material TypeGoogle Format
textText part
imageInline data (base64) or placeholder
documentText content or placeholder
dataFormatted text with label
audio / videoPlaceholder text

Node Transforms

FunctionDescription
imageUrlToBase64()Fetches remote images and converts to base64
documentToText()Extracts text from document parts
audioToText(options?)Audio transcription (stub available)
videoToFrames(options?)Video frame extraction (stub available)

@edv4h/alchemy-react

React hooks for building LLM-powered UIs. Peer dependency: react@^18 || ^19.

useTransmute<TOutput>

Low-level hook for single recipe execution.

ts
const {
  transmute,  // (recipeId, materials, options?) => Promise
  data,       // TOutput | null
  isLoading,  // boolean
  error,      // Error | null
  reset,      // () => void
} = useTransmute<TOutput>({
  baseUrl?: string;
  headers?: Record<string, string>;
});

Calls POST /api/transmute/{recipeId} with materials in the body. Supports request cancellation via AbortSignal.


useAlchemy<TOutput>

High-level orchestration hook combining useTransmute and useGenerate with full state management.

ts
const {
  // Recipe selection
  selectedRecipeId,
  selectRecipe,

  // Material selection (ID-based)
  selectedIds,
  toggleMaterial,
  clearSelection,

  // Language
  selectedLanguage,
  setLanguage,

  // Actions
  transmute,       // (materials) => Promise

  // Results
  result,          // TOutput | null
  isLoading,
  error,
  resetResults,
} = useAlchemy<TOutput>({
  baseUrl?: string;
  headers?: Record<string, string>;
  initialRecipeId: string;
});
State Reset Behavior

Changing the recipe resets results. Toggling materials resets results but preserves recipe selection.