promptopskit 0.2.6 → 0.3.1
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.
- package/README.md +89 -0
- package/SKILL.md +49 -0
- package/dist/{chunk-PU3UPUND.js → chunk-DDXFDVA6.js} +4 -4
- package/dist/{chunk-PU3UPUND.js.map → chunk-DDXFDVA6.js.map} +1 -1
- package/dist/chunk-DGFBS7YW.js +101 -0
- package/dist/chunk-DGFBS7YW.js.map +1 -0
- package/dist/chunk-HWEVRBKZ.js +387 -0
- package/dist/chunk-HWEVRBKZ.js.map +1 -0
- package/dist/{chunk-5BI5FP5L.js → chunk-LNZS3TIJ.js} +21 -18
- package/dist/chunk-LNZS3TIJ.js.map +1 -0
- package/dist/{chunk-VYVEVJC3.js → chunk-LRRSI4ON.js} +25 -22
- package/dist/chunk-LRRSI4ON.js.map +1 -0
- package/dist/chunk-Y2YYEGOY.js +86 -0
- package/dist/chunk-Y2YYEGOY.js.map +1 -0
- package/dist/cli/index.js +66 -40
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +479 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -4
- package/dist/index.d.ts +8 -4
- package/dist/index.js +41 -40
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.cjs +64 -19
- package/dist/providers/anthropic.cjs.map +1 -1
- package/dist/providers/anthropic.d.cts +2 -2
- package/dist/providers/anthropic.d.ts +2 -2
- package/dist/providers/anthropic.js +2 -2
- package/dist/providers/gemini.cjs +60 -15
- package/dist/providers/gemini.cjs.map +1 -1
- package/dist/providers/gemini.d.cts +2 -2
- package/dist/providers/gemini.d.ts +2 -2
- package/dist/providers/gemini.js +2 -2
- package/dist/providers/openai.cjs +64 -19
- package/dist/providers/openai.cjs.map +1 -1
- package/dist/providers/openai.d.cts +2 -2
- package/dist/providers/openai.d.ts +2 -2
- package/dist/providers/openai.js +2 -2
- package/dist/providers/openrouter.cjs +66 -21
- package/dist/providers/openrouter.cjs.map +1 -1
- package/dist/providers/openrouter.d.cts +2 -2
- package/dist/providers/openrouter.d.ts +2 -2
- package/dist/providers/openrouter.js +3 -3
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/{types-BUzJB5p_.d.cts → types-BsYdPHTU.d.ts} +5 -2
- package/dist/{types-DM0-tThJ.d.ts → types-DC-jI6iV.d.cts} +5 -2
- package/dist/usagetap/index.cjs +425 -0
- package/dist/usagetap/index.cjs.map +1 -0
- package/dist/usagetap/index.d.cts +147 -0
- package/dist/usagetap/index.d.ts +147 -0
- package/dist/usagetap/index.js +31 -0
- package/dist/usagetap/index.js.map +1 -0
- package/package.json +11 -1
- package/dist/chunk-5BI5FP5L.js.map +0 -1
- package/dist/chunk-6KGBPHSY.js +0 -56
- package/dist/chunk-6KGBPHSY.js.map +0 -1
- package/dist/chunk-UYTUGV7Z.js +0 -83
- package/dist/chunk-UYTUGV7Z.js.map +0 -1
- package/dist/chunk-VYVEVJC3.js.map +0 -1
- package/dist/{schema-DJ7C8Q6y.d.cts → schema-Dq0jKest.d.cts} +13 -13
- package/dist/{schema-DJ7C8Q6y.d.ts → schema-Dq0jKest.d.ts} +13 -13
|
@@ -65,25 +65,70 @@ function renderSections(asset, options = {}) {
|
|
|
65
65
|
return result;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
// src/overrides/apply-overrides.ts
|
|
69
|
+
function applyOverrides(asset, options = {}) {
|
|
70
|
+
let result = { ...asset };
|
|
71
|
+
if (options.environment && result.environments?.[options.environment]) {
|
|
72
|
+
result = mergeOverride(result, result.environments[options.environment]);
|
|
73
|
+
}
|
|
74
|
+
if (options.tier && result.tiers?.[options.tier]) {
|
|
75
|
+
result = mergeOverride(result, result.tiers[options.tier]);
|
|
76
|
+
}
|
|
77
|
+
if (options.runtime) {
|
|
78
|
+
result = mergeOverride(result, options.runtime);
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
function mergeOverride(base, override) {
|
|
83
|
+
const result = { ...base };
|
|
84
|
+
if (override.model !== void 0) result.model = override.model;
|
|
85
|
+
if (override.fallback_models !== void 0) result.fallback_models = override.fallback_models;
|
|
86
|
+
if (override.tools !== void 0) result.tools = override.tools;
|
|
87
|
+
if (override.reasoning !== void 0) {
|
|
88
|
+
result.reasoning = { ...result.reasoning, ...override.reasoning };
|
|
89
|
+
}
|
|
90
|
+
if (override.sampling !== void 0) {
|
|
91
|
+
result.sampling = { ...result.sampling, ...override.sampling };
|
|
92
|
+
}
|
|
93
|
+
if (override.response !== void 0) {
|
|
94
|
+
result.response = { ...result.response, ...override.response };
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/providers/resolve-asset.ts
|
|
100
|
+
function resolveAssetForProvider(asset, runtime = {}) {
|
|
101
|
+
if (!runtime.environment && !runtime.tier && !runtime.runtime) {
|
|
102
|
+
return asset;
|
|
103
|
+
}
|
|
104
|
+
return applyOverrides(asset, {
|
|
105
|
+
environment: runtime.environment,
|
|
106
|
+
tier: runtime.tier,
|
|
107
|
+
runtime: runtime.runtime
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
68
111
|
// src/providers/gemini.ts
|
|
69
112
|
var geminiAdapter = {
|
|
70
113
|
name: "gemini",
|
|
71
|
-
validate(asset) {
|
|
114
|
+
validate(asset, runtime) {
|
|
115
|
+
const resolvedAsset = resolveAssetForProvider(asset, runtime);
|
|
72
116
|
const errors = [];
|
|
73
117
|
const warnings = [];
|
|
74
|
-
if (!
|
|
118
|
+
if (!resolvedAsset.model) {
|
|
75
119
|
errors.push("Gemini adapter requires a model to be specified.");
|
|
76
120
|
}
|
|
77
|
-
if (
|
|
121
|
+
if (resolvedAsset.sampling?.frequency_penalty !== void 0) {
|
|
78
122
|
warnings.push("Gemini does not support frequency_penalty. It will be ignored.");
|
|
79
123
|
}
|
|
80
|
-
if (
|
|
124
|
+
if (resolvedAsset.sampling?.presence_penalty !== void 0) {
|
|
81
125
|
warnings.push("Gemini does not support presence_penalty. It will be ignored.");
|
|
82
126
|
}
|
|
83
127
|
return { valid: errors.length === 0, errors, warnings };
|
|
84
128
|
},
|
|
85
129
|
render(asset, runtime) {
|
|
86
|
-
const
|
|
130
|
+
const resolvedAsset = resolveAssetForProvider(asset, runtime);
|
|
131
|
+
const sections = renderSections(resolvedAsset, {
|
|
87
132
|
variables: runtime.variables,
|
|
88
133
|
strict: runtime.strict
|
|
89
134
|
});
|
|
@@ -111,23 +156,23 @@ var geminiAdapter = {
|
|
|
111
156
|
};
|
|
112
157
|
}
|
|
113
158
|
const generationConfig = {};
|
|
114
|
-
if (
|
|
115
|
-
if (
|
|
116
|
-
if (
|
|
117
|
-
if (
|
|
118
|
-
if (
|
|
159
|
+
if (resolvedAsset.sampling?.temperature !== void 0) generationConfig.temperature = resolvedAsset.sampling.temperature;
|
|
160
|
+
if (resolvedAsset.sampling?.top_p !== void 0) generationConfig.topP = resolvedAsset.sampling.top_p;
|
|
161
|
+
if (resolvedAsset.sampling?.max_output_tokens !== void 0) generationConfig.maxOutputTokens = resolvedAsset.sampling.max_output_tokens;
|
|
162
|
+
if (resolvedAsset.sampling?.stop !== void 0) generationConfig.stopSequences = resolvedAsset.sampling.stop;
|
|
163
|
+
if (resolvedAsset.response?.format === "json") {
|
|
119
164
|
generationConfig.responseMimeType = "application/json";
|
|
120
165
|
}
|
|
121
|
-
if (
|
|
166
|
+
if (resolvedAsset.reasoning?.effort) {
|
|
122
167
|
body.thinkingConfig = {
|
|
123
|
-
thinkingBudget:
|
|
168
|
+
thinkingBudget: resolvedAsset.reasoning.effort === "high" ? 8192 : resolvedAsset.reasoning.effort === "medium" ? 4096 : 1024
|
|
124
169
|
};
|
|
125
170
|
}
|
|
126
171
|
if (Object.keys(generationConfig).length > 0) {
|
|
127
172
|
body.generationConfig = generationConfig;
|
|
128
173
|
}
|
|
129
|
-
if (
|
|
130
|
-
const functionDeclarations =
|
|
174
|
+
if (resolvedAsset.tools && resolvedAsset.tools.length > 0) {
|
|
175
|
+
const functionDeclarations = resolvedAsset.tools.map((tool) => {
|
|
131
176
|
if (typeof tool === "string") {
|
|
132
177
|
const def = runtime.toolRegistry?.[tool];
|
|
133
178
|
if (def) return def;
|
|
@@ -144,7 +189,7 @@ var geminiAdapter = {
|
|
|
144
189
|
return {
|
|
145
190
|
body,
|
|
146
191
|
provider: "gemini",
|
|
147
|
-
model:
|
|
192
|
+
model: resolvedAsset.model ?? "unknown"
|
|
148
193
|
};
|
|
149
194
|
}
|
|
150
195
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers/gemini.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 * 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","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":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/providers/gemini.ts","../../src/renderer/interpolate.ts","../../src/renderer/renderer.ts","../../src/overrides/apply-overrides.ts","../../src/providers/resolve-asset.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';\nimport { resolveAssetForProvider } from './resolve-asset.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, runtime?: RuntimeRenderOptions): ValidationResult {\n const resolvedAsset = resolveAssetForProvider(asset, runtime);\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!resolvedAsset.model) {\n errors.push('Gemini adapter requires a model to be specified.');\n }\n\n if (resolvedAsset.sampling?.frequency_penalty !== undefined) {\n warnings.push('Gemini does not support frequency_penalty. It will be ignored.');\n }\n if (resolvedAsset.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 resolvedAsset = resolveAssetForProvider(asset, runtime);\n const sections = renderSections(resolvedAsset, {\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 (resolvedAsset.sampling?.temperature !== undefined) generationConfig.temperature = resolvedAsset.sampling.temperature;\n if (resolvedAsset.sampling?.top_p !== undefined) generationConfig.topP = resolvedAsset.sampling.top_p;\n if (resolvedAsset.sampling?.max_output_tokens !== undefined) generationConfig.maxOutputTokens = resolvedAsset.sampling.max_output_tokens;\n if (resolvedAsset.sampling?.stop !== undefined) generationConfig.stopSequences = resolvedAsset.sampling.stop;\n\n if (resolvedAsset.response?.format === 'json') {\n generationConfig.responseMimeType = 'application/json';\n }\n\n // Thinking config\n if (resolvedAsset.reasoning?.effort) {\n body.thinkingConfig = {\n thinkingBudget: resolvedAsset.reasoning.effort === 'high' ? 8192 : resolvedAsset.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 (resolvedAsset.tools && resolvedAsset.tools.length > 0) {\n const functionDeclarations = resolvedAsset.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: resolvedAsset.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","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","import { applyOverrides } from '../overrides/index.js';\nimport type { ResolvedPromptAsset } from '../schema/index.js';\nimport type { RuntimeRenderOptions } from './types.js';\n\nexport function resolveAssetForProvider(\n asset: ResolvedPromptAsset,\n runtime: Pick<RuntimeRenderOptions, 'environment' | 'tier' | 'runtime'> = {},\n): ResolvedPromptAsset {\n if (!runtime.environment && !runtime.tier && !runtime.runtime) {\n return asset;\n }\n\n return applyOverrides(asset, {\n environment: runtime.environment,\n tier: runtime.tier,\n runtime: runtime.runtime,\n }) as ResolvedPromptAsset;\n}"],"mappings":"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","names":[]}
|
package/dist/providers/gemini.js
CHANGED
|
@@ -65,22 +65,67 @@ function renderSections(asset, options = {}) {
|
|
|
65
65
|
return result;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
// src/overrides/apply-overrides.ts
|
|
69
|
+
function applyOverrides(asset, options = {}) {
|
|
70
|
+
let result = { ...asset };
|
|
71
|
+
if (options.environment && result.environments?.[options.environment]) {
|
|
72
|
+
result = mergeOverride(result, result.environments[options.environment]);
|
|
73
|
+
}
|
|
74
|
+
if (options.tier && result.tiers?.[options.tier]) {
|
|
75
|
+
result = mergeOverride(result, result.tiers[options.tier]);
|
|
76
|
+
}
|
|
77
|
+
if (options.runtime) {
|
|
78
|
+
result = mergeOverride(result, options.runtime);
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
function mergeOverride(base, override) {
|
|
83
|
+
const result = { ...base };
|
|
84
|
+
if (override.model !== void 0) result.model = override.model;
|
|
85
|
+
if (override.fallback_models !== void 0) result.fallback_models = override.fallback_models;
|
|
86
|
+
if (override.tools !== void 0) result.tools = override.tools;
|
|
87
|
+
if (override.reasoning !== void 0) {
|
|
88
|
+
result.reasoning = { ...result.reasoning, ...override.reasoning };
|
|
89
|
+
}
|
|
90
|
+
if (override.sampling !== void 0) {
|
|
91
|
+
result.sampling = { ...result.sampling, ...override.sampling };
|
|
92
|
+
}
|
|
93
|
+
if (override.response !== void 0) {
|
|
94
|
+
result.response = { ...result.response, ...override.response };
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/providers/resolve-asset.ts
|
|
100
|
+
function resolveAssetForProvider(asset, runtime = {}) {
|
|
101
|
+
if (!runtime.environment && !runtime.tier && !runtime.runtime) {
|
|
102
|
+
return asset;
|
|
103
|
+
}
|
|
104
|
+
return applyOverrides(asset, {
|
|
105
|
+
environment: runtime.environment,
|
|
106
|
+
tier: runtime.tier,
|
|
107
|
+
runtime: runtime.runtime
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
68
111
|
// src/providers/openai.ts
|
|
69
112
|
var openaiAdapter = {
|
|
70
113
|
name: "openai",
|
|
71
|
-
validate(asset) {
|
|
114
|
+
validate(asset, runtime) {
|
|
115
|
+
const resolvedAsset = resolveAssetForProvider(asset, runtime);
|
|
72
116
|
const errors = [];
|
|
73
117
|
const warnings = [];
|
|
74
|
-
if (!
|
|
118
|
+
if (!resolvedAsset.model) {
|
|
75
119
|
errors.push("OpenAI adapter requires a model to be specified.");
|
|
76
120
|
}
|
|
77
|
-
if (
|
|
121
|
+
if (resolvedAsset.reasoning?.budget_tokens !== void 0) {
|
|
78
122
|
warnings.push("OpenAI uses reasoning_effort, not budget_tokens. budget_tokens will be ignored.");
|
|
79
123
|
}
|
|
80
124
|
return { valid: errors.length === 0, errors, warnings };
|
|
81
125
|
},
|
|
82
126
|
render(asset, runtime) {
|
|
83
|
-
const
|
|
127
|
+
const resolvedAsset = resolveAssetForProvider(asset, runtime);
|
|
128
|
+
const sections = renderSections(resolvedAsset, {
|
|
84
129
|
variables: runtime.variables,
|
|
85
130
|
strict: runtime.strict
|
|
86
131
|
});
|
|
@@ -97,26 +142,26 @@ var openaiAdapter = {
|
|
|
97
142
|
messages.push({ role: "user", content: sections.prompt_template });
|
|
98
143
|
}
|
|
99
144
|
const body = {
|
|
100
|
-
model:
|
|
145
|
+
model: resolvedAsset.model,
|
|
101
146
|
messages
|
|
102
147
|
};
|
|
103
|
-
if (
|
|
104
|
-
if (
|
|
105
|
-
if (
|
|
106
|
-
if (
|
|
107
|
-
if (
|
|
108
|
-
if (
|
|
109
|
-
if (
|
|
110
|
-
body.reasoning_effort =
|
|
148
|
+
if (resolvedAsset.sampling?.temperature !== void 0) body.temperature = resolvedAsset.sampling.temperature;
|
|
149
|
+
if (resolvedAsset.sampling?.top_p !== void 0) body.top_p = resolvedAsset.sampling.top_p;
|
|
150
|
+
if (resolvedAsset.sampling?.frequency_penalty !== void 0) body.frequency_penalty = resolvedAsset.sampling.frequency_penalty;
|
|
151
|
+
if (resolvedAsset.sampling?.presence_penalty !== void 0) body.presence_penalty = resolvedAsset.sampling.presence_penalty;
|
|
152
|
+
if (resolvedAsset.sampling?.stop !== void 0) body.stop = resolvedAsset.sampling.stop;
|
|
153
|
+
if (resolvedAsset.sampling?.max_output_tokens !== void 0) body.max_tokens = resolvedAsset.sampling.max_output_tokens;
|
|
154
|
+
if (resolvedAsset.reasoning?.effort) {
|
|
155
|
+
body.reasoning_effort = resolvedAsset.reasoning.effort;
|
|
111
156
|
}
|
|
112
|
-
if (
|
|
157
|
+
if (resolvedAsset.response?.format === "json") {
|
|
113
158
|
body.response_format = { type: "json_object" };
|
|
114
159
|
}
|
|
115
|
-
if (
|
|
116
|
-
body.stream =
|
|
160
|
+
if (resolvedAsset.response?.stream !== void 0) {
|
|
161
|
+
body.stream = resolvedAsset.response.stream;
|
|
117
162
|
}
|
|
118
|
-
if (
|
|
119
|
-
body.tools =
|
|
163
|
+
if (resolvedAsset.tools && resolvedAsset.tools.length > 0) {
|
|
164
|
+
body.tools = resolvedAsset.tools.map((tool) => {
|
|
120
165
|
if (typeof tool === "string") {
|
|
121
166
|
const def = runtime.toolRegistry?.[tool];
|
|
122
167
|
if (def) return def;
|
|
@@ -135,7 +180,7 @@ var openaiAdapter = {
|
|
|
135
180
|
return {
|
|
136
181
|
body,
|
|
137
182
|
provider: "openai",
|
|
138
|
-
model:
|
|
183
|
+
model: resolvedAsset.model ?? "unknown"
|
|
139
184
|
};
|
|
140
185
|
}
|
|
141
186
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers/openai.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 * 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","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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACIA,IAAM,cAAc;AACpB,IAAM,eAAe;AACrB,IAAM,qBAAqB;AAWpB,SAAS,YACd,UACA,WACA,UAA8B,CAAC,GACvB;AACR,QAAM,EAAE,SAAS,MAAM,IAAI;AAG3B,MAAI,SAAS,SAAS,QAAQ,cAAc,kBAAkB;AAE9D,WAAS,OAAO,QAAQ,aAAa,CAAC,OAAO,SAAiB;AAC5D,QAAI,QAAQ,WAAW;AACrB,aAAO,UAAU,IAAI;AAAA,IACvB;AACA,QAAI,QAAQ;AACV,YAAM,IAAI,MAAM,+BAA+B,IAAI,GAAG;AAAA,IACxD;AACA,WAAO;AAAA,EACT,CAAC;AAGD,WAAS,OAAO,WAAW,oBAAoB,IAAI;AAEnD,SAAO;AACT;;;ACzBO,SAAS,eACd,OACA,UAAyB,CAAC,GACR;AAClB,QAAM,EAAE,YAAY,CAAC,GAAG,SAAS,MAAM,IAAI;AAE3C,QAAM,SAA2B,CAAC;AAElC,MAAI,MAAM,SAAS,qBAAqB;AACtC,WAAO,sBAAsB;AAAA,MAC3B,MAAM,SAAS;AAAA,MACf;AAAA,MACA,EAAE,OAAO;AAAA,IACX;AAAA,EACF;AAEA,MAAI,MAAM,SAAS,iBAAiB;AAClC,WAAO,kBAAkB;AAAA,MACvB,MAAM,SAAS;AAAA,MACf;AAAA,MACA,EAAE,OAAO;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AACT;;;AF5BO,IAAM,gBAAiC;AAAA,EAC5C,MAAM;AAAA,EAEN,SAAS,OAA8C;AACrD,UAAM,SAAmB,CAAC;AAC1B,UAAM,WAAqB,CAAC;AAE5B,QAAI,CAAC,MAAM,OAAO;AAChB,aAAO,KAAK,kDAAkD;AAAA,IAChE;AAEA,QAAI,MAAM,WAAW,kBAAkB,QAAW;AAChD,eAAS,KAAK,iFAAiF;AAAA,IACjG;AAEA,WAAO,EAAE,OAAO,OAAO,WAAW,GAAG,QAAQ,SAAS;AAAA,EACxD;AAAA,EAEA,OAAO,OAA4B,SAAgD;AACjF,UAAM,WAAW,eAAe,OAAO;AAAA,MACrC,WAAW,QAAQ;AAAA,MACnB,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAED,UAAM,WAA2C,CAAC;AAGlD,QAAI,SAAS,qBAAqB;AAChC,eAAS,KAAK,EAAE,MAAM,UAAU,SAAS,SAAS,oBAAoB,CAAC;AAAA,IACzE;AAGA,QAAI,QAAQ,SAAS;AACnB,iBAAW,OAAO,QAAQ,SAAS;AACjC,iBAAS,KAAK,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,QAAQ,CAAC;AAAA,MACxD;AAAA,IACF;AAGA,QAAI,SAAS,iBAAiB;AAC5B,eAAS,KAAK,EAAE,MAAM,QAAQ,SAAS,SAAS,gBAAgB,CAAC;AAAA,IACnE;AAEA,UAAM,OAAgC;AAAA,MACpC,OAAO,MAAM;AAAA,MACb;AAAA,IACF;AAGA,QAAI,MAAM,UAAU,gBAAgB,OAAW,MAAK,cAAc,MAAM,SAAS;AACjF,QAAI,MAAM,UAAU,UAAU,OAAW,MAAK,QAAQ,MAAM,SAAS;AACrE,QAAI,MAAM,UAAU,sBAAsB,OAAW,MAAK,oBAAoB,MAAM,SAAS;AAC7F,QAAI,MAAM,UAAU,qBAAqB,OAAW,MAAK,mBAAmB,MAAM,SAAS;AAC3F,QAAI,MAAM,UAAU,SAAS,OAAW,MAAK,OAAO,MAAM,SAAS;AACnE,QAAI,MAAM,UAAU,sBAAsB,OAAW,MAAK,aAAa,MAAM,SAAS;AAGtF,QAAI,MAAM,WAAW,QAAQ;AAC3B,WAAK,mBAAmB,MAAM,UAAU;AAAA,IAC1C;AAGA,QAAI,MAAM,UAAU,WAAW,QAAQ;AACrC,WAAK,kBAAkB,EAAE,MAAM,cAAc;AAAA,IAC/C;AAGA,QAAI,MAAM,UAAU,WAAW,QAAW;AACxC,WAAK,SAAS,MAAM,SAAS;AAAA,IAC/B;AAGA,QAAI,MAAM,SAAS,MAAM,MAAM,SAAS,GAAG;AACzC,WAAK,QAAQ,MAAM,MAAM,IAAI,CAAC,SAAS;AACrC,YAAI,OAAO,SAAS,UAAU;AAE5B,gBAAM,MAAM,QAAQ,eAAe,IAAI;AACvC,cAAI,IAAK,QAAO;AAChB,iBAAO,EAAE,MAAM,YAAY,UAAU,EAAE,MAAM,KAAK,EAAE;AAAA,QACtD;AACA,eAAO;AAAA,UACL,MAAM;AAAA,UACN,UAAU;AAAA,YACR,MAAM,KAAK;AAAA,YACX,aAAa,KAAK;AAAA,YAClB,YAAY,KAAK;AAAA,UACnB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL;AAAA,MACA,UAAU;AAAA,MACV,OAAO,MAAM,SAAS;AAAA,IACxB;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/providers/openai.ts","../../src/renderer/interpolate.ts","../../src/renderer/renderer.ts","../../src/overrides/apply-overrides.ts","../../src/providers/resolve-asset.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';\nimport { resolveAssetForProvider } from './resolve-asset.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, runtime?: RuntimeRenderOptions): ValidationResult {\n const resolvedAsset = resolveAssetForProvider(asset, runtime);\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!resolvedAsset.model) {\n errors.push('OpenAI adapter requires a model to be specified.');\n }\n\n if (resolvedAsset.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 resolvedAsset = resolveAssetForProvider(asset, runtime);\n const sections = renderSections(resolvedAsset, {\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: resolvedAsset.model,\n messages,\n };\n\n // Sampling params\n if (resolvedAsset.sampling?.temperature !== undefined) body.temperature = resolvedAsset.sampling.temperature;\n if (resolvedAsset.sampling?.top_p !== undefined) body.top_p = resolvedAsset.sampling.top_p;\n if (resolvedAsset.sampling?.frequency_penalty !== undefined) body.frequency_penalty = resolvedAsset.sampling.frequency_penalty;\n if (resolvedAsset.sampling?.presence_penalty !== undefined) body.presence_penalty = resolvedAsset.sampling.presence_penalty;\n if (resolvedAsset.sampling?.stop !== undefined) body.stop = resolvedAsset.sampling.stop;\n if (resolvedAsset.sampling?.max_output_tokens !== undefined) body.max_tokens = resolvedAsset.sampling.max_output_tokens;\n\n // Reasoning\n if (resolvedAsset.reasoning?.effort) {\n body.reasoning_effort = resolvedAsset.reasoning.effort;\n }\n\n // Response format\n if (resolvedAsset.response?.format === 'json') {\n body.response_format = { type: 'json_object' };\n }\n\n // Streaming\n if (resolvedAsset.response?.stream !== undefined) {\n body.stream = resolvedAsset.response.stream;\n }\n\n // Tools\n if (resolvedAsset.tools && resolvedAsset.tools.length > 0) {\n body.tools = resolvedAsset.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: resolvedAsset.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","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","import { applyOverrides } from '../overrides/index.js';\nimport type { ResolvedPromptAsset } from '../schema/index.js';\nimport type { RuntimeRenderOptions } from './types.js';\n\nexport function resolveAssetForProvider(\n asset: ResolvedPromptAsset,\n runtime: Pick<RuntimeRenderOptions, 'environment' | 'tier' | 'runtime'> = {},\n): ResolvedPromptAsset {\n if (!runtime.environment && !runtime.tier && !runtime.runtime) {\n return asset;\n }\n\n return applyOverrides(asset, {\n environment: runtime.environment,\n tier: runtime.tier,\n runtime: runtime.runtime,\n }) as ResolvedPromptAsset;\n}"],"mappings":"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","names":[]}
|
package/dist/providers/openai.js
CHANGED
|
@@ -65,22 +65,67 @@ function renderSections(asset, options = {}) {
|
|
|
65
65
|
return result;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
// src/overrides/apply-overrides.ts
|
|
69
|
+
function applyOverrides(asset, options = {}) {
|
|
70
|
+
let result = { ...asset };
|
|
71
|
+
if (options.environment && result.environments?.[options.environment]) {
|
|
72
|
+
result = mergeOverride(result, result.environments[options.environment]);
|
|
73
|
+
}
|
|
74
|
+
if (options.tier && result.tiers?.[options.tier]) {
|
|
75
|
+
result = mergeOverride(result, result.tiers[options.tier]);
|
|
76
|
+
}
|
|
77
|
+
if (options.runtime) {
|
|
78
|
+
result = mergeOverride(result, options.runtime);
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
function mergeOverride(base, override) {
|
|
83
|
+
const result = { ...base };
|
|
84
|
+
if (override.model !== void 0) result.model = override.model;
|
|
85
|
+
if (override.fallback_models !== void 0) result.fallback_models = override.fallback_models;
|
|
86
|
+
if (override.tools !== void 0) result.tools = override.tools;
|
|
87
|
+
if (override.reasoning !== void 0) {
|
|
88
|
+
result.reasoning = { ...result.reasoning, ...override.reasoning };
|
|
89
|
+
}
|
|
90
|
+
if (override.sampling !== void 0) {
|
|
91
|
+
result.sampling = { ...result.sampling, ...override.sampling };
|
|
92
|
+
}
|
|
93
|
+
if (override.response !== void 0) {
|
|
94
|
+
result.response = { ...result.response, ...override.response };
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/providers/resolve-asset.ts
|
|
100
|
+
function resolveAssetForProvider(asset, runtime = {}) {
|
|
101
|
+
if (!runtime.environment && !runtime.tier && !runtime.runtime) {
|
|
102
|
+
return asset;
|
|
103
|
+
}
|
|
104
|
+
return applyOverrides(asset, {
|
|
105
|
+
environment: runtime.environment,
|
|
106
|
+
tier: runtime.tier,
|
|
107
|
+
runtime: runtime.runtime
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
68
111
|
// src/providers/openai.ts
|
|
69
112
|
var openaiAdapter = {
|
|
70
113
|
name: "openai",
|
|
71
|
-
validate(asset) {
|
|
114
|
+
validate(asset, runtime) {
|
|
115
|
+
const resolvedAsset = resolveAssetForProvider(asset, runtime);
|
|
72
116
|
const errors = [];
|
|
73
117
|
const warnings = [];
|
|
74
|
-
if (!
|
|
118
|
+
if (!resolvedAsset.model) {
|
|
75
119
|
errors.push("OpenAI adapter requires a model to be specified.");
|
|
76
120
|
}
|
|
77
|
-
if (
|
|
121
|
+
if (resolvedAsset.reasoning?.budget_tokens !== void 0) {
|
|
78
122
|
warnings.push("OpenAI uses reasoning_effort, not budget_tokens. budget_tokens will be ignored.");
|
|
79
123
|
}
|
|
80
124
|
return { valid: errors.length === 0, errors, warnings };
|
|
81
125
|
},
|
|
82
126
|
render(asset, runtime) {
|
|
83
|
-
const
|
|
127
|
+
const resolvedAsset = resolveAssetForProvider(asset, runtime);
|
|
128
|
+
const sections = renderSections(resolvedAsset, {
|
|
84
129
|
variables: runtime.variables,
|
|
85
130
|
strict: runtime.strict
|
|
86
131
|
});
|
|
@@ -97,26 +142,26 @@ var openaiAdapter = {
|
|
|
97
142
|
messages.push({ role: "user", content: sections.prompt_template });
|
|
98
143
|
}
|
|
99
144
|
const body = {
|
|
100
|
-
model:
|
|
145
|
+
model: resolvedAsset.model,
|
|
101
146
|
messages
|
|
102
147
|
};
|
|
103
|
-
if (
|
|
104
|
-
if (
|
|
105
|
-
if (
|
|
106
|
-
if (
|
|
107
|
-
if (
|
|
108
|
-
if (
|
|
109
|
-
if (
|
|
110
|
-
body.reasoning_effort =
|
|
148
|
+
if (resolvedAsset.sampling?.temperature !== void 0) body.temperature = resolvedAsset.sampling.temperature;
|
|
149
|
+
if (resolvedAsset.sampling?.top_p !== void 0) body.top_p = resolvedAsset.sampling.top_p;
|
|
150
|
+
if (resolvedAsset.sampling?.frequency_penalty !== void 0) body.frequency_penalty = resolvedAsset.sampling.frequency_penalty;
|
|
151
|
+
if (resolvedAsset.sampling?.presence_penalty !== void 0) body.presence_penalty = resolvedAsset.sampling.presence_penalty;
|
|
152
|
+
if (resolvedAsset.sampling?.stop !== void 0) body.stop = resolvedAsset.sampling.stop;
|
|
153
|
+
if (resolvedAsset.sampling?.max_output_tokens !== void 0) body.max_tokens = resolvedAsset.sampling.max_output_tokens;
|
|
154
|
+
if (resolvedAsset.reasoning?.effort) {
|
|
155
|
+
body.reasoning_effort = resolvedAsset.reasoning.effort;
|
|
111
156
|
}
|
|
112
|
-
if (
|
|
157
|
+
if (resolvedAsset.response?.format === "json") {
|
|
113
158
|
body.response_format = { type: "json_object" };
|
|
114
159
|
}
|
|
115
|
-
if (
|
|
116
|
-
body.stream =
|
|
160
|
+
if (resolvedAsset.response?.stream !== void 0) {
|
|
161
|
+
body.stream = resolvedAsset.response.stream;
|
|
117
162
|
}
|
|
118
|
-
if (
|
|
119
|
-
body.tools =
|
|
163
|
+
if (resolvedAsset.tools && resolvedAsset.tools.length > 0) {
|
|
164
|
+
body.tools = resolvedAsset.tools.map((tool) => {
|
|
120
165
|
if (typeof tool === "string") {
|
|
121
166
|
const def = runtime.toolRegistry?.[tool];
|
|
122
167
|
if (def) return def;
|
|
@@ -135,7 +180,7 @@ var openaiAdapter = {
|
|
|
135
180
|
return {
|
|
136
181
|
body,
|
|
137
182
|
provider: "openai",
|
|
138
|
-
model:
|
|
183
|
+
model: resolvedAsset.model ?? "unknown"
|
|
139
184
|
};
|
|
140
185
|
}
|
|
141
186
|
};
|
|
@@ -143,8 +188,8 @@ var openaiAdapter = {
|
|
|
143
188
|
// src/providers/openrouter.ts
|
|
144
189
|
var openrouterAdapter = {
|
|
145
190
|
name: "openrouter",
|
|
146
|
-
validate(asset) {
|
|
147
|
-
return openaiAdapter.validate(asset);
|
|
191
|
+
validate(asset, runtime) {
|
|
192
|
+
return openaiAdapter.validate(asset, runtime);
|
|
148
193
|
},
|
|
149
194
|
render(asset, runtime) {
|
|
150
195
|
const result = openaiAdapter.render(asset, runtime);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers/openrouter.ts","../../src/renderer/interpolate.ts","../../src/renderer/renderer.ts","../../src/providers/openai.ts"],"sourcesContent":["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 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"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/providers/openrouter.ts","../../src/renderer/interpolate.ts","../../src/renderer/renderer.ts","../../src/overrides/apply-overrides.ts","../../src/providers/resolve-asset.ts","../../src/providers/openai.ts"],"sourcesContent":["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, runtime?: RuntimeRenderOptions): ValidationResult {\n return openaiAdapter.validate(asset, runtime);\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 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 { 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","import { applyOverrides } from '../overrides/index.js';\nimport type { ResolvedPromptAsset } from '../schema/index.js';\nimport type { RuntimeRenderOptions } from './types.js';\n\nexport function resolveAssetForProvider(\n asset: ResolvedPromptAsset,\n runtime: Pick<RuntimeRenderOptions, 'environment' | 'tier' | 'runtime'> = {},\n): ResolvedPromptAsset {\n if (!runtime.environment && !runtime.tier && !runtime.runtime) {\n return asset;\n }\n\n return applyOverrides(asset, {\n environment: runtime.environment,\n tier: runtime.tier,\n runtime: runtime.runtime,\n }) as ResolvedPromptAsset;\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';\nimport { resolveAssetForProvider } from './resolve-asset.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, runtime?: RuntimeRenderOptions): ValidationResult {\n const resolvedAsset = resolveAssetForProvider(asset, runtime);\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!resolvedAsset.model) {\n errors.push('OpenAI adapter requires a model to be specified.');\n }\n\n if (resolvedAsset.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 resolvedAsset = resolveAssetForProvider(asset, runtime);\n const sections = renderSections(resolvedAsset, {\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: resolvedAsset.model,\n messages,\n };\n\n // Sampling params\n if (resolvedAsset.sampling?.temperature !== undefined) body.temperature = resolvedAsset.sampling.temperature;\n if (resolvedAsset.sampling?.top_p !== undefined) body.top_p = resolvedAsset.sampling.top_p;\n if (resolvedAsset.sampling?.frequency_penalty !== undefined) body.frequency_penalty = resolvedAsset.sampling.frequency_penalty;\n if (resolvedAsset.sampling?.presence_penalty !== undefined) body.presence_penalty = resolvedAsset.sampling.presence_penalty;\n if (resolvedAsset.sampling?.stop !== undefined) body.stop = resolvedAsset.sampling.stop;\n if (resolvedAsset.sampling?.max_output_tokens !== undefined) body.max_tokens = resolvedAsset.sampling.max_output_tokens;\n\n // Reasoning\n if (resolvedAsset.reasoning?.effort) {\n body.reasoning_effort = resolvedAsset.reasoning.effort;\n }\n\n // Response format\n if (resolvedAsset.response?.format === 'json') {\n body.response_format = { type: 'json_object' };\n }\n\n // Streaming\n if (resolvedAsset.response?.stream !== undefined) {\n body.stream = resolvedAsset.response.stream;\n }\n\n // Tools\n if (resolvedAsset.tools && resolvedAsset.tools.length > 0) {\n body.tools = resolvedAsset.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: resolvedAsset.model ?? 'unknown',\n };\n },\n};\n"],"mappings":"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","names":[]}
|