promptopskit 0.3.4 → 0.3.6
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 +8 -9
- package/SKILL.md +4 -1
- package/dist/{chunk-2LK6IILW.js → chunk-6FLNJVE7.js} +5 -2
- package/dist/chunk-6FLNJVE7.js.map +1 -0
- package/dist/{chunk-UJA7XBQZ.js → chunk-J32I6DSG.js} +2 -2
- package/dist/{chunk-VU3WKLFI.js → chunk-MN3RQ7DZ.js} +2 -2
- package/dist/{chunk-R5PKK6Y7.js → chunk-MYXDJMWV.js} +2 -2
- package/dist/{chunk-S5YHGHK5.js → chunk-SHYKSLVR.js} +172 -16
- package/dist/chunk-SHYKSLVR.js.map +1 -0
- package/dist/{chunk-U7IDX2P7.js → chunk-SOY2CEJM.js} +3 -3
- package/dist/cli/index.js +145 -56
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +203 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -8
- package/dist/index.d.ts +10 -8
- package/dist/index.js +48 -56
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.cjs +144 -15
- 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 +3 -3
- package/dist/providers/gemini.cjs +144 -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 +3 -3
- package/dist/providers/openai.cjs +144 -15
- 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 +3 -3
- package/dist/providers/openrouter.cjs +144 -15
- 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 +4 -4
- package/dist/{schema-Dq0jKest.d.cts → schema-D145q3Dw.d.cts} +63 -42
- package/dist/{schema-Dq0jKest.d.ts → schema-D145q3Dw.d.ts} +63 -42
- package/dist/testing.cjs +4 -1
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/dist/{types-CgA7_wNI.d.cts → types-B3sWHzIo.d.cts} +9 -2
- package/dist/{types-D_-336jx.d.ts → types-CXlVWckk.d.ts} +9 -2
- package/dist/usagetap/index.d.cts +2 -2
- package/dist/usagetap/index.d.ts +2 -2
- package/package.json +4 -1
- package/dist/chunk-2LK6IILW.js.map +0 -1
- package/dist/chunk-S5YHGHK5.js.map +0 -1
- /package/dist/{chunk-UJA7XBQZ.js.map → chunk-J32I6DSG.js.map} +0 -0
- /package/dist/{chunk-VU3WKLFI.js.map → chunk-MN3RQ7DZ.js.map} +0 -0
- /package/dist/{chunk-R5PKK6Y7.js.map → chunk-MYXDJMWV.js.map} +0 -0
- /package/dist/{chunk-U7IDX2P7.js.map → chunk-SOY2CEJM.js.map} +0 -0
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { P as PromptAsset, a as PromptAssetOverrides, R as ResolvedPromptAsset } from './schema-
|
|
2
|
-
export { b as PromptAssetOverridesSchema, c as PromptAssetSchema } from './schema-
|
|
3
|
-
import { P as ProviderAdapter, a as ProviderRequest } from './types-
|
|
4
|
-
export { b as ProviderInlinePromptSource, c as ProviderPromptInput, d as ProviderPromptLookup,
|
|
1
|
+
import { P as PromptAsset, a as PromptAssetOverrides, R as ResolvedPromptAsset } from './schema-D145q3Dw.cjs';
|
|
2
|
+
export { b as PromptAssetOverridesSchema, c as PromptAssetSchema } from './schema-D145q3Dw.cjs';
|
|
3
|
+
import { P as ProviderAdapter, R as RuntimeRenderOptions, a as ProviderRequest } from './types-B3sWHzIo.cjs';
|
|
4
|
+
export { b as ProviderInlinePromptSource, c as ProviderPromptInput, d as ProviderPromptLookup, V as ValidationResult } from './types-B3sWHzIo.cjs';
|
|
5
5
|
export { UsageTapAllowed, UsageTapAllowedCapability, UsageTapBeginRequest, UsageTapBeginResponse, UsageTapCallOptions, UsageTapCallResult, UsageTapClient, UsageTapClientConfig, UsageTapEndRequest, UsageTapEndResponse, UsageTapEndUsage, UsageTapEntitlementMode, UsageTapEntitlementOptions, UsageTapErrorPayload, UsageTapInvokeContext, UsageTapInvokeResult, UsageTapProviderRunOptions, UsageTapProviderRunResult, UsageTapReasoningLevel, applyUsageTapEntitlements, beginUsageTapCall, createUsageTapClient, defaultUsageTapErrorMapper, endUsageTapCall, extractAnthropicUsage, extractGeminiUsage, extractOpenAIUsage, runAnthropicWithUsageTap, runGeminiWithUsageTap, runOpenAIWithUsageTap, runOpenRouterWithUsageTap, withUsageTapCall } from './usagetap/index.cjs';
|
|
6
6
|
export { anthropicAdapter } from './providers/anthropic.cjs';
|
|
7
7
|
export { geminiAdapter } from './providers/gemini.cjs';
|
|
@@ -119,7 +119,7 @@ declare function resolveIncludes(asset: PromptAsset, basePath: string, visited?:
|
|
|
119
119
|
declare function getAdapter(provider: string): ProviderAdapter;
|
|
120
120
|
|
|
121
121
|
interface PromptOpsKitConfig {
|
|
122
|
-
sourceDir
|
|
122
|
+
sourceDir?: string;
|
|
123
123
|
compiledDir?: string;
|
|
124
124
|
mode?: 'auto' | 'compiled-only' | 'source-only';
|
|
125
125
|
cache?: boolean;
|
|
@@ -142,6 +142,8 @@ interface RenderPromptOptions {
|
|
|
142
142
|
runtime?: Partial<PromptAssetOverrides>;
|
|
143
143
|
/** Variables for interpolation */
|
|
144
144
|
variables?: Record<string, string>;
|
|
145
|
+
/** Optional callback to transform oversized context values before warnings/rendering */
|
|
146
|
+
onContextOverflow?: RuntimeRenderOptions['onContextOverflow'];
|
|
145
147
|
/** Conversation history */
|
|
146
148
|
history?: Array<{
|
|
147
149
|
role: string;
|
|
@@ -186,14 +188,14 @@ declare class PromptOpsKit {
|
|
|
186
188
|
*/
|
|
187
189
|
clearCache(): void;
|
|
188
190
|
}
|
|
189
|
-
declare function createPromptOpsKit(config
|
|
191
|
+
declare function createPromptOpsKit(config?: PromptOpsKitConfig): PromptOpsKit;
|
|
190
192
|
/**
|
|
191
193
|
* Standalone renderPrompt for quick usage without creating a PromptOpsKit instance.
|
|
192
|
-
* Requires either `source` (inline) or `path` + implicit sourceDir of
|
|
194
|
+
* Requires either `source` (inline) or `path` + implicit sourceDir of ./prompts.
|
|
193
195
|
*/
|
|
194
196
|
declare function renderPrompt(options: RenderPromptOptions & {
|
|
195
197
|
sourceDir?: string;
|
|
196
198
|
warnings?: PromptOpsKitConfig['warnings'];
|
|
197
199
|
}): Promise<RenderResult>;
|
|
198
200
|
|
|
199
|
-
export { type OverrideOptions, type ParseResult, PromptAsset, PromptOpsKit, type PromptOpsKitConfig, type PromptValidationResult, ProviderAdapter, ProviderRequest, type RenderOptions, type RenderPromptOptions, type RenderResult, type RenderedSections, ResolvedPromptAsset, type ValidationError, applyOverrides, createPromptOpsKit, extractSections, extractVariables, getAdapter, interpolate, loadPromptFile, parsePrompt, renderPrompt, resolveIncludes, validateAsset, validateAssetWithIncludes };
|
|
201
|
+
export { type OverrideOptions, type ParseResult, PromptAsset, PromptOpsKit, type PromptOpsKitConfig, type PromptValidationResult, ProviderAdapter, ProviderRequest, type RenderOptions, type RenderPromptOptions, type RenderResult, type RenderedSections, ResolvedPromptAsset, RuntimeRenderOptions, type ValidationError, applyOverrides, createPromptOpsKit, extractSections, extractVariables, getAdapter, interpolate, loadPromptFile, parsePrompt, renderPrompt, resolveIncludes, validateAsset, validateAssetWithIncludes };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { P as PromptAsset, a as PromptAssetOverrides, R as ResolvedPromptAsset } from './schema-
|
|
2
|
-
export { b as PromptAssetOverridesSchema, c as PromptAssetSchema } from './schema-
|
|
3
|
-
import { P as ProviderAdapter, a as ProviderRequest } from './types-
|
|
4
|
-
export { b as ProviderInlinePromptSource, c as ProviderPromptInput, d as ProviderPromptLookup,
|
|
1
|
+
import { P as PromptAsset, a as PromptAssetOverrides, R as ResolvedPromptAsset } from './schema-D145q3Dw.js';
|
|
2
|
+
export { b as PromptAssetOverridesSchema, c as PromptAssetSchema } from './schema-D145q3Dw.js';
|
|
3
|
+
import { P as ProviderAdapter, R as RuntimeRenderOptions, a as ProviderRequest } from './types-CXlVWckk.js';
|
|
4
|
+
export { b as ProviderInlinePromptSource, c as ProviderPromptInput, d as ProviderPromptLookup, V as ValidationResult } from './types-CXlVWckk.js';
|
|
5
5
|
export { UsageTapAllowed, UsageTapAllowedCapability, UsageTapBeginRequest, UsageTapBeginResponse, UsageTapCallOptions, UsageTapCallResult, UsageTapClient, UsageTapClientConfig, UsageTapEndRequest, UsageTapEndResponse, UsageTapEndUsage, UsageTapEntitlementMode, UsageTapEntitlementOptions, UsageTapErrorPayload, UsageTapInvokeContext, UsageTapInvokeResult, UsageTapProviderRunOptions, UsageTapProviderRunResult, UsageTapReasoningLevel, applyUsageTapEntitlements, beginUsageTapCall, createUsageTapClient, defaultUsageTapErrorMapper, endUsageTapCall, extractAnthropicUsage, extractGeminiUsage, extractOpenAIUsage, runAnthropicWithUsageTap, runGeminiWithUsageTap, runOpenAIWithUsageTap, runOpenRouterWithUsageTap, withUsageTapCall } from './usagetap/index.js';
|
|
6
6
|
export { anthropicAdapter } from './providers/anthropic.js';
|
|
7
7
|
export { geminiAdapter } from './providers/gemini.js';
|
|
@@ -119,7 +119,7 @@ declare function resolveIncludes(asset: PromptAsset, basePath: string, visited?:
|
|
|
119
119
|
declare function getAdapter(provider: string): ProviderAdapter;
|
|
120
120
|
|
|
121
121
|
interface PromptOpsKitConfig {
|
|
122
|
-
sourceDir
|
|
122
|
+
sourceDir?: string;
|
|
123
123
|
compiledDir?: string;
|
|
124
124
|
mode?: 'auto' | 'compiled-only' | 'source-only';
|
|
125
125
|
cache?: boolean;
|
|
@@ -142,6 +142,8 @@ interface RenderPromptOptions {
|
|
|
142
142
|
runtime?: Partial<PromptAssetOverrides>;
|
|
143
143
|
/** Variables for interpolation */
|
|
144
144
|
variables?: Record<string, string>;
|
|
145
|
+
/** Optional callback to transform oversized context values before warnings/rendering */
|
|
146
|
+
onContextOverflow?: RuntimeRenderOptions['onContextOverflow'];
|
|
145
147
|
/** Conversation history */
|
|
146
148
|
history?: Array<{
|
|
147
149
|
role: string;
|
|
@@ -186,14 +188,14 @@ declare class PromptOpsKit {
|
|
|
186
188
|
*/
|
|
187
189
|
clearCache(): void;
|
|
188
190
|
}
|
|
189
|
-
declare function createPromptOpsKit(config
|
|
191
|
+
declare function createPromptOpsKit(config?: PromptOpsKitConfig): PromptOpsKit;
|
|
190
192
|
/**
|
|
191
193
|
* Standalone renderPrompt for quick usage without creating a PromptOpsKit instance.
|
|
192
|
-
* Requires either `source` (inline) or `path` + implicit sourceDir of
|
|
194
|
+
* Requires either `source` (inline) or `path` + implicit sourceDir of ./prompts.
|
|
193
195
|
*/
|
|
194
196
|
declare function renderPrompt(options: RenderPromptOptions & {
|
|
195
197
|
sourceDir?: string;
|
|
196
198
|
warnings?: PromptOpsKitConfig['warnings'];
|
|
197
199
|
}): Promise<RenderResult>;
|
|
198
200
|
|
|
199
|
-
export { type OverrideOptions, type ParseResult, PromptAsset, PromptOpsKit, type PromptOpsKitConfig, type PromptValidationResult, ProviderAdapter, ProviderRequest, type RenderOptions, type RenderPromptOptions, type RenderResult, type RenderedSections, ResolvedPromptAsset, type ValidationError, applyOverrides, createPromptOpsKit, extractSections, extractVariables, getAdapter, interpolate, loadPromptFile, parsePrompt, renderPrompt, resolveIncludes, validateAsset, validateAssetWithIncludes };
|
|
201
|
+
export { type OverrideOptions, type ParseResult, PromptAsset, PromptOpsKit, type PromptOpsKitConfig, type PromptValidationResult, ProviderAdapter, ProviderRequest, type RenderOptions, type RenderPromptOptions, type RenderResult, type RenderedSections, ResolvedPromptAsset, RuntimeRenderOptions, type ValidationError, applyOverrides, createPromptOpsKit, extractSections, extractVariables, getAdapter, interpolate, loadPromptFile, parsePrompt, renderPrompt, resolveIncludes, validateAsset, validateAssetWithIncludes };
|
package/dist/index.js
CHANGED
|
@@ -15,33 +15,39 @@ import {
|
|
|
15
15
|
} from "./chunk-HWEVRBKZ.js";
|
|
16
16
|
import {
|
|
17
17
|
anthropicAdapter
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-MYXDJMWV.js";
|
|
19
19
|
import {
|
|
20
20
|
geminiAdapter
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-J32I6DSG.js";
|
|
22
22
|
import {
|
|
23
23
|
openrouterAdapter
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-SOY2CEJM.js";
|
|
25
25
|
import {
|
|
26
26
|
openaiAdapter
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-MN3RQ7DZ.js";
|
|
28
28
|
import {
|
|
29
|
+
DEFAULT_PROMPTS_DIR,
|
|
29
30
|
PromptCache,
|
|
30
31
|
applyOverrides,
|
|
32
|
+
collectContextSizeWarnings,
|
|
31
33
|
extractVariables,
|
|
34
|
+
getContextInputNames,
|
|
35
|
+
getContextInputs,
|
|
32
36
|
interpolate,
|
|
33
37
|
loadPromptAsset,
|
|
34
38
|
resolveIncludes,
|
|
35
39
|
resolveInlinePromptSource,
|
|
36
|
-
resolvePromptAsset
|
|
37
|
-
|
|
40
|
+
resolvePromptAsset,
|
|
41
|
+
sanitizeContextVariables,
|
|
42
|
+
withPromptResolutionDefaults
|
|
43
|
+
} from "./chunk-SHYKSLVR.js";
|
|
38
44
|
import {
|
|
39
45
|
PromptAssetOverridesSchema,
|
|
40
46
|
PromptAssetSchema,
|
|
41
47
|
extractSections,
|
|
42
48
|
loadPromptFile,
|
|
43
49
|
parsePrompt
|
|
44
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-6FLNJVE7.js";
|
|
45
51
|
|
|
46
52
|
// src/index.ts
|
|
47
53
|
import { resolve } from "path";
|
|
@@ -64,48 +70,6 @@ function getAdapter(provider) {
|
|
|
64
70
|
return adapter;
|
|
65
71
|
}
|
|
66
72
|
|
|
67
|
-
// src/context.ts
|
|
68
|
-
var textEncoder = new TextEncoder();
|
|
69
|
-
function getContextInputs(asset) {
|
|
70
|
-
return (asset.context?.inputs ?? []).map(normalizeContextInput);
|
|
71
|
-
}
|
|
72
|
-
function getContextInputNames(asset) {
|
|
73
|
-
return getContextInputs(asset).map((input) => input.name);
|
|
74
|
-
}
|
|
75
|
-
function normalizeContextInput(input) {
|
|
76
|
-
if (typeof input === "string") {
|
|
77
|
-
return { name: input };
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
name: input.name,
|
|
81
|
-
max_size: input.max_size
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
function measureContextValueSize(value) {
|
|
85
|
-
return textEncoder.encode(value).length;
|
|
86
|
-
}
|
|
87
|
-
function collectContextSizeWarnings(asset, variables = {}) {
|
|
88
|
-
const warnings = [];
|
|
89
|
-
for (const input of getContextInputs(asset)) {
|
|
90
|
-
if (input.max_size === void 0) {
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
const value = variables[input.name];
|
|
94
|
-
if (value === void 0) {
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
const actualSize = measureContextValueSize(value);
|
|
98
|
-
if (actualSize > input.max_size) {
|
|
99
|
-
warnings.push({
|
|
100
|
-
variable: input.name,
|
|
101
|
-
maxSize: input.max_size,
|
|
102
|
-
actualSize
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return warnings;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
73
|
// src/validation/levenshtein.ts
|
|
110
74
|
function levenshtein(a, b) {
|
|
111
75
|
const m = a.length;
|
|
@@ -217,6 +181,30 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
217
181
|
});
|
|
218
182
|
}
|
|
219
183
|
}
|
|
184
|
+
for (const input of getContextInputs(asset)) {
|
|
185
|
+
if (input.trim !== void 0 && input.trim !== false && input.max_size === void 0) {
|
|
186
|
+
warnings.push({
|
|
187
|
+
code: "POK014",
|
|
188
|
+
message: `Context input "${input.name}" sets trim but has no max_size; trim-to-budget will be skipped.`,
|
|
189
|
+
filePath
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
const checks = [];
|
|
193
|
+
if (input.allow_regex) checks.push({ pattern: input.allow_regex, kind: "allow_regex" });
|
|
194
|
+
if (input.deny_regex) checks.push({ pattern: input.deny_regex, kind: "deny_regex" });
|
|
195
|
+
for (const check of checks) {
|
|
196
|
+
try {
|
|
197
|
+
new RegExp(check.pattern);
|
|
198
|
+
} catch (error) {
|
|
199
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
200
|
+
errors.push({
|
|
201
|
+
code: "POK013",
|
|
202
|
+
message: `Invalid context ${check.kind} for "${input.name}": ${reason}`,
|
|
203
|
+
filePath
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
220
208
|
return {
|
|
221
209
|
valid: errors.length === 0,
|
|
222
210
|
errors,
|
|
@@ -279,10 +267,11 @@ var PromptOpsKit = class {
|
|
|
279
267
|
config;
|
|
280
268
|
promptCache;
|
|
281
269
|
constructor(config) {
|
|
270
|
+
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
282
271
|
this.config = {
|
|
283
|
-
...
|
|
284
|
-
mode:
|
|
285
|
-
cache:
|
|
272
|
+
...resolvedConfig,
|
|
273
|
+
mode: resolvedConfig.mode ?? "auto",
|
|
274
|
+
cache: resolvedConfig.cache ?? true
|
|
286
275
|
};
|
|
287
276
|
this.promptCache = new PromptCache();
|
|
288
277
|
}
|
|
@@ -326,7 +315,10 @@ var PromptOpsKit = class {
|
|
|
326
315
|
` + validation.errors.map((e) => ` - ${e}`).join("\n")
|
|
327
316
|
);
|
|
328
317
|
}
|
|
329
|
-
const
|
|
318
|
+
const sanitizedVariables = sanitizeContextVariables(resolved, options.variables, {
|
|
319
|
+
onContextOverflow: options.onContextOverflow
|
|
320
|
+
});
|
|
321
|
+
const contextSizeWarnings = collectContextSizeWarnings(resolved, sanitizedVariables).map(
|
|
330
322
|
(warning) => formatContextSizeWarning(resolved, warning)
|
|
331
323
|
);
|
|
332
324
|
const contextWarningPolicy = this.config.warnings?.contextSize;
|
|
@@ -336,7 +328,7 @@ var PromptOpsKit = class {
|
|
|
336
328
|
}
|
|
337
329
|
}
|
|
338
330
|
const request = adapter.render(resolved, {
|
|
339
|
-
variables:
|
|
331
|
+
variables: sanitizedVariables,
|
|
340
332
|
history: options.history,
|
|
341
333
|
toolRegistry: options.toolRegistry,
|
|
342
334
|
strict: options.strict
|
|
@@ -362,12 +354,12 @@ var PromptOpsKit = class {
|
|
|
362
354
|
this.promptCache.clear();
|
|
363
355
|
}
|
|
364
356
|
};
|
|
365
|
-
function createPromptOpsKit(config) {
|
|
357
|
+
function createPromptOpsKit(config = {}) {
|
|
366
358
|
return new PromptOpsKit(config);
|
|
367
359
|
}
|
|
368
360
|
async function renderPrompt(options) {
|
|
369
361
|
const kit = createPromptOpsKit({
|
|
370
|
-
sourceDir: options.sourceDir ??
|
|
362
|
+
sourceDir: options.sourceDir ?? DEFAULT_PROMPTS_DIR,
|
|
371
363
|
cache: false,
|
|
372
364
|
warnings: options.warnings
|
|
373
365
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/providers/index.ts","../src/context.ts","../src/validation/levenshtein.ts","../src/validation/validate.ts"],"sourcesContent":["import { existsSync } 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, validateAssetWithIncludes } from './validation/index.js';\nimport { PromptCache } from './cache.js';\nimport { collectContextSizeWarnings } from './context.js';\nimport {\n loadPromptAsset,\n resolveInlinePromptSource,\n resolvePromptAsset,\n} from './prompt-resolution.js';\nimport type { PromptAsset, PromptAssetOverrides, 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 {\n ProviderRequest,\n RuntimeRenderOptions,\n ProviderAdapter,\n ProviderInlinePromptSource,\n ProviderPromptInput,\n ProviderPromptLookup,\n ValidationResult,\n} 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';\nexport type {\n UsageTapAllowed,\n UsageTapAllowedCapability,\n UsageTapBeginRequest,\n UsageTapBeginResponse,\n UsageTapCallOptions,\n UsageTapCallResult,\n UsageTapClient,\n UsageTapClientConfig,\n UsageTapEndRequest,\n UsageTapEndResponse,\n UsageTapEndUsage,\n UsageTapEntitlementMode,\n UsageTapEntitlementOptions,\n UsageTapErrorPayload,\n UsageTapInvokeContext,\n UsageTapInvokeResult,\n UsageTapProviderRunOptions,\n UsageTapProviderRunResult,\n UsageTapReasoningLevel,\n} from './usagetap/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';\nexport {\n applyUsageTapEntitlements,\n beginUsageTapCall,\n createUsageTapClient,\n defaultUsageTapErrorMapper,\n endUsageTapCall,\n extractAnthropicUsage,\n extractGeminiUsage,\n extractOpenAIUsage,\n runAnthropicWithUsageTap,\n runGeminiWithUsageTap,\n runOpenAIWithUsageTap,\n runOpenRouterWithUsageTap,\n withUsageTapCall,\n} from './usagetap/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 warnings?: {\n contextSize?: 'auto' | 'off' | 'result-only' | 'console' | 'console-and-result';\n };\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 /** Runtime overrides applied after environment and tier */\n runtime?: Partial<PromptAssetOverrides>;\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\nfunction shouldIncludeContextWarningsInResult(\n policy: NonNullable<PromptOpsKitConfig['warnings']>['contextSize'] | undefined,\n): boolean {\n return policy === undefined\n || policy === 'auto'\n || policy === 'result-only'\n || policy === 'console-and-result';\n}\n\nfunction shouldLogContextWarnings(\n policy: NonNullable<PromptOpsKitConfig['warnings']>['contextSize'] | undefined,\n options: Pick<RenderPromptOptions, 'source'>,\n mode: PromptOpsKitConfig['mode'],\n): boolean {\n if (policy === 'off' || policy === 'result-only') {\n return false;\n }\n\n if (policy === 'console' || policy === 'console-and-result') {\n return true;\n }\n\n return Boolean(options.source || mode !== 'compiled-only');\n}\n\nfunction formatContextSizeWarning(\n asset: ResolvedPromptAsset,\n warning: { variable: string; maxSize: number; actualSize: number },\n): string {\n return [\n 'POK030:',\n `Context variable \"${warning.variable}\" exceeded max_size`,\n `for prompt \"${asset.id}\"`,\n `(${warning.actualSize} bytes > ${warning.maxSize} bytes).`,\n ].join(' ');\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 return loadPromptAsset(promptPath, this.config, this.promptCache);\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; runtime?: Partial<PromptAssetOverrides> } = {},\n ): Promise<ResolvedPromptAsset> {\n return resolvePromptAsset(promptPath, this.config, options, this.promptCache);\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 resolved = resolveInlinePromptSource(options.source, {\n environment: options.environment,\n tier: options.tier,\n runtime: options.runtime,\n });\n } else if (options.path) {\n resolved = await this.resolvePrompt(options.path, {\n environment: options.environment,\n tier: options.tier,\n runtime: options.runtime,\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 contextSizeWarnings = collectContextSizeWarnings(resolved, options.variables).map((warning) =>\n formatContextSizeWarning(resolved, warning),\n );\n\n const contextWarningPolicy = this.config.warnings?.contextSize;\n\n if (contextSizeWarnings.length > 0 && shouldLogContextWarnings(contextWarningPolicy, options, this.config.mode)) {\n for (const warning of contextSizeWarnings) {\n console.warn(`[promptopskit] Warning: ${warning}`);\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: shouldIncludeContextWarningsInResult(contextWarningPolicy)\n ? [...validation.warnings, ...contextSizeWarnings]\n : 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\n const sourceFile = resolve(this.config.sourceDir, promptPath + '.md');\n return validateAssetWithIncludes(asset, sourceFile);\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 & {\n sourceDir?: string;\n warnings?: PromptOpsKitConfig['warnings'];\n },\n): Promise<RenderResult> {\n const kit = createPromptOpsKit({\n sourceDir: options.sourceDir ?? '.',\n cache: false,\n warnings: options.warnings,\n });\n return kit.renderPrompt(options);\n}\n","export type {\n ProviderAdapter,\n ProviderInlinePromptSource,\n ProviderPromptInput,\n ProviderPromptLookup,\n ProviderRequest,\n ValidationResult,\n RuntimeRenderOptions,\n} 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","import type { PromptAsset, ResolvedPromptAsset, ContextInputDefinition } from './schema/index.js';\n\nexport interface NormalizedContextInput {\n name: string;\n max_size?: number;\n}\n\nexport interface ContextSizeWarning {\n variable: string;\n maxSize: number;\n actualSize: number;\n}\n\nconst textEncoder = new TextEncoder();\n\nexport function getContextInputs(\n asset: Pick<PromptAsset | ResolvedPromptAsset, 'context'>,\n): NormalizedContextInput[] {\n return (asset.context?.inputs ?? []).map(normalizeContextInput);\n}\n\nexport function getContextInputNames(\n asset: Pick<PromptAsset | ResolvedPromptAsset, 'context'>,\n): string[] {\n return getContextInputs(asset).map((input) => input.name);\n}\n\nexport function normalizeContextInput(input: ContextInputDefinition): NormalizedContextInput {\n if (typeof input === 'string') {\n return { name: input };\n }\n\n return {\n name: input.name,\n max_size: input.max_size,\n };\n}\n\nexport function measureContextValueSize(value: string): number {\n return textEncoder.encode(value).length;\n}\n\nexport function collectContextSizeWarnings(\n asset: Pick<PromptAsset | ResolvedPromptAsset, 'context'>,\n variables: Record<string, string> = {},\n): ContextSizeWarning[] {\n const warnings: ContextSizeWarning[] = [];\n\n for (const input of getContextInputs(asset)) {\n if (input.max_size === undefined) {\n continue;\n }\n\n const value = variables[input.name];\n if (value === undefined) {\n continue;\n }\n\n const actualSize = measureContextValueSize(value);\n if (actualSize > input.max_size) {\n warnings.push({\n variable: input.name,\n maxSize: input.max_size,\n actualSize,\n });\n }\n }\n\n return warnings;\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 { getContextInputNames } from '../context.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(getContextInputNames(asset));\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.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"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/providers/index.ts","../src/validation/levenshtein.ts","../src/validation/validate.ts"],"sourcesContent":["import { existsSync } 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, validateAssetWithIncludes } from './validation/index.js';\nimport { PromptCache } from './cache.js';\nimport { collectContextSizeWarnings, sanitizeContextVariables } from './context.js';\nimport {\n DEFAULT_PROMPTS_DIR,\n loadPromptAsset,\n resolveInlinePromptSource,\n resolvePromptAsset,\n withPromptResolutionDefaults,\n} from './prompt-resolution.js';\nimport type { PromptAsset, PromptAssetOverrides, 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 {\n ProviderRequest,\n RuntimeRenderOptions,\n ProviderAdapter,\n ProviderInlinePromptSource,\n ProviderPromptInput,\n ProviderPromptLookup,\n ValidationResult,\n} 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';\nexport type {\n UsageTapAllowed,\n UsageTapAllowedCapability,\n UsageTapBeginRequest,\n UsageTapBeginResponse,\n UsageTapCallOptions,\n UsageTapCallResult,\n UsageTapClient,\n UsageTapClientConfig,\n UsageTapEndRequest,\n UsageTapEndResponse,\n UsageTapEndUsage,\n UsageTapEntitlementMode,\n UsageTapEntitlementOptions,\n UsageTapErrorPayload,\n UsageTapInvokeContext,\n UsageTapInvokeResult,\n UsageTapProviderRunOptions,\n UsageTapProviderRunResult,\n UsageTapReasoningLevel,\n} from './usagetap/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';\nexport {\n applyUsageTapEntitlements,\n beginUsageTapCall,\n createUsageTapClient,\n defaultUsageTapErrorMapper,\n endUsageTapCall,\n extractAnthropicUsage,\n extractGeminiUsage,\n extractOpenAIUsage,\n runAnthropicWithUsageTap,\n runGeminiWithUsageTap,\n runOpenAIWithUsageTap,\n runOpenRouterWithUsageTap,\n withUsageTapCall,\n} from './usagetap/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 warnings?: {\n contextSize?: 'auto' | 'off' | 'result-only' | 'console' | 'console-and-result';\n };\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 /** Runtime overrides applied after environment and tier */\n runtime?: Partial<PromptAssetOverrides>;\n /** Variables for interpolation */\n variables?: Record<string, string>;\n /** Optional callback to transform oversized context values before warnings/rendering */\n onContextOverflow?: RuntimeRenderOptions['onContextOverflow'];\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\nfunction shouldIncludeContextWarningsInResult(\n policy: NonNullable<PromptOpsKitConfig['warnings']>['contextSize'] | undefined,\n): boolean {\n return policy === undefined\n || policy === 'auto'\n || policy === 'result-only'\n || policy === 'console-and-result';\n}\n\nfunction shouldLogContextWarnings(\n policy: NonNullable<PromptOpsKitConfig['warnings']>['contextSize'] | undefined,\n options: Pick<RenderPromptOptions, 'source'>,\n mode: PromptOpsKitConfig['mode'],\n): boolean {\n if (policy === 'off' || policy === 'result-only') {\n return false;\n }\n\n if (policy === 'console' || policy === 'console-and-result') {\n return true;\n }\n\n return Boolean(options.source || mode !== 'compiled-only');\n}\n\nfunction formatContextSizeWarning(\n asset: ResolvedPromptAsset,\n warning: { variable: string; maxSize: number; actualSize: number },\n): string {\n return [\n 'POK030:',\n `Context variable \"${warning.variable}\" exceeded max_size`,\n `for prompt \"${asset.id}\"`,\n `(${warning.actualSize} bytes > ${warning.maxSize} bytes).`,\n ].join(' ');\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 const resolvedConfig = withPromptResolutionDefaults(config);\n this.config = {\n ...resolvedConfig,\n mode: resolvedConfig.mode ?? 'auto',\n cache: resolvedConfig.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 return loadPromptAsset(promptPath, this.config, this.promptCache);\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; runtime?: Partial<PromptAssetOverrides> } = {},\n ): Promise<ResolvedPromptAsset> {\n return resolvePromptAsset(promptPath, this.config, options, this.promptCache);\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 resolved = resolveInlinePromptSource(options.source, {\n environment: options.environment,\n tier: options.tier,\n runtime: options.runtime,\n });\n } else if (options.path) {\n resolved = await this.resolvePrompt(options.path, {\n environment: options.environment,\n tier: options.tier,\n runtime: options.runtime,\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 sanitizedVariables = sanitizeContextVariables(resolved, options.variables, {\n onContextOverflow: options.onContextOverflow,\n });\n\n const contextSizeWarnings = collectContextSizeWarnings(resolved, sanitizedVariables).map((warning) =>\n formatContextSizeWarning(resolved, warning),\n );\n\n const contextWarningPolicy = this.config.warnings?.contextSize;\n\n if (contextSizeWarnings.length > 0 && shouldLogContextWarnings(contextWarningPolicy, options, this.config.mode)) {\n for (const warning of contextSizeWarnings) {\n console.warn(`[promptopskit] Warning: ${warning}`);\n }\n }\n\n const request = adapter.render(resolved, {\n variables: sanitizedVariables,\n history: options.history,\n toolRegistry: options.toolRegistry,\n strict: options.strict,\n });\n\n return {\n resolved,\n request,\n warnings: shouldIncludeContextWarningsInResult(contextWarningPolicy)\n ? [...validation.warnings, ...contextSizeWarnings]\n : 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\n const sourceFile = resolve(this.config.sourceDir, promptPath + '.md');\n return validateAssetWithIncludes(asset, sourceFile);\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 ./prompts.\n */\nexport async function renderPrompt(\n options: RenderPromptOptions & {\n sourceDir?: string;\n warnings?: PromptOpsKitConfig['warnings'];\n },\n): Promise<RenderResult> {\n const kit = createPromptOpsKit({\n sourceDir: options.sourceDir ?? DEFAULT_PROMPTS_DIR,\n cache: false,\n warnings: options.warnings,\n });\n return kit.renderPrompt(options);\n}\n","export type {\n ProviderAdapter,\n ProviderInlinePromptSource,\n ProviderPromptInput,\n ProviderPromptLookup,\n ProviderRequest,\n ValidationResult,\n RuntimeRenderOptions,\n} 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 { getContextInputs, getContextInputNames } from '../context.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(getContextInputNames(asset));\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.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 // Context regex definitions compile successfully\n for (const input of getContextInputs(asset)) {\n if (input.trim !== undefined && input.trim !== false && input.max_size === undefined) {\n warnings.push({\n code: 'POK014',\n message: `Context input \"${input.name}\" sets trim but has no max_size; trim-to-budget will be skipped.`,\n filePath,\n });\n }\n\n const checks: Array<{ pattern: string; kind: 'allow_regex' | 'deny_regex' }> = [];\n\n if (input.allow_regex) checks.push({ pattern: input.allow_regex, kind: 'allow_regex' });\n if (input.deny_regex) checks.push({ pattern: input.deny_regex, kind: 'deny_regex' });\n\n for (const check of checks) {\n try {\n // eslint-disable-next-line no-new\n new RegExp(check.pattern);\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n errors.push({\n code: 'POK013',\n message: `Invalid context ${check.kind} for \"${input.name}\": ${reason}`,\n filePath,\n });\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"],"mappings":"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","names":[]}
|
|
@@ -212,7 +212,10 @@ var HistorySchema = import_zod.z.object({
|
|
|
212
212
|
});
|
|
213
213
|
var ContextInputDefinitionObjectSchema = import_zod.z.object({
|
|
214
214
|
name: import_zod.z.string(),
|
|
215
|
-
max_size: import_zod.z.number().int().positive().optional()
|
|
215
|
+
max_size: import_zod.z.number().int().positive().optional(),
|
|
216
|
+
trim: import_zod.z.union([import_zod.z.boolean(), import_zod.z.enum(["start", "end", "both"])]).optional(),
|
|
217
|
+
allow_regex: import_zod.z.string().optional(),
|
|
218
|
+
deny_regex: import_zod.z.string().optional()
|
|
216
219
|
});
|
|
217
220
|
var ContextInputDefinitionSchema = import_zod.z.union([
|
|
218
221
|
import_zod.z.string(),
|
|
@@ -466,14 +469,24 @@ async function resolveIncludes(asset, basePath, visited = /* @__PURE__ */ new Se
|
|
|
466
469
|
}
|
|
467
470
|
|
|
468
471
|
// src/prompt-resolution.ts
|
|
472
|
+
var DEFAULT_PROMPTS_DIR = "./prompts";
|
|
473
|
+
var DEFAULT_COMPILED_JSON_DIR = "./.generated-prompts/json";
|
|
474
|
+
function withPromptResolutionDefaults(config) {
|
|
475
|
+
return {
|
|
476
|
+
...config,
|
|
477
|
+
sourceDir: config.sourceDir ?? DEFAULT_PROMPTS_DIR,
|
|
478
|
+
compiledDir: config.compiledDir ?? DEFAULT_COMPILED_JSON_DIR
|
|
479
|
+
};
|
|
480
|
+
}
|
|
469
481
|
var sharedPromptCache = new PromptCache();
|
|
470
482
|
async function loadPromptAsset(promptPath, config, promptCache = sharedPromptCache) {
|
|
471
|
-
const
|
|
472
|
-
|
|
473
|
-
|
|
483
|
+
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
484
|
+
const mode = resolvedConfig.mode ?? "auto";
|
|
485
|
+
if (mode !== "source-only" && resolvedConfig.compiledDir) {
|
|
486
|
+
const compiledFile = (0, import_node_path3.resolve)(resolvedConfig.compiledDir, promptPath + ".json");
|
|
474
487
|
if ((0, import_node_fs2.existsSync)(compiledFile)) {
|
|
475
488
|
if (mode === "auto") {
|
|
476
|
-
const sourceFile = (0, import_node_path3.resolve)(
|
|
489
|
+
const sourceFile = (0, import_node_path3.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
477
490
|
if ((0, import_node_fs2.existsSync)(sourceFile)) {
|
|
478
491
|
const compiledMtime = (0, import_node_fs2.statSync)(compiledFile).mtimeMs;
|
|
479
492
|
const sourceMtime = (0, import_node_fs2.statSync)(sourceFile).mtimeMs;
|
|
@@ -496,8 +509,8 @@ Run "promptopskit compile" to generate it.`
|
|
|
496
509
|
}
|
|
497
510
|
}
|
|
498
511
|
if (mode !== "compiled-only") {
|
|
499
|
-
const sourceFile = (0, import_node_path3.resolve)(
|
|
500
|
-
if (
|
|
512
|
+
const sourceFile = (0, import_node_path3.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
513
|
+
if (resolvedConfig.cache !== false) {
|
|
501
514
|
const cached = promptCache.get(sourceFile);
|
|
502
515
|
if (cached) {
|
|
503
516
|
return cached;
|
|
@@ -505,8 +518,8 @@ Run "promptopskit compile" to generate it.`
|
|
|
505
518
|
}
|
|
506
519
|
if (!(0, import_node_fs2.existsSync)(sourceFile)) {
|
|
507
520
|
const paths = [sourceFile];
|
|
508
|
-
if (
|
|
509
|
-
paths.unshift((0, import_node_path3.resolve)(
|
|
521
|
+
if (resolvedConfig.compiledDir) {
|
|
522
|
+
paths.unshift((0, import_node_path3.resolve)(resolvedConfig.compiledDir, promptPath + ".json"));
|
|
510
523
|
}
|
|
511
524
|
throw new Error(
|
|
512
525
|
`Prompt not found: "${promptPath}"
|
|
@@ -514,8 +527,8 @@ Searched:
|
|
|
514
527
|
${paths.map((candidate) => ` - ${candidate}`).join("\n")}`
|
|
515
528
|
);
|
|
516
529
|
}
|
|
517
|
-
const { asset } = await loadPromptFile(sourceFile, { defaultsRoot:
|
|
518
|
-
if (
|
|
530
|
+
const { asset } = await loadPromptFile(sourceFile, { defaultsRoot: resolvedConfig.sourceDir });
|
|
531
|
+
if (resolvedConfig.cache !== false) {
|
|
519
532
|
promptCache.set(sourceFile, asset);
|
|
520
533
|
}
|
|
521
534
|
return asset;
|
|
@@ -523,8 +536,9 @@ ${paths.map((candidate) => ` - ${candidate}`).join("\n")}`
|
|
|
523
536
|
throw new Error(`Prompt not found: "${promptPath}"`);
|
|
524
537
|
}
|
|
525
538
|
async function resolvePromptAsset(promptPath, config, options = {}, promptCache = sharedPromptCache) {
|
|
526
|
-
|
|
527
|
-
|
|
539
|
+
const resolvedConfig = withPromptResolutionDefaults(config);
|
|
540
|
+
let asset = await loadPromptAsset(promptPath, resolvedConfig, promptCache);
|
|
541
|
+
const sourceFile = (0, import_node_path3.resolve)(resolvedConfig.sourceDir, promptPath + ".md");
|
|
528
542
|
if (asset.includes && asset.includes.length > 0 && (0, import_node_fs2.existsSync)(sourceFile)) {
|
|
529
543
|
asset = await resolveIncludes(asset, sourceFile);
|
|
530
544
|
}
|
|
@@ -544,9 +558,118 @@ function resolveInlinePromptSource(source, options = {}) {
|
|
|
544
558
|
});
|
|
545
559
|
}
|
|
546
560
|
|
|
561
|
+
// src/context.ts
|
|
562
|
+
var textEncoder = new TextEncoder();
|
|
563
|
+
function getContextInputs(asset) {
|
|
564
|
+
return (asset.context?.inputs ?? []).map(normalizeContextInput);
|
|
565
|
+
}
|
|
566
|
+
function normalizeContextInput(input) {
|
|
567
|
+
if (typeof input === "string") {
|
|
568
|
+
return { name: input };
|
|
569
|
+
}
|
|
570
|
+
return {
|
|
571
|
+
name: input.name,
|
|
572
|
+
max_size: input.max_size,
|
|
573
|
+
trim: input.trim,
|
|
574
|
+
allow_regex: input.allow_regex,
|
|
575
|
+
deny_regex: input.deny_regex
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
function isTrimEnabled(mode) {
|
|
579
|
+
return mode === true || mode === "start" || mode === "end" || mode === "both";
|
|
580
|
+
}
|
|
581
|
+
function normalizeTrimMode(mode) {
|
|
582
|
+
if (mode === "start") {
|
|
583
|
+
return "start";
|
|
584
|
+
}
|
|
585
|
+
return "end";
|
|
586
|
+
}
|
|
587
|
+
function trimToMaxSize(value, maxSize, mode) {
|
|
588
|
+
const measured = measureContextValueSize(value);
|
|
589
|
+
if (measured <= maxSize) {
|
|
590
|
+
return value;
|
|
591
|
+
}
|
|
592
|
+
const characters = Array.from(value);
|
|
593
|
+
const normalizedMode = normalizeTrimMode(mode);
|
|
594
|
+
if (normalizedMode === "start") {
|
|
595
|
+
let collected2 = "";
|
|
596
|
+
let size2 = 0;
|
|
597
|
+
for (let i = characters.length - 1; i >= 0; i -= 1) {
|
|
598
|
+
const next = characters[i];
|
|
599
|
+
const charSize = measureContextValueSize(next);
|
|
600
|
+
if (size2 + charSize > maxSize) {
|
|
601
|
+
break;
|
|
602
|
+
}
|
|
603
|
+
collected2 = next + collected2;
|
|
604
|
+
size2 += charSize;
|
|
605
|
+
}
|
|
606
|
+
return collected2;
|
|
607
|
+
}
|
|
608
|
+
let collected = "";
|
|
609
|
+
let size = 0;
|
|
610
|
+
for (const char of characters) {
|
|
611
|
+
const charSize = measureContextValueSize(char);
|
|
612
|
+
if (size + charSize > maxSize) {
|
|
613
|
+
break;
|
|
614
|
+
}
|
|
615
|
+
collected += char;
|
|
616
|
+
size += charSize;
|
|
617
|
+
}
|
|
618
|
+
return collected;
|
|
619
|
+
}
|
|
620
|
+
function sanitizeContextVariables(asset, variables = {}, options = {}) {
|
|
621
|
+
const { onContextOverflow } = options;
|
|
622
|
+
const sanitized = { ...variables };
|
|
623
|
+
for (const input of getContextInputs(asset)) {
|
|
624
|
+
const value = sanitized[input.name];
|
|
625
|
+
if (value === void 0) {
|
|
626
|
+
continue;
|
|
627
|
+
}
|
|
628
|
+
let candidate = value;
|
|
629
|
+
if (input.max_size !== void 0) {
|
|
630
|
+
const actualSize = measureContextValueSize(candidate);
|
|
631
|
+
if (actualSize > input.max_size && onContextOverflow) {
|
|
632
|
+
candidate = onContextOverflow({
|
|
633
|
+
promptId: asset.id,
|
|
634
|
+
variable: input.name,
|
|
635
|
+
value: candidate,
|
|
636
|
+
maxSize: input.max_size,
|
|
637
|
+
actualSize
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
if (isTrimEnabled(input.trim) && input.max_size !== void 0) {
|
|
642
|
+
candidate = trimToMaxSize(candidate, input.max_size, input.trim);
|
|
643
|
+
}
|
|
644
|
+
sanitized[input.name] = candidate;
|
|
645
|
+
if (input.allow_regex) {
|
|
646
|
+
const candidate2 = sanitized[input.name];
|
|
647
|
+
const matcher = new RegExp(input.allow_regex);
|
|
648
|
+
if (!matcher.test(candidate2)) {
|
|
649
|
+
throw new Error(
|
|
650
|
+
`POK031: Context variable "${input.name}" failed allow_regex validation for prompt "${asset.id}".`
|
|
651
|
+
);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
if (input.deny_regex) {
|
|
655
|
+
const candidate2 = sanitized[input.name];
|
|
656
|
+
const matcher = new RegExp(input.deny_regex);
|
|
657
|
+
if (matcher.test(candidate2)) {
|
|
658
|
+
throw new Error(
|
|
659
|
+
`POK032: Context variable "${input.name}" matched deny_regex for prompt "${asset.id}".`
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return sanitized;
|
|
665
|
+
}
|
|
666
|
+
function measureContextValueSize(value) {
|
|
667
|
+
return textEncoder.encode(value).length;
|
|
668
|
+
}
|
|
669
|
+
|
|
547
670
|
// src/providers/prompt-input.ts
|
|
548
671
|
function isPromptLookup(input) {
|
|
549
|
-
return "path" in input && typeof input.path === "string"
|
|
672
|
+
return "path" in input && typeof input.path === "string";
|
|
550
673
|
}
|
|
551
674
|
function isInlinePromptSource(input) {
|
|
552
675
|
return "source" in input && typeof input.source === "string";
|
|
@@ -567,7 +690,13 @@ function withPromptInputSupport(adapter) {
|
|
|
567
690
|
};
|
|
568
691
|
const renderPrompt = async (input, runtime) => {
|
|
569
692
|
const resolved = await resolveProviderPromptInput(input, runtime);
|
|
570
|
-
|
|
693
|
+
const variables = sanitizeContextVariables(resolved, runtime.variables, {
|
|
694
|
+
onContextOverflow: runtime.onContextOverflow
|
|
695
|
+
});
|
|
696
|
+
return adapter.render(resolved, {
|
|
697
|
+
...runtime,
|
|
698
|
+
variables
|
|
699
|
+
});
|
|
571
700
|
};
|
|
572
701
|
return {
|
|
573
702
|
...adapter,
|