promptopskit 0.3.6 → 0.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +41 -12
  2. package/SKILL.md +31 -4
  3. package/dist/{chunk-6FLNJVE7.js → chunk-5OYWNRNC.js} +19 -3
  4. package/dist/{chunk-6FLNJVE7.js.map → chunk-5OYWNRNC.js.map} +1 -1
  5. package/dist/{chunk-MYXDJMWV.js → chunk-BBVVA27J.js} +2 -2
  6. package/dist/{chunk-SOY2CEJM.js → chunk-E2NXJLS6.js} +3 -3
  7. package/dist/{chunk-J32I6DSG.js → chunk-E6NPZOJL.js} +2 -2
  8. package/dist/{chunk-MN3RQ7DZ.js → chunk-UJU5XERR.js} +2 -2
  9. package/dist/{chunk-SHYKSLVR.js → chunk-X73VG645.js} +182 -9
  10. package/dist/chunk-X73VG645.js.map +1 -0
  11. package/dist/cli/index.js +252 -100
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/index.cjs +216 -17
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +6 -5
  16. package/dist/index.d.ts +6 -5
  17. package/dist/index.js +26 -14
  18. package/dist/index.js.map +1 -1
  19. package/dist/providers/anthropic.cjs +197 -9
  20. package/dist/providers/anthropic.cjs.map +1 -1
  21. package/dist/providers/anthropic.d.cts +2 -2
  22. package/dist/providers/anthropic.d.ts +2 -2
  23. package/dist/providers/anthropic.js +3 -3
  24. package/dist/providers/gemini.cjs +197 -9
  25. package/dist/providers/gemini.cjs.map +1 -1
  26. package/dist/providers/gemini.d.cts +2 -2
  27. package/dist/providers/gemini.d.ts +2 -2
  28. package/dist/providers/gemini.js +3 -3
  29. package/dist/providers/openai.cjs +197 -9
  30. package/dist/providers/openai.cjs.map +1 -1
  31. package/dist/providers/openai.d.cts +2 -2
  32. package/dist/providers/openai.d.ts +2 -2
  33. package/dist/providers/openai.js +3 -3
  34. package/dist/providers/openrouter.cjs +197 -9
  35. package/dist/providers/openrouter.cjs.map +1 -1
  36. package/dist/providers/openrouter.d.cts +2 -2
  37. package/dist/providers/openrouter.d.ts +2 -2
  38. package/dist/providers/openrouter.js +4 -4
  39. package/dist/{schema-D145q3Dw.d.cts → schema-DwzYbZba.d.cts} +178 -56
  40. package/dist/{schema-D145q3Dw.d.ts → schema-DwzYbZba.d.ts} +178 -56
  41. package/dist/testing.cjs +18 -2
  42. package/dist/testing.cjs.map +1 -1
  43. package/dist/testing.d.cts +1 -1
  44. package/dist/testing.d.ts +1 -1
  45. package/dist/testing.js +1 -1
  46. package/dist/{types-B3sWHzIo.d.cts → types-C6RG0Si0.d.cts} +12 -5
  47. package/dist/{types-CXlVWckk.d.ts → types-fBvo_d4k.d.ts} +12 -5
  48. package/dist/usagetap/index.d.cts +2 -2
  49. package/dist/usagetap/index.d.ts +2 -2
  50. package/package.json +1 -1
  51. package/dist/chunk-SHYKSLVR.js.map +0 -1
  52. /package/dist/{chunk-MYXDJMWV.js.map → chunk-BBVVA27J.js.map} +0 -0
  53. /package/dist/{chunk-SOY2CEJM.js.map → chunk-E2NXJLS6.js.map} +0 -0
  54. /package/dist/{chunk-J32I6DSG.js.map → chunk-E6NPZOJL.js.map} +0 -0
  55. /package/dist/{chunk-MN3RQ7DZ.js.map → chunk-UJU5XERR.js.map} +0 -0
package/dist/cli/index.js CHANGED
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // src/cli/index.ts
4
+ import { readFileSync as readFileSync2 } from "fs";
5
+
3
6
  // src/cli/commands/validate.ts
4
7
  import { readdir } from "fs/promises";
5
8
  import { join as join2, extname } from "path";
@@ -41,12 +44,28 @@ var ResponseSchema = z.object({
41
44
  var HistorySchema = z.object({
42
45
  max_items: z.number().int().positive().optional()
43
46
  });
47
+ var ContextRegexSchema = z.union([
48
+ z.string(),
49
+ z.object({
50
+ pattern: z.string(),
51
+ flags: z.string().optional(),
52
+ return_message: z.string().optional()
53
+ })
54
+ ]);
55
+ var ContextBuiltInValidatorSchema = z.union([
56
+ z.boolean(),
57
+ z.object({
58
+ return_message: z.string().optional()
59
+ })
60
+ ]);
44
61
  var ContextInputDefinitionObjectSchema = z.object({
45
62
  name: z.string(),
46
63
  max_size: z.number().int().positive().optional(),
47
64
  trim: z.union([z.boolean(), z.enum(["start", "end", "both"])]).optional(),
48
- allow_regex: z.string().optional(),
49
- deny_regex: z.string().optional()
65
+ allow_regex: ContextRegexSchema.optional(),
66
+ deny_regex: ContextRegexSchema.optional(),
67
+ non_empty: ContextBuiltInValidatorSchema.optional(),
68
+ reject_secrets: ContextBuiltInValidatorSchema.optional()
50
69
  });
51
70
  var ContextInputDefinitionSchema = z.union([
52
71
  z.string(),
@@ -346,10 +365,97 @@ function normalizeContextInput(input) {
346
365
  name: input.name,
347
366
  max_size: input.max_size,
348
367
  trim: input.trim,
349
- allow_regex: input.allow_regex,
350
- deny_regex: input.deny_regex
368
+ allow_regex: normalizeContextRegex(input.allow_regex),
369
+ deny_regex: normalizeContextRegex(input.deny_regex),
370
+ non_empty: normalizeBuiltInValidator(input.non_empty),
371
+ reject_secrets: normalizeBuiltInValidator(input.reject_secrets)
372
+ };
373
+ }
374
+ function normalizeContextRegex(value) {
375
+ if (value === void 0) {
376
+ return void 0;
377
+ }
378
+ if (typeof value === "string") {
379
+ const literal = parseRegexLiteral(value);
380
+ if (value.startsWith("/") && !literal) {
381
+ return {
382
+ pattern: value,
383
+ flags: "",
384
+ raw: value,
385
+ invalidLiteral: true
386
+ };
387
+ }
388
+ return {
389
+ pattern: literal?.pattern ?? value,
390
+ flags: literal?.flags ?? "",
391
+ raw: value
392
+ };
393
+ }
394
+ return {
395
+ pattern: value.pattern,
396
+ flags: value.flags ?? "",
397
+ raw: JSON.stringify(value),
398
+ returnMessage: value.return_message
351
399
  };
352
400
  }
401
+ function normalizeBuiltInValidator(value) {
402
+ if (value === void 0 || value === false) {
403
+ return void 0;
404
+ }
405
+ if (value === true) {
406
+ return {};
407
+ }
408
+ return {
409
+ returnMessage: value.return_message
410
+ };
411
+ }
412
+ function parseRegexLiteral(value) {
413
+ if (!value.startsWith("/")) {
414
+ return void 0;
415
+ }
416
+ for (let index = value.length - 1; index > 0; index -= 1) {
417
+ if (value[index] !== "/") {
418
+ continue;
419
+ }
420
+ let backslashCount = 0;
421
+ for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
422
+ backslashCount += 1;
423
+ }
424
+ if (backslashCount % 2 === 1) {
425
+ continue;
426
+ }
427
+ return {
428
+ pattern: value.slice(1, index),
429
+ flags: value.slice(index + 1)
430
+ };
431
+ }
432
+ return void 0;
433
+ }
434
+ function formatInvalidContextRegexMessage(details) {
435
+ return [
436
+ `Invalid context regex for prompt "${details.promptId}"`,
437
+ `variable "${details.variable}"`,
438
+ `field "${details.field}"`,
439
+ `value ${JSON.stringify(details.raw)}: ${details.reason}`
440
+ ].join(", ");
441
+ }
442
+ function compileContextRegex(regex, details) {
443
+ if (regex.invalidLiteral) {
444
+ throw new Error(
445
+ `POK013: ${formatInvalidContextRegexMessage({
446
+ ...details,
447
+ raw: regex.raw,
448
+ reason: "Malformed regex literal. Use /pattern/flags or { pattern, flags }."
449
+ })}`
450
+ );
451
+ }
452
+ try {
453
+ return new RegExp(regex.pattern, regex.flags);
454
+ } catch (error) {
455
+ const reason = error instanceof Error ? error.message : String(error);
456
+ throw new Error(`POK013: ${formatInvalidContextRegexMessage({ ...details, raw: regex.raw, reason })}`);
457
+ }
458
+ }
353
459
 
354
460
  // src/validation/levenshtein.ts
355
461
  function levenshtein(a, b) {
@@ -471,16 +577,20 @@ function validateAsset(asset, frontMatterKeys, filePath) {
471
577
  });
472
578
  }
473
579
  const checks = [];
474
- if (input.allow_regex) checks.push({ pattern: input.allow_regex, kind: "allow_regex" });
475
- if (input.deny_regex) checks.push({ pattern: input.deny_regex, kind: "deny_regex" });
580
+ if (input.allow_regex) checks.push({ regex: input.allow_regex, kind: "allow_regex" });
581
+ if (input.deny_regex) checks.push({ regex: input.deny_regex, kind: "deny_regex" });
476
582
  for (const check of checks) {
477
583
  try {
478
- new RegExp(check.pattern);
584
+ compileContextRegex(check.regex, {
585
+ promptId: asset.id,
586
+ variable: input.name,
587
+ field: check.kind
588
+ });
479
589
  } catch (error) {
480
- const reason = error instanceof Error ? error.message : String(error);
590
+ const reason = error instanceof Error ? error.message.replace(/^POK013:\s*/, "") : String(error);
481
591
  errors.push({
482
592
  code: "POK013",
483
- message: `Invalid context ${check.kind} for "${input.name}": ${reason}`,
593
+ message: reason,
484
594
  filePath
485
595
  });
486
596
  }
@@ -523,82 +633,6 @@ function findClosestMatch(input, candidates) {
523
633
  return best;
524
634
  }
525
635
 
526
- // src/cli/commands/validate.ts
527
- var HELP = `
528
- promptopskit validate <dir>
529
-
530
- Validate all prompt .md files in a directory.
531
-
532
- Options:
533
- --strict Treat warnings as errors
534
- --help, -h Show this help
535
- `.trim();
536
- async function validate(args) {
537
- if (args.includes("--help") || args.includes("-h")) {
538
- console.log(HELP);
539
- return;
540
- }
541
- const dir = args.find((a) => !a.startsWith("--"));
542
- if (!dir) {
543
- console.error("Error: Please provide a directory to validate.");
544
- process.exit(1);
545
- }
546
- const strict = args.includes("--strict");
547
- const files = await collectPromptFiles(dir);
548
- if (files.length === 0) {
549
- console.log(`No .md prompt files found in ${dir}`);
550
- return;
551
- }
552
- let errorCount = 0;
553
- let warnCount = 0;
554
- for (const file of files) {
555
- try {
556
- const { asset, raw } = await loadPromptFile(file, { defaultsRoot: dir });
557
- const result = await validateAssetWithIncludes(asset, file, Object.keys(raw.frontMatter));
558
- if (result.errors.length > 0) {
559
- errorCount += result.errors.length;
560
- console.error(` \u2717 ${file}`);
561
- for (const err of result.errors) {
562
- console.error(` ${err.code}: ${err.message}`);
563
- }
564
- } else {
565
- console.log(` \u2713 ${file}`);
566
- }
567
- if (result.warnings.length > 0) {
568
- warnCount += result.warnings.length;
569
- for (const warn of result.warnings) {
570
- const suggestion = warn.suggestion ? ` (${warn.suggestion})` : "";
571
- console.warn(` \u26A0 ${warn.code}: ${warn.message}${suggestion}`);
572
- }
573
- }
574
- } catch (err) {
575
- errorCount++;
576
- const message = err instanceof Error ? err.message : String(err);
577
- console.error(` \u2717 ${file}`);
578
- console.error(` ${message}`);
579
- }
580
- }
581
- console.log();
582
- console.log(`Validated ${files.length} file(s): ${errorCount} error(s), ${warnCount} warning(s)`);
583
- if (errorCount > 0 || strict && warnCount > 0) {
584
- process.exit(1);
585
- }
586
- }
587
- async function collectPromptFiles(dir) {
588
- const results = [];
589
- const entries = await readdir(dir, { withFileTypes: true, recursive: true });
590
- for (const entry of entries) {
591
- if (entry.isFile() && extname(entry.name) === ".md" && !entry.name.endsWith(".test.md") && entry.name !== "defaults.md") {
592
- results.push(join2(entry.parentPath ?? dir, entry.name));
593
- }
594
- }
595
- return results.sort();
596
- }
597
-
598
- // src/cli/commands/compile.ts
599
- import { readdir as readdir2, writeFile, mkdir, rm } from "fs/promises";
600
- import { join as join3, extname as extname2, relative, dirname as dirname3 } from "path";
601
-
602
636
  // src/prompt-resolution.ts
603
637
  import { readFile as readFile3 } from "fs/promises";
604
638
  import { existsSync, statSync as statSync2 } from "fs";
@@ -690,7 +724,103 @@ function defaultCompiledDirForFormat(format) {
690
724
  }
691
725
  var sharedPromptCache = new PromptCache();
692
726
 
727
+ // src/cli/commands/validate.ts
728
+ var HELP = `
729
+ promptopskit validate [sourceDir] [options]
730
+
731
+ Validate all prompt .md files in a directory.
732
+
733
+ Options:
734
+ --source, -s Source directory (default: ./prompts)
735
+ --strict Treat warnings as errors
736
+ --help, -h Show this help
737
+ `.trim();
738
+ async function validate(args) {
739
+ if (args.includes("--help") || args.includes("-h")) {
740
+ console.log(HELP);
741
+ return;
742
+ }
743
+ const positional = getPositionalArgs(args, /* @__PURE__ */ new Set(["--source", "-s"]));
744
+ const dir = getFlag(args, "--source", "-s") ?? positional[0] ?? DEFAULT_PROMPTS_DIR;
745
+ const strict = args.includes("--strict");
746
+ const files = await collectPromptFiles(dir);
747
+ if (files.length === 0) {
748
+ console.log(`No .md prompt files found in ${dir}`);
749
+ return;
750
+ }
751
+ let errorCount = 0;
752
+ let warnCount = 0;
753
+ for (const file of files) {
754
+ try {
755
+ const { asset, raw } = await loadPromptFile(file, { defaultsRoot: dir });
756
+ const result = await validateAssetWithIncludes(asset, file, Object.keys(raw.frontMatter));
757
+ if (result.errors.length > 0) {
758
+ errorCount += result.errors.length;
759
+ console.error(` \u2717 ${file}`);
760
+ for (const err of result.errors) {
761
+ console.error(` ${err.code}: ${err.message}`);
762
+ }
763
+ } else {
764
+ console.log(` \u2713 ${file}`);
765
+ }
766
+ if (result.warnings.length > 0) {
767
+ warnCount += result.warnings.length;
768
+ for (const warn of result.warnings) {
769
+ const suggestion = warn.suggestion ? ` (${warn.suggestion})` : "";
770
+ console.warn(` \u26A0 ${warn.code}: ${warn.message}${suggestion}`);
771
+ }
772
+ }
773
+ } catch (err) {
774
+ errorCount++;
775
+ const message = err instanceof Error ? err.message : String(err);
776
+ console.error(` \u2717 ${file}`);
777
+ console.error(` ${message}`);
778
+ }
779
+ }
780
+ console.log();
781
+ console.log(`Validated ${files.length} file(s): ${errorCount} error(s), ${warnCount} warning(s)`);
782
+ if (errorCount > 0 || strict && warnCount > 0) {
783
+ process.exit(1);
784
+ }
785
+ }
786
+ function getPositionalArgs(args, flagsWithValues) {
787
+ const positional = [];
788
+ for (let index = 0; index < args.length; index++) {
789
+ const arg = args[index];
790
+ if (flagsWithValues.has(arg)) {
791
+ index += 1;
792
+ continue;
793
+ }
794
+ if (arg.startsWith("-")) {
795
+ continue;
796
+ }
797
+ positional.push(arg);
798
+ }
799
+ return positional;
800
+ }
801
+ function getFlag(args, ...flags) {
802
+ for (const flag of flags) {
803
+ const index = args.indexOf(flag);
804
+ if (index >= 0 && index + 1 < args.length) {
805
+ return args[index + 1];
806
+ }
807
+ }
808
+ return void 0;
809
+ }
810
+ async function collectPromptFiles(dir) {
811
+ const results = [];
812
+ const entries = await readdir(dir, { withFileTypes: true, recursive: true });
813
+ for (const entry of entries) {
814
+ if (entry.isFile() && extname(entry.name) === ".md" && !entry.name.endsWith(".test.md") && entry.name !== "defaults.md") {
815
+ results.push(join2(entry.parentPath ?? dir, entry.name));
816
+ }
817
+ }
818
+ return results.sort();
819
+ }
820
+
693
821
  // src/cli/commands/compile.ts
822
+ import { readdir as readdir2, writeFile, mkdir, rm } from "fs/promises";
823
+ import { join as join3, extname as extname2, relative, dirname as dirname3 } from "path";
694
824
  var HELP2 = `
695
825
  promptopskit compile [sourceDir] [outputDir] [options]
696
826
 
@@ -709,16 +839,16 @@ async function compile(args) {
709
839
  console.log(HELP2);
710
840
  return;
711
841
  }
712
- const positional = getPositionalArgs(args, /* @__PURE__ */ new Set(["--format", "--source", "--output", "-s", "-o"]));
842
+ const positional = getPositionalArgs2(args, /* @__PURE__ */ new Set(["--format", "--source", "--output", "-s", "-o"]));
713
843
  const dryRun = args.includes("--dry-run");
714
844
  const noClean = args.includes("--no-clean");
715
- const format = getFlag(args, "--format") ?? "json";
845
+ const format = getFlag2(args, "--format") ?? "json";
716
846
  if (format !== "json" && format !== "esm") {
717
847
  console.error(`Error: Unknown format "${format}". Use "json" or "esm".`);
718
848
  process.exit(1);
719
849
  }
720
- const sourceDir = getFlag(args, "--source", "-s") ?? positional[0] ?? DEFAULT_PROMPTS_DIR;
721
- const outputDir = getFlag(args, "--output", "-o") ?? positional[1] ?? defaultCompiledDirForFormat(format);
850
+ const sourceDir = getFlag2(args, "--source", "-s") ?? positional[0] ?? DEFAULT_PROMPTS_DIR;
851
+ const outputDir = getFlag2(args, "--output", "-o") ?? positional[1] ?? defaultCompiledDirForFormat(format);
722
852
  const files = await collectPromptFiles2(sourceDir);
723
853
  if (files.length === 0) {
724
854
  console.log(`No .md prompt files found in ${sourceDir}`);
@@ -734,7 +864,11 @@ async function compile(args) {
734
864
  const outExt = format === "esm" ? ".mjs" : ".json";
735
865
  const outPath = join3(outputDir, rel + outExt);
736
866
  try {
737
- const { asset: parsed } = await loadPromptFile(file, { defaultsRoot: sourceDir });
867
+ const { asset: parsed, raw } = await loadPromptFile(file, { defaultsRoot: sourceDir });
868
+ const validation = await validateAssetWithIncludes(parsed, file, Object.keys(raw.frontMatter));
869
+ if (validation.errors.length > 0) {
870
+ throw new Error(validation.errors.map((error) => `${error.code}: ${error.message}`).join("\n "));
871
+ }
738
872
  const asset = parsed.includes && parsed.includes.length > 0 ? await resolveIncludes(parsed, file) : parsed;
739
873
  if (dryRun) {
740
874
  console.log(` Would create: ${outPath}`);
@@ -767,7 +901,7 @@ async function compile(args) {
767
901
  process.exit(1);
768
902
  }
769
903
  }
770
- function getPositionalArgs(args, flagsWithValues) {
904
+ function getPositionalArgs2(args, flagsWithValues) {
771
905
  const positional = [];
772
906
  for (let index = 0; index < args.length; index++) {
773
907
  const arg = args[index];
@@ -782,7 +916,7 @@ function getPositionalArgs(args, flagsWithValues) {
782
916
  }
783
917
  return positional;
784
918
  }
785
- function getFlag(args, ...flags) {
919
+ function getFlag2(args, ...flags) {
786
920
  for (const flag of flags) {
787
921
  const idx = args.indexOf(flag);
788
922
  if (idx >= 0 && idx + 1 < args.length) {
@@ -846,14 +980,15 @@ async function render(args) {
846
980
  console.log(HELP3);
847
981
  return;
848
982
  }
849
- const file = args.find((a) => !a.startsWith("--"));
983
+ const positional = getPositionalArgs3(args, /* @__PURE__ */ new Set(["--env", "--tier", "--vars"]));
984
+ const file = positional[0];
850
985
  if (!file) {
851
986
  console.error("Error: Please provide a prompt file to render.");
852
987
  process.exit(1);
853
988
  }
854
- const env = getFlag2(args, "--env");
855
- const tier = getFlag2(args, "--tier");
856
- const varsFile = getFlag2(args, "--vars");
989
+ const env = getFlag3(args, "--env");
990
+ const tier = getFlag3(args, "--tier");
991
+ const varsFile = getFlag3(args, "--vars");
857
992
  const jsonOutput = args.includes("--json");
858
993
  let variables = {};
859
994
  if (varsFile) {
@@ -912,7 +1047,22 @@ ${sidecarContent}---
912
1047
  console.log(`Model: ${overridden.model ?? "not set"}`);
913
1048
  console.log("\u2500".repeat(60));
914
1049
  }
915
- function getFlag2(args, flag) {
1050
+ function getPositionalArgs3(args, flagsWithValues) {
1051
+ const positional = [];
1052
+ for (let index = 0; index < args.length; index++) {
1053
+ const arg = args[index];
1054
+ if (flagsWithValues.has(arg)) {
1055
+ index += 1;
1056
+ continue;
1057
+ }
1058
+ if (arg.startsWith("-")) {
1059
+ continue;
1060
+ }
1061
+ positional.push(arg);
1062
+ }
1063
+ return positional;
1064
+ }
1065
+ function getFlag3(args, flag) {
916
1066
  const idx = args.indexOf(flag);
917
1067
  if (idx >= 0 && idx + 1 < args.length) {
918
1068
  return args[idx + 1];
@@ -1277,8 +1427,9 @@ Usage:
1277
1427
 
1278
1428
  Commands:
1279
1429
  init [dir] Scaffold a prompts directory with starter files
1280
- validate <dir> Validate prompt files
1281
- compile [src] [out] [options] Compile .md prompts to JSON/ESM artifacts
1430
+ validate [sourceDir] [options] Validate prompt files
1431
+ compile [sourceDir] [outputDir] [options]
1432
+ Compile .md prompts to JSON/ESM artifacts
1282
1433
  render <file> [options] Render a prompt preview
1283
1434
  inspect <file> Print normalized prompt asset
1284
1435
  skill [options] Deploy AI agent instructions into your project
@@ -1297,7 +1448,8 @@ async function main() {
1297
1448
  process.exit(0);
1298
1449
  }
1299
1450
  if (command === "--version" || command === "-v") {
1300
- console.log("0.0.1");
1451
+ const pkg = JSON.parse(readFileSync2(new URL("../../package.json", import.meta.url), "utf-8"));
1452
+ console.log(pkg.version);
1301
1453
  process.exit(0);
1302
1454
  }
1303
1455
  const commandArgs = args.slice(1);