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/index.cjs CHANGED
@@ -251,12 +251,21 @@ var ResponseSchema = import_zod.z.object({
251
251
  var HistorySchema = import_zod.z.object({
252
252
  max_items: import_zod.z.number().int().positive().optional()
253
253
  });
254
+ var ContextRegexSchema = import_zod.z.union([
255
+ import_zod.z.string(),
256
+ import_zod.z.object({
257
+ pattern: import_zod.z.string(),
258
+ flags: import_zod.z.string().optional()
259
+ })
260
+ ]);
254
261
  var ContextInputDefinitionObjectSchema = import_zod.z.object({
255
262
  name: import_zod.z.string(),
256
263
  max_size: import_zod.z.number().int().positive().optional(),
257
264
  trim: import_zod.z.union([import_zod.z.boolean(), import_zod.z.enum(["start", "end", "both"])]).optional(),
258
- allow_regex: import_zod.z.string().optional(),
259
- deny_regex: import_zod.z.string().optional()
265
+ allow_regex: ContextRegexSchema.optional(),
266
+ deny_regex: ContextRegexSchema.optional(),
267
+ non_empty: import_zod.z.boolean().optional(),
268
+ reject_secrets: import_zod.z.boolean().optional()
260
269
  });
261
270
  var ContextInputDefinitionSchema = import_zod.z.union([
262
271
  import_zod.z.string(),
@@ -601,6 +610,8 @@ function resolveInlinePromptSource(source, options = {}) {
601
610
 
602
611
  // src/context.ts
603
612
  var textEncoder = new TextEncoder();
613
+ var REJECT_SECRETS_PATTERN = "(secret|api[_-]?key|password)";
614
+ var REJECT_SECRETS_FLAGS = "i";
604
615
  function getContextInputs(asset) {
605
616
  return (asset.context?.inputs ?? []).map(normalizeContextInput);
606
617
  }
@@ -615,8 +626,90 @@ function normalizeContextInput(input) {
615
626
  name: input.name,
616
627
  max_size: input.max_size,
617
628
  trim: input.trim,
618
- allow_regex: input.allow_regex,
619
- deny_regex: input.deny_regex
629
+ allow_regex: normalizeContextRegex(input.allow_regex),
630
+ deny_regex: normalizeContextRegex(input.deny_regex),
631
+ non_empty: input.non_empty,
632
+ reject_secrets: input.reject_secrets
633
+ };
634
+ }
635
+ function normalizeContextRegex(value) {
636
+ if (value === void 0) {
637
+ return void 0;
638
+ }
639
+ if (typeof value === "string") {
640
+ const literal = parseRegexLiteral(value);
641
+ if (value.startsWith("/") && !literal) {
642
+ return {
643
+ pattern: value,
644
+ flags: "",
645
+ raw: value,
646
+ invalidLiteral: true
647
+ };
648
+ }
649
+ return {
650
+ pattern: literal?.pattern ?? value,
651
+ flags: literal?.flags ?? "",
652
+ raw: value
653
+ };
654
+ }
655
+ return {
656
+ pattern: value.pattern,
657
+ flags: value.flags ?? "",
658
+ raw: JSON.stringify(value)
659
+ };
660
+ }
661
+ function parseRegexLiteral(value) {
662
+ if (!value.startsWith("/")) {
663
+ return void 0;
664
+ }
665
+ for (let index = value.length - 1; index > 0; index -= 1) {
666
+ if (value[index] !== "/") {
667
+ continue;
668
+ }
669
+ let backslashCount = 0;
670
+ for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
671
+ backslashCount += 1;
672
+ }
673
+ if (backslashCount % 2 === 1) {
674
+ continue;
675
+ }
676
+ return {
677
+ pattern: value.slice(1, index),
678
+ flags: value.slice(index + 1)
679
+ };
680
+ }
681
+ return void 0;
682
+ }
683
+ function formatInvalidContextRegexMessage(details) {
684
+ return [
685
+ `Invalid context regex for prompt "${details.promptId}"`,
686
+ `variable "${details.variable}"`,
687
+ `field "${details.field}"`,
688
+ `value ${JSON.stringify(details.raw)}: ${details.reason}`
689
+ ].join(", ");
690
+ }
691
+ function compileContextRegex(regex, details) {
692
+ if (regex.invalidLiteral) {
693
+ throw new Error(
694
+ `POK013: ${formatInvalidContextRegexMessage({
695
+ ...details,
696
+ raw: regex.raw,
697
+ reason: "Malformed regex literal. Use /pattern/flags or { pattern, flags }."
698
+ })}`
699
+ );
700
+ }
701
+ try {
702
+ return new RegExp(regex.pattern, regex.flags);
703
+ } catch (error) {
704
+ const reason = error instanceof Error ? error.message : String(error);
705
+ throw new Error(`POK013: ${formatInvalidContextRegexMessage({ ...details, raw: regex.raw, reason })}`);
706
+ }
707
+ }
708
+ function getRejectSecretsRegex() {
709
+ return {
710
+ pattern: REJECT_SECRETS_PATTERN,
711
+ flags: REJECT_SECRETS_FLAGS,
712
+ raw: JSON.stringify({ pattern: REJECT_SECRETS_PATTERN, flags: REJECT_SECRETS_FLAGS })
620
713
  };
621
714
  }
622
715
  function isTrimEnabled(mode) {
@@ -688,7 +781,11 @@ function sanitizeContextVariables(asset, variables = {}, options = {}) {
688
781
  sanitized[input.name] = candidate;
689
782
  if (input.allow_regex) {
690
783
  const candidate2 = sanitized[input.name];
691
- const matcher = new RegExp(input.allow_regex);
784
+ const matcher = compileContextRegex(input.allow_regex, {
785
+ promptId: asset.id,
786
+ variable: input.name,
787
+ field: "allow_regex"
788
+ });
692
789
  if (!matcher.test(candidate2)) {
693
790
  throw new Error(
694
791
  `POK031: Context variable "${input.name}" failed allow_regex validation for prompt "${asset.id}".`
@@ -697,13 +794,34 @@ function sanitizeContextVariables(asset, variables = {}, options = {}) {
697
794
  }
698
795
  if (input.deny_regex) {
699
796
  const candidate2 = sanitized[input.name];
700
- const matcher = new RegExp(input.deny_regex);
797
+ const matcher = compileContextRegex(input.deny_regex, {
798
+ promptId: asset.id,
799
+ variable: input.name,
800
+ field: "deny_regex"
801
+ });
701
802
  if (matcher.test(candidate2)) {
702
803
  throw new Error(
703
804
  `POK032: Context variable "${input.name}" matched deny_regex for prompt "${asset.id}".`
704
805
  );
705
806
  }
706
807
  }
808
+ if (input.non_empty && candidate.trim().length === 0) {
809
+ throw new Error(
810
+ `POK033: Context variable "${input.name}" failed non_empty validation for prompt "${asset.id}".`
811
+ );
812
+ }
813
+ if (input.reject_secrets) {
814
+ const matcher = compileContextRegex(getRejectSecretsRegex(), {
815
+ promptId: asset.id,
816
+ variable: input.name,
817
+ field: "reject_secrets"
818
+ });
819
+ if (matcher.test(candidate)) {
820
+ throw new Error(
821
+ `POK034: Context variable "${input.name}" matched reject_secrets validation for prompt "${asset.id}".`
822
+ );
823
+ }
824
+ }
707
825
  }
708
826
  return sanitized;
709
827
  }
@@ -1168,16 +1286,20 @@ function validateAsset(asset, frontMatterKeys, filePath) {
1168
1286
  });
1169
1287
  }
1170
1288
  const checks = [];
1171
- if (input.allow_regex) checks.push({ pattern: input.allow_regex, kind: "allow_regex" });
1172
- if (input.deny_regex) checks.push({ pattern: input.deny_regex, kind: "deny_regex" });
1289
+ if (input.allow_regex) checks.push({ regex: input.allow_regex, kind: "allow_regex" });
1290
+ if (input.deny_regex) checks.push({ regex: input.deny_regex, kind: "deny_regex" });
1173
1291
  for (const check of checks) {
1174
1292
  try {
1175
- new RegExp(check.pattern);
1293
+ compileContextRegex(check.regex, {
1294
+ promptId: asset.id,
1295
+ variable: input.name,
1296
+ field: check.kind
1297
+ });
1176
1298
  } catch (error) {
1177
- const reason = error instanceof Error ? error.message : String(error);
1299
+ const reason = error instanceof Error ? error.message.replace(/^POK013:\s*/, "") : String(error);
1178
1300
  errors.push({
1179
1301
  code: "POK013",
1180
- message: `Invalid context ${check.kind} for "${input.name}": ${reason}`,
1302
+ message: reason,
1181
1303
  filePath
1182
1304
  });
1183
1305
  }