promptopskit 0.3.5 → 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 (56) hide show
  1. package/README.md +12 -5
  2. package/SKILL.md +8 -1
  3. package/dist/{chunk-7RWTFGMS.js → chunk-5TLHYSP7.js} +2 -2
  4. package/dist/{chunk-M5VKRDIY.js → chunk-6XKV4YVK.js} +256 -3
  5. package/dist/chunk-6XKV4YVK.js.map +1 -0
  6. package/dist/{chunk-ROBYCHAW.js → chunk-DGLLQ3FR.js} +3 -3
  7. package/dist/{chunk-2LK6IILW.js → chunk-IXPIBZXT.js} +14 -2
  8. package/dist/chunk-IXPIBZXT.js.map +1 -0
  9. package/dist/{chunk-4QW4BSGE.js → chunk-KFSP5KN4.js} +2 -2
  10. package/dist/{chunk-2X5HFPSD.js → chunk-QPOHKVY5.js} +2 -2
  11. package/dist/cli/index.js +256 -93
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/index.cjs +295 -46
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +7 -5
  16. package/dist/index.d.ts +7 -5
  17. package/dist/index.js +44 -50
  18. package/dist/index.js.map +1 -1
  19. package/dist/providers/anthropic.cjs +238 -2
  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 +238 -2
  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 +238 -2
  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 +238 -2
  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-Dq0jKest.d.cts → schema-Bgoff-CN.d.cts} +89 -0
  40. package/dist/{schema-Dq0jKest.d.ts → schema-Bgoff-CN.d.ts} +89 -0
  41. package/dist/testing.cjs +13 -1
  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-ClXTFaX-.d.cts → types-7U58bgVW.d.cts} +8 -1
  47. package/dist/{types-lLD7m02V.d.ts → types-HnZ46u5Q.d.ts} +8 -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-2LK6IILW.js.map +0 -1
  52. package/dist/chunk-M5VKRDIY.js.map +0 -1
  53. /package/dist/{chunk-7RWTFGMS.js.map → chunk-5TLHYSP7.js.map} +0 -0
  54. /package/dist/{chunk-ROBYCHAW.js.map → chunk-DGLLQ3FR.js.map} +0 -0
  55. /package/dist/{chunk-4QW4BSGE.js.map → chunk-KFSP5KN4.js.map} +0 -0
  56. /package/dist/{chunk-2X5HFPSD.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,9 +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
- max_size: z.number().int().positive().optional()
56
+ max_size: z.number().int().positive().optional(),
57
+ trim: z.union([z.boolean(), z.enum(["start", "end", "both"])]).optional(),
58
+ allow_regex: ContextRegexSchema.optional(),
59
+ deny_regex: ContextRegexSchema.optional(),
60
+ non_empty: z.boolean().optional(),
61
+ reject_secrets: z.boolean().optional()
47
62
  });
48
63
  var ContextInputDefinitionSchema = z.union([
49
64
  z.string(),
@@ -341,9 +356,87 @@ function normalizeContextInput(input) {
341
356
  }
342
357
  return {
343
358
  name: input.name,
344
- max_size: input.max_size
359
+ max_size: input.max_size,
360
+ trim: input.trim,
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
365
+ };
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)
345
391
  };
346
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
+ }
347
440
 
348
441
  // src/validation/levenshtein.ts
349
442
  function levenshtein(a, b) {
@@ -456,6 +549,34 @@ function validateAsset(asset, frontMatterKeys, filePath) {
456
549
  });
457
550
  }
458
551
  }
552
+ for (const input of getContextInputs(asset)) {
553
+ if (input.trim !== void 0 && input.trim !== false && input.max_size === void 0) {
554
+ warnings.push({
555
+ code: "POK014",
556
+ message: `Context input "${input.name}" sets trim but has no max_size; trim-to-budget will be skipped.`,
557
+ filePath
558
+ });
559
+ }
560
+ const checks = [];
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" });
563
+ for (const check of checks) {
564
+ try {
565
+ compileContextRegex(check.regex, {
566
+ promptId: asset.id,
567
+ variable: input.name,
568
+ field: check.kind
569
+ });
570
+ } catch (error) {
571
+ const reason = error instanceof Error ? error.message.replace(/^POK013:\s*/, "") : String(error);
572
+ errors.push({
573
+ code: "POK013",
574
+ message: reason,
575
+ filePath
576
+ });
577
+ }
578
+ }
579
+ }
459
580
  return {
460
581
  valid: errors.length === 0,
461
582
  errors,
@@ -493,82 +614,6 @@ function findClosestMatch(input, candidates) {
493
614
  return best;
494
615
  }
495
616
 
496
- // src/cli/commands/validate.ts
497
- var HELP = `
498
- promptopskit validate <dir>
499
-
500
- Validate all prompt .md files in a directory.
501
-
502
- Options:
503
- --strict Treat warnings as errors
504
- --help, -h Show this help
505
- `.trim();
506
- async function validate(args) {
507
- if (args.includes("--help") || args.includes("-h")) {
508
- console.log(HELP);
509
- return;
510
- }
511
- const dir = args.find((a) => !a.startsWith("--"));
512
- if (!dir) {
513
- console.error("Error: Please provide a directory to validate.");
514
- process.exit(1);
515
- }
516
- const strict = args.includes("--strict");
517
- const files = await collectPromptFiles(dir);
518
- if (files.length === 0) {
519
- console.log(`No .md prompt files found in ${dir}`);
520
- return;
521
- }
522
- let errorCount = 0;
523
- let warnCount = 0;
524
- for (const file of files) {
525
- try {
526
- const { asset, raw } = await loadPromptFile(file, { defaultsRoot: dir });
527
- const result = await validateAssetWithIncludes(asset, file, Object.keys(raw.frontMatter));
528
- if (result.errors.length > 0) {
529
- errorCount += result.errors.length;
530
- console.error(` \u2717 ${file}`);
531
- for (const err of result.errors) {
532
- console.error(` ${err.code}: ${err.message}`);
533
- }
534
- } else {
535
- console.log(` \u2713 ${file}`);
536
- }
537
- if (result.warnings.length > 0) {
538
- warnCount += result.warnings.length;
539
- for (const warn of result.warnings) {
540
- const suggestion = warn.suggestion ? ` (${warn.suggestion})` : "";
541
- console.warn(` \u26A0 ${warn.code}: ${warn.message}${suggestion}`);
542
- }
543
- }
544
- } catch (err) {
545
- errorCount++;
546
- const message = err instanceof Error ? err.message : String(err);
547
- console.error(` \u2717 ${file}`);
548
- console.error(` ${message}`);
549
- }
550
- }
551
- console.log();
552
- console.log(`Validated ${files.length} file(s): ${errorCount} error(s), ${warnCount} warning(s)`);
553
- if (errorCount > 0 || strict && warnCount > 0) {
554
- process.exit(1);
555
- }
556
- }
557
- async function collectPromptFiles(dir) {
558
- const results = [];
559
- const entries = await readdir(dir, { withFileTypes: true, recursive: true });
560
- for (const entry of entries) {
561
- if (entry.isFile() && extname(entry.name) === ".md" && !entry.name.endsWith(".test.md") && entry.name !== "defaults.md") {
562
- results.push(join2(entry.parentPath ?? dir, entry.name));
563
- }
564
- }
565
- return results.sort();
566
- }
567
-
568
- // src/cli/commands/compile.ts
569
- import { readdir as readdir2, writeFile, mkdir, rm } from "fs/promises";
570
- import { join as join3, extname as extname2, relative, dirname as dirname3 } from "path";
571
-
572
617
  // src/prompt-resolution.ts
573
618
  import { readFile as readFile3 } from "fs/promises";
574
619
  import { existsSync, statSync as statSync2 } from "fs";
@@ -660,7 +705,103 @@ function defaultCompiledDirForFormat(format) {
660
705
  }
661
706
  var sharedPromptCache = new PromptCache();
662
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
+
663
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";
664
805
  var HELP2 = `
665
806
  promptopskit compile [sourceDir] [outputDir] [options]
666
807
 
@@ -679,16 +820,16 @@ async function compile(args) {
679
820
  console.log(HELP2);
680
821
  return;
681
822
  }
682
- 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"]));
683
824
  const dryRun = args.includes("--dry-run");
684
825
  const noClean = args.includes("--no-clean");
685
- const format = getFlag(args, "--format") ?? "json";
826
+ const format = getFlag2(args, "--format") ?? "json";
686
827
  if (format !== "json" && format !== "esm") {
687
828
  console.error(`Error: Unknown format "${format}". Use "json" or "esm".`);
688
829
  process.exit(1);
689
830
  }
690
- const sourceDir = getFlag(args, "--source", "-s") ?? positional[0] ?? DEFAULT_PROMPTS_DIR;
691
- 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);
692
833
  const files = await collectPromptFiles2(sourceDir);
693
834
  if (files.length === 0) {
694
835
  console.log(`No .md prompt files found in ${sourceDir}`);
@@ -704,7 +845,11 @@ async function compile(args) {
704
845
  const outExt = format === "esm" ? ".mjs" : ".json";
705
846
  const outPath = join3(outputDir, rel + outExt);
706
847
  try {
707
- 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
+ }
708
853
  const asset = parsed.includes && parsed.includes.length > 0 ? await resolveIncludes(parsed, file) : parsed;
709
854
  if (dryRun) {
710
855
  console.log(` Would create: ${outPath}`);
@@ -737,7 +882,7 @@ async function compile(args) {
737
882
  process.exit(1);
738
883
  }
739
884
  }
740
- function getPositionalArgs(args, flagsWithValues) {
885
+ function getPositionalArgs2(args, flagsWithValues) {
741
886
  const positional = [];
742
887
  for (let index = 0; index < args.length; index++) {
743
888
  const arg = args[index];
@@ -752,7 +897,7 @@ function getPositionalArgs(args, flagsWithValues) {
752
897
  }
753
898
  return positional;
754
899
  }
755
- function getFlag(args, ...flags) {
900
+ function getFlag2(args, ...flags) {
756
901
  for (const flag of flags) {
757
902
  const idx = args.indexOf(flag);
758
903
  if (idx >= 0 && idx + 1 < args.length) {
@@ -816,14 +961,15 @@ async function render(args) {
816
961
  console.log(HELP3);
817
962
  return;
818
963
  }
819
- const file = args.find((a) => !a.startsWith("--"));
964
+ const positional = getPositionalArgs3(args, /* @__PURE__ */ new Set(["--env", "--tier", "--vars"]));
965
+ const file = positional[0];
820
966
  if (!file) {
821
967
  console.error("Error: Please provide a prompt file to render.");
822
968
  process.exit(1);
823
969
  }
824
- const env = getFlag2(args, "--env");
825
- const tier = getFlag2(args, "--tier");
826
- const varsFile = getFlag2(args, "--vars");
970
+ const env = getFlag3(args, "--env");
971
+ const tier = getFlag3(args, "--tier");
972
+ const varsFile = getFlag3(args, "--vars");
827
973
  const jsonOutput = args.includes("--json");
828
974
  let variables = {};
829
975
  if (varsFile) {
@@ -882,7 +1028,22 @@ ${sidecarContent}---
882
1028
  console.log(`Model: ${overridden.model ?? "not set"}`);
883
1029
  console.log("\u2500".repeat(60));
884
1030
  }
885
- 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) {
886
1047
  const idx = args.indexOf(flag);
887
1048
  if (idx >= 0 && idx + 1 < args.length) {
888
1049
  return args[idx + 1];
@@ -1247,8 +1408,9 @@ Usage:
1247
1408
 
1248
1409
  Commands:
1249
1410
  init [dir] Scaffold a prompts directory with starter files
1250
- validate <dir> Validate prompt files
1251
- 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
1252
1414
  render <file> [options] Render a prompt preview
1253
1415
  inspect <file> Print normalized prompt asset
1254
1416
  skill [options] Deploy AI agent instructions into your project
@@ -1267,7 +1429,8 @@ async function main() {
1267
1429
  process.exit(0);
1268
1430
  }
1269
1431
  if (command === "--version" || command === "-v") {
1270
- 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);
1271
1434
  process.exit(0);
1272
1435
  }
1273
1436
  const commandArgs = args.slice(1);