promptopskit 0.3.9 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -7
- package/SKILL.md +69 -6
- package/dist/chunk-5AAYDOPU.js +60 -0
- package/dist/chunk-5AAYDOPU.js.map +1 -0
- package/dist/{chunk-YNIAA4ZJ.js → chunk-7MRMN3SW.js} +5 -3
- package/dist/chunk-7MRMN3SW.js.map +1 -0
- package/dist/{chunk-4LEPCCSA.js → chunk-JKBWC5WJ.js} +176 -4
- package/dist/chunk-JKBWC5WJ.js.map +1 -0
- package/dist/{chunk-AN3OR7YC.js → chunk-MI3M6KDD.js} +7 -5
- package/dist/chunk-MI3M6KDD.js.map +1 -0
- package/dist/{chunk-LMURMZUA.js → chunk-XL76NHZR.js} +5 -3
- package/dist/chunk-XL76NHZR.js.map +1 -0
- package/dist/{chunk-V7QY7MRM.js → chunk-YI4LILPY.js} +50 -3
- package/dist/chunk-YI4LILPY.js.map +1 -0
- package/dist/{chunk-O6RQZYS4.js → chunk-Z4IPWEUU.js} +16 -5
- package/dist/chunk-Z4IPWEUU.js.map +1 -0
- package/dist/cli/index.js +440 -52
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +430 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +162 -10
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.cjs +232 -6
- 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 +223 -6
- 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-responses.cjs +221 -4
- package/dist/providers/openai-responses.cjs.map +1 -1
- package/dist/providers/openai-responses.d.cts +2 -2
- package/dist/providers/openai-responses.d.ts +2 -2
- package/dist/providers/openai-responses.js +3 -3
- package/dist/providers/openai.cjs +221 -4
- 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 +256 -7
- 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-BKkg93rL.d.cts → schema-B9A1zLRk.d.cts} +482 -2
- package/dist/{schema-BKkg93rL.d.ts → schema-B9A1zLRk.d.ts} +482 -2
- package/dist/testing.cjs +217 -4
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +59 -2
- package/dist/testing.d.ts +59 -2
- package/dist/testing.js +70 -2
- package/dist/testing.js.map +1 -1
- package/dist/{types-CsQ8tON_.d.ts → types-DjGAwJxC.d.ts} +1 -1
- package/dist/{types-7cC17GWp.d.cts → types-DpbzzZO2.d.cts} +1 -1
- package/dist/usagetap/index.d.cts +2 -2
- package/dist/usagetap/index.d.ts +2 -2
- package/package.json +2 -2
- package/dist/chunk-4LEPCCSA.js.map +0 -1
- package/dist/chunk-AN3OR7YC.js.map +0 -1
- package/dist/chunk-LMURMZUA.js.map +0 -1
- package/dist/chunk-O6RQZYS4.js.map +0 -1
- package/dist/chunk-V7QY7MRM.js.map +0 -1
- package/dist/chunk-YAD6COQX.js +0 -26
- package/dist/chunk-YAD6COQX.js.map +0 -1
- package/dist/chunk-YNIAA4ZJ.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -145,6 +145,29 @@ function mergeOverride(base, override) {
|
|
|
145
145
|
if (override.response !== void 0) {
|
|
146
146
|
result.response = { ...result.response, ...override.response };
|
|
147
147
|
}
|
|
148
|
+
if (override.cache !== void 0) {
|
|
149
|
+
result.cache = {
|
|
150
|
+
...result.cache,
|
|
151
|
+
...override.cache,
|
|
152
|
+
openai: mergeRecordBlock(result.cache?.openai, override.cache.openai),
|
|
153
|
+
anthropic: mergeRecordBlock(result.cache?.anthropic, override.cache.anthropic),
|
|
154
|
+
gemini: mergeRecordBlock(result.cache?.gemini, override.cache.gemini),
|
|
155
|
+
google: mergeRecordBlock(result.cache?.google, override.cache.google)
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
if (override.raw !== void 0) {
|
|
159
|
+
result.raw = {
|
|
160
|
+
...result.raw,
|
|
161
|
+
...override.raw,
|
|
162
|
+
openai: mergeRecordBlock(result.raw?.openai, override.raw.openai),
|
|
163
|
+
"openai-responses": mergeRecordBlock(result.raw?.["openai-responses"], override.raw["openai-responses"]),
|
|
164
|
+
openai_responses: mergeRecordBlock(result.raw?.openai_responses, override.raw.openai_responses),
|
|
165
|
+
anthropic: mergeRecordBlock(result.raw?.anthropic, override.raw.anthropic),
|
|
166
|
+
gemini: mergeRecordBlock(result.raw?.gemini, override.raw.gemini),
|
|
167
|
+
google: mergeRecordBlock(result.raw?.google, override.raw.google),
|
|
168
|
+
openrouter: mergeRecordBlock(result.raw?.openrouter, override.raw.openrouter)
|
|
169
|
+
};
|
|
170
|
+
}
|
|
148
171
|
if (override.provider_options !== void 0) {
|
|
149
172
|
result.provider_options = {
|
|
150
173
|
...result.provider_options,
|
|
@@ -156,11 +179,19 @@ function mergeOverride(base, override) {
|
|
|
156
179
|
gemini: {
|
|
157
180
|
...result.provider_options?.gemini,
|
|
158
181
|
...override.provider_options.gemini
|
|
182
|
+
},
|
|
183
|
+
openrouter: {
|
|
184
|
+
...result.provider_options?.openrouter,
|
|
185
|
+
...override.provider_options.openrouter
|
|
159
186
|
}
|
|
160
187
|
};
|
|
161
188
|
}
|
|
162
189
|
return result;
|
|
163
190
|
}
|
|
191
|
+
function mergeRecordBlock(base, override) {
|
|
192
|
+
if (override === void 0) return base;
|
|
193
|
+
return { ...base, ...override };
|
|
194
|
+
}
|
|
164
195
|
|
|
165
196
|
// src/providers/resolve-asset.ts
|
|
166
197
|
function resolveAssetForProvider(asset, runtime = {}) {
|
|
@@ -264,23 +295,42 @@ var ResponseSchema = import_zod.z.object({
|
|
|
264
295
|
stream: import_zod.z.boolean().optional(),
|
|
265
296
|
schema: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
266
297
|
schema_name: import_zod.z.string().optional(),
|
|
298
|
+
schema_description: import_zod.z.string().optional(),
|
|
267
299
|
schema_strict: import_zod.z.boolean().optional()
|
|
268
300
|
});
|
|
269
301
|
var AnthropicProviderOptionsSchema = import_zod.z.object({
|
|
270
302
|
top_k: import_zod.z.number().int().min(0).optional(),
|
|
271
|
-
tool_choice: import_zod.z.record(import_zod.z.unknown()).optional()
|
|
303
|
+
tool_choice: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
304
|
+
output_config: import_zod.z.record(import_zod.z.unknown()).optional()
|
|
272
305
|
});
|
|
273
306
|
var GeminiProviderOptionsSchema = import_zod.z.object({
|
|
274
307
|
candidate_count: import_zod.z.number().int().positive().optional(),
|
|
275
308
|
top_k: import_zod.z.number().int().min(0).optional(),
|
|
276
309
|
seed: import_zod.z.number().int().optional(),
|
|
277
310
|
response_schema: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
311
|
+
response_json_schema: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
278
312
|
response_modalities: import_zod.z.array(import_zod.z.string()).optional(),
|
|
279
313
|
thinking_budget_tokens: import_zod.z.number().int().positive().optional()
|
|
280
314
|
});
|
|
315
|
+
var OpenRouterProviderOptionsSchema = import_zod.z.object({
|
|
316
|
+
provider: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
317
|
+
transforms: import_zod.z.array(import_zod.z.string()).optional(),
|
|
318
|
+
plugins: import_zod.z.array(import_zod.z.record(import_zod.z.unknown())).optional(),
|
|
319
|
+
models: import_zod.z.array(import_zod.z.string()).optional()
|
|
320
|
+
});
|
|
281
321
|
var ProviderOptionsSchema = import_zod.z.object({
|
|
282
322
|
anthropic: AnthropicProviderOptionsSchema.optional(),
|
|
283
|
-
gemini: GeminiProviderOptionsSchema.optional()
|
|
323
|
+
gemini: GeminiProviderOptionsSchema.optional(),
|
|
324
|
+
openrouter: OpenRouterProviderOptionsSchema.optional()
|
|
325
|
+
});
|
|
326
|
+
var RawProviderBodySchema = import_zod.z.object({
|
|
327
|
+
openai: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
328
|
+
"openai-responses": import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
329
|
+
openai_responses: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
330
|
+
anthropic: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
331
|
+
gemini: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
332
|
+
google: import_zod.z.record(import_zod.z.unknown()).optional(),
|
|
333
|
+
openrouter: import_zod.z.record(import_zod.z.unknown()).optional()
|
|
284
334
|
});
|
|
285
335
|
var OpenAICacheSchema = import_zod.z.object({
|
|
286
336
|
prompt_cache_key: import_zod.z.string().min(1).optional(),
|
|
@@ -353,6 +403,7 @@ var PromptAssetOverridesSchema = import_zod.z.object({
|
|
|
353
403
|
sampling: SamplingSchema.optional(),
|
|
354
404
|
response: ResponseSchema.optional(),
|
|
355
405
|
cache: CacheSchema.optional(),
|
|
406
|
+
raw: RawProviderBodySchema.optional(),
|
|
356
407
|
tools: import_zod.z.array(ToolRefSchema).optional(),
|
|
357
408
|
provider_options: ProviderOptionsSchema.optional()
|
|
358
409
|
});
|
|
@@ -385,6 +436,7 @@ var PromptAssetSchema = import_zod.z.object({
|
|
|
385
436
|
sampling: SamplingSchema.optional(),
|
|
386
437
|
response: ResponseSchema.optional(),
|
|
387
438
|
cache: CacheSchema.optional(),
|
|
439
|
+
raw: RawProviderBodySchema.optional(),
|
|
388
440
|
tools: import_zod.z.array(ToolRefSchema).optional(),
|
|
389
441
|
provider_options: ProviderOptionsSchema.optional(),
|
|
390
442
|
mcp: MCPSchema.optional(),
|
|
@@ -398,6 +450,123 @@ var PromptAssetSchema = import_zod.z.object({
|
|
|
398
450
|
source: SourceSchema.optional()
|
|
399
451
|
});
|
|
400
452
|
|
|
453
|
+
// src/parser/frontmatter-guard.ts
|
|
454
|
+
var FRONT_MATTER_DELIMITER = /^---[ \t]*$/;
|
|
455
|
+
var REGEX_FIELD = /^(?<indent>\s*)(?<field>allow_regex|deny_regex)\s*:\s*(?<value>.*)$/;
|
|
456
|
+
var PATTERN_FIELD = /^(?<indent>\s*)pattern\s*:\s*(?<value>.*)$/;
|
|
457
|
+
var INLINE_PATTERN_FIELD = /(?:^|[{,]\s*)pattern\s*:\s*(?<value>"(?:\\.|[^"\\])*")/;
|
|
458
|
+
function assertRegexFrontMatterQuoting(content, filePath) {
|
|
459
|
+
const frontMatter = extractFrontMatter(content);
|
|
460
|
+
if (!frontMatter) {
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
let pendingRegex;
|
|
464
|
+
for (const [index, line] of frontMatter.lines.entries()) {
|
|
465
|
+
const lineNumber = frontMatter.startLine + index;
|
|
466
|
+
const regexMatch = line.match(REGEX_FIELD);
|
|
467
|
+
if (regexMatch?.groups) {
|
|
468
|
+
const field = regexMatch.groups.field;
|
|
469
|
+
const indent2 = regexMatch.groups.indent.length;
|
|
470
|
+
const value = regexMatch.groups.value.trim();
|
|
471
|
+
pendingRegex = value === "" ? { field, indent: indent2 } : void 0;
|
|
472
|
+
assertNoUnescapedBackslashInDoubleQuotedRegex(value, field, filePath, lineNumber);
|
|
473
|
+
assertNoUnescapedBackslashInInlinePattern(value, field, filePath, lineNumber);
|
|
474
|
+
continue;
|
|
475
|
+
}
|
|
476
|
+
if (!pendingRegex) {
|
|
477
|
+
continue;
|
|
478
|
+
}
|
|
479
|
+
if (line.trim() === "" || line.trimStart().startsWith("#")) {
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
482
|
+
const indent = line.match(/^\s*/)?.[0].length ?? 0;
|
|
483
|
+
if (indent <= pendingRegex.indent) {
|
|
484
|
+
pendingRegex = void 0;
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
const patternMatch = line.match(PATTERN_FIELD);
|
|
488
|
+
if (!patternMatch?.groups) {
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
assertNoUnescapedBackslashInDoubleQuotedRegex(
|
|
492
|
+
patternMatch.groups.value.trim(),
|
|
493
|
+
`${pendingRegex.field}.pattern`,
|
|
494
|
+
filePath,
|
|
495
|
+
lineNumber
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
function assertNoUnescapedBackslashInInlinePattern(value, field, filePath, lineNumber) {
|
|
500
|
+
const match = value.match(INLINE_PATTERN_FIELD);
|
|
501
|
+
const pattern = match?.groups?.value;
|
|
502
|
+
if (!pattern) {
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
assertNoUnescapedBackslashInDoubleQuotedRegex(pattern, `${field}.pattern`, filePath, lineNumber);
|
|
506
|
+
}
|
|
507
|
+
function extractFrontMatter(content) {
|
|
508
|
+
const lines = content.split(/\r?\n/);
|
|
509
|
+
if (!FRONT_MATTER_DELIMITER.test(lines[0] ?? "")) {
|
|
510
|
+
return void 0;
|
|
511
|
+
}
|
|
512
|
+
for (let index = 1; index < lines.length; index += 1) {
|
|
513
|
+
if (FRONT_MATTER_DELIMITER.test(lines[index] ?? "")) {
|
|
514
|
+
return {
|
|
515
|
+
lines: lines.slice(1, index),
|
|
516
|
+
startLine: 2
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
return void 0;
|
|
521
|
+
}
|
|
522
|
+
function assertNoUnescapedBackslashInDoubleQuotedRegex(value, field, filePath, lineNumber) {
|
|
523
|
+
if (!value.startsWith('"')) {
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
const quoted = readDoubleQuotedScalar(value);
|
|
527
|
+
if (!quoted) {
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
if (!hasUnescapedBackslash(quoted)) {
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
const location = filePath ? `${filePath}:${lineNumber}` : `line ${lineNumber}`;
|
|
534
|
+
throw new Error(
|
|
535
|
+
`POK013: Invalid context regex YAML at ${location}, field "${field}": double-quoted regex strings treat backslashes as YAML escapes. Use unquoted /pattern/i literal form, single quotes, or double each backslash.`
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
function readDoubleQuotedScalar(value) {
|
|
539
|
+
let result = "";
|
|
540
|
+
for (let index = 1; index < value.length; index += 1) {
|
|
541
|
+
const char = value[index];
|
|
542
|
+
if (char === '"') {
|
|
543
|
+
return result;
|
|
544
|
+
}
|
|
545
|
+
result += char;
|
|
546
|
+
if (char === "\\" && index + 1 < value.length) {
|
|
547
|
+
index += 1;
|
|
548
|
+
result += value[index];
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
return void 0;
|
|
552
|
+
}
|
|
553
|
+
function hasUnescapedBackslash(value) {
|
|
554
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
555
|
+
if (value[index] !== "\\") {
|
|
556
|
+
continue;
|
|
557
|
+
}
|
|
558
|
+
let count = 1;
|
|
559
|
+
while (value[index + count] === "\\") {
|
|
560
|
+
count += 1;
|
|
561
|
+
}
|
|
562
|
+
if (count % 2 === 1) {
|
|
563
|
+
return true;
|
|
564
|
+
}
|
|
565
|
+
index += count - 1;
|
|
566
|
+
}
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
569
|
+
|
|
401
570
|
// src/parser/sections.ts
|
|
402
571
|
var SECTION_MAP = {
|
|
403
572
|
"system instructions": "system_instructions",
|
|
@@ -438,6 +607,7 @@ function extractSections(body) {
|
|
|
438
607
|
|
|
439
608
|
// src/parser/parser.ts
|
|
440
609
|
function parsePrompt(content, filePath) {
|
|
610
|
+
assertRegexFrontMatterQuoting(content, filePath);
|
|
441
611
|
const { data: frontMatter, content: body } = (0, import_gray_matter.default)(content);
|
|
442
612
|
const sections = extractSections(body);
|
|
443
613
|
const raw = {
|
|
@@ -515,6 +685,7 @@ function mergeDefaults(base, local) {
|
|
|
515
685
|
return {
|
|
516
686
|
provider: local.provider ?? base.provider,
|
|
517
687
|
model: local.model ?? base.model,
|
|
688
|
+
cache: mergeCache(base.cache, local.cache),
|
|
518
689
|
metadata: {
|
|
519
690
|
...base.metadata ?? {},
|
|
520
691
|
...local.metadata ?? {}
|
|
@@ -526,10 +697,12 @@ function mergeDefaults(base, local) {
|
|
|
526
697
|
};
|
|
527
698
|
}
|
|
528
699
|
function applyDefaults(asset, defaults) {
|
|
700
|
+
const cache = mergeCache(defaults.cache, asset.cache);
|
|
529
701
|
const hasDefaultMetadata = defaults.metadata && Object.keys(defaults.metadata).length > 0;
|
|
530
702
|
const hasDefaultSystem = !!defaults.sections?.system_instructions;
|
|
531
703
|
const hasDefaultScalars = defaults.provider !== void 0 || defaults.model !== void 0;
|
|
532
|
-
|
|
704
|
+
const hasDefaultCache = cache !== void 0;
|
|
705
|
+
if (!hasDefaultMetadata && !hasDefaultSystem && !hasDefaultScalars && !hasDefaultCache) {
|
|
533
706
|
return asset;
|
|
534
707
|
}
|
|
535
708
|
const mergedMetadata = {
|
|
@@ -543,10 +716,38 @@ function applyDefaults(asset, defaults) {
|
|
|
543
716
|
...asset,
|
|
544
717
|
provider: asset.provider ?? defaults.provider,
|
|
545
718
|
model: asset.model ?? defaults.model,
|
|
719
|
+
cache,
|
|
546
720
|
metadata,
|
|
547
721
|
sections
|
|
548
722
|
};
|
|
549
723
|
}
|
|
724
|
+
function mergeCache(base, local) {
|
|
725
|
+
const merged = {
|
|
726
|
+
...base ?? {},
|
|
727
|
+
...local ?? {},
|
|
728
|
+
openai: {
|
|
729
|
+
...base?.openai ?? {},
|
|
730
|
+
...local?.openai ?? {}
|
|
731
|
+
},
|
|
732
|
+
anthropic: {
|
|
733
|
+
...base?.anthropic ?? {},
|
|
734
|
+
...local?.anthropic ?? {}
|
|
735
|
+
},
|
|
736
|
+
gemini: {
|
|
737
|
+
...base?.gemini ?? {},
|
|
738
|
+
...local?.gemini ?? {}
|
|
739
|
+
},
|
|
740
|
+
google: {
|
|
741
|
+
...base?.google ?? {},
|
|
742
|
+
...local?.google ?? {}
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
if (merged.openai && Object.keys(merged.openai).length === 0) delete merged.openai;
|
|
746
|
+
if (merged.anthropic && Object.keys(merged.anthropic).length === 0) delete merged.anthropic;
|
|
747
|
+
if (merged.gemini && Object.keys(merged.gemini).length === 0) delete merged.gemini;
|
|
748
|
+
if (merged.google && Object.keys(merged.google).length === 0) delete merged.google;
|
|
749
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
750
|
+
}
|
|
550
751
|
|
|
551
752
|
// src/composition/resolve-includes.ts
|
|
552
753
|
async function resolveIncludes(asset, basePath, visited = /* @__PURE__ */ new Set()) {
|
|
@@ -1018,6 +1219,21 @@ function withPromptInputSupport(adapter) {
|
|
|
1018
1219
|
};
|
|
1019
1220
|
}
|
|
1020
1221
|
|
|
1222
|
+
// src/providers/raw.ts
|
|
1223
|
+
function applyRawProviderBody(body, asset, provider) {
|
|
1224
|
+
const raw = getRawProviderBody(asset, provider);
|
|
1225
|
+
return raw ? { ...body, ...raw } : body;
|
|
1226
|
+
}
|
|
1227
|
+
function getRawProviderBody(asset, provider) {
|
|
1228
|
+
if (provider === "openai-responses") {
|
|
1229
|
+
return asset.raw?.["openai-responses"] ?? asset.raw?.openai_responses;
|
|
1230
|
+
}
|
|
1231
|
+
if (provider === "gemini") {
|
|
1232
|
+
return asset.raw?.gemini ?? asset.raw?.google;
|
|
1233
|
+
}
|
|
1234
|
+
return asset.raw?.[provider];
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1021
1237
|
// src/providers/openai.ts
|
|
1022
1238
|
var openaiAdapter = withPromptInputSupport({
|
|
1023
1239
|
name: "openai",
|
|
@@ -1073,6 +1289,7 @@ var openaiAdapter = withPromptInputSupport({
|
|
|
1073
1289
|
type: "json_schema",
|
|
1074
1290
|
json_schema: {
|
|
1075
1291
|
name: resolvedAsset.response.schema_name ?? `${resolvedAsset.id}_response`,
|
|
1292
|
+
...resolvedAsset.response.schema_description ? { description: resolvedAsset.response.schema_description } : {},
|
|
1076
1293
|
schema: resolvedAsset.response.schema,
|
|
1077
1294
|
strict: resolvedAsset.response.schema_strict ?? true
|
|
1078
1295
|
}
|
|
@@ -1107,7 +1324,7 @@ var openaiAdapter = withPromptInputSupport({
|
|
|
1107
1324
|
});
|
|
1108
1325
|
}
|
|
1109
1326
|
return {
|
|
1110
|
-
body,
|
|
1327
|
+
body: applyRawProviderBody(body, resolvedAsset, "openai"),
|
|
1111
1328
|
provider: "openai",
|
|
1112
1329
|
model: resolvedAsset.model ?? "unknown"
|
|
1113
1330
|
};
|
|
@@ -1174,6 +1391,7 @@ var openaiResponsesAdapter = withPromptInputSupport({
|
|
|
1174
1391
|
format: {
|
|
1175
1392
|
type: "json_schema",
|
|
1176
1393
|
name: resolvedAsset.response.schema_name ?? `${resolvedAsset.id}_response`,
|
|
1394
|
+
...resolvedAsset.response.schema_description ? { description: resolvedAsset.response.schema_description } : {},
|
|
1177
1395
|
schema: resolvedAsset.response.schema,
|
|
1178
1396
|
strict: resolvedAsset.response.schema_strict ?? true
|
|
1179
1397
|
}
|
|
@@ -1208,7 +1426,7 @@ var openaiResponsesAdapter = withPromptInputSupport({
|
|
|
1208
1426
|
if (responseOptions?.include !== void 0) body.include = responseOptions.include;
|
|
1209
1427
|
if (responseOptions?.background !== void 0) body.background = responseOptions.background;
|
|
1210
1428
|
return {
|
|
1211
|
-
body,
|
|
1429
|
+
body: applyRawProviderBody(body, resolvedAsset, "openai-responses"),
|
|
1212
1430
|
provider: "openai-responses",
|
|
1213
1431
|
model: resolvedAsset.model ?? "unknown"
|
|
1214
1432
|
};
|
|
@@ -1234,8 +1452,8 @@ var anthropicAdapter = withPromptInputSupport({
|
|
|
1234
1452
|
if (resolvedAsset.reasoning?.effort !== void 0) {
|
|
1235
1453
|
warnings.push("Anthropic uses budget_tokens for thinking, not effort. effort will be mapped approximately.");
|
|
1236
1454
|
}
|
|
1237
|
-
if (resolvedAsset.response?.schema !== void 0) {
|
|
1238
|
-
warnings.push("Anthropic
|
|
1455
|
+
if (resolvedAsset.response?.schema !== void 0 && resolvedAsset.response?.format !== "json") {
|
|
1456
|
+
warnings.push("Anthropic response.schema is mapped to output_config.format and should usually be paired with response.format: json.");
|
|
1239
1457
|
}
|
|
1240
1458
|
if (resolvedAsset.provider_options?.anthropic?.top_k !== void 0 && resolvedAsset.provider_options.anthropic.top_k < 0) {
|
|
1241
1459
|
errors.push("Anthropic provider_options.top_k must be >= 0.");
|
|
@@ -1299,6 +1517,16 @@ var anthropicAdapter = withPromptInputSupport({
|
|
|
1299
1517
|
if (resolvedAsset.provider_options?.anthropic?.top_k !== void 0) {
|
|
1300
1518
|
body.top_k = resolvedAsset.provider_options.anthropic.top_k;
|
|
1301
1519
|
}
|
|
1520
|
+
if (resolvedAsset.provider_options?.anthropic?.output_config !== void 0) {
|
|
1521
|
+
body.output_config = resolvedAsset.provider_options.anthropic.output_config;
|
|
1522
|
+
} else if (resolvedAsset.response?.schema !== void 0) {
|
|
1523
|
+
body.output_config = {
|
|
1524
|
+
format: {
|
|
1525
|
+
type: "json_schema",
|
|
1526
|
+
schema: resolvedAsset.response.schema
|
|
1527
|
+
}
|
|
1528
|
+
};
|
|
1529
|
+
}
|
|
1302
1530
|
if (resolvedAsset.response?.stream !== void 0) {
|
|
1303
1531
|
body.stream = resolvedAsset.response.stream;
|
|
1304
1532
|
}
|
|
@@ -1332,7 +1560,7 @@ var anthropicAdapter = withPromptInputSupport({
|
|
|
1332
1560
|
body.tool_choice = resolvedAsset.provider_options.anthropic.tool_choice;
|
|
1333
1561
|
}
|
|
1334
1562
|
return {
|
|
1335
|
-
body,
|
|
1563
|
+
body: applyRawProviderBody(body, resolvedAsset, "anthropic"),
|
|
1336
1564
|
provider: "anthropic",
|
|
1337
1565
|
model: resolvedAsset.model ?? "unknown"
|
|
1338
1566
|
};
|
|
@@ -1404,9 +1632,10 @@ var geminiAdapter = withPromptInputSupport({
|
|
|
1404
1632
|
if (geminiOptions?.candidate_count !== void 0) generationConfig.candidateCount = geminiOptions.candidate_count;
|
|
1405
1633
|
if (geminiOptions?.top_k !== void 0) generationConfig.topK = geminiOptions.top_k;
|
|
1406
1634
|
if (geminiOptions?.seed !== void 0) generationConfig.seed = geminiOptions.seed;
|
|
1407
|
-
if (geminiOptions?.response_schema !== void 0) generationConfig.responseSchema = geminiOptions.response_schema;
|
|
1408
1635
|
if (geminiOptions?.response_modalities !== void 0) generationConfig.responseModalities = geminiOptions.response_modalities;
|
|
1409
|
-
if (resolvedAsset.response?.schema !== void 0) generationConfig.
|
|
1636
|
+
if (resolvedAsset.response?.schema !== void 0) generationConfig.responseJsonSchema = resolvedAsset.response.schema;
|
|
1637
|
+
if (geminiOptions?.response_schema !== void 0) generationConfig.responseSchema = geminiOptions.response_schema;
|
|
1638
|
+
if (geminiOptions?.response_json_schema !== void 0) generationConfig.responseJsonSchema = geminiOptions.response_json_schema;
|
|
1410
1639
|
if (resolvedAsset.response?.format === "json") {
|
|
1411
1640
|
generationConfig.responseMimeType = "application/json";
|
|
1412
1641
|
}
|
|
@@ -1441,7 +1670,7 @@ var geminiAdapter = withPromptInputSupport({
|
|
|
1441
1670
|
body.tools = [{ functionDeclarations }];
|
|
1442
1671
|
}
|
|
1443
1672
|
return {
|
|
1444
|
-
body,
|
|
1673
|
+
body: applyRawProviderBody(body, resolvedAsset, "gemini"),
|
|
1445
1674
|
provider: "gemini",
|
|
1446
1675
|
model: resolvedAsset.model ?? "unknown"
|
|
1447
1676
|
};
|
|
@@ -1452,13 +1681,45 @@ var geminiAdapter = withPromptInputSupport({
|
|
|
1452
1681
|
var openrouterAdapter = withPromptInputSupport({
|
|
1453
1682
|
name: "openrouter",
|
|
1454
1683
|
validate(asset, runtime) {
|
|
1455
|
-
|
|
1684
|
+
const resolvedAsset = resolveAssetForProvider(asset, runtime);
|
|
1685
|
+
const validation = openaiAdapter.validate(asset, runtime);
|
|
1686
|
+
const hasOpenRouterModels = (resolvedAsset.provider_options?.openrouter?.models?.length ?? 0) > 0;
|
|
1687
|
+
if (!hasOpenRouterModels) {
|
|
1688
|
+
return validation;
|
|
1689
|
+
}
|
|
1690
|
+
const modelRequiredError = "OpenAI adapter requires a model to be specified.";
|
|
1691
|
+
const errors = validation.errors.filter((error) => error !== modelRequiredError);
|
|
1692
|
+
const warnings = validation.warnings.filter((warning) => warning !== modelRequiredError);
|
|
1693
|
+
return {
|
|
1694
|
+
valid: errors.length === 0,
|
|
1695
|
+
errors,
|
|
1696
|
+
warnings
|
|
1697
|
+
};
|
|
1456
1698
|
},
|
|
1457
1699
|
render(asset, runtime) {
|
|
1458
|
-
const
|
|
1700
|
+
const resolvedAsset = resolveAssetForProvider(asset, runtime);
|
|
1701
|
+
const result = openaiAdapter.render(
|
|
1702
|
+
{ ...resolvedAsset, raw: void 0 },
|
|
1703
|
+
{
|
|
1704
|
+
variables: runtime.variables,
|
|
1705
|
+
history: runtime.history,
|
|
1706
|
+
toolRegistry: runtime.toolRegistry,
|
|
1707
|
+
strict: runtime.strict
|
|
1708
|
+
}
|
|
1709
|
+
);
|
|
1710
|
+
const openrouterOptions = resolvedAsset.provider_options?.openrouter;
|
|
1711
|
+
let body = { ...result.body };
|
|
1712
|
+
if (openrouterOptions?.provider !== void 0) body.provider = openrouterOptions.provider;
|
|
1713
|
+
if (openrouterOptions?.transforms !== void 0) body.transforms = openrouterOptions.transforms;
|
|
1714
|
+
if (openrouterOptions?.plugins !== void 0) body.plugins = openrouterOptions.plugins;
|
|
1715
|
+
if (openrouterOptions?.models !== void 0) body.models = openrouterOptions.models;
|
|
1716
|
+
if (body.model === void 0) delete body.model;
|
|
1717
|
+
body = applyRawProviderBody(body, resolvedAsset, "openrouter");
|
|
1459
1718
|
return {
|
|
1460
1719
|
...result,
|
|
1461
|
-
|
|
1720
|
+
body,
|
|
1721
|
+
provider: "openrouter",
|
|
1722
|
+
model: resolvedAsset.model ?? openrouterOptions?.models?.[0] ?? "unknown"
|
|
1462
1723
|
};
|
|
1463
1724
|
}
|
|
1464
1725
|
});
|
|
@@ -1522,8 +1783,21 @@ var KNOWN_FRONT_MATTER_KEYS = /* @__PURE__ */ new Set([
|
|
|
1522
1783
|
"environments",
|
|
1523
1784
|
"tiers",
|
|
1524
1785
|
"metadata",
|
|
1525
|
-
"cache"
|
|
1786
|
+
"cache",
|
|
1787
|
+
"provider_options",
|
|
1788
|
+
"raw"
|
|
1526
1789
|
]);
|
|
1790
|
+
var RISKY_UNBOUNDED_INPUT_NAMES = [
|
|
1791
|
+
"message",
|
|
1792
|
+
"prompt",
|
|
1793
|
+
"history",
|
|
1794
|
+
"transcript",
|
|
1795
|
+
"document",
|
|
1796
|
+
"content",
|
|
1797
|
+
"input",
|
|
1798
|
+
"body",
|
|
1799
|
+
"context"
|
|
1800
|
+
];
|
|
1527
1801
|
function validateAsset(asset, frontMatterKeys, filePath) {
|
|
1528
1802
|
const errors = [];
|
|
1529
1803
|
const warnings = [];
|
|
@@ -1594,7 +1868,32 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
1594
1868
|
});
|
|
1595
1869
|
}
|
|
1596
1870
|
}
|
|
1871
|
+
if (usedVars.size > 0 && (!asset.context?.inputs || asset.context.inputs.length === 0)) {
|
|
1872
|
+
warnings.push({
|
|
1873
|
+
code: "POK046",
|
|
1874
|
+
message: `Template uses ${usedVars.size === 1 ? "a variable" : "variables"} but context.inputs is not declared.`,
|
|
1875
|
+
filePath,
|
|
1876
|
+
suggestion: "Declare context.inputs to enable input policy validation."
|
|
1877
|
+
});
|
|
1878
|
+
}
|
|
1597
1879
|
for (const input of getContextInputs(asset)) {
|
|
1880
|
+
const lowerName = input.name.toLowerCase();
|
|
1881
|
+
if (input.max_size === void 0 && RISKY_UNBOUNDED_INPUT_NAMES.some((needle) => lowerName.includes(needle))) {
|
|
1882
|
+
warnings.push({
|
|
1883
|
+
code: "POK040",
|
|
1884
|
+
message: `Context input "${input.name}" has no max_size and appears unbounded.`,
|
|
1885
|
+
filePath,
|
|
1886
|
+
suggestion: "Add max_size to constrain prompt payload growth."
|
|
1887
|
+
});
|
|
1888
|
+
}
|
|
1889
|
+
if (input.allow_regex === void 0 && input.deny_regex === void 0 && input.non_empty === void 0 && input.reject_secrets === void 0) {
|
|
1890
|
+
warnings.push({
|
|
1891
|
+
code: "POK041",
|
|
1892
|
+
message: `Context input "${input.name}" has no input hardening validators.`,
|
|
1893
|
+
filePath,
|
|
1894
|
+
suggestion: "Consider non_empty/reject_secrets and allow/deny regex validators."
|
|
1895
|
+
});
|
|
1896
|
+
}
|
|
1598
1897
|
if (input.trim !== void 0 && input.trim !== false && input.max_size === void 0) {
|
|
1599
1898
|
warnings.push({
|
|
1600
1899
|
code: "POK014",
|
|
@@ -1622,6 +1921,91 @@ function validateAsset(asset, frontMatterKeys, filePath) {
|
|
|
1622
1921
|
}
|
|
1623
1922
|
}
|
|
1624
1923
|
}
|
|
1924
|
+
if (asset.provider) {
|
|
1925
|
+
let providerCache;
|
|
1926
|
+
let cacheSuggestionField;
|
|
1927
|
+
switch (asset.provider) {
|
|
1928
|
+
case "openai":
|
|
1929
|
+
providerCache = asset.cache?.openai;
|
|
1930
|
+
cacheSuggestionField = "cache.openai";
|
|
1931
|
+
break;
|
|
1932
|
+
case "anthropic":
|
|
1933
|
+
providerCache = asset.cache?.anthropic;
|
|
1934
|
+
cacheSuggestionField = "cache.anthropic";
|
|
1935
|
+
break;
|
|
1936
|
+
case "gemini":
|
|
1937
|
+
case "google":
|
|
1938
|
+
providerCache = asset.cache?.gemini ?? asset.cache?.google;
|
|
1939
|
+
cacheSuggestionField = "cache.gemini";
|
|
1940
|
+
break;
|
|
1941
|
+
default:
|
|
1942
|
+
break;
|
|
1943
|
+
}
|
|
1944
|
+
if (cacheSuggestionField && providerCache === void 0) {
|
|
1945
|
+
warnings.push({
|
|
1946
|
+
code: "POK042",
|
|
1947
|
+
message: `Provider "${asset.provider}" has no provider-specific cache settings.`,
|
|
1948
|
+
filePath,
|
|
1949
|
+
suggestion: `Consider configuring ${cacheSuggestionField} for better cache-hit behavior.`
|
|
1950
|
+
});
|
|
1951
|
+
}
|
|
1952
|
+
if (!asset.model) {
|
|
1953
|
+
warnings.push({
|
|
1954
|
+
code: "POK044",
|
|
1955
|
+
message: `Provider "${asset.provider}" is configured without a model.`,
|
|
1956
|
+
filePath,
|
|
1957
|
+
suggestion: "Set model in prompt or defaults to avoid adapter-time errors."
|
|
1958
|
+
});
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
if (asset.cache?.gemini?.cached_content && asset.cache.google?.cached_content && asset.cache.gemini.cached_content !== asset.cache.google.cached_content) {
|
|
1962
|
+
warnings.push({
|
|
1963
|
+
code: "POK043",
|
|
1964
|
+
message: "cache.gemini.cached_content and cache.google.cached_content are both set to different values.",
|
|
1965
|
+
filePath,
|
|
1966
|
+
suggestion: "Use one canonical value; Gemini prefers cache.gemini.cached_content."
|
|
1967
|
+
});
|
|
1968
|
+
}
|
|
1969
|
+
for (const [envName, overrides] of Object.entries(asset.environments ?? {})) {
|
|
1970
|
+
if (asset.cache && (!isRecord(overrides) || !overrides.cache)) {
|
|
1971
|
+
warnings.push({
|
|
1972
|
+
code: "POK045",
|
|
1973
|
+
message: `Environment "${envName}" does not override cache while prompt-level cache is defined.`,
|
|
1974
|
+
filePath,
|
|
1975
|
+
suggestion: "Confirm cache strategy is intentionally shared across environments."
|
|
1976
|
+
});
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
for (const [tierName, overrides] of Object.entries(asset.tiers ?? {})) {
|
|
1980
|
+
if (asset.cache && (!isRecord(overrides) || !overrides.cache)) {
|
|
1981
|
+
warnings.push({
|
|
1982
|
+
code: "POK045",
|
|
1983
|
+
message: `Tier "${tierName}" does not override cache while prompt-level cache is defined.`,
|
|
1984
|
+
filePath,
|
|
1985
|
+
suggestion: "Confirm cache strategy is intentionally shared across tiers."
|
|
1986
|
+
});
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
for (const tool of asset.tools ?? []) {
|
|
1990
|
+
if (isRecord(tool)) {
|
|
1991
|
+
if (!tool.description) {
|
|
1992
|
+
warnings.push({
|
|
1993
|
+
code: "POK047",
|
|
1994
|
+
message: `Inline tool "${tool.name}" is missing a description.`,
|
|
1995
|
+
filePath,
|
|
1996
|
+
suggestion: "Add description to improve model tool-selection quality."
|
|
1997
|
+
});
|
|
1998
|
+
}
|
|
1999
|
+
if (!tool.input_schema) {
|
|
2000
|
+
warnings.push({
|
|
2001
|
+
code: "POK047",
|
|
2002
|
+
message: `Inline tool "${tool.name}" is missing input_schema.`,
|
|
2003
|
+
filePath,
|
|
2004
|
+
suggestion: "Add input_schema so tool inputs are strongly typed."
|
|
2005
|
+
});
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
1625
2009
|
return {
|
|
1626
2010
|
valid: errors.length === 0,
|
|
1627
2011
|
errors,
|
|
@@ -1658,6 +2042,9 @@ function findClosestMatch(input, candidates) {
|
|
|
1658
2042
|
}
|
|
1659
2043
|
return best;
|
|
1660
2044
|
}
|
|
2045
|
+
function isRecord(value) {
|
|
2046
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2047
|
+
}
|
|
1661
2048
|
|
|
1662
2049
|
// src/usagetap/client.ts
|
|
1663
2050
|
var DEFAULT_BASE_URL = "https://api.usagetap.com";
|
|
@@ -2141,9 +2528,21 @@ var PromptOpsKit = class {
|
|
|
2141
2528
|
* Validate a prompt file.
|
|
2142
2529
|
*/
|
|
2143
2530
|
async validatePrompt(promptPath) {
|
|
2144
|
-
const asset = await this.loadPrompt(promptPath);
|
|
2145
2531
|
const sourceFile = (0, import_node_path4.resolve)(this.config.sourceDir, promptPath + ".md");
|
|
2146
|
-
|
|
2532
|
+
try {
|
|
2533
|
+
const asset = await this.loadPrompt(promptPath);
|
|
2534
|
+
return validateAssetWithIncludes(asset, sourceFile);
|
|
2535
|
+
} catch (error) {
|
|
2536
|
+
const validationError = toPromptValidationError(error, sourceFile);
|
|
2537
|
+
if (validationError) {
|
|
2538
|
+
return {
|
|
2539
|
+
valid: false,
|
|
2540
|
+
errors: [validationError],
|
|
2541
|
+
warnings: []
|
|
2542
|
+
};
|
|
2543
|
+
}
|
|
2544
|
+
throw error;
|
|
2545
|
+
}
|
|
2147
2546
|
}
|
|
2148
2547
|
/**
|
|
2149
2548
|
* Clear the internal cache.
|
|
@@ -2155,6 +2554,20 @@ var PromptOpsKit = class {
|
|
|
2155
2554
|
function createPromptOpsKit(config = {}) {
|
|
2156
2555
|
return new PromptOpsKit(config);
|
|
2157
2556
|
}
|
|
2557
|
+
function toPromptValidationError(error, filePath) {
|
|
2558
|
+
if (!(error instanceof Error)) {
|
|
2559
|
+
return void 0;
|
|
2560
|
+
}
|
|
2561
|
+
const match = error.message.match(/^(POK\d+):\s*(.*)$/);
|
|
2562
|
+
if (!match) {
|
|
2563
|
+
return void 0;
|
|
2564
|
+
}
|
|
2565
|
+
return {
|
|
2566
|
+
code: match[1],
|
|
2567
|
+
message: match[2],
|
|
2568
|
+
filePath
|
|
2569
|
+
};
|
|
2570
|
+
}
|
|
2158
2571
|
async function renderPrompt(options) {
|
|
2159
2572
|
const kit = createPromptOpsKit({
|
|
2160
2573
|
sourceDir: options.sourceDir ?? DEFAULT_PROMPTS_DIR,
|