promptopskit 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/LICENSE +211 -211
  2. package/README.md +382 -382
  3. package/dist/{chunk-FSOJVXC4.js → chunk-5BI5FP5L.js} +2 -2
  4. package/dist/chunk-5BI5FP5L.js.map +1 -0
  5. package/dist/{chunk-HEFOFQ2K.js → chunk-6KGBPHSY.js} +1 -1
  6. package/dist/chunk-6KGBPHSY.js.map +1 -0
  7. package/dist/{chunk-YCRWYE6N.js → chunk-PU3UPUND.js} +2 -2
  8. package/dist/chunk-PU3UPUND.js.map +1 -0
  9. package/dist/{chunk-HMYPMHTG.js → chunk-QDGJFINW.js} +1 -1
  10. package/dist/chunk-QDGJFINW.js.map +1 -0
  11. package/dist/{chunk-V375NQ6C.js → chunk-UYTUGV7Z.js} +2 -2
  12. package/dist/chunk-UYTUGV7Z.js.map +1 -0
  13. package/dist/{chunk-B5UFGNDV.js → chunk-VYVEVJC3.js} +2 -2
  14. package/dist/chunk-VYVEVJC3.js.map +1 -0
  15. package/dist/cli/index.js +0 -0
  16. package/dist/cli/index.js.map +1 -1
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.js +6 -6
  19. package/dist/index.js.map +1 -1
  20. package/dist/providers/anthropic.cjs.map +1 -1
  21. package/dist/providers/anthropic.js +2 -2
  22. package/dist/providers/gemini.cjs.map +1 -1
  23. package/dist/providers/gemini.js +2 -2
  24. package/dist/providers/openai.cjs.map +1 -1
  25. package/dist/providers/openai.js +2 -2
  26. package/dist/providers/openrouter.cjs.map +1 -1
  27. package/dist/providers/openrouter.js +3 -3
  28. package/dist/testing.cjs.map +1 -1
  29. package/dist/testing.js +1 -1
  30. package/dist/testing.js.map +1 -1
  31. package/package.json +117 -117
  32. package/dist/chunk-B5UFGNDV.js.map +0 -1
  33. package/dist/chunk-FSOJVXC4.js.map +0 -1
  34. package/dist/chunk-HEFOFQ2K.js.map +0 -1
  35. package/dist/chunk-HMYPMHTG.js.map +0 -1
  36. package/dist/chunk-V375NQ6C.js.map +0 -1
  37. package/dist/chunk-YCRWYE6N.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/parser/parser.ts","../src/schema/schema.ts","../src/parser/sections.ts","../src/parser/loader.ts","../src/composition/resolve-includes.ts","../src/overrides/apply-overrides.ts","../src/renderer/interpolate.ts","../src/renderer/renderer.ts","../src/providers/openai.ts","../src/providers/anthropic.ts","../src/providers/gemini.ts","../src/providers/openrouter.ts","../src/providers/index.ts","../src/validation/levenshtein.ts","../src/validation/validate.ts","../src/cache.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\r\nimport { existsSync, statSync } from 'node:fs';\r\nimport { resolve, join } from 'node:path';\r\n\r\nimport { parsePrompt, loadPromptFile } from './parser/index.js';\r\nimport { resolveIncludes } from './composition/index.js';\r\nimport { applyOverrides } from './overrides/index.js';\r\nimport { renderSections } from './renderer/index.js';\r\nimport { getAdapter } from './providers/index.js';\r\nimport { validateAsset } from './validation/index.js';\r\nimport { PromptCache } from './cache.js';\r\nimport type { PromptAsset, ResolvedPromptAsset } from './schema/index.js';\r\nimport type { ProviderRequest, RuntimeRenderOptions } from './providers/types.js';\r\nimport type { PromptValidationResult } from './validation/index.js';\r\n\r\n// --- Re-exports ---\r\nexport type { PromptAsset, ResolvedPromptAsset } from './schema/index.js';\r\nexport type { ProviderRequest, RuntimeRenderOptions, ProviderAdapter, ValidationResult } from './providers/types.js';\r\nexport type { PromptValidationResult, ValidationError } from './validation/index.js';\r\nexport type { RenderedSections, RenderOptions } from './renderer/index.js';\r\nexport type { ParseResult } from './parser/index.js';\r\nexport type { OverrideOptions } from './overrides/index.js';\r\n\r\nexport { parsePrompt, loadPromptFile, extractSections } from './parser/index.js';\r\nexport { interpolate, extractVariables } from './renderer/index.js';\r\nexport { resolveIncludes } from './composition/index.js';\r\nexport { applyOverrides } from './overrides/index.js';\r\nexport { validateAsset, validateAssetWithIncludes } from './validation/index.js';\r\nexport { getAdapter, openaiAdapter } from './providers/index.js';\r\nexport { anthropicAdapter } from './providers/anthropic.js';\r\nexport { geminiAdapter } from './providers/gemini.js';\r\nexport { openrouterAdapter } from './providers/openrouter.js';\r\nexport { PromptAssetSchema, PromptAssetOverridesSchema } from './schema/index.js';\r\n\r\n// --- Config ---\r\n\r\nexport interface PromptOpsKitConfig {\r\n sourceDir: string;\r\n compiledDir?: string;\r\n mode?: 'auto' | 'compiled-only' | 'source-only';\r\n cache?: boolean;\r\n}\r\n\r\n// --- Render options ---\r\n\r\nexport interface RenderPromptOptions {\r\n /** Prompt path (no extension), e.g. 'support/reply' */\r\n path?: string;\r\n /** Inline prompt source string (alternative to path) */\r\n source?: string;\r\n /** Provider name */\r\n provider: string;\r\n /** Environment override */\r\n environment?: string;\r\n /** Tier override */\r\n tier?: string;\r\n /** Variables for interpolation */\r\n variables?: Record<string, string>;\r\n /** Conversation history */\r\n history?: Array<{ role: string; content: string }>;\r\n /** Tool registry for resolving tool references */\r\n toolRegistry?: Record<string, unknown>;\r\n /** Strict mode — fail on missing variables */\r\n strict?: boolean;\r\n}\r\n\r\n// --- Result ---\r\n\r\nexport interface RenderResult {\r\n resolved: ResolvedPromptAsset;\r\n request: ProviderRequest;\r\n warnings: string[];\r\n}\r\n\r\n// --- Main class ---\r\n\r\nexport class PromptOpsKit {\r\n private config: Required<Pick<PromptOpsKitConfig, 'sourceDir' | 'mode'>> & PromptOpsKitConfig;\r\n private promptCache: PromptCache<PromptAsset>;\r\n\r\n constructor(config: PromptOpsKitConfig) {\r\n this.config = {\r\n ...config,\r\n mode: config.mode ?? 'auto',\r\n cache: config.cache ?? true,\r\n };\r\n this.promptCache = new PromptCache();\r\n }\r\n\r\n /**\r\n * Load a prompt asset from compiled or source, based on mode.\r\n */\r\n async loadPrompt(promptPath: string): Promise<PromptAsset> {\r\n const mode = this.config.mode;\r\n\r\n // Try compiled first (unless source-only)\r\n if (mode !== 'source-only' && this.config.compiledDir) {\r\n const compiledFile = resolve(this.config.compiledDir, promptPath + '.json');\r\n if (existsSync(compiledFile)) {\r\n // Check for stale artifact in auto mode\r\n if (mode === 'auto') {\r\n const sourceFile = resolve(this.config.sourceDir, promptPath + '.md');\r\n if (existsSync(sourceFile)) {\r\n const compiledMtime = statSync(compiledFile).mtimeMs;\r\n const sourceMtime = statSync(sourceFile).mtimeMs;\r\n if (sourceMtime > compiledMtime) {\r\n console.warn(\r\n `[promptopskit] Warning: compiled artifact for \"${promptPath}\" is older than source .md file.\\n` +\r\n ` Run \"promptopskit compile\" or switch to source-only mode.`,\r\n );\r\n }\r\n }\r\n }\r\n const content = await readFile(compiledFile, 'utf-8');\r\n return JSON.parse(content) as PromptAsset;\r\n }\r\n if (mode === 'compiled-only') {\r\n throw new Error(\r\n `Compiled artifact not found: ${compiledFile}\\n` +\r\n `Run \"promptopskit compile\" to generate it.`,\r\n );\r\n }\r\n }\r\n\r\n // Fall back to source\r\n if (mode !== 'compiled-only') {\r\n const sourceFile = resolve(this.config.sourceDir, promptPath + '.md');\r\n\r\n // Check cache\r\n if (this.config.cache) {\r\n const cached = this.promptCache.get(sourceFile);\r\n if (cached) return cached;\r\n }\r\n\r\n if (!existsSync(sourceFile)) {\r\n const paths = [sourceFile];\r\n if (this.config.compiledDir) {\r\n paths.unshift(resolve(this.config.compiledDir, promptPath + '.json'));\r\n }\r\n throw new Error(\r\n `Prompt not found: \"${promptPath}\"\\nSearched:\\n${paths.map((p) => ` - ${p}`).join('\\n')}`,\r\n );\r\n }\r\n\r\n const { asset } = await loadPromptFile(sourceFile, { defaultsRoot: this.config.sourceDir });\r\n\r\n if (this.config.cache) {\r\n this.promptCache.set(sourceFile, asset);\r\n }\r\n\r\n return asset;\r\n }\r\n\r\n throw new Error(`Prompt not found: \"${promptPath}\"`);\r\n }\r\n\r\n /**\r\n * Resolve a prompt: load, resolve includes, apply overrides.\r\n */\r\n async resolvePrompt(\r\n promptPath: string,\r\n options: { environment?: string; tier?: string } = {},\r\n ): Promise<ResolvedPromptAsset> {\r\n let asset = await this.loadPrompt(promptPath);\r\n\r\n // Resolve includes\r\n const sourceFile = resolve(this.config.sourceDir, promptPath + '.md');\r\n if (asset.includes && asset.includes.length > 0 && existsSync(sourceFile)) {\r\n asset = await resolveIncludes(asset, sourceFile);\r\n }\r\n\r\n // Apply overrides\r\n asset = applyOverrides(asset, {\r\n environment: options.environment,\r\n tier: options.tier,\r\n });\r\n\r\n return asset as ResolvedPromptAsset;\r\n }\r\n\r\n /**\r\n * Render a prompt for a specific provider.\r\n */\r\n async renderPrompt(options: RenderPromptOptions): Promise<RenderResult> {\r\n let resolved: ResolvedPromptAsset;\r\n\r\n if (options.source) {\r\n // Inline source mode\r\n const { asset } = parsePrompt(options.source);\r\n const overridden = applyOverrides(asset, {\r\n environment: options.environment,\r\n tier: options.tier,\r\n });\r\n resolved = overridden as ResolvedPromptAsset;\r\n } else if (options.path) {\r\n resolved = await this.resolvePrompt(options.path, {\r\n environment: options.environment,\r\n tier: options.tier,\r\n });\r\n } else {\r\n throw new Error('Either \"path\" or \"source\" must be provided to renderPrompt()');\r\n }\r\n\r\n const adapter = getAdapter(options.provider);\r\n const validation = adapter.validate(resolved);\r\n\r\n if (!validation.valid) {\r\n throw new Error(\r\n `Provider validation failed for \"${options.provider}\":\\n` +\r\n validation.errors.map((e) => ` - ${e}`).join('\\n'),\r\n );\r\n }\r\n\r\n const request = adapter.render(resolved, {\r\n variables: options.variables,\r\n history: options.history,\r\n toolRegistry: options.toolRegistry,\r\n strict: options.strict,\r\n });\r\n\r\n return {\r\n resolved,\r\n request,\r\n warnings: validation.warnings,\r\n };\r\n }\r\n\r\n /**\r\n * Validate a prompt file.\r\n */\r\n async validatePrompt(promptPath: string): Promise<PromptValidationResult> {\r\n const asset = await this.loadPrompt(promptPath);\r\n return validateAsset(asset, undefined, promptPath);\r\n }\r\n\r\n /**\r\n * Clear the internal cache.\r\n */\r\n clearCache(): void {\r\n this.promptCache.clear();\r\n }\r\n}\r\n\r\n// --- Factory ---\r\n\r\nexport function createPromptOpsKit(config: PromptOpsKitConfig): PromptOpsKit {\r\n return new PromptOpsKit(config);\r\n}\r\n\r\n// --- Standalone convenience ---\r\n\r\n/**\r\n * Standalone renderPrompt for quick usage without creating a PromptOpsKit instance.\r\n * Requires either `source` (inline) or `path` + implicit sourceDir of '.'.\r\n */\r\nexport async function renderPrompt(\r\n options: RenderPromptOptions & { sourceDir?: string },\r\n): Promise<RenderResult> {\r\n const kit = createPromptOpsKit({\r\n sourceDir: options.sourceDir ?? '.',\r\n cache: false,\r\n });\r\n return kit.renderPrompt(options);\r\n}\r\n","import matter from 'gray-matter';\r\nimport { PromptAssetSchema } from '../schema/index.js';\r\nimport type { PromptAsset } from '../schema/index.js';\r\nimport { extractSections } from './sections.js';\r\n\r\nexport interface ParseResult {\r\n asset: PromptAsset;\r\n raw: {\r\n frontMatter: Record<string, unknown>;\r\n body: string;\r\n };\r\n}\r\n\r\n/**\r\n * Parse a prompt markdown string (YAML front matter + markdown body)\r\n * into a validated PromptAsset.\r\n */\r\nexport function parsePrompt(content: string, filePath?: string): ParseResult {\r\n const { data: frontMatter, content: body } = matter(content);\r\n\r\n const sections = extractSections(body);\r\n\r\n const raw = {\r\n ...frontMatter,\r\n sections,\r\n source: filePath ? { file_path: filePath } : undefined,\r\n };\r\n\r\n const asset = PromptAssetSchema.parse(raw);\r\n\r\n return {\r\n asset,\r\n raw: {\r\n frontMatter: frontMatter as Record<string, unknown>,\r\n body,\r\n },\r\n };\r\n}\r\n","import { z } from 'zod';\r\n\r\n// --- Tool definitions ---\r\n\r\nexport const InlineToolDefSchema = z.object({\r\n name: z.string(),\r\n description: z.string().optional(),\r\n input_schema: z.record(z.unknown()).optional(),\r\n});\r\n\r\nexport type InlineToolDef = z.infer<typeof InlineToolDefSchema>;\r\n\r\nexport const ToolRefSchema = z.union([z.string(), InlineToolDefSchema]);\r\n\r\n// --- MCP ---\r\n\r\nexport const MCPServerRefSchema = z.union([\r\n z.string(),\r\n z.object({\r\n name: z.string(),\r\n config: z.record(z.unknown()).optional(),\r\n }),\r\n]);\r\n\r\nexport type MCPServerRef = z.infer<typeof MCPServerRefSchema>;\r\n\r\n// --- Reasoning ---\r\n\r\nexport const ReasoningSchema = z.object({\r\n effort: z.enum(['low', 'medium', 'high']).optional(),\r\n budget_tokens: z.number().int().positive().optional(),\r\n});\r\n\r\n// --- Sampling ---\r\n\r\nexport const SamplingSchema = z.object({\r\n temperature: z.number().min(0).max(2).optional(),\r\n top_p: z.number().min(0).max(1).optional(),\r\n frequency_penalty: z.number().optional(),\r\n presence_penalty: z.number().optional(),\r\n stop: z.array(z.string()).optional(),\r\n max_output_tokens: z.number().int().positive().optional(),\r\n});\r\n\r\n// --- Response ---\r\n\r\nexport const ResponseSchema = z.object({\r\n format: z.enum(['text', 'json', 'markdown']).optional(),\r\n stream: z.boolean().optional(),\r\n});\r\n\r\n// --- Context ---\r\n\r\nexport const HistorySchema = z.object({\r\n max_items: z.number().int().positive().optional(),\r\n});\r\n\r\nexport const ContextSchema = z.object({\r\n inputs: z.array(z.string()).optional(),\r\n history: HistorySchema.optional(),\r\n});\r\n\r\n// --- Metadata ---\r\n\r\nexport const MetadataSchema = z.object({\r\n owner: z.string().optional(),\r\n tags: z.array(z.string()).optional(),\r\n review_required: z.boolean().optional(),\r\n stable: z.boolean().optional(),\r\n});\r\n\r\n// --- MCP block ---\r\n\r\nexport const MCPSchema = z.object({\r\n servers: z.array(MCPServerRefSchema).optional(),\r\n});\r\n\r\n// --- Overrides (subset allowed in environments/tiers) ---\r\n\r\nexport const PromptAssetOverridesSchema = z.object({\r\n model: z.string().optional(),\r\n fallback_models: z.array(z.string()).optional(),\r\n reasoning: ReasoningSchema.optional(),\r\n sampling: SamplingSchema.optional(),\r\n response: ResponseSchema.optional(),\r\n tools: z.array(ToolRefSchema).optional(),\r\n});\r\n\r\nexport type PromptAssetOverrides = z.infer<typeof PromptAssetOverridesSchema>;\r\n\r\n// --- Source tracking ---\r\n\r\nexport const SourceSchema = z.object({\r\n file_path: z.string().optional(),\r\n checksum: z.string().optional(),\r\n});\r\n\r\n// --- Sections (populated by parser) ---\r\n\r\nexport const SectionsSchema = z.object({\r\n system_instructions: z.string().optional(),\r\n prompt_template: z.string().optional(),\r\n notes: z.string().optional(),\r\n});\r\n\r\n// --- Defaults files (folder-level inheritance) ---\r\n\r\nexport const PromptDefaultsSchema = z.object({\r\n metadata: MetadataSchema.optional(),\r\n sections: z.object({\r\n system_instructions: z.string().optional(),\r\n }).optional(),\r\n});\r\n\r\nexport type PromptDefaults = z.infer<typeof PromptDefaultsSchema>;\r\n\r\n// --- Top-level PromptAsset ---\r\n\r\nexport const PromptAssetSchema = z.object({\r\n id: z.string(),\r\n schema_version: z.number().int().positive().default(1),\r\n description: z.string().optional(),\r\n\r\n provider: z.enum(['openai', 'anthropic', 'google', 'gemini', 'openrouter', 'any']).optional(),\r\n model: z.string().optional(),\r\n fallback_models: z.array(z.string()).optional(),\r\n\r\n reasoning: ReasoningSchema.optional(),\r\n sampling: SamplingSchema.optional(),\r\n response: ResponseSchema.optional(),\r\n\r\n tools: z.array(ToolRefSchema).optional(),\r\n mcp: MCPSchema.optional(),\r\n\r\n context: ContextSchema.optional(),\r\n\r\n includes: z.array(z.string()).optional(),\r\n\r\n environments: z.record(PromptAssetOverridesSchema).optional(),\r\n tiers: z.record(PromptAssetOverridesSchema).optional(),\r\n\r\n metadata: MetadataSchema.optional(),\r\n\r\n // Populated by parser, not authored in YAML\r\n sections: SectionsSchema.optional(),\r\n source: SourceSchema.optional(),\r\n});\r\n\r\nexport type PromptAsset = z.infer<typeof PromptAssetSchema>;\r\n\r\n// --- Resolved asset (after includes, overrides applied) ---\r\n\r\nexport interface ResolvedPromptAsset extends PromptAsset {\r\n sections: {\r\n system_instructions?: string;\r\n prompt_template?: string;\r\n notes?: string;\r\n };\r\n source: {\r\n file_path?: string;\r\n checksum?: string;\r\n };\r\n}\r\n","export interface Sections {\r\n system_instructions?: string;\r\n prompt_template?: string;\r\n notes?: string;\r\n}\r\n\r\nconst SECTION_MAP: Record<string, keyof Sections> = {\r\n 'system instructions': 'system_instructions',\r\n 'prompt template': 'prompt_template',\r\n 'notes': 'notes',\r\n};\r\n\r\n/**\r\n * Extract named sections from the markdown body using H1 headings.\r\n * Case-insensitive. H2+ within a section is treated as content.\r\n * If no H1 headings are found, the entire body is treated as prompt_template.\r\n */\r\nexport function extractSections(body: string): Sections {\r\n const lines = body.split('\\n');\r\n const sections: Sections = {};\r\n\r\n let currentKey: keyof Sections | null = null;\r\n let currentLines: string[] = [];\r\n let foundAnyH1 = false;\r\n\r\n for (const line of lines) {\r\n const h1Match = line.match(/^#\\s+(.+)$/);\r\n if (h1Match) {\r\n // Flush previous section\r\n if (currentKey) {\r\n sections[currentKey] = currentLines.join('\\n').trim();\r\n }\r\n\r\n foundAnyH1 = true;\r\n const heading = h1Match[1].trim().toLowerCase();\r\n currentKey = SECTION_MAP[heading] ?? null;\r\n currentLines = [];\r\n } else {\r\n currentLines.push(line);\r\n }\r\n }\r\n\r\n // Flush last section\r\n if (currentKey) {\r\n sections[currentKey] = currentLines.join('\\n').trim();\r\n }\r\n\r\n // If no H1 headings found, treat entire body as prompt_template\r\n if (!foundAnyH1) {\r\n const trimmed = body.trim();\r\n if (trimmed) {\r\n sections.prompt_template = trimmed;\r\n }\r\n }\r\n\r\n return sections;\r\n}\r\n","import { readFile } from 'node:fs/promises';\r\nimport { dirname, join, resolve } from 'node:path';\r\nimport matter from 'gray-matter';\r\nimport { parsePrompt } from './parser.js';\r\nimport type { ParseResult } from './parser.js';\r\nimport { extractSections } from './sections.js';\r\nimport { PromptDefaultsSchema } from '../schema/index.js';\r\nimport type { PromptDefaults } from '../schema/index.js';\r\n\r\nconst DEFAULTS_FILE_NAME = 'defaults.md';\r\n\r\nexport interface LoadPromptOptions {\r\n /**\r\n * Optional boundary directory for defaults discovery.\r\n * If provided, defaults are loaded from this directory down to the prompt directory.\r\n */\r\n defaultsRoot?: string;\r\n}\r\n\r\n/**\r\n * Load and parse a prompt file from disk.\r\n */\r\nexport async function loadPromptFile(filePath: string, options: LoadPromptOptions = {}): Promise<ParseResult> {\r\n const content = await readFile(filePath, 'utf-8');\r\n const parsed = parsePrompt(content, filePath);\r\n // Default the boundary to the file's own directory so traversal never\r\n // walks above the prompt tree when no explicit root is provided.\r\n const root = options.defaultsRoot ?? dirname(filePath);\r\n const defaults = await loadDefaultsForPath(filePath, root);\r\n const asset = applyDefaults(parsed.asset, defaults);\r\n\r\n return {\r\n ...parsed,\r\n asset,\r\n };\r\n}\r\n\r\nasync function loadDefaultsForPath(filePath: string, defaultsRoot?: string): Promise<PromptDefaults> {\r\n const directories = getDirectoriesToCheck(filePath, defaultsRoot);\r\n let merged: PromptDefaults = {};\r\n\r\n for (const dir of directories) {\r\n const defaultsPath = join(dir, DEFAULTS_FILE_NAME);\r\n try {\r\n const defaultsContent = await readFile(defaultsPath, 'utf-8');\r\n const defaults = parseDefaults(defaultsContent);\r\n merged = mergeDefaults(merged, defaults);\r\n } catch (error) {\r\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\r\n throw error;\r\n }\r\n }\r\n }\r\n\r\n return merged;\r\n}\r\n\r\nfunction getDirectoriesToCheck(filePath: string, defaultsRoot?: string): string[] {\r\n const dirs: string[] = [];\r\n let current = resolve(dirname(filePath));\r\n const boundary = defaultsRoot ? resolve(defaultsRoot) : undefined;\r\n\r\n while (true) {\r\n dirs.unshift(current);\r\n if ((boundary && current === boundary) || current === dirname(current)) {\r\n break;\r\n }\r\n current = dirname(current);\r\n }\r\n\r\n return dirs;\r\n}\r\n\r\nfunction parseDefaults(content: string): PromptDefaults {\r\n const { data: frontMatter, content: body } = matter(content);\r\n const sections = extractSections(body);\r\n\r\n return PromptDefaultsSchema.parse({\r\n ...frontMatter,\r\n sections: {\r\n system_instructions: sections.system_instructions,\r\n },\r\n });\r\n}\r\n\r\nfunction mergeDefaults(base: PromptDefaults, local: PromptDefaults): PromptDefaults {\r\n return {\r\n metadata: {\r\n ...(base.metadata ?? {}),\r\n ...(local.metadata ?? {}),\r\n },\r\n sections: {\r\n ...(base.sections ?? {}),\r\n ...(local.sections ?? {}),\r\n },\r\n };\r\n}\r\n\r\nfunction applyDefaults(asset: ParseResult['asset'], defaults: PromptDefaults): ParseResult['asset'] {\r\n const hasDefaultMetadata = defaults.metadata && Object.keys(defaults.metadata).length > 0;\r\n const hasDefaultSystem = !!defaults.sections?.system_instructions;\r\n\r\n // Short-circuit: nothing to merge\r\n if (!hasDefaultMetadata && !hasDefaultSystem) {\r\n return asset;\r\n }\r\n\r\n const mergedMetadata = {\r\n ...(defaults.metadata ?? {}),\r\n ...(asset.metadata ?? {}),\r\n };\r\n const metadata = Object.keys(mergedMetadata).length > 0 ? mergedMetadata : undefined;\r\n\r\n const systemInstructions = asset.sections?.system_instructions ?? defaults.sections?.system_instructions;\r\n\r\n const sections = asset.sections\r\n ? { ...asset.sections, system_instructions: systemInstructions }\r\n : systemInstructions\r\n ? { system_instructions: systemInstructions }\r\n : undefined;\r\n\r\n return {\r\n ...asset,\r\n metadata,\r\n sections,\r\n };\r\n}\r\n","import { readFile } from 'node:fs/promises';\r\nimport { resolve, dirname } from 'node:path';\r\nimport { parsePrompt } from '../parser/index.js';\r\nimport type { PromptAsset } from '../schema/index.js';\r\n\r\n/**\r\n * Resolve includes for a prompt asset, inlining content from referenced files.\r\n * Detects and rejects circular includes.\r\n */\r\nexport async function resolveIncludes(\r\n asset: PromptAsset,\r\n basePath: string,\r\n visited: Set<string> = new Set(),\r\n): Promise<PromptAsset> {\r\n if (!asset.includes || asset.includes.length === 0) {\r\n return asset;\r\n }\r\n\r\n const baseDir = dirname(basePath);\r\n const resolvedPath = resolve(basePath);\r\n\r\n if (visited.has(resolvedPath)) {\r\n throw new Error(`Circular include detected: ${resolvedPath}`);\r\n }\r\n visited.add(resolvedPath);\r\n\r\n let mergedSystemInstructions = '';\r\n\r\n for (const includePath of asset.includes) {\r\n const fullPath = resolve(baseDir, includePath);\r\n\r\n if (visited.has(fullPath)) {\r\n throw new Error(`Circular include detected: ${fullPath} (included from ${basePath})`);\r\n }\r\n\r\n const content = await readFile(fullPath, 'utf-8');\r\n const { asset: includedAsset } = parsePrompt(content, fullPath);\r\n\r\n // Recursively resolve nested includes\r\n const resolved = await resolveIncludes(includedAsset, fullPath, new Set(visited));\r\n\r\n // Append included system instructions before local ones\r\n if (resolved.sections?.system_instructions) {\r\n mergedSystemInstructions += resolved.sections.system_instructions + '\\n\\n';\r\n }\r\n }\r\n\r\n // Prepend included system instructions before the local ones\r\n const localSystem = asset.sections?.system_instructions ?? '';\r\n const combinedSystem = (mergedSystemInstructions + localSystem).trim() || undefined;\r\n\r\n return {\r\n ...asset,\r\n sections: {\r\n ...asset.sections,\r\n system_instructions: combinedSystem,\r\n },\r\n // Drop includes from the resolved asset — they've been inlined\r\n includes: undefined,\r\n };\r\n}\r\n","import type { PromptAsset, PromptAssetOverrides } from '../schema/index.js';\r\n\r\nexport interface OverrideOptions {\r\n environment?: string;\r\n tier?: string;\r\n runtime?: Partial<PromptAssetOverrides>;\r\n}\r\n\r\n/**\r\n * Apply environment, tier, and runtime overrides to a prompt asset.\r\n *\r\n * Precedence: base → environment → tier → runtime\r\n * Scalars are replaced. Arrays are replaced (not concatenated).\r\n */\r\nexport function applyOverrides(\r\n asset: PromptAsset,\r\n options: OverrideOptions = {},\r\n): PromptAsset {\r\n let result = { ...asset };\r\n\r\n // Apply environment override\r\n if (options.environment && result.environments?.[options.environment]) {\r\n result = mergeOverride(result, result.environments[options.environment]);\r\n }\r\n\r\n // Apply tier override\r\n if (options.tier && result.tiers?.[options.tier]) {\r\n result = mergeOverride(result, result.tiers[options.tier]);\r\n }\r\n\r\n // Apply runtime overrides\r\n if (options.runtime) {\r\n result = mergeOverride(result, options.runtime);\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction mergeOverride(\r\n base: PromptAsset,\r\n override: Partial<PromptAssetOverrides>,\r\n): PromptAsset {\r\n const result = { ...base };\r\n\r\n if (override.model !== undefined) result.model = override.model;\r\n if (override.fallback_models !== undefined) result.fallback_models = override.fallback_models;\r\n if (override.tools !== undefined) result.tools = override.tools;\r\n\r\n if (override.reasoning !== undefined) {\r\n result.reasoning = { ...result.reasoning, ...override.reasoning };\r\n }\r\n if (override.sampling !== undefined) {\r\n result.sampling = { ...result.sampling, ...override.sampling };\r\n }\r\n if (override.response !== undefined) {\r\n result.response = { ...result.response, ...override.response };\r\n }\r\n\r\n return result;\r\n}\r\n","export interface InterpolateOptions {\r\n strict?: boolean;\r\n}\r\n\r\nconst VARIABLE_RE = /\\{\\{\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\}\\}/g;\r\nconst ESCAPED_OPEN = /\\\\\\{\\\\\\{/g;\r\nconst ESCAPE_PLACEHOLDER = '\\x00ESCAPED_OPEN\\x00';\r\n\r\n/**\r\n * Interpolate variables into a template string.\r\n *\r\n * Syntax: {{ variable_name }}\r\n * Escape: \\{\\{ produces literal {{\r\n *\r\n * In strict mode, throws on missing variables.\r\n * In permissive mode, leaves {{ placeholder }} intact.\r\n */\r\nexport function interpolate(\r\n template: string,\r\n variables: Record<string, string>,\r\n options: InterpolateOptions = {},\r\n): string {\r\n const { strict = false } = options;\r\n\r\n // Replace escaped sequences with placeholder\r\n let result = template.replace(ESCAPED_OPEN, ESCAPE_PLACEHOLDER);\r\n\r\n result = result.replace(VARIABLE_RE, (match, name: string) => {\r\n if (name in variables) {\r\n return variables[name];\r\n }\r\n if (strict) {\r\n throw new Error(`Missing required variable: \"${name}\"`);\r\n }\r\n return match; // leave placeholder intact in permissive mode\r\n });\r\n\r\n // Restore escaped sequences\r\n result = result.replaceAll(ESCAPE_PLACEHOLDER, '{{');\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Extract all variable names referenced in a template.\r\n */\r\nexport function extractVariables(template: string): string[] {\r\n const vars = new Set<string>();\r\n let match: RegExpExecArray | null;\r\n const re = new RegExp(VARIABLE_RE.source, 'g');\r\n while ((match = re.exec(template)) !== null) {\r\n vars.add(match[1]);\r\n }\r\n return [...vars];\r\n}\r\n","import type { ResolvedPromptAsset } from '../schema/index.js';\r\nimport { interpolate, extractVariables } from './interpolate.js';\r\n\r\nexport interface RenderOptions {\r\n variables?: Record<string, string>;\r\n strict?: boolean;\r\n}\r\n\r\nexport interface RenderedSections {\r\n system_instructions?: string;\r\n prompt_template?: string;\r\n}\r\n\r\n/**\r\n * Render the sections of a resolved prompt asset with variable interpolation.\r\n */\r\nexport function renderSections(\r\n asset: ResolvedPromptAsset,\r\n options: RenderOptions = {},\r\n): RenderedSections {\r\n const { variables = {}, strict = false } = options;\r\n\r\n const result: RenderedSections = {};\r\n\r\n if (asset.sections.system_instructions) {\r\n result.system_instructions = interpolate(\r\n asset.sections.system_instructions,\r\n variables,\r\n { strict },\r\n );\r\n }\r\n\r\n if (asset.sections.prompt_template) {\r\n result.prompt_template = interpolate(\r\n asset.sections.prompt_template,\r\n variables,\r\n { strict },\r\n );\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Get all variable names used across all sections.\r\n */\r\nexport function getRequiredVariables(asset: ResolvedPromptAsset): string[] {\r\n const vars = new Set<string>();\r\n\r\n if (asset.sections.system_instructions) {\r\n for (const v of extractVariables(asset.sections.system_instructions)) {\r\n vars.add(v);\r\n }\r\n }\r\n\r\n if (asset.sections.prompt_template) {\r\n for (const v of extractVariables(asset.sections.prompt_template)) {\r\n vars.add(v);\r\n }\r\n }\r\n\r\n return [...vars];\r\n}\r\n","import type { ResolvedPromptAsset } from '../schema/index.js';\r\nimport type {\r\n ProviderAdapter,\r\n ProviderRequest,\r\n ValidationResult,\r\n RuntimeRenderOptions,\r\n} from './types.js';\r\nimport { renderSections } from '../renderer/index.js';\r\n\r\n/**\r\n * OpenAI provider adapter.\r\n * Produces request bodies compatible with the OpenAI Chat Completions API.\r\n */\r\nexport const openaiAdapter: ProviderAdapter = {\r\n name: 'openai',\r\n\r\n validate(asset: ResolvedPromptAsset): ValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!asset.model) {\r\n errors.push('OpenAI adapter requires a model to be specified.');\r\n }\r\n\r\n if (asset.reasoning?.budget_tokens !== undefined) {\r\n warnings.push('OpenAI uses reasoning_effort, not budget_tokens. budget_tokens will be ignored.');\r\n }\r\n\r\n return { valid: errors.length === 0, errors, warnings };\r\n },\r\n\r\n render(asset: ResolvedPromptAsset, runtime: RuntimeRenderOptions): ProviderRequest {\r\n const sections = renderSections(asset, {\r\n variables: runtime.variables,\r\n strict: runtime.strict,\r\n });\r\n\r\n const messages: Array<Record<string, unknown>> = [];\r\n\r\n // System message\r\n if (sections.system_instructions) {\r\n messages.push({ role: 'system', content: sections.system_instructions });\r\n }\r\n\r\n // History\r\n if (runtime.history) {\r\n for (const msg of runtime.history) {\r\n messages.push({ role: msg.role, content: msg.content });\r\n }\r\n }\r\n\r\n // User message (prompt template)\r\n if (sections.prompt_template) {\r\n messages.push({ role: 'user', content: sections.prompt_template });\r\n }\r\n\r\n const body: Record<string, unknown> = {\r\n model: asset.model,\r\n messages,\r\n };\r\n\r\n // Sampling params\r\n if (asset.sampling?.temperature !== undefined) body.temperature = asset.sampling.temperature;\r\n if (asset.sampling?.top_p !== undefined) body.top_p = asset.sampling.top_p;\r\n if (asset.sampling?.frequency_penalty !== undefined) body.frequency_penalty = asset.sampling.frequency_penalty;\r\n if (asset.sampling?.presence_penalty !== undefined) body.presence_penalty = asset.sampling.presence_penalty;\r\n if (asset.sampling?.stop !== undefined) body.stop = asset.sampling.stop;\r\n if (asset.sampling?.max_output_tokens !== undefined) body.max_tokens = asset.sampling.max_output_tokens;\r\n\r\n // Reasoning\r\n if (asset.reasoning?.effort) {\r\n body.reasoning_effort = asset.reasoning.effort;\r\n }\r\n\r\n // Response format\r\n if (asset.response?.format === 'json') {\r\n body.response_format = { type: 'json_object' };\r\n }\r\n\r\n // Streaming\r\n if (asset.response?.stream !== undefined) {\r\n body.stream = asset.response.stream;\r\n }\r\n\r\n // Tools\r\n if (asset.tools && asset.tools.length > 0) {\r\n body.tools = asset.tools.map((tool) => {\r\n if (typeof tool === 'string') {\r\n // Look up from registry\r\n const def = runtime.toolRegistry?.[tool];\r\n if (def) return def;\r\n return { type: 'function', function: { name: tool } };\r\n }\r\n return {\r\n type: 'function',\r\n function: {\r\n name: tool.name,\r\n description: tool.description,\r\n parameters: tool.input_schema,\r\n },\r\n };\r\n });\r\n }\r\n\r\n return {\r\n body,\r\n provider: 'openai',\r\n model: asset.model ?? 'unknown',\r\n };\r\n },\r\n};\r\n","import type { ResolvedPromptAsset } from '../schema/index.js';\r\nimport type {\r\n ProviderAdapter,\r\n ProviderRequest,\r\n ValidationResult,\r\n RuntimeRenderOptions,\r\n} from './types.js';\r\nimport { renderSections } from '../renderer/index.js';\r\n\r\n/**\r\n * Anthropic provider adapter.\r\n * Produces request bodies compatible with the Anthropic Messages API.\r\n */\r\nexport const anthropicAdapter: ProviderAdapter = {\r\n name: 'anthropic',\r\n\r\n validate(asset: ResolvedPromptAsset): ValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!asset.model) {\r\n errors.push('Anthropic adapter requires a model to be specified.');\r\n }\r\n\r\n if (asset.sampling?.frequency_penalty !== undefined) {\r\n warnings.push('Anthropic does not support frequency_penalty. It will be ignored.');\r\n }\r\n if (asset.sampling?.presence_penalty !== undefined) {\r\n warnings.push('Anthropic does not support presence_penalty. It will be ignored.');\r\n }\r\n if (asset.reasoning?.effort !== undefined) {\r\n warnings.push('Anthropic uses budget_tokens for thinking, not effort. effort will be mapped approximately.');\r\n }\r\n\r\n return { valid: errors.length === 0, errors, warnings };\r\n },\r\n\r\n render(asset: ResolvedPromptAsset, runtime: RuntimeRenderOptions): ProviderRequest {\r\n const sections = renderSections(asset, {\r\n variables: runtime.variables,\r\n strict: runtime.strict,\r\n });\r\n\r\n const messages: Array<Record<string, unknown>> = [];\r\n\r\n // History\r\n if (runtime.history) {\r\n for (const msg of runtime.history) {\r\n messages.push({ role: msg.role, content: msg.content });\r\n }\r\n }\r\n\r\n // User message (prompt template)\r\n if (sections.prompt_template) {\r\n messages.push({ role: 'user', content: sections.prompt_template });\r\n }\r\n\r\n const body: Record<string, unknown> = {\r\n model: asset.model,\r\n messages,\r\n };\r\n\r\n // System goes as top-level field in Anthropic\r\n if (sections.system_instructions) {\r\n body.system = sections.system_instructions;\r\n }\r\n\r\n // Sampling params\r\n if (asset.sampling?.temperature !== undefined) body.temperature = asset.sampling.temperature;\r\n if (asset.sampling?.top_p !== undefined) body.top_p = asset.sampling.top_p;\r\n if (asset.sampling?.stop !== undefined) body.stop_sequences = asset.sampling.stop;\r\n if (asset.sampling?.max_output_tokens !== undefined) {\r\n body.max_tokens = asset.sampling.max_output_tokens;\r\n } else {\r\n // Anthropic requires max_tokens\r\n body.max_tokens = 4096;\r\n }\r\n\r\n // Thinking/reasoning\r\n if (asset.reasoning?.budget_tokens) {\r\n body.thinking = {\r\n type: 'enabled',\r\n budget_tokens: asset.reasoning.budget_tokens,\r\n };\r\n }\r\n\r\n // Streaming\r\n if (asset.response?.stream !== undefined) {\r\n body.stream = asset.response.stream;\r\n }\r\n\r\n // Tools\r\n if (asset.tools && asset.tools.length > 0) {\r\n body.tools = asset.tools.map((tool) => {\r\n if (typeof tool === 'string') {\r\n const def = runtime.toolRegistry?.[tool];\r\n if (def) return def;\r\n return { name: tool };\r\n }\r\n return {\r\n name: tool.name,\r\n description: tool.description,\r\n input_schema: tool.input_schema ?? { type: 'object', properties: {} },\r\n };\r\n });\r\n }\r\n\r\n return {\r\n body,\r\n provider: 'anthropic',\r\n model: asset.model ?? 'unknown',\r\n };\r\n },\r\n};\r\n","import type { ResolvedPromptAsset } from '../schema/index.js';\r\nimport type {\r\n ProviderAdapter,\r\n ProviderRequest,\r\n ValidationResult,\r\n RuntimeRenderOptions,\r\n} from './types.js';\r\nimport { renderSections } from '../renderer/index.js';\r\n\r\n/**\r\n * Google Gemini provider adapter.\r\n * Produces request bodies compatible with the Gemini generateContent API.\r\n */\r\nexport const geminiAdapter: ProviderAdapter = {\r\n name: 'gemini',\r\n\r\n validate(asset: ResolvedPromptAsset): ValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!asset.model) {\r\n errors.push('Gemini adapter requires a model to be specified.');\r\n }\r\n\r\n if (asset.sampling?.frequency_penalty !== undefined) {\r\n warnings.push('Gemini does not support frequency_penalty. It will be ignored.');\r\n }\r\n if (asset.sampling?.presence_penalty !== undefined) {\r\n warnings.push('Gemini does not support presence_penalty. It will be ignored.');\r\n }\r\n\r\n return { valid: errors.length === 0, errors, warnings };\r\n },\r\n\r\n render(asset: ResolvedPromptAsset, runtime: RuntimeRenderOptions): ProviderRequest {\r\n const sections = renderSections(asset, {\r\n variables: runtime.variables,\r\n strict: runtime.strict,\r\n });\r\n\r\n const contents: Array<Record<string, unknown>> = [];\r\n\r\n // History\r\n if (runtime.history) {\r\n for (const msg of runtime.history) {\r\n contents.push({\r\n role: msg.role === 'assistant' ? 'model' : 'user',\r\n parts: [{ text: msg.content }],\r\n });\r\n }\r\n }\r\n\r\n // User message (prompt template)\r\n if (sections.prompt_template) {\r\n contents.push({\r\n role: 'user',\r\n parts: [{ text: sections.prompt_template }],\r\n });\r\n }\r\n\r\n const body: Record<string, unknown> = {\r\n contents,\r\n };\r\n\r\n // System instruction\r\n if (sections.system_instructions) {\r\n body.systemInstruction = {\r\n parts: [{ text: sections.system_instructions }],\r\n };\r\n }\r\n\r\n // Generation config\r\n const generationConfig: Record<string, unknown> = {};\r\n\r\n if (asset.sampling?.temperature !== undefined) generationConfig.temperature = asset.sampling.temperature;\r\n if (asset.sampling?.top_p !== undefined) generationConfig.topP = asset.sampling.top_p;\r\n if (asset.sampling?.max_output_tokens !== undefined) generationConfig.maxOutputTokens = asset.sampling.max_output_tokens;\r\n if (asset.sampling?.stop !== undefined) generationConfig.stopSequences = asset.sampling.stop;\r\n\r\n if (asset.response?.format === 'json') {\r\n generationConfig.responseMimeType = 'application/json';\r\n }\r\n\r\n // Thinking config\r\n if (asset.reasoning?.effort) {\r\n body.thinkingConfig = {\r\n thinkingBudget: asset.reasoning.effort === 'high' ? 8192 : asset.reasoning.effort === 'medium' ? 4096 : 1024,\r\n };\r\n }\r\n\r\n if (Object.keys(generationConfig).length > 0) {\r\n body.generationConfig = generationConfig;\r\n }\r\n\r\n // Tools\r\n if (asset.tools && asset.tools.length > 0) {\r\n const functionDeclarations = asset.tools.map((tool) => {\r\n if (typeof tool === 'string') {\r\n const def = runtime.toolRegistry?.[tool];\r\n if (def) return def;\r\n return { name: tool };\r\n }\r\n return {\r\n name: tool.name,\r\n description: tool.description,\r\n parameters: tool.input_schema,\r\n };\r\n });\r\n body.tools = [{ functionDeclarations }];\r\n }\r\n\r\n return {\r\n body,\r\n provider: 'gemini',\r\n model: asset.model ?? 'unknown',\r\n };\r\n },\r\n};\r\n","import { openaiAdapter } from './openai.js';\r\nimport type { ResolvedPromptAsset } from '../schema/index.js';\r\nimport type {\r\n ProviderAdapter,\r\n ProviderRequest,\r\n ValidationResult,\r\n RuntimeRenderOptions,\r\n} from './types.js';\r\n\r\n/**\r\n * OpenRouter provider adapter.\r\n * Thin preset over the OpenAI adapter — body format is identical,\r\n * only the provider label differs. The app handles the different\r\n * base URL and extra headers (HTTP-Referer, X-Title).\r\n */\r\nexport const openrouterAdapter: ProviderAdapter = {\r\n name: 'openrouter',\r\n\r\n validate(asset: ResolvedPromptAsset): ValidationResult {\r\n return openaiAdapter.validate(asset);\r\n },\r\n\r\n render(asset: ResolvedPromptAsset, runtime: RuntimeRenderOptions): ProviderRequest {\r\n const result = openaiAdapter.render(asset, runtime);\r\n return {\r\n ...result,\r\n provider: 'openrouter',\r\n };\r\n },\r\n};\r\n","export type { ProviderAdapter, ProviderRequest, ValidationResult, RuntimeRenderOptions } from './types.js';\r\nexport { openaiAdapter } from './openai.js';\r\nexport { anthropicAdapter } from './anthropic.js';\r\nexport { geminiAdapter } from './gemini.js';\r\nexport { openrouterAdapter } from './openrouter.js';\r\n\r\nimport type { ProviderAdapter } from './types.js';\r\nimport { openaiAdapter } from './openai.js';\r\nimport { anthropicAdapter } from './anthropic.js';\r\nimport { geminiAdapter } from './gemini.js';\r\nimport { openrouterAdapter } from './openrouter.js';\r\n\r\nconst adapters: Record<string, ProviderAdapter> = {\r\n openai: openaiAdapter,\r\n anthropic: anthropicAdapter,\r\n google: geminiAdapter,\r\n gemini: geminiAdapter,\r\n openrouter: openrouterAdapter,\r\n};\r\n\r\n/**\r\n * Get a provider adapter by name.\r\n */\r\nexport function getAdapter(provider: string): ProviderAdapter {\r\n const adapter = adapters[provider];\r\n if (!adapter) {\r\n throw new Error(\r\n `Unknown provider: \"${provider}\". Supported: ${Object.keys(adapters).join(', ')}`,\r\n );\r\n }\r\n return adapter;\r\n}\r\n","/**\r\n * Compute the Levenshtein distance between two strings.\r\n * Used for \"did you mean?\" suggestions on unknown fields.\r\n */\r\nexport function levenshtein(a: string, b: string): number {\r\n const m = a.length;\r\n const n = b.length;\r\n\r\n if (m === 0) return n;\r\n if (n === 0) return m;\r\n\r\n const dp: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0) as number[]);\r\n\r\n for (let i = 0; i <= m; i++) dp[i][0] = i;\r\n for (let j = 0; j <= n; j++) dp[0][j] = j;\r\n\r\n for (let i = 1; i <= m; i++) {\r\n for (let j = 1; j <= n; j++) {\r\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\r\n dp[i][j] = Math.min(\r\n dp[i - 1][j] + 1,\r\n dp[i][j - 1] + 1,\r\n dp[i - 1][j - 1] + cost,\r\n );\r\n }\r\n }\r\n\r\n return dp[m][n];\r\n}\r\n","import { PromptAssetSchema } from '../schema/index.js';\r\nimport type { PromptAsset } from '../schema/index.js';\r\nimport { extractVariables } from '../renderer/index.js';\r\nimport { resolveIncludes } from '../composition/index.js';\r\nimport { levenshtein } from './levenshtein.js';\r\n\r\nexport interface ValidationError {\r\n code: string;\r\n message: string;\r\n filePath?: string;\r\n suggestion?: string;\r\n}\r\n\r\nexport interface PromptValidationResult {\r\n valid: boolean;\r\n errors: ValidationError[];\r\n warnings: ValidationError[];\r\n}\r\n\r\nconst KNOWN_FRONT_MATTER_KEYS = new Set([\r\n 'id', 'schema_version', 'description', 'provider', 'model', 'fallback_models',\r\n 'reasoning', 'sampling', 'response', 'tools', 'mcp', 'context', 'includes',\r\n 'environments', 'tiers', 'metadata',\r\n]);\r\n\r\n/**\r\n * Validate a parsed prompt asset, returning all errors and warnings.\r\n */\r\nexport function validateAsset(\r\n asset: PromptAsset,\r\n frontMatterKeys?: string[],\r\n filePath?: string,\r\n): PromptValidationResult {\r\n const errors: ValidationError[] = [];\r\n const warnings: ValidationError[] = [];\r\n\r\n // Schema validation\r\n const result = PromptAssetSchema.safeParse(asset);\r\n if (!result.success) {\r\n for (const issue of result.error.issues) {\r\n errors.push({\r\n code: 'POK001',\r\n message: `Schema error at ${issue.path.join('.')}: ${issue.message}`,\r\n filePath,\r\n });\r\n }\r\n }\r\n\r\n // Missing id\r\n if (!asset.id) {\r\n errors.push({\r\n code: 'POK002',\r\n message: 'Missing required field: \"id\"',\r\n filePath,\r\n });\r\n }\r\n\r\n // Missing body sections\r\n if (!asset.sections?.system_instructions && !asset.sections?.prompt_template) {\r\n errors.push({\r\n code: 'POK003',\r\n message: 'Prompt must have at least one body section (System instructions or Prompt template)',\r\n filePath,\r\n });\r\n }\r\n\r\n // Unknown front matter keys with \"did you mean?\"\r\n if (frontMatterKeys) {\r\n for (const key of frontMatterKeys) {\r\n if (!KNOWN_FRONT_MATTER_KEYS.has(key)) {\r\n const suggestion = findClosestMatch(key, KNOWN_FRONT_MATTER_KEYS);\r\n warnings.push({\r\n code: 'POK010',\r\n message: `Unknown front matter field: \"${key}\"`,\r\n filePath,\r\n suggestion: suggestion ? `Did you mean \"${suggestion}\"?` : undefined,\r\n });\r\n }\r\n }\r\n }\r\n\r\n // Variable validation: used but not declared\r\n const declaredInputs = new Set(asset.context?.inputs ?? []);\r\n const usedVars = new Set<string>();\r\n\r\n if (asset.sections?.system_instructions) {\r\n for (const v of extractVariables(asset.sections.system_instructions)) {\r\n usedVars.add(v);\r\n }\r\n }\r\n if (asset.sections?.prompt_template) {\r\n for (const v of extractVariables(asset.sections.prompt_template)) {\r\n usedVars.add(v);\r\n }\r\n }\r\n\r\n for (const v of usedVars) {\r\n if (declaredInputs.size > 0 && !declaredInputs.has(v)) {\r\n warnings.push({\r\n code: 'POK011',\r\n message: `Variable \"{{ ${v} }}\" is used but not declared in context.inputs`,\r\n filePath,\r\n });\r\n }\r\n }\r\n\r\n // Declared but unused\r\n for (const v of declaredInputs) {\r\n if (!usedVars.has(v)) {\r\n warnings.push({\r\n code: 'POK012',\r\n message: `Variable \"${v}\" is declared in context.inputs but never used`,\r\n filePath,\r\n });\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors,\r\n warnings,\r\n };\r\n}\r\n\r\n/**\r\n * Validate a prompt asset including its include graph.\r\n * Catches missing include files, circular includes, and parse errors in included files.\r\n */\r\nexport async function validateAssetWithIncludes(\r\n asset: PromptAsset,\r\n filePath: string,\r\n frontMatterKeys?: string[],\r\n): Promise<PromptValidationResult> {\r\n // Run standard validation first\r\n const result = validateAsset(asset, frontMatterKeys, filePath);\r\n\r\n // Validate includes\r\n if (asset.includes && asset.includes.length > 0) {\r\n try {\r\n await resolveIncludes(asset, filePath);\r\n } catch (err) {\r\n const message = err instanceof Error ? err.message : String(err);\r\n const isCircular = message.includes('Circular include');\r\n result.errors.push({\r\n code: isCircular ? 'POK021' : 'POK020',\r\n message: isCircular\r\n ? `Circular include detected: ${message}`\r\n : `Include resolution failed: ${message}`,\r\n filePath,\r\n });\r\n result.valid = false;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction findClosestMatch(input: string, candidates: Set<string>): string | undefined {\r\n let best: string | undefined;\r\n let bestDist = Infinity;\r\n\r\n for (const candidate of candidates) {\r\n const dist = levenshtein(input.toLowerCase(), candidate.toLowerCase());\r\n if (dist < bestDist && dist <= 3) {\r\n bestDist = dist;\r\n best = candidate;\r\n }\r\n }\r\n\r\n return best;\r\n}\r\n","import { statSync } from 'node:fs';\r\n\r\ninterface CacheEntry<T> {\r\n value: T;\r\n mtime: number;\r\n}\r\n\r\n/**\r\n * Simple in-memory LRU cache keyed by file path + mtime.\r\n * Used to avoid re-parsing prompt files on every renderPrompt() call.\r\n */\r\nexport class PromptCache<T> {\r\n private cache = new Map<string, CacheEntry<T>>();\r\n private maxSize: number;\r\n\r\n constructor(maxSize = 100) {\r\n this.maxSize = maxSize;\r\n }\r\n\r\n get(filePath: string): T | undefined {\r\n const entry = this.cache.get(filePath);\r\n if (!entry) return undefined;\r\n\r\n try {\r\n const stat = statSync(filePath);\r\n if (stat.mtimeMs !== entry.mtime) {\r\n this.cache.delete(filePath);\r\n return undefined;\r\n }\r\n } catch {\r\n this.cache.delete(filePath);\r\n return undefined;\r\n }\r\n\r\n return entry.value;\r\n }\r\n\r\n set(filePath: string, value: T): void {\r\n // Evict oldest if at capacity\r\n if (this.cache.size >= this.maxSize) {\r\n const oldest = this.cache.keys().next().value;\r\n if (oldest) this.cache.delete(oldest);\r\n }\r\n\r\n try {\r\n const stat = statSync(filePath);\r\n this.cache.set(filePath, { value, mtime: stat.mtimeMs });\r\n } catch {\r\n // Can't stat the file — don't cache\r\n }\r\n }\r\n\r\n clear(): void {\r\n this.cache.clear();\r\n }\r\n\r\n get size(): number {\r\n return this.cache.size;\r\n }\r\n}\r\n"],"mappings":"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","names":["import_promises","import_node_fs","import_node_path","matter","import_gray_matter","matter","import_promises","import_node_path"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/parser/parser.ts","../src/schema/schema.ts","../src/parser/sections.ts","../src/parser/loader.ts","../src/composition/resolve-includes.ts","../src/overrides/apply-overrides.ts","../src/renderer/interpolate.ts","../src/renderer/renderer.ts","../src/providers/openai.ts","../src/providers/anthropic.ts","../src/providers/gemini.ts","../src/providers/openrouter.ts","../src/providers/index.ts","../src/validation/levenshtein.ts","../src/validation/validate.ts","../src/cache.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { existsSync, statSync } from 'node:fs';\nimport { resolve, join } from 'node:path';\n\nimport { parsePrompt, loadPromptFile } from './parser/index.js';\nimport { resolveIncludes } from './composition/index.js';\nimport { applyOverrides } from './overrides/index.js';\nimport { renderSections } from './renderer/index.js';\nimport { getAdapter } from './providers/index.js';\nimport { validateAsset } from './validation/index.js';\nimport { PromptCache } from './cache.js';\nimport type { PromptAsset, ResolvedPromptAsset } from './schema/index.js';\nimport type { ProviderRequest, RuntimeRenderOptions } from './providers/types.js';\nimport type { PromptValidationResult } from './validation/index.js';\n\n// --- Re-exports ---\nexport type { PromptAsset, ResolvedPromptAsset } from './schema/index.js';\nexport type { ProviderRequest, RuntimeRenderOptions, ProviderAdapter, ValidationResult } from './providers/types.js';\nexport type { PromptValidationResult, ValidationError } from './validation/index.js';\nexport type { RenderedSections, RenderOptions } from './renderer/index.js';\nexport type { ParseResult } from './parser/index.js';\nexport type { OverrideOptions } from './overrides/index.js';\n\nexport { parsePrompt, loadPromptFile, extractSections } from './parser/index.js';\nexport { interpolate, extractVariables } from './renderer/index.js';\nexport { resolveIncludes } from './composition/index.js';\nexport { applyOverrides } from './overrides/index.js';\nexport { validateAsset, validateAssetWithIncludes } from './validation/index.js';\nexport { getAdapter, openaiAdapter } from './providers/index.js';\nexport { anthropicAdapter } from './providers/anthropic.js';\nexport { geminiAdapter } from './providers/gemini.js';\nexport { openrouterAdapter } from './providers/openrouter.js';\nexport { PromptAssetSchema, PromptAssetOverridesSchema } from './schema/index.js';\n\n// --- Config ---\n\nexport interface PromptOpsKitConfig {\n sourceDir: string;\n compiledDir?: string;\n mode?: 'auto' | 'compiled-only' | 'source-only';\n cache?: boolean;\n}\n\n// --- Render options ---\n\nexport interface RenderPromptOptions {\n /** Prompt path (no extension), e.g. 'support/reply' */\n path?: string;\n /** Inline prompt source string (alternative to path) */\n source?: string;\n /** Provider name */\n provider: string;\n /** Environment override */\n environment?: string;\n /** Tier override */\n tier?: string;\n /** Variables for interpolation */\n variables?: Record<string, string>;\n /** Conversation history */\n history?: Array<{ role: string; content: string }>;\n /** Tool registry for resolving tool references */\n toolRegistry?: Record<string, unknown>;\n /** Strict mode — fail on missing variables */\n strict?: boolean;\n}\n\n// --- Result ---\n\nexport interface RenderResult {\n resolved: ResolvedPromptAsset;\n request: ProviderRequest;\n warnings: string[];\n}\n\n// --- Main class ---\n\nexport class PromptOpsKit {\n private config: Required<Pick<PromptOpsKitConfig, 'sourceDir' | 'mode'>> & PromptOpsKitConfig;\n private promptCache: PromptCache<PromptAsset>;\n\n constructor(config: PromptOpsKitConfig) {\n this.config = {\n ...config,\n mode: config.mode ?? 'auto',\n cache: config.cache ?? true,\n };\n this.promptCache = new PromptCache();\n }\n\n /**\n * Load a prompt asset from compiled or source, based on mode.\n */\n async loadPrompt(promptPath: string): Promise<PromptAsset> {\n const mode = this.config.mode;\n\n // Try compiled first (unless source-only)\n if (mode !== 'source-only' && this.config.compiledDir) {\n const compiledFile = resolve(this.config.compiledDir, promptPath + '.json');\n if (existsSync(compiledFile)) {\n // Check for stale artifact in auto mode\n if (mode === 'auto') {\n const sourceFile = resolve(this.config.sourceDir, promptPath + '.md');\n if (existsSync(sourceFile)) {\n const compiledMtime = statSync(compiledFile).mtimeMs;\n const sourceMtime = statSync(sourceFile).mtimeMs;\n if (sourceMtime > compiledMtime) {\n console.warn(\n `[promptopskit] Warning: compiled artifact for \"${promptPath}\" is older than source .md file.\\n` +\n ` Run \"promptopskit compile\" or switch to source-only mode.`,\n );\n }\n }\n }\n const content = await readFile(compiledFile, 'utf-8');\n return JSON.parse(content) as PromptAsset;\n }\n if (mode === 'compiled-only') {\n throw new Error(\n `Compiled artifact not found: ${compiledFile}\\n` +\n `Run \"promptopskit compile\" to generate it.`,\n );\n }\n }\n\n // Fall back to source\n if (mode !== 'compiled-only') {\n const sourceFile = resolve(this.config.sourceDir, promptPath + '.md');\n\n // Check cache\n if (this.config.cache) {\n const cached = this.promptCache.get(sourceFile);\n if (cached) return cached;\n }\n\n if (!existsSync(sourceFile)) {\n const paths = [sourceFile];\n if (this.config.compiledDir) {\n paths.unshift(resolve(this.config.compiledDir, promptPath + '.json'));\n }\n throw new Error(\n `Prompt not found: \"${promptPath}\"\\nSearched:\\n${paths.map((p) => ` - ${p}`).join('\\n')}`,\n );\n }\n\n const { asset } = await loadPromptFile(sourceFile, { defaultsRoot: this.config.sourceDir });\n\n if (this.config.cache) {\n this.promptCache.set(sourceFile, asset);\n }\n\n return asset;\n }\n\n throw new Error(`Prompt not found: \"${promptPath}\"`);\n }\n\n /**\n * Resolve a prompt: load, resolve includes, apply overrides.\n */\n async resolvePrompt(\n promptPath: string,\n options: { environment?: string; tier?: string } = {},\n ): Promise<ResolvedPromptAsset> {\n let asset = await this.loadPrompt(promptPath);\n\n // Resolve includes\n const sourceFile = resolve(this.config.sourceDir, promptPath + '.md');\n if (asset.includes && asset.includes.length > 0 && existsSync(sourceFile)) {\n asset = await resolveIncludes(asset, sourceFile);\n }\n\n // Apply overrides\n asset = applyOverrides(asset, {\n environment: options.environment,\n tier: options.tier,\n });\n\n return asset as ResolvedPromptAsset;\n }\n\n /**\n * Render a prompt for a specific provider.\n */\n async renderPrompt(options: RenderPromptOptions): Promise<RenderResult> {\n let resolved: ResolvedPromptAsset;\n\n if (options.source) {\n // Inline source mode\n const { asset } = parsePrompt(options.source);\n const overridden = applyOverrides(asset, {\n environment: options.environment,\n tier: options.tier,\n });\n resolved = overridden as ResolvedPromptAsset;\n } else if (options.path) {\n resolved = await this.resolvePrompt(options.path, {\n environment: options.environment,\n tier: options.tier,\n });\n } else {\n throw new Error('Either \"path\" or \"source\" must be provided to renderPrompt()');\n }\n\n const adapter = getAdapter(options.provider);\n const validation = adapter.validate(resolved);\n\n if (!validation.valid) {\n throw new Error(\n `Provider validation failed for \"${options.provider}\":\\n` +\n validation.errors.map((e) => ` - ${e}`).join('\\n'),\n );\n }\n\n const request = adapter.render(resolved, {\n variables: options.variables,\n history: options.history,\n toolRegistry: options.toolRegistry,\n strict: options.strict,\n });\n\n return {\n resolved,\n request,\n warnings: validation.warnings,\n };\n }\n\n /**\n * Validate a prompt file.\n */\n async validatePrompt(promptPath: string): Promise<PromptValidationResult> {\n const asset = await this.loadPrompt(promptPath);\n return validateAsset(asset, undefined, promptPath);\n }\n\n /**\n * Clear the internal cache.\n */\n clearCache(): void {\n this.promptCache.clear();\n }\n}\n\n// --- Factory ---\n\nexport function createPromptOpsKit(config: PromptOpsKitConfig): PromptOpsKit {\n return new PromptOpsKit(config);\n}\n\n// --- Standalone convenience ---\n\n/**\n * Standalone renderPrompt for quick usage without creating a PromptOpsKit instance.\n * Requires either `source` (inline) or `path` + implicit sourceDir of '.'.\n */\nexport async function renderPrompt(\n options: RenderPromptOptions & { sourceDir?: string },\n): Promise<RenderResult> {\n const kit = createPromptOpsKit({\n sourceDir: options.sourceDir ?? '.',\n cache: false,\n });\n return kit.renderPrompt(options);\n}\n","import matter from 'gray-matter';\nimport { PromptAssetSchema } from '../schema/index.js';\nimport type { PromptAsset } from '../schema/index.js';\nimport { extractSections } from './sections.js';\n\nexport interface ParseResult {\n asset: PromptAsset;\n raw: {\n frontMatter: Record<string, unknown>;\n body: string;\n };\n}\n\n/**\n * Parse a prompt markdown string (YAML front matter + markdown body)\n * into a validated PromptAsset.\n */\nexport function parsePrompt(content: string, filePath?: string): ParseResult {\n const { data: frontMatter, content: body } = matter(content);\n\n const sections = extractSections(body);\n\n const raw = {\n ...frontMatter,\n sections,\n source: filePath ? { file_path: filePath } : undefined,\n };\n\n const asset = PromptAssetSchema.parse(raw);\n\n return {\n asset,\n raw: {\n frontMatter: frontMatter as Record<string, unknown>,\n body,\n },\n };\n}\n","import { z } from 'zod';\n\n// --- Tool definitions ---\n\nexport const InlineToolDefSchema = z.object({\n name: z.string(),\n description: z.string().optional(),\n input_schema: z.record(z.unknown()).optional(),\n});\n\nexport type InlineToolDef = z.infer<typeof InlineToolDefSchema>;\n\nexport const ToolRefSchema = z.union([z.string(), InlineToolDefSchema]);\n\n// --- MCP ---\n\nexport const MCPServerRefSchema = z.union([\n z.string(),\n z.object({\n name: z.string(),\n config: z.record(z.unknown()).optional(),\n }),\n]);\n\nexport type MCPServerRef = z.infer<typeof MCPServerRefSchema>;\n\n// --- Reasoning ---\n\nexport const ReasoningSchema = z.object({\n effort: z.enum(['low', 'medium', 'high']).optional(),\n budget_tokens: z.number().int().positive().optional(),\n});\n\n// --- Sampling ---\n\nexport const SamplingSchema = z.object({\n temperature: z.number().min(0).max(2).optional(),\n top_p: z.number().min(0).max(1).optional(),\n frequency_penalty: z.number().optional(),\n presence_penalty: z.number().optional(),\n stop: z.array(z.string()).optional(),\n max_output_tokens: z.number().int().positive().optional(),\n});\n\n// --- Response ---\n\nexport const ResponseSchema = z.object({\n format: z.enum(['text', 'json', 'markdown']).optional(),\n stream: z.boolean().optional(),\n});\n\n// --- Context ---\n\nexport const HistorySchema = z.object({\n max_items: z.number().int().positive().optional(),\n});\n\nexport const ContextSchema = z.object({\n inputs: z.array(z.string()).optional(),\n history: HistorySchema.optional(),\n});\n\n// --- Metadata ---\n\nexport const MetadataSchema = z.object({\n owner: z.string().optional(),\n tags: z.array(z.string()).optional(),\n review_required: z.boolean().optional(),\n stable: z.boolean().optional(),\n});\n\n// --- MCP block ---\n\nexport const MCPSchema = z.object({\n servers: z.array(MCPServerRefSchema).optional(),\n});\n\n// --- Overrides (subset allowed in environments/tiers) ---\n\nexport const PromptAssetOverridesSchema = z.object({\n model: z.string().optional(),\n fallback_models: z.array(z.string()).optional(),\n reasoning: ReasoningSchema.optional(),\n sampling: SamplingSchema.optional(),\n response: ResponseSchema.optional(),\n tools: z.array(ToolRefSchema).optional(),\n});\n\nexport type PromptAssetOverrides = z.infer<typeof PromptAssetOverridesSchema>;\n\n// --- Source tracking ---\n\nexport const SourceSchema = z.object({\n file_path: z.string().optional(),\n checksum: z.string().optional(),\n});\n\n// --- Sections (populated by parser) ---\n\nexport const SectionsSchema = z.object({\n system_instructions: z.string().optional(),\n prompt_template: z.string().optional(),\n notes: z.string().optional(),\n});\n\n// --- Defaults files (folder-level inheritance) ---\n\nexport const PromptDefaultsSchema = z.object({\n metadata: MetadataSchema.optional(),\n sections: z.object({\n system_instructions: z.string().optional(),\n }).optional(),\n});\n\nexport type PromptDefaults = z.infer<typeof PromptDefaultsSchema>;\n\n// --- Top-level PromptAsset ---\n\nexport const PromptAssetSchema = z.object({\n id: z.string(),\n schema_version: z.number().int().positive().default(1),\n description: z.string().optional(),\n\n provider: z.enum(['openai', 'anthropic', 'google', 'gemini', 'openrouter', 'any']).optional(),\n model: z.string().optional(),\n fallback_models: z.array(z.string()).optional(),\n\n reasoning: ReasoningSchema.optional(),\n sampling: SamplingSchema.optional(),\n response: ResponseSchema.optional(),\n\n tools: z.array(ToolRefSchema).optional(),\n mcp: MCPSchema.optional(),\n\n context: ContextSchema.optional(),\n\n includes: z.array(z.string()).optional(),\n\n environments: z.record(PromptAssetOverridesSchema).optional(),\n tiers: z.record(PromptAssetOverridesSchema).optional(),\n\n metadata: MetadataSchema.optional(),\n\n // Populated by parser, not authored in YAML\n sections: SectionsSchema.optional(),\n source: SourceSchema.optional(),\n});\n\nexport type PromptAsset = z.infer<typeof PromptAssetSchema>;\n\n// --- Resolved asset (after includes, overrides applied) ---\n\nexport interface ResolvedPromptAsset extends PromptAsset {\n sections: {\n system_instructions?: string;\n prompt_template?: string;\n notes?: string;\n };\n source: {\n file_path?: string;\n checksum?: string;\n };\n}\n","export interface Sections {\n system_instructions?: string;\n prompt_template?: string;\n notes?: string;\n}\n\nconst SECTION_MAP: Record<string, keyof Sections> = {\n 'system instructions': 'system_instructions',\n 'prompt template': 'prompt_template',\n 'notes': 'notes',\n};\n\n/**\n * Extract named sections from the markdown body using H1 headings.\n * Case-insensitive. H2+ within a section is treated as content.\n * If no H1 headings are found, the entire body is treated as prompt_template.\n */\nexport function extractSections(body: string): Sections {\n const lines = body.split('\\n');\n const sections: Sections = {};\n\n let currentKey: keyof Sections | null = null;\n let currentLines: string[] = [];\n let foundAnyH1 = false;\n\n for (const line of lines) {\n const h1Match = line.match(/^#\\s+(.+)$/);\n if (h1Match) {\n // Flush previous section\n if (currentKey) {\n sections[currentKey] = currentLines.join('\\n').trim();\n }\n\n foundAnyH1 = true;\n const heading = h1Match[1].trim().toLowerCase();\n currentKey = SECTION_MAP[heading] ?? null;\n currentLines = [];\n } else {\n currentLines.push(line);\n }\n }\n\n // Flush last section\n if (currentKey) {\n sections[currentKey] = currentLines.join('\\n').trim();\n }\n\n // If no H1 headings found, treat entire body as prompt_template\n if (!foundAnyH1) {\n const trimmed = body.trim();\n if (trimmed) {\n sections.prompt_template = trimmed;\n }\n }\n\n return sections;\n}\n","import { readFile } from 'node:fs/promises';\nimport { dirname, join, resolve } from 'node:path';\nimport matter from 'gray-matter';\nimport { parsePrompt } from './parser.js';\nimport type { ParseResult } from './parser.js';\nimport { extractSections } from './sections.js';\nimport { PromptDefaultsSchema } from '../schema/index.js';\nimport type { PromptDefaults } from '../schema/index.js';\n\nconst DEFAULTS_FILE_NAME = 'defaults.md';\n\nexport interface LoadPromptOptions {\n /**\n * Optional boundary directory for defaults discovery.\n * If provided, defaults are loaded from this directory down to the prompt directory.\n */\n defaultsRoot?: string;\n}\n\n/**\n * Load and parse a prompt file from disk.\n */\nexport async function loadPromptFile(filePath: string, options: LoadPromptOptions = {}): Promise<ParseResult> {\n const content = await readFile(filePath, 'utf-8');\n const parsed = parsePrompt(content, filePath);\n // Default the boundary to the file's own directory so traversal never\n // walks above the prompt tree when no explicit root is provided.\n const root = options.defaultsRoot ?? dirname(filePath);\n const defaults = await loadDefaultsForPath(filePath, root);\n const asset = applyDefaults(parsed.asset, defaults);\n\n return {\n ...parsed,\n asset,\n };\n}\n\nasync function loadDefaultsForPath(filePath: string, defaultsRoot?: string): Promise<PromptDefaults> {\n const directories = getDirectoriesToCheck(filePath, defaultsRoot);\n let merged: PromptDefaults = {};\n\n for (const dir of directories) {\n const defaultsPath = join(dir, DEFAULTS_FILE_NAME);\n try {\n const defaultsContent = await readFile(defaultsPath, 'utf-8');\n const defaults = parseDefaults(defaultsContent);\n merged = mergeDefaults(merged, defaults);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw error;\n }\n }\n }\n\n return merged;\n}\n\nfunction getDirectoriesToCheck(filePath: string, defaultsRoot?: string): string[] {\n const dirs: string[] = [];\n let current = resolve(dirname(filePath));\n const boundary = defaultsRoot ? resolve(defaultsRoot) : undefined;\n\n while (true) {\n dirs.unshift(current);\n if ((boundary && current === boundary) || current === dirname(current)) {\n break;\n }\n current = dirname(current);\n }\n\n return dirs;\n}\n\nfunction parseDefaults(content: string): PromptDefaults {\n const { data: frontMatter, content: body } = matter(content);\n const sections = extractSections(body);\n\n return PromptDefaultsSchema.parse({\n ...frontMatter,\n sections: {\n system_instructions: sections.system_instructions,\n },\n });\n}\n\nfunction mergeDefaults(base: PromptDefaults, local: PromptDefaults): PromptDefaults {\n return {\n metadata: {\n ...(base.metadata ?? {}),\n ...(local.metadata ?? {}),\n },\n sections: {\n ...(base.sections ?? {}),\n ...(local.sections ?? {}),\n },\n };\n}\n\nfunction applyDefaults(asset: ParseResult['asset'], defaults: PromptDefaults): ParseResult['asset'] {\n const hasDefaultMetadata = defaults.metadata && Object.keys(defaults.metadata).length > 0;\n const hasDefaultSystem = !!defaults.sections?.system_instructions;\n\n // Short-circuit: nothing to merge\n if (!hasDefaultMetadata && !hasDefaultSystem) {\n return asset;\n }\n\n const mergedMetadata = {\n ...(defaults.metadata ?? {}),\n ...(asset.metadata ?? {}),\n };\n const metadata = Object.keys(mergedMetadata).length > 0 ? mergedMetadata : undefined;\n\n const systemInstructions = asset.sections?.system_instructions ?? defaults.sections?.system_instructions;\n\n const sections = asset.sections\n ? { ...asset.sections, system_instructions: systemInstructions }\n : systemInstructions\n ? { system_instructions: systemInstructions }\n : undefined;\n\n return {\n ...asset,\n metadata,\n sections,\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport { resolve, dirname } from 'node:path';\nimport { parsePrompt } from '../parser/index.js';\nimport type { PromptAsset } from '../schema/index.js';\n\n/**\n * Resolve includes for a prompt asset, inlining content from referenced files.\n * Detects and rejects circular includes.\n */\nexport async function resolveIncludes(\n asset: PromptAsset,\n basePath: string,\n visited: Set<string> = new Set(),\n): Promise<PromptAsset> {\n if (!asset.includes || asset.includes.length === 0) {\n return asset;\n }\n\n const baseDir = dirname(basePath);\n const resolvedPath = resolve(basePath);\n\n if (visited.has(resolvedPath)) {\n throw new Error(`Circular include detected: ${resolvedPath}`);\n }\n visited.add(resolvedPath);\n\n let mergedSystemInstructions = '';\n\n for (const includePath of asset.includes) {\n const fullPath = resolve(baseDir, includePath);\n\n if (visited.has(fullPath)) {\n throw new Error(`Circular include detected: ${fullPath} (included from ${basePath})`);\n }\n\n const content = await readFile(fullPath, 'utf-8');\n const { asset: includedAsset } = parsePrompt(content, fullPath);\n\n // Recursively resolve nested includes\n const resolved = await resolveIncludes(includedAsset, fullPath, new Set(visited));\n\n // Append included system instructions before local ones\n if (resolved.sections?.system_instructions) {\n mergedSystemInstructions += resolved.sections.system_instructions + '\\n\\n';\n }\n }\n\n // Prepend included system instructions before the local ones\n const localSystem = asset.sections?.system_instructions ?? '';\n const combinedSystem = (mergedSystemInstructions + localSystem).trim() || undefined;\n\n return {\n ...asset,\n sections: {\n ...asset.sections,\n system_instructions: combinedSystem,\n },\n // Drop includes from the resolved asset — they've been inlined\n includes: undefined,\n };\n}\n","import type { PromptAsset, PromptAssetOverrides } from '../schema/index.js';\n\nexport interface OverrideOptions {\n environment?: string;\n tier?: string;\n runtime?: Partial<PromptAssetOverrides>;\n}\n\n/**\n * Apply environment, tier, and runtime overrides to a prompt asset.\n *\n * Precedence: base → environment → tier → runtime\n * Scalars are replaced. Arrays are replaced (not concatenated).\n */\nexport function applyOverrides(\n asset: PromptAsset,\n options: OverrideOptions = {},\n): PromptAsset {\n let result = { ...asset };\n\n // Apply environment override\n if (options.environment && result.environments?.[options.environment]) {\n result = mergeOverride(result, result.environments[options.environment]);\n }\n\n // Apply tier override\n if (options.tier && result.tiers?.[options.tier]) {\n result = mergeOverride(result, result.tiers[options.tier]);\n }\n\n // Apply runtime overrides\n if (options.runtime) {\n result = mergeOverride(result, options.runtime);\n }\n\n return result;\n}\n\nfunction mergeOverride(\n base: PromptAsset,\n override: Partial<PromptAssetOverrides>,\n): PromptAsset {\n const result = { ...base };\n\n if (override.model !== undefined) result.model = override.model;\n if (override.fallback_models !== undefined) result.fallback_models = override.fallback_models;\n if (override.tools !== undefined) result.tools = override.tools;\n\n if (override.reasoning !== undefined) {\n result.reasoning = { ...result.reasoning, ...override.reasoning };\n }\n if (override.sampling !== undefined) {\n result.sampling = { ...result.sampling, ...override.sampling };\n }\n if (override.response !== undefined) {\n result.response = { ...result.response, ...override.response };\n }\n\n return result;\n}\n","export interface InterpolateOptions {\n strict?: boolean;\n}\n\nconst VARIABLE_RE = /\\{\\{\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\}\\}/g;\nconst ESCAPED_OPEN = /\\\\\\{\\\\\\{/g;\nconst ESCAPE_PLACEHOLDER = '\\x00ESCAPED_OPEN\\x00';\n\n/**\n * Interpolate variables into a template string.\n *\n * Syntax: {{ variable_name }}\n * Escape: \\{\\{ produces literal {{\n *\n * In strict mode, throws on missing variables.\n * In permissive mode, leaves {{ placeholder }} intact.\n */\nexport function interpolate(\n template: string,\n variables: Record<string, string>,\n options: InterpolateOptions = {},\n): string {\n const { strict = false } = options;\n\n // Replace escaped sequences with placeholder\n let result = template.replace(ESCAPED_OPEN, ESCAPE_PLACEHOLDER);\n\n result = result.replace(VARIABLE_RE, (match, name: string) => {\n if (name in variables) {\n return variables[name];\n }\n if (strict) {\n throw new Error(`Missing required variable: \"${name}\"`);\n }\n return match; // leave placeholder intact in permissive mode\n });\n\n // Restore escaped sequences\n result = result.replaceAll(ESCAPE_PLACEHOLDER, '{{');\n\n return result;\n}\n\n/**\n * Extract all variable names referenced in a template.\n */\nexport function extractVariables(template: string): string[] {\n const vars = new Set<string>();\n let match: RegExpExecArray | null;\n const re = new RegExp(VARIABLE_RE.source, 'g');\n while ((match = re.exec(template)) !== null) {\n vars.add(match[1]);\n }\n return [...vars];\n}\n","import type { ResolvedPromptAsset } from '../schema/index.js';\nimport { interpolate, extractVariables } from './interpolate.js';\n\nexport interface RenderOptions {\n variables?: Record<string, string>;\n strict?: boolean;\n}\n\nexport interface RenderedSections {\n system_instructions?: string;\n prompt_template?: string;\n}\n\n/**\n * Render the sections of a resolved prompt asset with variable interpolation.\n */\nexport function renderSections(\n asset: ResolvedPromptAsset,\n options: RenderOptions = {},\n): RenderedSections {\n const { variables = {}, strict = false } = options;\n\n const result: RenderedSections = {};\n\n if (asset.sections.system_instructions) {\n result.system_instructions = interpolate(\n asset.sections.system_instructions,\n variables,\n { strict },\n );\n }\n\n if (asset.sections.prompt_template) {\n result.prompt_template = interpolate(\n asset.sections.prompt_template,\n variables,\n { strict },\n );\n }\n\n return result;\n}\n\n/**\n * Get all variable names used across all sections.\n */\nexport function getRequiredVariables(asset: ResolvedPromptAsset): string[] {\n const vars = new Set<string>();\n\n if (asset.sections.system_instructions) {\n for (const v of extractVariables(asset.sections.system_instructions)) {\n vars.add(v);\n }\n }\n\n if (asset.sections.prompt_template) {\n for (const v of extractVariables(asset.sections.prompt_template)) {\n vars.add(v);\n }\n }\n\n return [...vars];\n}\n","import type { ResolvedPromptAsset } from '../schema/index.js';\nimport type {\n ProviderAdapter,\n ProviderRequest,\n ValidationResult,\n RuntimeRenderOptions,\n} from './types.js';\nimport { renderSections } from '../renderer/index.js';\n\n/**\n * OpenAI provider adapter.\n * Produces request bodies compatible with the OpenAI Chat Completions API.\n */\nexport const openaiAdapter: ProviderAdapter = {\n name: 'openai',\n\n validate(asset: ResolvedPromptAsset): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!asset.model) {\n errors.push('OpenAI adapter requires a model to be specified.');\n }\n\n if (asset.reasoning?.budget_tokens !== undefined) {\n warnings.push('OpenAI uses reasoning_effort, not budget_tokens. budget_tokens will be ignored.');\n }\n\n return { valid: errors.length === 0, errors, warnings };\n },\n\n render(asset: ResolvedPromptAsset, runtime: RuntimeRenderOptions): ProviderRequest {\n const sections = renderSections(asset, {\n variables: runtime.variables,\n strict: runtime.strict,\n });\n\n const messages: Array<Record<string, unknown>> = [];\n\n // System message\n if (sections.system_instructions) {\n messages.push({ role: 'system', content: sections.system_instructions });\n }\n\n // History\n if (runtime.history) {\n for (const msg of runtime.history) {\n messages.push({ role: msg.role, content: msg.content });\n }\n }\n\n // User message (prompt template)\n if (sections.prompt_template) {\n messages.push({ role: 'user', content: sections.prompt_template });\n }\n\n const body: Record<string, unknown> = {\n model: asset.model,\n messages,\n };\n\n // Sampling params\n if (asset.sampling?.temperature !== undefined) body.temperature = asset.sampling.temperature;\n if (asset.sampling?.top_p !== undefined) body.top_p = asset.sampling.top_p;\n if (asset.sampling?.frequency_penalty !== undefined) body.frequency_penalty = asset.sampling.frequency_penalty;\n if (asset.sampling?.presence_penalty !== undefined) body.presence_penalty = asset.sampling.presence_penalty;\n if (asset.sampling?.stop !== undefined) body.stop = asset.sampling.stop;\n if (asset.sampling?.max_output_tokens !== undefined) body.max_tokens = asset.sampling.max_output_tokens;\n\n // Reasoning\n if (asset.reasoning?.effort) {\n body.reasoning_effort = asset.reasoning.effort;\n }\n\n // Response format\n if (asset.response?.format === 'json') {\n body.response_format = { type: 'json_object' };\n }\n\n // Streaming\n if (asset.response?.stream !== undefined) {\n body.stream = asset.response.stream;\n }\n\n // Tools\n if (asset.tools && asset.tools.length > 0) {\n body.tools = asset.tools.map((tool) => {\n if (typeof tool === 'string') {\n // Look up from registry\n const def = runtime.toolRegistry?.[tool];\n if (def) return def;\n return { type: 'function', function: { name: tool } };\n }\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.input_schema,\n },\n };\n });\n }\n\n return {\n body,\n provider: 'openai',\n model: asset.model ?? 'unknown',\n };\n },\n};\n","import type { ResolvedPromptAsset } from '../schema/index.js';\nimport type {\n ProviderAdapter,\n ProviderRequest,\n ValidationResult,\n RuntimeRenderOptions,\n} from './types.js';\nimport { renderSections } from '../renderer/index.js';\n\n/**\n * Anthropic provider adapter.\n * Produces request bodies compatible with the Anthropic Messages API.\n */\nexport const anthropicAdapter: ProviderAdapter = {\n name: 'anthropic',\n\n validate(asset: ResolvedPromptAsset): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!asset.model) {\n errors.push('Anthropic adapter requires a model to be specified.');\n }\n\n if (asset.sampling?.frequency_penalty !== undefined) {\n warnings.push('Anthropic does not support frequency_penalty. It will be ignored.');\n }\n if (asset.sampling?.presence_penalty !== undefined) {\n warnings.push('Anthropic does not support presence_penalty. It will be ignored.');\n }\n if (asset.reasoning?.effort !== undefined) {\n warnings.push('Anthropic uses budget_tokens for thinking, not effort. effort will be mapped approximately.');\n }\n\n return { valid: errors.length === 0, errors, warnings };\n },\n\n render(asset: ResolvedPromptAsset, runtime: RuntimeRenderOptions): ProviderRequest {\n const sections = renderSections(asset, {\n variables: runtime.variables,\n strict: runtime.strict,\n });\n\n const messages: Array<Record<string, unknown>> = [];\n\n // History\n if (runtime.history) {\n for (const msg of runtime.history) {\n messages.push({ role: msg.role, content: msg.content });\n }\n }\n\n // User message (prompt template)\n if (sections.prompt_template) {\n messages.push({ role: 'user', content: sections.prompt_template });\n }\n\n const body: Record<string, unknown> = {\n model: asset.model,\n messages,\n };\n\n // System goes as top-level field in Anthropic\n if (sections.system_instructions) {\n body.system = sections.system_instructions;\n }\n\n // Sampling params\n if (asset.sampling?.temperature !== undefined) body.temperature = asset.sampling.temperature;\n if (asset.sampling?.top_p !== undefined) body.top_p = asset.sampling.top_p;\n if (asset.sampling?.stop !== undefined) body.stop_sequences = asset.sampling.stop;\n if (asset.sampling?.max_output_tokens !== undefined) {\n body.max_tokens = asset.sampling.max_output_tokens;\n } else {\n // Anthropic requires max_tokens\n body.max_tokens = 4096;\n }\n\n // Thinking/reasoning\n if (asset.reasoning?.budget_tokens) {\n body.thinking = {\n type: 'enabled',\n budget_tokens: asset.reasoning.budget_tokens,\n };\n }\n\n // Streaming\n if (asset.response?.stream !== undefined) {\n body.stream = asset.response.stream;\n }\n\n // Tools\n if (asset.tools && asset.tools.length > 0) {\n body.tools = asset.tools.map((tool) => {\n if (typeof tool === 'string') {\n const def = runtime.toolRegistry?.[tool];\n if (def) return def;\n return { name: tool };\n }\n return {\n name: tool.name,\n description: tool.description,\n input_schema: tool.input_schema ?? { type: 'object', properties: {} },\n };\n });\n }\n\n return {\n body,\n provider: 'anthropic',\n model: asset.model ?? 'unknown',\n };\n },\n};\n","import type { ResolvedPromptAsset } from '../schema/index.js';\nimport type {\n ProviderAdapter,\n ProviderRequest,\n ValidationResult,\n RuntimeRenderOptions,\n} from './types.js';\nimport { renderSections } from '../renderer/index.js';\n\n/**\n * Google Gemini provider adapter.\n * Produces request bodies compatible with the Gemini generateContent API.\n */\nexport const geminiAdapter: ProviderAdapter = {\n name: 'gemini',\n\n validate(asset: ResolvedPromptAsset): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!asset.model) {\n errors.push('Gemini adapter requires a model to be specified.');\n }\n\n if (asset.sampling?.frequency_penalty !== undefined) {\n warnings.push('Gemini does not support frequency_penalty. It will be ignored.');\n }\n if (asset.sampling?.presence_penalty !== undefined) {\n warnings.push('Gemini does not support presence_penalty. It will be ignored.');\n }\n\n return { valid: errors.length === 0, errors, warnings };\n },\n\n render(asset: ResolvedPromptAsset, runtime: RuntimeRenderOptions): ProviderRequest {\n const sections = renderSections(asset, {\n variables: runtime.variables,\n strict: runtime.strict,\n });\n\n const contents: Array<Record<string, unknown>> = [];\n\n // History\n if (runtime.history) {\n for (const msg of runtime.history) {\n contents.push({\n role: msg.role === 'assistant' ? 'model' : 'user',\n parts: [{ text: msg.content }],\n });\n }\n }\n\n // User message (prompt template)\n if (sections.prompt_template) {\n contents.push({\n role: 'user',\n parts: [{ text: sections.prompt_template }],\n });\n }\n\n const body: Record<string, unknown> = {\n contents,\n };\n\n // System instruction\n if (sections.system_instructions) {\n body.systemInstruction = {\n parts: [{ text: sections.system_instructions }],\n };\n }\n\n // Generation config\n const generationConfig: Record<string, unknown> = {};\n\n if (asset.sampling?.temperature !== undefined) generationConfig.temperature = asset.sampling.temperature;\n if (asset.sampling?.top_p !== undefined) generationConfig.topP = asset.sampling.top_p;\n if (asset.sampling?.max_output_tokens !== undefined) generationConfig.maxOutputTokens = asset.sampling.max_output_tokens;\n if (asset.sampling?.stop !== undefined) generationConfig.stopSequences = asset.sampling.stop;\n\n if (asset.response?.format === 'json') {\n generationConfig.responseMimeType = 'application/json';\n }\n\n // Thinking config\n if (asset.reasoning?.effort) {\n body.thinkingConfig = {\n thinkingBudget: asset.reasoning.effort === 'high' ? 8192 : asset.reasoning.effort === 'medium' ? 4096 : 1024,\n };\n }\n\n if (Object.keys(generationConfig).length > 0) {\n body.generationConfig = generationConfig;\n }\n\n // Tools\n if (asset.tools && asset.tools.length > 0) {\n const functionDeclarations = asset.tools.map((tool) => {\n if (typeof tool === 'string') {\n const def = runtime.toolRegistry?.[tool];\n if (def) return def;\n return { name: tool };\n }\n return {\n name: tool.name,\n description: tool.description,\n parameters: tool.input_schema,\n };\n });\n body.tools = [{ functionDeclarations }];\n }\n\n return {\n body,\n provider: 'gemini',\n model: asset.model ?? 'unknown',\n };\n },\n};\n","import { openaiAdapter } from './openai.js';\nimport type { ResolvedPromptAsset } from '../schema/index.js';\nimport type {\n ProviderAdapter,\n ProviderRequest,\n ValidationResult,\n RuntimeRenderOptions,\n} from './types.js';\n\n/**\n * OpenRouter provider adapter.\n * Thin preset over the OpenAI adapter — body format is identical,\n * only the provider label differs. The app handles the different\n * base URL and extra headers (HTTP-Referer, X-Title).\n */\nexport const openrouterAdapter: ProviderAdapter = {\n name: 'openrouter',\n\n validate(asset: ResolvedPromptAsset): ValidationResult {\n return openaiAdapter.validate(asset);\n },\n\n render(asset: ResolvedPromptAsset, runtime: RuntimeRenderOptions): ProviderRequest {\n const result = openaiAdapter.render(asset, runtime);\n return {\n ...result,\n provider: 'openrouter',\n };\n },\n};\n","export type { ProviderAdapter, ProviderRequest, ValidationResult, RuntimeRenderOptions } from './types.js';\nexport { openaiAdapter } from './openai.js';\nexport { anthropicAdapter } from './anthropic.js';\nexport { geminiAdapter } from './gemini.js';\nexport { openrouterAdapter } from './openrouter.js';\n\nimport type { ProviderAdapter } from './types.js';\nimport { openaiAdapter } from './openai.js';\nimport { anthropicAdapter } from './anthropic.js';\nimport { geminiAdapter } from './gemini.js';\nimport { openrouterAdapter } from './openrouter.js';\n\nconst adapters: Record<string, ProviderAdapter> = {\n openai: openaiAdapter,\n anthropic: anthropicAdapter,\n google: geminiAdapter,\n gemini: geminiAdapter,\n openrouter: openrouterAdapter,\n};\n\n/**\n * Get a provider adapter by name.\n */\nexport function getAdapter(provider: string): ProviderAdapter {\n const adapter = adapters[provider];\n if (!adapter) {\n throw new Error(\n `Unknown provider: \"${provider}\". Supported: ${Object.keys(adapters).join(', ')}`,\n );\n }\n return adapter;\n}\n","/**\n * Compute the Levenshtein distance between two strings.\n * Used for \"did you mean?\" suggestions on unknown fields.\n */\nexport function levenshtein(a: string, b: string): number {\n const m = a.length;\n const n = b.length;\n\n if (m === 0) return n;\n if (n === 0) return m;\n\n const dp: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0) as number[]);\n\n for (let i = 0; i <= m; i++) dp[i][0] = i;\n for (let j = 0; j <= n; j++) dp[0][j] = j;\n\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n dp[i][j] = Math.min(\n dp[i - 1][j] + 1,\n dp[i][j - 1] + 1,\n dp[i - 1][j - 1] + cost,\n );\n }\n }\n\n return dp[m][n];\n}\n","import { PromptAssetSchema } from '../schema/index.js';\nimport type { PromptAsset } from '../schema/index.js';\nimport { extractVariables } from '../renderer/index.js';\nimport { resolveIncludes } from '../composition/index.js';\nimport { levenshtein } from './levenshtein.js';\n\nexport interface ValidationError {\n code: string;\n message: string;\n filePath?: string;\n suggestion?: string;\n}\n\nexport interface PromptValidationResult {\n valid: boolean;\n errors: ValidationError[];\n warnings: ValidationError[];\n}\n\nconst KNOWN_FRONT_MATTER_KEYS = new Set([\n 'id', 'schema_version', 'description', 'provider', 'model', 'fallback_models',\n 'reasoning', 'sampling', 'response', 'tools', 'mcp', 'context', 'includes',\n 'environments', 'tiers', 'metadata',\n]);\n\n/**\n * Validate a parsed prompt asset, returning all errors and warnings.\n */\nexport function validateAsset(\n asset: PromptAsset,\n frontMatterKeys?: string[],\n filePath?: string,\n): PromptValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationError[] = [];\n\n // Schema validation\n const result = PromptAssetSchema.safeParse(asset);\n if (!result.success) {\n for (const issue of result.error.issues) {\n errors.push({\n code: 'POK001',\n message: `Schema error at ${issue.path.join('.')}: ${issue.message}`,\n filePath,\n });\n }\n }\n\n // Missing id\n if (!asset.id) {\n errors.push({\n code: 'POK002',\n message: 'Missing required field: \"id\"',\n filePath,\n });\n }\n\n // Missing body sections\n if (!asset.sections?.system_instructions && !asset.sections?.prompt_template) {\n errors.push({\n code: 'POK003',\n message: 'Prompt must have at least one body section (System instructions or Prompt template)',\n filePath,\n });\n }\n\n // Unknown front matter keys with \"did you mean?\"\n if (frontMatterKeys) {\n for (const key of frontMatterKeys) {\n if (!KNOWN_FRONT_MATTER_KEYS.has(key)) {\n const suggestion = findClosestMatch(key, KNOWN_FRONT_MATTER_KEYS);\n warnings.push({\n code: 'POK010',\n message: `Unknown front matter field: \"${key}\"`,\n filePath,\n suggestion: suggestion ? `Did you mean \"${suggestion}\"?` : undefined,\n });\n }\n }\n }\n\n // Variable validation: used but not declared\n const declaredInputs = new Set(asset.context?.inputs ?? []);\n const usedVars = new Set<string>();\n\n if (asset.sections?.system_instructions) {\n for (const v of extractVariables(asset.sections.system_instructions)) {\n usedVars.add(v);\n }\n }\n if (asset.sections?.prompt_template) {\n for (const v of extractVariables(asset.sections.prompt_template)) {\n usedVars.add(v);\n }\n }\n\n for (const v of usedVars) {\n if (declaredInputs.size > 0 && !declaredInputs.has(v)) {\n warnings.push({\n code: 'POK011',\n message: `Variable \"{{ ${v} }}\" is used but not declared in context.inputs`,\n filePath,\n });\n }\n }\n\n // Declared but unused\n for (const v of declaredInputs) {\n if (!usedVars.has(v)) {\n warnings.push({\n code: 'POK012',\n message: `Variable \"${v}\" is declared in context.inputs but never used`,\n filePath,\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Validate a prompt asset including its include graph.\n * Catches missing include files, circular includes, and parse errors in included files.\n */\nexport async function validateAssetWithIncludes(\n asset: PromptAsset,\n filePath: string,\n frontMatterKeys?: string[],\n): Promise<PromptValidationResult> {\n // Run standard validation first\n const result = validateAsset(asset, frontMatterKeys, filePath);\n\n // Validate includes\n if (asset.includes && asset.includes.length > 0) {\n try {\n await resolveIncludes(asset, filePath);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const isCircular = message.includes('Circular include');\n result.errors.push({\n code: isCircular ? 'POK021' : 'POK020',\n message: isCircular\n ? `Circular include detected: ${message}`\n : `Include resolution failed: ${message}`,\n filePath,\n });\n result.valid = false;\n }\n }\n\n return result;\n}\n\nfunction findClosestMatch(input: string, candidates: Set<string>): string | undefined {\n let best: string | undefined;\n let bestDist = Infinity;\n\n for (const candidate of candidates) {\n const dist = levenshtein(input.toLowerCase(), candidate.toLowerCase());\n if (dist < bestDist && dist <= 3) {\n bestDist = dist;\n best = candidate;\n }\n }\n\n return best;\n}\n","import { statSync } from 'node:fs';\n\ninterface CacheEntry<T> {\n value: T;\n mtime: number;\n}\n\n/**\n * Simple in-memory LRU cache keyed by file path + mtime.\n * Used to avoid re-parsing prompt files on every renderPrompt() call.\n */\nexport class PromptCache<T> {\n private cache = new Map<string, CacheEntry<T>>();\n private maxSize: number;\n\n constructor(maxSize = 100) {\n this.maxSize = maxSize;\n }\n\n get(filePath: string): T | undefined {\n const entry = this.cache.get(filePath);\n if (!entry) return undefined;\n\n try {\n const stat = statSync(filePath);\n if (stat.mtimeMs !== entry.mtime) {\n this.cache.delete(filePath);\n return undefined;\n }\n } catch {\n this.cache.delete(filePath);\n return undefined;\n }\n\n return entry.value;\n }\n\n set(filePath: string, value: T): void {\n // Evict oldest if at capacity\n if (this.cache.size >= this.maxSize) {\n const oldest = this.cache.keys().next().value;\n if (oldest) this.cache.delete(oldest);\n }\n\n try {\n const stat = statSync(filePath);\n this.cache.set(filePath, { value, mtime: stat.mtimeMs });\n } catch {\n // Can't stat the file — don't cache\n }\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n get size(): number {\n return this.cache.size;\n }\n}\n"],"mappings":"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","names":["import_promises","import_node_fs","import_node_path","matter","import_gray_matter","matter","import_promises","import_node_path"]}
package/dist/index.js CHANGED
@@ -4,23 +4,23 @@ import {
4
4
  extractSections,
5
5
  loadPromptFile,
6
6
  parsePrompt
7
- } from "./chunk-HMYPMHTG.js";
7
+ } from "./chunk-QDGJFINW.js";
8
8
  import {
9
9
  anthropicAdapter
10
- } from "./chunk-B5UFGNDV.js";
10
+ } from "./chunk-VYVEVJC3.js";
11
11
  import {
12
12
  geminiAdapter
13
- } from "./chunk-FSOJVXC4.js";
13
+ } from "./chunk-5BI5FP5L.js";
14
14
  import {
15
15
  openrouterAdapter
16
- } from "./chunk-YCRWYE6N.js";
16
+ } from "./chunk-PU3UPUND.js";
17
17
  import {
18
18
  openaiAdapter
19
- } from "./chunk-V375NQ6C.js";
19
+ } from "./chunk-UYTUGV7Z.js";
20
20
  import {
21
21
  extractVariables,
22
22
  interpolate
23
- } from "./chunk-HEFOFQ2K.js";
23
+ } from "./chunk-6KGBPHSY.js";
24
24
 
25
25
  // src/index.ts
26
26
  import { readFile as readFile2 } from "fs/promises";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/composition/resolve-includes.ts","../src/overrides/apply-overrides.ts","../src/providers/index.ts","../src/validation/levenshtein.ts","../src/validation/validate.ts","../src/cache.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\r\nimport { existsSync, statSync } from 'node:fs';\r\nimport { resolve, join } from 'node:path';\r\n\r\nimport { parsePrompt, loadPromptFile } from './parser/index.js';\r\nimport { resolveIncludes } from './composition/index.js';\r\nimport { applyOverrides } from './overrides/index.js';\r\nimport { renderSections } from './renderer/index.js';\r\nimport { getAdapter } from './providers/index.js';\r\nimport { validateAsset } from './validation/index.js';\r\nimport { PromptCache } from './cache.js';\r\nimport type { PromptAsset, ResolvedPromptAsset } from './schema/index.js';\r\nimport type { ProviderRequest, RuntimeRenderOptions } from './providers/types.js';\r\nimport type { PromptValidationResult } from './validation/index.js';\r\n\r\n// --- Re-exports ---\r\nexport type { PromptAsset, ResolvedPromptAsset } from './schema/index.js';\r\nexport type { ProviderRequest, RuntimeRenderOptions, ProviderAdapter, ValidationResult } from './providers/types.js';\r\nexport type { PromptValidationResult, ValidationError } from './validation/index.js';\r\nexport type { RenderedSections, RenderOptions } from './renderer/index.js';\r\nexport type { ParseResult } from './parser/index.js';\r\nexport type { OverrideOptions } from './overrides/index.js';\r\n\r\nexport { parsePrompt, loadPromptFile, extractSections } from './parser/index.js';\r\nexport { interpolate, extractVariables } from './renderer/index.js';\r\nexport { resolveIncludes } from './composition/index.js';\r\nexport { applyOverrides } from './overrides/index.js';\r\nexport { validateAsset, validateAssetWithIncludes } from './validation/index.js';\r\nexport { getAdapter, openaiAdapter } from './providers/index.js';\r\nexport { anthropicAdapter } from './providers/anthropic.js';\r\nexport { geminiAdapter } from './providers/gemini.js';\r\nexport { openrouterAdapter } from './providers/openrouter.js';\r\nexport { PromptAssetSchema, PromptAssetOverridesSchema } from './schema/index.js';\r\n\r\n// --- Config ---\r\n\r\nexport interface PromptOpsKitConfig {\r\n sourceDir: string;\r\n compiledDir?: string;\r\n mode?: 'auto' | 'compiled-only' | 'source-only';\r\n cache?: boolean;\r\n}\r\n\r\n// --- Render options ---\r\n\r\nexport interface RenderPromptOptions {\r\n /** Prompt path (no extension), e.g. 'support/reply' */\r\n path?: string;\r\n /** Inline prompt source string (alternative to path) */\r\n source?: string;\r\n /** Provider name */\r\n provider: string;\r\n /** Environment override */\r\n environment?: string;\r\n /** Tier override */\r\n tier?: string;\r\n /** Variables for interpolation */\r\n variables?: Record<string, string>;\r\n /** Conversation history */\r\n history?: Array<{ role: string; content: string }>;\r\n /** Tool registry for resolving tool references */\r\n toolRegistry?: Record<string, unknown>;\r\n /** Strict mode — fail on missing variables */\r\n strict?: boolean;\r\n}\r\n\r\n// --- Result ---\r\n\r\nexport interface RenderResult {\r\n resolved: ResolvedPromptAsset;\r\n request: ProviderRequest;\r\n warnings: string[];\r\n}\r\n\r\n// --- Main class ---\r\n\r\nexport class PromptOpsKit {\r\n private config: Required<Pick<PromptOpsKitConfig, 'sourceDir' | 'mode'>> & PromptOpsKitConfig;\r\n private promptCache: PromptCache<PromptAsset>;\r\n\r\n constructor(config: PromptOpsKitConfig) {\r\n this.config = {\r\n ...config,\r\n mode: config.mode ?? 'auto',\r\n cache: config.cache ?? true,\r\n };\r\n this.promptCache = new PromptCache();\r\n }\r\n\r\n /**\r\n * Load a prompt asset from compiled or source, based on mode.\r\n */\r\n async loadPrompt(promptPath: string): Promise<PromptAsset> {\r\n const mode = this.config.mode;\r\n\r\n // Try compiled first (unless source-only)\r\n if (mode !== 'source-only' && this.config.compiledDir) {\r\n const compiledFile = resolve(this.config.compiledDir, promptPath + '.json');\r\n if (existsSync(compiledFile)) {\r\n // Check for stale artifact in auto mode\r\n if (mode === 'auto') {\r\n const sourceFile = resolve(this.config.sourceDir, promptPath + '.md');\r\n if (existsSync(sourceFile)) {\r\n const compiledMtime = statSync(compiledFile).mtimeMs;\r\n const sourceMtime = statSync(sourceFile).mtimeMs;\r\n if (sourceMtime > compiledMtime) {\r\n console.warn(\r\n `[promptopskit] Warning: compiled artifact for \"${promptPath}\" is older than source .md file.\\n` +\r\n ` Run \"promptopskit compile\" or switch to source-only mode.`,\r\n );\r\n }\r\n }\r\n }\r\n const content = await readFile(compiledFile, 'utf-8');\r\n return JSON.parse(content) as PromptAsset;\r\n }\r\n if (mode === 'compiled-only') {\r\n throw new Error(\r\n `Compiled artifact not found: ${compiledFile}\\n` +\r\n `Run \"promptopskit compile\" to generate it.`,\r\n );\r\n }\r\n }\r\n\r\n // Fall back to source\r\n if (mode !== 'compiled-only') {\r\n const sourceFile = resolve(this.config.sourceDir, promptPath + '.md');\r\n\r\n // Check cache\r\n if (this.config.cache) {\r\n const cached = this.promptCache.get(sourceFile);\r\n if (cached) return cached;\r\n }\r\n\r\n if (!existsSync(sourceFile)) {\r\n const paths = [sourceFile];\r\n if (this.config.compiledDir) {\r\n paths.unshift(resolve(this.config.compiledDir, promptPath + '.json'));\r\n }\r\n throw new Error(\r\n `Prompt not found: \"${promptPath}\"\\nSearched:\\n${paths.map((p) => ` - ${p}`).join('\\n')}`,\r\n );\r\n }\r\n\r\n const { asset } = await loadPromptFile(sourceFile, { defaultsRoot: this.config.sourceDir });\r\n\r\n if (this.config.cache) {\r\n this.promptCache.set(sourceFile, asset);\r\n }\r\n\r\n return asset;\r\n }\r\n\r\n throw new Error(`Prompt not found: \"${promptPath}\"`);\r\n }\r\n\r\n /**\r\n * Resolve a prompt: load, resolve includes, apply overrides.\r\n */\r\n async resolvePrompt(\r\n promptPath: string,\r\n options: { environment?: string; tier?: string } = {},\r\n ): Promise<ResolvedPromptAsset> {\r\n let asset = await this.loadPrompt(promptPath);\r\n\r\n // Resolve includes\r\n const sourceFile = resolve(this.config.sourceDir, promptPath + '.md');\r\n if (asset.includes && asset.includes.length > 0 && existsSync(sourceFile)) {\r\n asset = await resolveIncludes(asset, sourceFile);\r\n }\r\n\r\n // Apply overrides\r\n asset = applyOverrides(asset, {\r\n environment: options.environment,\r\n tier: options.tier,\r\n });\r\n\r\n return asset as ResolvedPromptAsset;\r\n }\r\n\r\n /**\r\n * Render a prompt for a specific provider.\r\n */\r\n async renderPrompt(options: RenderPromptOptions): Promise<RenderResult> {\r\n let resolved: ResolvedPromptAsset;\r\n\r\n if (options.source) {\r\n // Inline source mode\r\n const { asset } = parsePrompt(options.source);\r\n const overridden = applyOverrides(asset, {\r\n environment: options.environment,\r\n tier: options.tier,\r\n });\r\n resolved = overridden as ResolvedPromptAsset;\r\n } else if (options.path) {\r\n resolved = await this.resolvePrompt(options.path, {\r\n environment: options.environment,\r\n tier: options.tier,\r\n });\r\n } else {\r\n throw new Error('Either \"path\" or \"source\" must be provided to renderPrompt()');\r\n }\r\n\r\n const adapter = getAdapter(options.provider);\r\n const validation = adapter.validate(resolved);\r\n\r\n if (!validation.valid) {\r\n throw new Error(\r\n `Provider validation failed for \"${options.provider}\":\\n` +\r\n validation.errors.map((e) => ` - ${e}`).join('\\n'),\r\n );\r\n }\r\n\r\n const request = adapter.render(resolved, {\r\n variables: options.variables,\r\n history: options.history,\r\n toolRegistry: options.toolRegistry,\r\n strict: options.strict,\r\n });\r\n\r\n return {\r\n resolved,\r\n request,\r\n warnings: validation.warnings,\r\n };\r\n }\r\n\r\n /**\r\n * Validate a prompt file.\r\n */\r\n async validatePrompt(promptPath: string): Promise<PromptValidationResult> {\r\n const asset = await this.loadPrompt(promptPath);\r\n return validateAsset(asset, undefined, promptPath);\r\n }\r\n\r\n /**\r\n * Clear the internal cache.\r\n */\r\n clearCache(): void {\r\n this.promptCache.clear();\r\n }\r\n}\r\n\r\n// --- Factory ---\r\n\r\nexport function createPromptOpsKit(config: PromptOpsKitConfig): PromptOpsKit {\r\n return new PromptOpsKit(config);\r\n}\r\n\r\n// --- Standalone convenience ---\r\n\r\n/**\r\n * Standalone renderPrompt for quick usage without creating a PromptOpsKit instance.\r\n * Requires either `source` (inline) or `path` + implicit sourceDir of '.'.\r\n */\r\nexport async function renderPrompt(\r\n options: RenderPromptOptions & { sourceDir?: string },\r\n): Promise<RenderResult> {\r\n const kit = createPromptOpsKit({\r\n sourceDir: options.sourceDir ?? '.',\r\n cache: false,\r\n });\r\n return kit.renderPrompt(options);\r\n}\r\n","import { readFile } from 'node:fs/promises';\r\nimport { resolve, dirname } from 'node:path';\r\nimport { parsePrompt } from '../parser/index.js';\r\nimport type { PromptAsset } from '../schema/index.js';\r\n\r\n/**\r\n * Resolve includes for a prompt asset, inlining content from referenced files.\r\n * Detects and rejects circular includes.\r\n */\r\nexport async function resolveIncludes(\r\n asset: PromptAsset,\r\n basePath: string,\r\n visited: Set<string> = new Set(),\r\n): Promise<PromptAsset> {\r\n if (!asset.includes || asset.includes.length === 0) {\r\n return asset;\r\n }\r\n\r\n const baseDir = dirname(basePath);\r\n const resolvedPath = resolve(basePath);\r\n\r\n if (visited.has(resolvedPath)) {\r\n throw new Error(`Circular include detected: ${resolvedPath}`);\r\n }\r\n visited.add(resolvedPath);\r\n\r\n let mergedSystemInstructions = '';\r\n\r\n for (const includePath of asset.includes) {\r\n const fullPath = resolve(baseDir, includePath);\r\n\r\n if (visited.has(fullPath)) {\r\n throw new Error(`Circular include detected: ${fullPath} (included from ${basePath})`);\r\n }\r\n\r\n const content = await readFile(fullPath, 'utf-8');\r\n const { asset: includedAsset } = parsePrompt(content, fullPath);\r\n\r\n // Recursively resolve nested includes\r\n const resolved = await resolveIncludes(includedAsset, fullPath, new Set(visited));\r\n\r\n // Append included system instructions before local ones\r\n if (resolved.sections?.system_instructions) {\r\n mergedSystemInstructions += resolved.sections.system_instructions + '\\n\\n';\r\n }\r\n }\r\n\r\n // Prepend included system instructions before the local ones\r\n const localSystem = asset.sections?.system_instructions ?? '';\r\n const combinedSystem = (mergedSystemInstructions + localSystem).trim() || undefined;\r\n\r\n return {\r\n ...asset,\r\n sections: {\r\n ...asset.sections,\r\n system_instructions: combinedSystem,\r\n },\r\n // Drop includes from the resolved asset — they've been inlined\r\n includes: undefined,\r\n };\r\n}\r\n","import type { PromptAsset, PromptAssetOverrides } from '../schema/index.js';\r\n\r\nexport interface OverrideOptions {\r\n environment?: string;\r\n tier?: string;\r\n runtime?: Partial<PromptAssetOverrides>;\r\n}\r\n\r\n/**\r\n * Apply environment, tier, and runtime overrides to a prompt asset.\r\n *\r\n * Precedence: base → environment → tier → runtime\r\n * Scalars are replaced. Arrays are replaced (not concatenated).\r\n */\r\nexport function applyOverrides(\r\n asset: PromptAsset,\r\n options: OverrideOptions = {},\r\n): PromptAsset {\r\n let result = { ...asset };\r\n\r\n // Apply environment override\r\n if (options.environment && result.environments?.[options.environment]) {\r\n result = mergeOverride(result, result.environments[options.environment]);\r\n }\r\n\r\n // Apply tier override\r\n if (options.tier && result.tiers?.[options.tier]) {\r\n result = mergeOverride(result, result.tiers[options.tier]);\r\n }\r\n\r\n // Apply runtime overrides\r\n if (options.runtime) {\r\n result = mergeOverride(result, options.runtime);\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction mergeOverride(\r\n base: PromptAsset,\r\n override: Partial<PromptAssetOverrides>,\r\n): PromptAsset {\r\n const result = { ...base };\r\n\r\n if (override.model !== undefined) result.model = override.model;\r\n if (override.fallback_models !== undefined) result.fallback_models = override.fallback_models;\r\n if (override.tools !== undefined) result.tools = override.tools;\r\n\r\n if (override.reasoning !== undefined) {\r\n result.reasoning = { ...result.reasoning, ...override.reasoning };\r\n }\r\n if (override.sampling !== undefined) {\r\n result.sampling = { ...result.sampling, ...override.sampling };\r\n }\r\n if (override.response !== undefined) {\r\n result.response = { ...result.response, ...override.response };\r\n }\r\n\r\n return result;\r\n}\r\n","export type { ProviderAdapter, ProviderRequest, ValidationResult, RuntimeRenderOptions } from './types.js';\r\nexport { openaiAdapter } from './openai.js';\r\nexport { anthropicAdapter } from './anthropic.js';\r\nexport { geminiAdapter } from './gemini.js';\r\nexport { openrouterAdapter } from './openrouter.js';\r\n\r\nimport type { ProviderAdapter } from './types.js';\r\nimport { openaiAdapter } from './openai.js';\r\nimport { anthropicAdapter } from './anthropic.js';\r\nimport { geminiAdapter } from './gemini.js';\r\nimport { openrouterAdapter } from './openrouter.js';\r\n\r\nconst adapters: Record<string, ProviderAdapter> = {\r\n openai: openaiAdapter,\r\n anthropic: anthropicAdapter,\r\n google: geminiAdapter,\r\n gemini: geminiAdapter,\r\n openrouter: openrouterAdapter,\r\n};\r\n\r\n/**\r\n * Get a provider adapter by name.\r\n */\r\nexport function getAdapter(provider: string): ProviderAdapter {\r\n const adapter = adapters[provider];\r\n if (!adapter) {\r\n throw new Error(\r\n `Unknown provider: \"${provider}\". Supported: ${Object.keys(adapters).join(', ')}`,\r\n );\r\n }\r\n return adapter;\r\n}\r\n","/**\r\n * Compute the Levenshtein distance between two strings.\r\n * Used for \"did you mean?\" suggestions on unknown fields.\r\n */\r\nexport function levenshtein(a: string, b: string): number {\r\n const m = a.length;\r\n const n = b.length;\r\n\r\n if (m === 0) return n;\r\n if (n === 0) return m;\r\n\r\n const dp: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0) as number[]);\r\n\r\n for (let i = 0; i <= m; i++) dp[i][0] = i;\r\n for (let j = 0; j <= n; j++) dp[0][j] = j;\r\n\r\n for (let i = 1; i <= m; i++) {\r\n for (let j = 1; j <= n; j++) {\r\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\r\n dp[i][j] = Math.min(\r\n dp[i - 1][j] + 1,\r\n dp[i][j - 1] + 1,\r\n dp[i - 1][j - 1] + cost,\r\n );\r\n }\r\n }\r\n\r\n return dp[m][n];\r\n}\r\n","import { PromptAssetSchema } from '../schema/index.js';\r\nimport type { PromptAsset } from '../schema/index.js';\r\nimport { extractVariables } from '../renderer/index.js';\r\nimport { resolveIncludes } from '../composition/index.js';\r\nimport { levenshtein } from './levenshtein.js';\r\n\r\nexport interface ValidationError {\r\n code: string;\r\n message: string;\r\n filePath?: string;\r\n suggestion?: string;\r\n}\r\n\r\nexport interface PromptValidationResult {\r\n valid: boolean;\r\n errors: ValidationError[];\r\n warnings: ValidationError[];\r\n}\r\n\r\nconst KNOWN_FRONT_MATTER_KEYS = new Set([\r\n 'id', 'schema_version', 'description', 'provider', 'model', 'fallback_models',\r\n 'reasoning', 'sampling', 'response', 'tools', 'mcp', 'context', 'includes',\r\n 'environments', 'tiers', 'metadata',\r\n]);\r\n\r\n/**\r\n * Validate a parsed prompt asset, returning all errors and warnings.\r\n */\r\nexport function validateAsset(\r\n asset: PromptAsset,\r\n frontMatterKeys?: string[],\r\n filePath?: string,\r\n): PromptValidationResult {\r\n const errors: ValidationError[] = [];\r\n const warnings: ValidationError[] = [];\r\n\r\n // Schema validation\r\n const result = PromptAssetSchema.safeParse(asset);\r\n if (!result.success) {\r\n for (const issue of result.error.issues) {\r\n errors.push({\r\n code: 'POK001',\r\n message: `Schema error at ${issue.path.join('.')}: ${issue.message}`,\r\n filePath,\r\n });\r\n }\r\n }\r\n\r\n // Missing id\r\n if (!asset.id) {\r\n errors.push({\r\n code: 'POK002',\r\n message: 'Missing required field: \"id\"',\r\n filePath,\r\n });\r\n }\r\n\r\n // Missing body sections\r\n if (!asset.sections?.system_instructions && !asset.sections?.prompt_template) {\r\n errors.push({\r\n code: 'POK003',\r\n message: 'Prompt must have at least one body section (System instructions or Prompt template)',\r\n filePath,\r\n });\r\n }\r\n\r\n // Unknown front matter keys with \"did you mean?\"\r\n if (frontMatterKeys) {\r\n for (const key of frontMatterKeys) {\r\n if (!KNOWN_FRONT_MATTER_KEYS.has(key)) {\r\n const suggestion = findClosestMatch(key, KNOWN_FRONT_MATTER_KEYS);\r\n warnings.push({\r\n code: 'POK010',\r\n message: `Unknown front matter field: \"${key}\"`,\r\n filePath,\r\n suggestion: suggestion ? `Did you mean \"${suggestion}\"?` : undefined,\r\n });\r\n }\r\n }\r\n }\r\n\r\n // Variable validation: used but not declared\r\n const declaredInputs = new Set(asset.context?.inputs ?? []);\r\n const usedVars = new Set<string>();\r\n\r\n if (asset.sections?.system_instructions) {\r\n for (const v of extractVariables(asset.sections.system_instructions)) {\r\n usedVars.add(v);\r\n }\r\n }\r\n if (asset.sections?.prompt_template) {\r\n for (const v of extractVariables(asset.sections.prompt_template)) {\r\n usedVars.add(v);\r\n }\r\n }\r\n\r\n for (const v of usedVars) {\r\n if (declaredInputs.size > 0 && !declaredInputs.has(v)) {\r\n warnings.push({\r\n code: 'POK011',\r\n message: `Variable \"{{ ${v} }}\" is used but not declared in context.inputs`,\r\n filePath,\r\n });\r\n }\r\n }\r\n\r\n // Declared but unused\r\n for (const v of declaredInputs) {\r\n if (!usedVars.has(v)) {\r\n warnings.push({\r\n code: 'POK012',\r\n message: `Variable \"${v}\" is declared in context.inputs but never used`,\r\n filePath,\r\n });\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n errors,\r\n warnings,\r\n };\r\n}\r\n\r\n/**\r\n * Validate a prompt asset including its include graph.\r\n * Catches missing include files, circular includes, and parse errors in included files.\r\n */\r\nexport async function validateAssetWithIncludes(\r\n asset: PromptAsset,\r\n filePath: string,\r\n frontMatterKeys?: string[],\r\n): Promise<PromptValidationResult> {\r\n // Run standard validation first\r\n const result = validateAsset(asset, frontMatterKeys, filePath);\r\n\r\n // Validate includes\r\n if (asset.includes && asset.includes.length > 0) {\r\n try {\r\n await resolveIncludes(asset, filePath);\r\n } catch (err) {\r\n const message = err instanceof Error ? err.message : String(err);\r\n const isCircular = message.includes('Circular include');\r\n result.errors.push({\r\n code: isCircular ? 'POK021' : 'POK020',\r\n message: isCircular\r\n ? `Circular include detected: ${message}`\r\n : `Include resolution failed: ${message}`,\r\n filePath,\r\n });\r\n result.valid = false;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction findClosestMatch(input: string, candidates: Set<string>): string | undefined {\r\n let best: string | undefined;\r\n let bestDist = Infinity;\r\n\r\n for (const candidate of candidates) {\r\n const dist = levenshtein(input.toLowerCase(), candidate.toLowerCase());\r\n if (dist < bestDist && dist <= 3) {\r\n bestDist = dist;\r\n best = candidate;\r\n }\r\n }\r\n\r\n return best;\r\n}\r\n","import { statSync } from 'node:fs';\r\n\r\ninterface CacheEntry<T> {\r\n value: T;\r\n mtime: number;\r\n}\r\n\r\n/**\r\n * Simple in-memory LRU cache keyed by file path + mtime.\r\n * Used to avoid re-parsing prompt files on every renderPrompt() call.\r\n */\r\nexport class PromptCache<T> {\r\n private cache = new Map<string, CacheEntry<T>>();\r\n private maxSize: number;\r\n\r\n constructor(maxSize = 100) {\r\n this.maxSize = maxSize;\r\n }\r\n\r\n get(filePath: string): T | undefined {\r\n const entry = this.cache.get(filePath);\r\n if (!entry) return undefined;\r\n\r\n try {\r\n const stat = statSync(filePath);\r\n if (stat.mtimeMs !== entry.mtime) {\r\n this.cache.delete(filePath);\r\n return undefined;\r\n }\r\n } catch {\r\n this.cache.delete(filePath);\r\n return undefined;\r\n }\r\n\r\n return entry.value;\r\n }\r\n\r\n set(filePath: string, value: T): void {\r\n // Evict oldest if at capacity\r\n if (this.cache.size >= this.maxSize) {\r\n const oldest = this.cache.keys().next().value;\r\n if (oldest) this.cache.delete(oldest);\r\n }\r\n\r\n try {\r\n const stat = statSync(filePath);\r\n this.cache.set(filePath, { value, mtime: stat.mtimeMs });\r\n } catch {\r\n // Can't stat the file — don't cache\r\n }\r\n }\r\n\r\n clear(): void {\r\n this.cache.clear();\r\n }\r\n\r\n get size(): number {\r\n return this.cache.size;\r\n }\r\n}\r\n"],"mappings":"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","names":["readFile","statSync","resolve","resolve","statSync","readFile"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/composition/resolve-includes.ts","../src/overrides/apply-overrides.ts","../src/providers/index.ts","../src/validation/levenshtein.ts","../src/validation/validate.ts","../src/cache.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { existsSync, statSync } from 'node:fs';\nimport { resolve, join } from 'node:path';\n\nimport { parsePrompt, loadPromptFile } from './parser/index.js';\nimport { resolveIncludes } from './composition/index.js';\nimport { applyOverrides } from './overrides/index.js';\nimport { renderSections } from './renderer/index.js';\nimport { getAdapter } from './providers/index.js';\nimport { validateAsset } from './validation/index.js';\nimport { PromptCache } from './cache.js';\nimport type { PromptAsset, ResolvedPromptAsset } from './schema/index.js';\nimport type { ProviderRequest, RuntimeRenderOptions } from './providers/types.js';\nimport type { PromptValidationResult } from './validation/index.js';\n\n// --- Re-exports ---\nexport type { PromptAsset, ResolvedPromptAsset } from './schema/index.js';\nexport type { ProviderRequest, RuntimeRenderOptions, ProviderAdapter, ValidationResult } from './providers/types.js';\nexport type { PromptValidationResult, ValidationError } from './validation/index.js';\nexport type { RenderedSections, RenderOptions } from './renderer/index.js';\nexport type { ParseResult } from './parser/index.js';\nexport type { OverrideOptions } from './overrides/index.js';\n\nexport { parsePrompt, loadPromptFile, extractSections } from './parser/index.js';\nexport { interpolate, extractVariables } from './renderer/index.js';\nexport { resolveIncludes } from './composition/index.js';\nexport { applyOverrides } from './overrides/index.js';\nexport { validateAsset, validateAssetWithIncludes } from './validation/index.js';\nexport { getAdapter, openaiAdapter } from './providers/index.js';\nexport { anthropicAdapter } from './providers/anthropic.js';\nexport { geminiAdapter } from './providers/gemini.js';\nexport { openrouterAdapter } from './providers/openrouter.js';\nexport { PromptAssetSchema, PromptAssetOverridesSchema } from './schema/index.js';\n\n// --- Config ---\n\nexport interface PromptOpsKitConfig {\n sourceDir: string;\n compiledDir?: string;\n mode?: 'auto' | 'compiled-only' | 'source-only';\n cache?: boolean;\n}\n\n// --- Render options ---\n\nexport interface RenderPromptOptions {\n /** Prompt path (no extension), e.g. 'support/reply' */\n path?: string;\n /** Inline prompt source string (alternative to path) */\n source?: string;\n /** Provider name */\n provider: string;\n /** Environment override */\n environment?: string;\n /** Tier override */\n tier?: string;\n /** Variables for interpolation */\n variables?: Record<string, string>;\n /** Conversation history */\n history?: Array<{ role: string; content: string }>;\n /** Tool registry for resolving tool references */\n toolRegistry?: Record<string, unknown>;\n /** Strict mode — fail on missing variables */\n strict?: boolean;\n}\n\n// --- Result ---\n\nexport interface RenderResult {\n resolved: ResolvedPromptAsset;\n request: ProviderRequest;\n warnings: string[];\n}\n\n// --- Main class ---\n\nexport class PromptOpsKit {\n private config: Required<Pick<PromptOpsKitConfig, 'sourceDir' | 'mode'>> & PromptOpsKitConfig;\n private promptCache: PromptCache<PromptAsset>;\n\n constructor(config: PromptOpsKitConfig) {\n this.config = {\n ...config,\n mode: config.mode ?? 'auto',\n cache: config.cache ?? true,\n };\n this.promptCache = new PromptCache();\n }\n\n /**\n * Load a prompt asset from compiled or source, based on mode.\n */\n async loadPrompt(promptPath: string): Promise<PromptAsset> {\n const mode = this.config.mode;\n\n // Try compiled first (unless source-only)\n if (mode !== 'source-only' && this.config.compiledDir) {\n const compiledFile = resolve(this.config.compiledDir, promptPath + '.json');\n if (existsSync(compiledFile)) {\n // Check for stale artifact in auto mode\n if (mode === 'auto') {\n const sourceFile = resolve(this.config.sourceDir, promptPath + '.md');\n if (existsSync(sourceFile)) {\n const compiledMtime = statSync(compiledFile).mtimeMs;\n const sourceMtime = statSync(sourceFile).mtimeMs;\n if (sourceMtime > compiledMtime) {\n console.warn(\n `[promptopskit] Warning: compiled artifact for \"${promptPath}\" is older than source .md file.\\n` +\n ` Run \"promptopskit compile\" or switch to source-only mode.`,\n );\n }\n }\n }\n const content = await readFile(compiledFile, 'utf-8');\n return JSON.parse(content) as PromptAsset;\n }\n if (mode === 'compiled-only') {\n throw new Error(\n `Compiled artifact not found: ${compiledFile}\\n` +\n `Run \"promptopskit compile\" to generate it.`,\n );\n }\n }\n\n // Fall back to source\n if (mode !== 'compiled-only') {\n const sourceFile = resolve(this.config.sourceDir, promptPath + '.md');\n\n // Check cache\n if (this.config.cache) {\n const cached = this.promptCache.get(sourceFile);\n if (cached) return cached;\n }\n\n if (!existsSync(sourceFile)) {\n const paths = [sourceFile];\n if (this.config.compiledDir) {\n paths.unshift(resolve(this.config.compiledDir, promptPath + '.json'));\n }\n throw new Error(\n `Prompt not found: \"${promptPath}\"\\nSearched:\\n${paths.map((p) => ` - ${p}`).join('\\n')}`,\n );\n }\n\n const { asset } = await loadPromptFile(sourceFile, { defaultsRoot: this.config.sourceDir });\n\n if (this.config.cache) {\n this.promptCache.set(sourceFile, asset);\n }\n\n return asset;\n }\n\n throw new Error(`Prompt not found: \"${promptPath}\"`);\n }\n\n /**\n * Resolve a prompt: load, resolve includes, apply overrides.\n */\n async resolvePrompt(\n promptPath: string,\n options: { environment?: string; tier?: string } = {},\n ): Promise<ResolvedPromptAsset> {\n let asset = await this.loadPrompt(promptPath);\n\n // Resolve includes\n const sourceFile = resolve(this.config.sourceDir, promptPath + '.md');\n if (asset.includes && asset.includes.length > 0 && existsSync(sourceFile)) {\n asset = await resolveIncludes(asset, sourceFile);\n }\n\n // Apply overrides\n asset = applyOverrides(asset, {\n environment: options.environment,\n tier: options.tier,\n });\n\n return asset as ResolvedPromptAsset;\n }\n\n /**\n * Render a prompt for a specific provider.\n */\n async renderPrompt(options: RenderPromptOptions): Promise<RenderResult> {\n let resolved: ResolvedPromptAsset;\n\n if (options.source) {\n // Inline source mode\n const { asset } = parsePrompt(options.source);\n const overridden = applyOverrides(asset, {\n environment: options.environment,\n tier: options.tier,\n });\n resolved = overridden as ResolvedPromptAsset;\n } else if (options.path) {\n resolved = await this.resolvePrompt(options.path, {\n environment: options.environment,\n tier: options.tier,\n });\n } else {\n throw new Error('Either \"path\" or \"source\" must be provided to renderPrompt()');\n }\n\n const adapter = getAdapter(options.provider);\n const validation = adapter.validate(resolved);\n\n if (!validation.valid) {\n throw new Error(\n `Provider validation failed for \"${options.provider}\":\\n` +\n validation.errors.map((e) => ` - ${e}`).join('\\n'),\n );\n }\n\n const request = adapter.render(resolved, {\n variables: options.variables,\n history: options.history,\n toolRegistry: options.toolRegistry,\n strict: options.strict,\n });\n\n return {\n resolved,\n request,\n warnings: validation.warnings,\n };\n }\n\n /**\n * Validate a prompt file.\n */\n async validatePrompt(promptPath: string): Promise<PromptValidationResult> {\n const asset = await this.loadPrompt(promptPath);\n return validateAsset(asset, undefined, promptPath);\n }\n\n /**\n * Clear the internal cache.\n */\n clearCache(): void {\n this.promptCache.clear();\n }\n}\n\n// --- Factory ---\n\nexport function createPromptOpsKit(config: PromptOpsKitConfig): PromptOpsKit {\n return new PromptOpsKit(config);\n}\n\n// --- Standalone convenience ---\n\n/**\n * Standalone renderPrompt for quick usage without creating a PromptOpsKit instance.\n * Requires either `source` (inline) or `path` + implicit sourceDir of '.'.\n */\nexport async function renderPrompt(\n options: RenderPromptOptions & { sourceDir?: string },\n): Promise<RenderResult> {\n const kit = createPromptOpsKit({\n sourceDir: options.sourceDir ?? '.',\n cache: false,\n });\n return kit.renderPrompt(options);\n}\n","import { readFile } from 'node:fs/promises';\nimport { resolve, dirname } from 'node:path';\nimport { parsePrompt } from '../parser/index.js';\nimport type { PromptAsset } from '../schema/index.js';\n\n/**\n * Resolve includes for a prompt asset, inlining content from referenced files.\n * Detects and rejects circular includes.\n */\nexport async function resolveIncludes(\n asset: PromptAsset,\n basePath: string,\n visited: Set<string> = new Set(),\n): Promise<PromptAsset> {\n if (!asset.includes || asset.includes.length === 0) {\n return asset;\n }\n\n const baseDir = dirname(basePath);\n const resolvedPath = resolve(basePath);\n\n if (visited.has(resolvedPath)) {\n throw new Error(`Circular include detected: ${resolvedPath}`);\n }\n visited.add(resolvedPath);\n\n let mergedSystemInstructions = '';\n\n for (const includePath of asset.includes) {\n const fullPath = resolve(baseDir, includePath);\n\n if (visited.has(fullPath)) {\n throw new Error(`Circular include detected: ${fullPath} (included from ${basePath})`);\n }\n\n const content = await readFile(fullPath, 'utf-8');\n const { asset: includedAsset } = parsePrompt(content, fullPath);\n\n // Recursively resolve nested includes\n const resolved = await resolveIncludes(includedAsset, fullPath, new Set(visited));\n\n // Append included system instructions before local ones\n if (resolved.sections?.system_instructions) {\n mergedSystemInstructions += resolved.sections.system_instructions + '\\n\\n';\n }\n }\n\n // Prepend included system instructions before the local ones\n const localSystem = asset.sections?.system_instructions ?? '';\n const combinedSystem = (mergedSystemInstructions + localSystem).trim() || undefined;\n\n return {\n ...asset,\n sections: {\n ...asset.sections,\n system_instructions: combinedSystem,\n },\n // Drop includes from the resolved asset — they've been inlined\n includes: undefined,\n };\n}\n","import type { PromptAsset, PromptAssetOverrides } from '../schema/index.js';\n\nexport interface OverrideOptions {\n environment?: string;\n tier?: string;\n runtime?: Partial<PromptAssetOverrides>;\n}\n\n/**\n * Apply environment, tier, and runtime overrides to a prompt asset.\n *\n * Precedence: base → environment → tier → runtime\n * Scalars are replaced. Arrays are replaced (not concatenated).\n */\nexport function applyOverrides(\n asset: PromptAsset,\n options: OverrideOptions = {},\n): PromptAsset {\n let result = { ...asset };\n\n // Apply environment override\n if (options.environment && result.environments?.[options.environment]) {\n result = mergeOverride(result, result.environments[options.environment]);\n }\n\n // Apply tier override\n if (options.tier && result.tiers?.[options.tier]) {\n result = mergeOverride(result, result.tiers[options.tier]);\n }\n\n // Apply runtime overrides\n if (options.runtime) {\n result = mergeOverride(result, options.runtime);\n }\n\n return result;\n}\n\nfunction mergeOverride(\n base: PromptAsset,\n override: Partial<PromptAssetOverrides>,\n): PromptAsset {\n const result = { ...base };\n\n if (override.model !== undefined) result.model = override.model;\n if (override.fallback_models !== undefined) result.fallback_models = override.fallback_models;\n if (override.tools !== undefined) result.tools = override.tools;\n\n if (override.reasoning !== undefined) {\n result.reasoning = { ...result.reasoning, ...override.reasoning };\n }\n if (override.sampling !== undefined) {\n result.sampling = { ...result.sampling, ...override.sampling };\n }\n if (override.response !== undefined) {\n result.response = { ...result.response, ...override.response };\n }\n\n return result;\n}\n","export type { ProviderAdapter, ProviderRequest, ValidationResult, RuntimeRenderOptions } from './types.js';\nexport { openaiAdapter } from './openai.js';\nexport { anthropicAdapter } from './anthropic.js';\nexport { geminiAdapter } from './gemini.js';\nexport { openrouterAdapter } from './openrouter.js';\n\nimport type { ProviderAdapter } from './types.js';\nimport { openaiAdapter } from './openai.js';\nimport { anthropicAdapter } from './anthropic.js';\nimport { geminiAdapter } from './gemini.js';\nimport { openrouterAdapter } from './openrouter.js';\n\nconst adapters: Record<string, ProviderAdapter> = {\n openai: openaiAdapter,\n anthropic: anthropicAdapter,\n google: geminiAdapter,\n gemini: geminiAdapter,\n openrouter: openrouterAdapter,\n};\n\n/**\n * Get a provider adapter by name.\n */\nexport function getAdapter(provider: string): ProviderAdapter {\n const adapter = adapters[provider];\n if (!adapter) {\n throw new Error(\n `Unknown provider: \"${provider}\". Supported: ${Object.keys(adapters).join(', ')}`,\n );\n }\n return adapter;\n}\n","/**\n * Compute the Levenshtein distance between two strings.\n * Used for \"did you mean?\" suggestions on unknown fields.\n */\nexport function levenshtein(a: string, b: string): number {\n const m = a.length;\n const n = b.length;\n\n if (m === 0) return n;\n if (n === 0) return m;\n\n const dp: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0) as number[]);\n\n for (let i = 0; i <= m; i++) dp[i][0] = i;\n for (let j = 0; j <= n; j++) dp[0][j] = j;\n\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n dp[i][j] = Math.min(\n dp[i - 1][j] + 1,\n dp[i][j - 1] + 1,\n dp[i - 1][j - 1] + cost,\n );\n }\n }\n\n return dp[m][n];\n}\n","import { PromptAssetSchema } from '../schema/index.js';\nimport type { PromptAsset } from '../schema/index.js';\nimport { extractVariables } from '../renderer/index.js';\nimport { resolveIncludes } from '../composition/index.js';\nimport { levenshtein } from './levenshtein.js';\n\nexport interface ValidationError {\n code: string;\n message: string;\n filePath?: string;\n suggestion?: string;\n}\n\nexport interface PromptValidationResult {\n valid: boolean;\n errors: ValidationError[];\n warnings: ValidationError[];\n}\n\nconst KNOWN_FRONT_MATTER_KEYS = new Set([\n 'id', 'schema_version', 'description', 'provider', 'model', 'fallback_models',\n 'reasoning', 'sampling', 'response', 'tools', 'mcp', 'context', 'includes',\n 'environments', 'tiers', 'metadata',\n]);\n\n/**\n * Validate a parsed prompt asset, returning all errors and warnings.\n */\nexport function validateAsset(\n asset: PromptAsset,\n frontMatterKeys?: string[],\n filePath?: string,\n): PromptValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationError[] = [];\n\n // Schema validation\n const result = PromptAssetSchema.safeParse(asset);\n if (!result.success) {\n for (const issue of result.error.issues) {\n errors.push({\n code: 'POK001',\n message: `Schema error at ${issue.path.join('.')}: ${issue.message}`,\n filePath,\n });\n }\n }\n\n // Missing id\n if (!asset.id) {\n errors.push({\n code: 'POK002',\n message: 'Missing required field: \"id\"',\n filePath,\n });\n }\n\n // Missing body sections\n if (!asset.sections?.system_instructions && !asset.sections?.prompt_template) {\n errors.push({\n code: 'POK003',\n message: 'Prompt must have at least one body section (System instructions or Prompt template)',\n filePath,\n });\n }\n\n // Unknown front matter keys with \"did you mean?\"\n if (frontMatterKeys) {\n for (const key of frontMatterKeys) {\n if (!KNOWN_FRONT_MATTER_KEYS.has(key)) {\n const suggestion = findClosestMatch(key, KNOWN_FRONT_MATTER_KEYS);\n warnings.push({\n code: 'POK010',\n message: `Unknown front matter field: \"${key}\"`,\n filePath,\n suggestion: suggestion ? `Did you mean \"${suggestion}\"?` : undefined,\n });\n }\n }\n }\n\n // Variable validation: used but not declared\n const declaredInputs = new Set(asset.context?.inputs ?? []);\n const usedVars = new Set<string>();\n\n if (asset.sections?.system_instructions) {\n for (const v of extractVariables(asset.sections.system_instructions)) {\n usedVars.add(v);\n }\n }\n if (asset.sections?.prompt_template) {\n for (const v of extractVariables(asset.sections.prompt_template)) {\n usedVars.add(v);\n }\n }\n\n for (const v of usedVars) {\n if (declaredInputs.size > 0 && !declaredInputs.has(v)) {\n warnings.push({\n code: 'POK011',\n message: `Variable \"{{ ${v} }}\" is used but not declared in context.inputs`,\n filePath,\n });\n }\n }\n\n // Declared but unused\n for (const v of declaredInputs) {\n if (!usedVars.has(v)) {\n warnings.push({\n code: 'POK012',\n message: `Variable \"${v}\" is declared in context.inputs but never used`,\n filePath,\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\n/**\n * Validate a prompt asset including its include graph.\n * Catches missing include files, circular includes, and parse errors in included files.\n */\nexport async function validateAssetWithIncludes(\n asset: PromptAsset,\n filePath: string,\n frontMatterKeys?: string[],\n): Promise<PromptValidationResult> {\n // Run standard validation first\n const result = validateAsset(asset, frontMatterKeys, filePath);\n\n // Validate includes\n if (asset.includes && asset.includes.length > 0) {\n try {\n await resolveIncludes(asset, filePath);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const isCircular = message.includes('Circular include');\n result.errors.push({\n code: isCircular ? 'POK021' : 'POK020',\n message: isCircular\n ? `Circular include detected: ${message}`\n : `Include resolution failed: ${message}`,\n filePath,\n });\n result.valid = false;\n }\n }\n\n return result;\n}\n\nfunction findClosestMatch(input: string, candidates: Set<string>): string | undefined {\n let best: string | undefined;\n let bestDist = Infinity;\n\n for (const candidate of candidates) {\n const dist = levenshtein(input.toLowerCase(), candidate.toLowerCase());\n if (dist < bestDist && dist <= 3) {\n bestDist = dist;\n best = candidate;\n }\n }\n\n return best;\n}\n","import { statSync } from 'node:fs';\n\ninterface CacheEntry<T> {\n value: T;\n mtime: number;\n}\n\n/**\n * Simple in-memory LRU cache keyed by file path + mtime.\n * Used to avoid re-parsing prompt files on every renderPrompt() call.\n */\nexport class PromptCache<T> {\n private cache = new Map<string, CacheEntry<T>>();\n private maxSize: number;\n\n constructor(maxSize = 100) {\n this.maxSize = maxSize;\n }\n\n get(filePath: string): T | undefined {\n const entry = this.cache.get(filePath);\n if (!entry) return undefined;\n\n try {\n const stat = statSync(filePath);\n if (stat.mtimeMs !== entry.mtime) {\n this.cache.delete(filePath);\n return undefined;\n }\n } catch {\n this.cache.delete(filePath);\n return undefined;\n }\n\n return entry.value;\n }\n\n set(filePath: string, value: T): void {\n // Evict oldest if at capacity\n if (this.cache.size >= this.maxSize) {\n const oldest = this.cache.keys().next().value;\n if (oldest) this.cache.delete(oldest);\n }\n\n try {\n const stat = statSync(filePath);\n this.cache.set(filePath, { value, mtime: stat.mtimeMs });\n } catch {\n // Can't stat the file — don't cache\n }\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n get size(): number {\n return this.cache.size;\n }\n}\n"],"mappings":"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","names":["readFile","statSync","resolve","resolve","statSync","readFile"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/anthropic.ts","../../src/renderer/interpolate.ts","../../src/renderer/renderer.ts"],"sourcesContent":["import type { ResolvedPromptAsset } from '../schema/index.js';\r\nimport type {\r\n ProviderAdapter,\r\n ProviderRequest,\r\n ValidationResult,\r\n RuntimeRenderOptions,\r\n} from './types.js';\r\nimport { renderSections } from '../renderer/index.js';\r\n\r\n/**\r\n * Anthropic provider adapter.\r\n * Produces request bodies compatible with the Anthropic Messages API.\r\n */\r\nexport const anthropicAdapter: ProviderAdapter = {\r\n name: 'anthropic',\r\n\r\n validate(asset: ResolvedPromptAsset): ValidationResult {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n if (!asset.model) {\r\n errors.push('Anthropic adapter requires a model to be specified.');\r\n }\r\n\r\n if (asset.sampling?.frequency_penalty !== undefined) {\r\n warnings.push('Anthropic does not support frequency_penalty. It will be ignored.');\r\n }\r\n if (asset.sampling?.presence_penalty !== undefined) {\r\n warnings.push('Anthropic does not support presence_penalty. It will be ignored.');\r\n }\r\n if (asset.reasoning?.effort !== undefined) {\r\n warnings.push('Anthropic uses budget_tokens for thinking, not effort. effort will be mapped approximately.');\r\n }\r\n\r\n return { valid: errors.length === 0, errors, warnings };\r\n },\r\n\r\n render(asset: ResolvedPromptAsset, runtime: RuntimeRenderOptions): ProviderRequest {\r\n const sections = renderSections(asset, {\r\n variables: runtime.variables,\r\n strict: runtime.strict,\r\n });\r\n\r\n const messages: Array<Record<string, unknown>> = [];\r\n\r\n // History\r\n if (runtime.history) {\r\n for (const msg of runtime.history) {\r\n messages.push({ role: msg.role, content: msg.content });\r\n }\r\n }\r\n\r\n // User message (prompt template)\r\n if (sections.prompt_template) {\r\n messages.push({ role: 'user', content: sections.prompt_template });\r\n }\r\n\r\n const body: Record<string, unknown> = {\r\n model: asset.model,\r\n messages,\r\n };\r\n\r\n // System goes as top-level field in Anthropic\r\n if (sections.system_instructions) {\r\n body.system = sections.system_instructions;\r\n }\r\n\r\n // Sampling params\r\n if (asset.sampling?.temperature !== undefined) body.temperature = asset.sampling.temperature;\r\n if (asset.sampling?.top_p !== undefined) body.top_p = asset.sampling.top_p;\r\n if (asset.sampling?.stop !== undefined) body.stop_sequences = asset.sampling.stop;\r\n if (asset.sampling?.max_output_tokens !== undefined) {\r\n body.max_tokens = asset.sampling.max_output_tokens;\r\n } else {\r\n // Anthropic requires max_tokens\r\n body.max_tokens = 4096;\r\n }\r\n\r\n // Thinking/reasoning\r\n if (asset.reasoning?.budget_tokens) {\r\n body.thinking = {\r\n type: 'enabled',\r\n budget_tokens: asset.reasoning.budget_tokens,\r\n };\r\n }\r\n\r\n // Streaming\r\n if (asset.response?.stream !== undefined) {\r\n body.stream = asset.response.stream;\r\n }\r\n\r\n // Tools\r\n if (asset.tools && asset.tools.length > 0) {\r\n body.tools = asset.tools.map((tool) => {\r\n if (typeof tool === 'string') {\r\n const def = runtime.toolRegistry?.[tool];\r\n if (def) return def;\r\n return { name: tool };\r\n }\r\n return {\r\n name: tool.name,\r\n description: tool.description,\r\n input_schema: tool.input_schema ?? { type: 'object', properties: {} },\r\n };\r\n });\r\n }\r\n\r\n return {\r\n body,\r\n provider: 'anthropic',\r\n model: asset.model ?? 'unknown',\r\n };\r\n },\r\n};\r\n","export interface InterpolateOptions {\r\n strict?: boolean;\r\n}\r\n\r\nconst VARIABLE_RE = /\\{\\{\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\}\\}/g;\r\nconst ESCAPED_OPEN = /\\\\\\{\\\\\\{/g;\r\nconst ESCAPE_PLACEHOLDER = '\\x00ESCAPED_OPEN\\x00';\r\n\r\n/**\r\n * Interpolate variables into a template string.\r\n *\r\n * Syntax: {{ variable_name }}\r\n * Escape: \\{\\{ produces literal {{\r\n *\r\n * In strict mode, throws on missing variables.\r\n * In permissive mode, leaves {{ placeholder }} intact.\r\n */\r\nexport function interpolate(\r\n template: string,\r\n variables: Record<string, string>,\r\n options: InterpolateOptions = {},\r\n): string {\r\n const { strict = false } = options;\r\n\r\n // Replace escaped sequences with placeholder\r\n let result = template.replace(ESCAPED_OPEN, ESCAPE_PLACEHOLDER);\r\n\r\n result = result.replace(VARIABLE_RE, (match, name: string) => {\r\n if (name in variables) {\r\n return variables[name];\r\n }\r\n if (strict) {\r\n throw new Error(`Missing required variable: \"${name}\"`);\r\n }\r\n return match; // leave placeholder intact in permissive mode\r\n });\r\n\r\n // Restore escaped sequences\r\n result = result.replaceAll(ESCAPE_PLACEHOLDER, '{{');\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Extract all variable names referenced in a template.\r\n */\r\nexport function extractVariables(template: string): string[] {\r\n const vars = new Set<string>();\r\n let match: RegExpExecArray | null;\r\n const re = new RegExp(VARIABLE_RE.source, 'g');\r\n while ((match = re.exec(template)) !== null) {\r\n vars.add(match[1]);\r\n }\r\n return [...vars];\r\n}\r\n","import type { ResolvedPromptAsset } from '../schema/index.js';\r\nimport { interpolate, extractVariables } from './interpolate.js';\r\n\r\nexport interface RenderOptions {\r\n variables?: Record<string, string>;\r\n strict?: boolean;\r\n}\r\n\r\nexport interface RenderedSections {\r\n system_instructions?: string;\r\n prompt_template?: string;\r\n}\r\n\r\n/**\r\n * Render the sections of a resolved prompt asset with variable interpolation.\r\n */\r\nexport function renderSections(\r\n asset: ResolvedPromptAsset,\r\n options: RenderOptions = {},\r\n): RenderedSections {\r\n const { variables = {}, strict = false } = options;\r\n\r\n const result: RenderedSections = {};\r\n\r\n if (asset.sections.system_instructions) {\r\n result.system_instructions = interpolate(\r\n asset.sections.system_instructions,\r\n variables,\r\n { strict },\r\n );\r\n }\r\n\r\n if (asset.sections.prompt_template) {\r\n result.prompt_template = interpolate(\r\n asset.sections.prompt_template,\r\n variables,\r\n { strict },\r\n );\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Get all variable names used across all sections.\r\n */\r\nexport function getRequiredVariables(asset: ResolvedPromptAsset): string[] {\r\n const vars = new Set<string>();\r\n\r\n if (asset.sections.system_instructions) {\r\n for (const v of extractVariables(asset.sections.system_instructions)) {\r\n vars.add(v);\r\n }\r\n }\r\n\r\n if (asset.sections.prompt_template) {\r\n for (const v of extractVariables(asset.sections.prompt_template)) {\r\n vars.add(v);\r\n }\r\n }\r\n\r\n return [...vars];\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/providers/anthropic.ts","../../src/renderer/interpolate.ts","../../src/renderer/renderer.ts"],"sourcesContent":["import type { ResolvedPromptAsset } from '../schema/index.js';\nimport type {\n ProviderAdapter,\n ProviderRequest,\n ValidationResult,\n RuntimeRenderOptions,\n} from './types.js';\nimport { renderSections } from '../renderer/index.js';\n\n/**\n * Anthropic provider adapter.\n * Produces request bodies compatible with the Anthropic Messages API.\n */\nexport const anthropicAdapter: ProviderAdapter = {\n name: 'anthropic',\n\n validate(asset: ResolvedPromptAsset): ValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!asset.model) {\n errors.push('Anthropic adapter requires a model to be specified.');\n }\n\n if (asset.sampling?.frequency_penalty !== undefined) {\n warnings.push('Anthropic does not support frequency_penalty. It will be ignored.');\n }\n if (asset.sampling?.presence_penalty !== undefined) {\n warnings.push('Anthropic does not support presence_penalty. It will be ignored.');\n }\n if (asset.reasoning?.effort !== undefined) {\n warnings.push('Anthropic uses budget_tokens for thinking, not effort. effort will be mapped approximately.');\n }\n\n return { valid: errors.length === 0, errors, warnings };\n },\n\n render(asset: ResolvedPromptAsset, runtime: RuntimeRenderOptions): ProviderRequest {\n const sections = renderSections(asset, {\n variables: runtime.variables,\n strict: runtime.strict,\n });\n\n const messages: Array<Record<string, unknown>> = [];\n\n // History\n if (runtime.history) {\n for (const msg of runtime.history) {\n messages.push({ role: msg.role, content: msg.content });\n }\n }\n\n // User message (prompt template)\n if (sections.prompt_template) {\n messages.push({ role: 'user', content: sections.prompt_template });\n }\n\n const body: Record<string, unknown> = {\n model: asset.model,\n messages,\n };\n\n // System goes as top-level field in Anthropic\n if (sections.system_instructions) {\n body.system = sections.system_instructions;\n }\n\n // Sampling params\n if (asset.sampling?.temperature !== undefined) body.temperature = asset.sampling.temperature;\n if (asset.sampling?.top_p !== undefined) body.top_p = asset.sampling.top_p;\n if (asset.sampling?.stop !== undefined) body.stop_sequences = asset.sampling.stop;\n if (asset.sampling?.max_output_tokens !== undefined) {\n body.max_tokens = asset.sampling.max_output_tokens;\n } else {\n // Anthropic requires max_tokens\n body.max_tokens = 4096;\n }\n\n // Thinking/reasoning\n if (asset.reasoning?.budget_tokens) {\n body.thinking = {\n type: 'enabled',\n budget_tokens: asset.reasoning.budget_tokens,\n };\n }\n\n // Streaming\n if (asset.response?.stream !== undefined) {\n body.stream = asset.response.stream;\n }\n\n // Tools\n if (asset.tools && asset.tools.length > 0) {\n body.tools = asset.tools.map((tool) => {\n if (typeof tool === 'string') {\n const def = runtime.toolRegistry?.[tool];\n if (def) return def;\n return { name: tool };\n }\n return {\n name: tool.name,\n description: tool.description,\n input_schema: tool.input_schema ?? { type: 'object', properties: {} },\n };\n });\n }\n\n return {\n body,\n provider: 'anthropic',\n model: asset.model ?? 'unknown',\n };\n },\n};\n","export interface InterpolateOptions {\n strict?: boolean;\n}\n\nconst VARIABLE_RE = /\\{\\{\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\}\\}/g;\nconst ESCAPED_OPEN = /\\\\\\{\\\\\\{/g;\nconst ESCAPE_PLACEHOLDER = '\\x00ESCAPED_OPEN\\x00';\n\n/**\n * Interpolate variables into a template string.\n *\n * Syntax: {{ variable_name }}\n * Escape: \\{\\{ produces literal {{\n *\n * In strict mode, throws on missing variables.\n * In permissive mode, leaves {{ placeholder }} intact.\n */\nexport function interpolate(\n template: string,\n variables: Record<string, string>,\n options: InterpolateOptions = {},\n): string {\n const { strict = false } = options;\n\n // Replace escaped sequences with placeholder\n let result = template.replace(ESCAPED_OPEN, ESCAPE_PLACEHOLDER);\n\n result = result.replace(VARIABLE_RE, (match, name: string) => {\n if (name in variables) {\n return variables[name];\n }\n if (strict) {\n throw new Error(`Missing required variable: \"${name}\"`);\n }\n return match; // leave placeholder intact in permissive mode\n });\n\n // Restore escaped sequences\n result = result.replaceAll(ESCAPE_PLACEHOLDER, '{{');\n\n return result;\n}\n\n/**\n * Extract all variable names referenced in a template.\n */\nexport function extractVariables(template: string): string[] {\n const vars = new Set<string>();\n let match: RegExpExecArray | null;\n const re = new RegExp(VARIABLE_RE.source, 'g');\n while ((match = re.exec(template)) !== null) {\n vars.add(match[1]);\n }\n return [...vars];\n}\n","import type { ResolvedPromptAsset } from '../schema/index.js';\nimport { interpolate, extractVariables } from './interpolate.js';\n\nexport interface RenderOptions {\n variables?: Record<string, string>;\n strict?: boolean;\n}\n\nexport interface RenderedSections {\n system_instructions?: string;\n prompt_template?: string;\n}\n\n/**\n * Render the sections of a resolved prompt asset with variable interpolation.\n */\nexport function renderSections(\n asset: ResolvedPromptAsset,\n options: RenderOptions = {},\n): RenderedSections {\n const { variables = {}, strict = false } = options;\n\n const result: RenderedSections = {};\n\n if (asset.sections.system_instructions) {\n result.system_instructions = interpolate(\n asset.sections.system_instructions,\n variables,\n { strict },\n );\n }\n\n if (asset.sections.prompt_template) {\n result.prompt_template = interpolate(\n asset.sections.prompt_template,\n variables,\n { strict },\n );\n }\n\n return result;\n}\n\n/**\n * Get all variable names used across all sections.\n */\nexport function getRequiredVariables(asset: ResolvedPromptAsset): string[] {\n const vars = new Set<string>();\n\n if (asset.sections.system_instructions) {\n for (const v of extractVariables(asset.sections.system_instructions)) {\n vars.add(v);\n }\n }\n\n if (asset.sections.prompt_template) {\n for (const v of extractVariables(asset.sections.prompt_template)) {\n vars.add(v);\n }\n }\n\n return [...vars];\n}\n"],"mappings":"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","names":[]}