promptopskit 0.3.6 → 0.3.7

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 +11 -5
  2. package/SKILL.md +5 -1
  3. package/dist/{chunk-J32I6DSG.js → chunk-5TLHYSP7.js} +2 -2
  4. package/dist/{chunk-SHYKSLVR.js → chunk-6XKV4YVK.js} +116 -6
  5. package/dist/chunk-6XKV4YVK.js.map +1 -0
  6. package/dist/{chunk-SOY2CEJM.js → chunk-DGLLQ3FR.js} +3 -3
  7. package/dist/{chunk-6FLNJVE7.js → chunk-IXPIBZXT.js} +12 -3
  8. package/dist/{chunk-6FLNJVE7.js.map → chunk-IXPIBZXT.js.map} +1 -1
  9. package/dist/{chunk-MYXDJMWV.js → chunk-KFSP5KN4.js} +2 -2
  10. package/dist/{chunk-MN3RQ7DZ.js → chunk-QPOHKVY5.js} +2 -2
  11. package/dist/cli/index.js +233 -100
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/index.cjs +133 -11
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +4 -4
  16. package/dist/index.d.ts +4 -4
  17. package/dist/index.js +16 -11
  18. package/dist/index.js.map +1 -1
  19. package/dist/providers/anthropic.cjs +124 -6
  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 +124 -6
  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 +124 -6
  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 +124 -6
  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-Bgoff-CN.d.cts} +124 -56
  40. package/dist/{schema-D145q3Dw.d.ts → schema-Bgoff-CN.d.ts} +124 -56
  41. package/dist/testing.cjs +11 -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-7U58bgVW.d.cts} +1 -1
  47. package/dist/{types-CXlVWckk.d.ts → types-HnZ46u5Q.d.ts} +1 -1
  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-J32I6DSG.js.map → chunk-5TLHYSP7.js.map} +0 -0
  53. /package/dist/{chunk-SOY2CEJM.js.map → chunk-DGLLQ3FR.js.map} +0 -0
  54. /package/dist/{chunk-MYXDJMWV.js.map → chunk-KFSP5KN4.js.map} +0 -0
  55. /package/dist/{chunk-MN3RQ7DZ.js.map → chunk-QPOHKVY5.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,21 @@ 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
+ })
53
+ ]);
44
54
  var ContextInputDefinitionObjectSchema = z.object({
45
55
  name: z.string(),
46
56
  max_size: z.number().int().positive().optional(),
47
57
  trim: z.union([z.boolean(), z.enum(["start", "end", "both"])]).optional(),
48
- allow_regex: z.string().optional(),
49
- deny_regex: z.string().optional()
58
+ allow_regex: ContextRegexSchema.optional(),
59
+ deny_regex: ContextRegexSchema.optional(),
60
+ non_empty: z.boolean().optional(),
61
+ reject_secrets: z.boolean().optional()
50
62
  });
51
63
  var ContextInputDefinitionSchema = z.union([
52
64
  z.string(),
@@ -346,10 +358,85 @@ function normalizeContextInput(input) {
346
358
  name: input.name,
347
359
  max_size: input.max_size,
348
360
  trim: input.trim,
349
- allow_regex: input.allow_regex,
350
- deny_regex: input.deny_regex
361
+ allow_regex: normalizeContextRegex(input.allow_regex),
362
+ deny_regex: normalizeContextRegex(input.deny_regex),
363
+ non_empty: input.non_empty,
364
+ reject_secrets: input.reject_secrets
351
365
  };
352
366
  }
367
+ function normalizeContextRegex(value) {
368
+ if (value === void 0) {
369
+ return void 0;
370
+ }
371
+ if (typeof value === "string") {
372
+ const literal = parseRegexLiteral(value);
373
+ if (value.startsWith("/") && !literal) {
374
+ return {
375
+ pattern: value,
376
+ flags: "",
377
+ raw: value,
378
+ invalidLiteral: true
379
+ };
380
+ }
381
+ return {
382
+ pattern: literal?.pattern ?? value,
383
+ flags: literal?.flags ?? "",
384
+ raw: value
385
+ };
386
+ }
387
+ return {
388
+ pattern: value.pattern,
389
+ flags: value.flags ?? "",
390
+ raw: JSON.stringify(value)
391
+ };
392
+ }
393
+ function parseRegexLiteral(value) {
394
+ if (!value.startsWith("/")) {
395
+ return void 0;
396
+ }
397
+ for (let index = value.length - 1; index > 0; index -= 1) {
398
+ if (value[index] !== "/") {
399
+ continue;
400
+ }
401
+ let backslashCount = 0;
402
+ for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
403
+ backslashCount += 1;
404
+ }
405
+ if (backslashCount % 2 === 1) {
406
+ continue;
407
+ }
408
+ return {
409
+ pattern: value.slice(1, index),
410
+ flags: value.slice(index + 1)
411
+ };
412
+ }
413
+ return void 0;
414
+ }
415
+ function formatInvalidContextRegexMessage(details) {
416
+ return [
417
+ `Invalid context regex for prompt "${details.promptId}"`,
418
+ `variable "${details.variable}"`,
419
+ `field "${details.field}"`,
420
+ `value ${JSON.stringify(details.raw)}: ${details.reason}`
421
+ ].join(", ");
422
+ }
423
+ function compileContextRegex(regex, details) {
424
+ if (regex.invalidLiteral) {
425
+ throw new Error(
426
+ `POK013: ${formatInvalidContextRegexMessage({
427
+ ...details,
428
+ raw: regex.raw,
429
+ reason: "Malformed regex literal. Use /pattern/flags or { pattern, flags }."
430
+ })}`
431
+ );
432
+ }
433
+ try {
434
+ return new RegExp(regex.pattern, regex.flags);
435
+ } catch (error) {
436
+ const reason = error instanceof Error ? error.message : String(error);
437
+ throw new Error(`POK013: ${formatInvalidContextRegexMessage({ ...details, raw: regex.raw, reason })}`);
438
+ }
439
+ }
353
440
 
354
441
  // src/validation/levenshtein.ts
355
442
  function levenshtein(a, b) {
@@ -471,16 +558,20 @@ function validateAsset(asset, frontMatterKeys, filePath) {
471
558
  });
472
559
  }
473
560
  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" });
561
+ if (input.allow_regex) checks.push({ regex: input.allow_regex, kind: "allow_regex" });
562
+ if (input.deny_regex) checks.push({ regex: input.deny_regex, kind: "deny_regex" });
476
563
  for (const check of checks) {
477
564
  try {
478
- new RegExp(check.pattern);
565
+ compileContextRegex(check.regex, {
566
+ promptId: asset.id,
567
+ variable: input.name,
568
+ field: check.kind
569
+ });
479
570
  } catch (error) {
480
- const reason = error instanceof Error ? error.message : String(error);
571
+ const reason = error instanceof Error ? error.message.replace(/^POK013:\s*/, "") : String(error);
481
572
  errors.push({
482
573
  code: "POK013",
483
- message: `Invalid context ${check.kind} for "${input.name}": ${reason}`,
574
+ message: reason,
484
575
  filePath
485
576
  });
486
577
  }
@@ -523,82 +614,6 @@ function findClosestMatch(input, candidates) {
523
614
  return best;
524
615
  }
525
616
 
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
617
  // src/prompt-resolution.ts
603
618
  import { readFile as readFile3 } from "fs/promises";
604
619
  import { existsSync, statSync as statSync2 } from "fs";
@@ -690,7 +705,103 @@ function defaultCompiledDirForFormat(format) {
690
705
  }
691
706
  var sharedPromptCache = new PromptCache();
692
707
 
708
+ // src/cli/commands/validate.ts
709
+ var HELP = `
710
+ promptopskit validate [sourceDir] [options]
711
+
712
+ Validate all prompt .md files in a directory.
713
+
714
+ Options:
715
+ --source, -s Source directory (default: ./prompts)
716
+ --strict Treat warnings as errors
717
+ --help, -h Show this help
718
+ `.trim();
719
+ async function validate(args) {
720
+ if (args.includes("--help") || args.includes("-h")) {
721
+ console.log(HELP);
722
+ return;
723
+ }
724
+ const positional = getPositionalArgs(args, /* @__PURE__ */ new Set(["--source", "-s"]));
725
+ const dir = getFlag(args, "--source", "-s") ?? positional[0] ?? DEFAULT_PROMPTS_DIR;
726
+ const strict = args.includes("--strict");
727
+ const files = await collectPromptFiles(dir);
728
+ if (files.length === 0) {
729
+ console.log(`No .md prompt files found in ${dir}`);
730
+ return;
731
+ }
732
+ let errorCount = 0;
733
+ let warnCount = 0;
734
+ for (const file of files) {
735
+ try {
736
+ const { asset, raw } = await loadPromptFile(file, { defaultsRoot: dir });
737
+ const result = await validateAssetWithIncludes(asset, file, Object.keys(raw.frontMatter));
738
+ if (result.errors.length > 0) {
739
+ errorCount += result.errors.length;
740
+ console.error(` \u2717 ${file}`);
741
+ for (const err of result.errors) {
742
+ console.error(` ${err.code}: ${err.message}`);
743
+ }
744
+ } else {
745
+ console.log(` \u2713 ${file}`);
746
+ }
747
+ if (result.warnings.length > 0) {
748
+ warnCount += result.warnings.length;
749
+ for (const warn of result.warnings) {
750
+ const suggestion = warn.suggestion ? ` (${warn.suggestion})` : "";
751
+ console.warn(` \u26A0 ${warn.code}: ${warn.message}${suggestion}`);
752
+ }
753
+ }
754
+ } catch (err) {
755
+ errorCount++;
756
+ const message = err instanceof Error ? err.message : String(err);
757
+ console.error(` \u2717 ${file}`);
758
+ console.error(` ${message}`);
759
+ }
760
+ }
761
+ console.log();
762
+ console.log(`Validated ${files.length} file(s): ${errorCount} error(s), ${warnCount} warning(s)`);
763
+ if (errorCount > 0 || strict && warnCount > 0) {
764
+ process.exit(1);
765
+ }
766
+ }
767
+ function getPositionalArgs(args, flagsWithValues) {
768
+ const positional = [];
769
+ for (let index = 0; index < args.length; index++) {
770
+ const arg = args[index];
771
+ if (flagsWithValues.has(arg)) {
772
+ index += 1;
773
+ continue;
774
+ }
775
+ if (arg.startsWith("-")) {
776
+ continue;
777
+ }
778
+ positional.push(arg);
779
+ }
780
+ return positional;
781
+ }
782
+ function getFlag(args, ...flags) {
783
+ for (const flag of flags) {
784
+ const index = args.indexOf(flag);
785
+ if (index >= 0 && index + 1 < args.length) {
786
+ return args[index + 1];
787
+ }
788
+ }
789
+ return void 0;
790
+ }
791
+ async function collectPromptFiles(dir) {
792
+ const results = [];
793
+ const entries = await readdir(dir, { withFileTypes: true, recursive: true });
794
+ for (const entry of entries) {
795
+ if (entry.isFile() && extname(entry.name) === ".md" && !entry.name.endsWith(".test.md") && entry.name !== "defaults.md") {
796
+ results.push(join2(entry.parentPath ?? dir, entry.name));
797
+ }
798
+ }
799
+ return results.sort();
800
+ }
801
+
693
802
  // src/cli/commands/compile.ts
803
+ import { readdir as readdir2, writeFile, mkdir, rm } from "fs/promises";
804
+ import { join as join3, extname as extname2, relative, dirname as dirname3 } from "path";
694
805
  var HELP2 = `
695
806
  promptopskit compile [sourceDir] [outputDir] [options]
696
807
 
@@ -709,16 +820,16 @@ async function compile(args) {
709
820
  console.log(HELP2);
710
821
  return;
711
822
  }
712
- const positional = getPositionalArgs(args, /* @__PURE__ */ new Set(["--format", "--source", "--output", "-s", "-o"]));
823
+ const positional = getPositionalArgs2(args, /* @__PURE__ */ new Set(["--format", "--source", "--output", "-s", "-o"]));
713
824
  const dryRun = args.includes("--dry-run");
714
825
  const noClean = args.includes("--no-clean");
715
- const format = getFlag(args, "--format") ?? "json";
826
+ const format = getFlag2(args, "--format") ?? "json";
716
827
  if (format !== "json" && format !== "esm") {
717
828
  console.error(`Error: Unknown format "${format}". Use "json" or "esm".`);
718
829
  process.exit(1);
719
830
  }
720
- const sourceDir = getFlag(args, "--source", "-s") ?? positional[0] ?? DEFAULT_PROMPTS_DIR;
721
- const outputDir = getFlag(args, "--output", "-o") ?? positional[1] ?? defaultCompiledDirForFormat(format);
831
+ const sourceDir = getFlag2(args, "--source", "-s") ?? positional[0] ?? DEFAULT_PROMPTS_DIR;
832
+ const outputDir = getFlag2(args, "--output", "-o") ?? positional[1] ?? defaultCompiledDirForFormat(format);
722
833
  const files = await collectPromptFiles2(sourceDir);
723
834
  if (files.length === 0) {
724
835
  console.log(`No .md prompt files found in ${sourceDir}`);
@@ -734,7 +845,11 @@ async function compile(args) {
734
845
  const outExt = format === "esm" ? ".mjs" : ".json";
735
846
  const outPath = join3(outputDir, rel + outExt);
736
847
  try {
737
- const { asset: parsed } = await loadPromptFile(file, { defaultsRoot: sourceDir });
848
+ const { asset: parsed, raw } = await loadPromptFile(file, { defaultsRoot: sourceDir });
849
+ const validation = await validateAssetWithIncludes(parsed, file, Object.keys(raw.frontMatter));
850
+ if (validation.errors.length > 0) {
851
+ throw new Error(validation.errors.map((error) => `${error.code}: ${error.message}`).join("\n "));
852
+ }
738
853
  const asset = parsed.includes && parsed.includes.length > 0 ? await resolveIncludes(parsed, file) : parsed;
739
854
  if (dryRun) {
740
855
  console.log(` Would create: ${outPath}`);
@@ -767,7 +882,7 @@ async function compile(args) {
767
882
  process.exit(1);
768
883
  }
769
884
  }
770
- function getPositionalArgs(args, flagsWithValues) {
885
+ function getPositionalArgs2(args, flagsWithValues) {
771
886
  const positional = [];
772
887
  for (let index = 0; index < args.length; index++) {
773
888
  const arg = args[index];
@@ -782,7 +897,7 @@ function getPositionalArgs(args, flagsWithValues) {
782
897
  }
783
898
  return positional;
784
899
  }
785
- function getFlag(args, ...flags) {
900
+ function getFlag2(args, ...flags) {
786
901
  for (const flag of flags) {
787
902
  const idx = args.indexOf(flag);
788
903
  if (idx >= 0 && idx + 1 < args.length) {
@@ -846,14 +961,15 @@ async function render(args) {
846
961
  console.log(HELP3);
847
962
  return;
848
963
  }
849
- const file = args.find((a) => !a.startsWith("--"));
964
+ const positional = getPositionalArgs3(args, /* @__PURE__ */ new Set(["--env", "--tier", "--vars"]));
965
+ const file = positional[0];
850
966
  if (!file) {
851
967
  console.error("Error: Please provide a prompt file to render.");
852
968
  process.exit(1);
853
969
  }
854
- const env = getFlag2(args, "--env");
855
- const tier = getFlag2(args, "--tier");
856
- const varsFile = getFlag2(args, "--vars");
970
+ const env = getFlag3(args, "--env");
971
+ const tier = getFlag3(args, "--tier");
972
+ const varsFile = getFlag3(args, "--vars");
857
973
  const jsonOutput = args.includes("--json");
858
974
  let variables = {};
859
975
  if (varsFile) {
@@ -912,7 +1028,22 @@ ${sidecarContent}---
912
1028
  console.log(`Model: ${overridden.model ?? "not set"}`);
913
1029
  console.log("\u2500".repeat(60));
914
1030
  }
915
- function getFlag2(args, flag) {
1031
+ function getPositionalArgs3(args, flagsWithValues) {
1032
+ const positional = [];
1033
+ for (let index = 0; index < args.length; index++) {
1034
+ const arg = args[index];
1035
+ if (flagsWithValues.has(arg)) {
1036
+ index += 1;
1037
+ continue;
1038
+ }
1039
+ if (arg.startsWith("-")) {
1040
+ continue;
1041
+ }
1042
+ positional.push(arg);
1043
+ }
1044
+ return positional;
1045
+ }
1046
+ function getFlag3(args, flag) {
916
1047
  const idx = args.indexOf(flag);
917
1048
  if (idx >= 0 && idx + 1 < args.length) {
918
1049
  return args[idx + 1];
@@ -1277,8 +1408,9 @@ Usage:
1277
1408
 
1278
1409
  Commands:
1279
1410
  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
1411
+ validate [sourceDir] [options] Validate prompt files
1412
+ compile [sourceDir] [outputDir] [options]
1413
+ Compile .md prompts to JSON/ESM artifacts
1282
1414
  render <file> [options] Render a prompt preview
1283
1415
  inspect <file> Print normalized prompt asset
1284
1416
  skill [options] Deploy AI agent instructions into your project
@@ -1297,7 +1429,8 @@ async function main() {
1297
1429
  process.exit(0);
1298
1430
  }
1299
1431
  if (command === "--version" || command === "-v") {
1300
- console.log("0.0.1");
1432
+ const pkg = JSON.parse(readFileSync2(new URL("../../package.json", import.meta.url), "utf-8"));
1433
+ console.log(pkg.version);
1301
1434
  process.exit(0);
1302
1435
  }
1303
1436
  const commandArgs = args.slice(1);