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/index.cjs CHANGED
@@ -251,12 +251,28 @@ 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
+ return_message: import_zod.z.string().optional()
260
+ })
261
+ ]);
262
+ var ContextBuiltInValidatorSchema = import_zod.z.union([
263
+ import_zod.z.boolean(),
264
+ import_zod.z.object({
265
+ return_message: import_zod.z.string().optional()
266
+ })
267
+ ]);
254
268
  var ContextInputDefinitionObjectSchema = import_zod.z.object({
255
269
  name: import_zod.z.string(),
256
270
  max_size: import_zod.z.number().int().positive().optional(),
257
271
  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()
272
+ allow_regex: ContextRegexSchema.optional(),
273
+ deny_regex: ContextRegexSchema.optional(),
274
+ non_empty: ContextBuiltInValidatorSchema.optional(),
275
+ reject_secrets: ContextBuiltInValidatorSchema.optional()
260
276
  });
261
277
  var ContextInputDefinitionSchema = import_zod.z.union([
262
278
  import_zod.z.string(),
@@ -601,6 +617,8 @@ function resolveInlinePromptSource(source, options = {}) {
601
617
 
602
618
  // src/context.ts
603
619
  var textEncoder = new TextEncoder();
620
+ var REJECT_SECRETS_PATTERN = "(secret|api[_-]?key|password)";
621
+ var REJECT_SECRETS_FLAGS = "i";
604
622
  function getContextInputs(asset) {
605
623
  return (asset.context?.inputs ?? []).map(normalizeContextInput);
606
624
  }
@@ -615,8 +633,102 @@ function normalizeContextInput(input) {
615
633
  name: input.name,
616
634
  max_size: input.max_size,
617
635
  trim: input.trim,
618
- allow_regex: input.allow_regex,
619
- deny_regex: input.deny_regex
636
+ allow_regex: normalizeContextRegex(input.allow_regex),
637
+ deny_regex: normalizeContextRegex(input.deny_regex),
638
+ non_empty: normalizeBuiltInValidator(input.non_empty),
639
+ reject_secrets: normalizeBuiltInValidator(input.reject_secrets)
640
+ };
641
+ }
642
+ function normalizeContextRegex(value) {
643
+ if (value === void 0) {
644
+ return void 0;
645
+ }
646
+ if (typeof value === "string") {
647
+ const literal = parseRegexLiteral(value);
648
+ if (value.startsWith("/") && !literal) {
649
+ return {
650
+ pattern: value,
651
+ flags: "",
652
+ raw: value,
653
+ invalidLiteral: true
654
+ };
655
+ }
656
+ return {
657
+ pattern: literal?.pattern ?? value,
658
+ flags: literal?.flags ?? "",
659
+ raw: value
660
+ };
661
+ }
662
+ return {
663
+ pattern: value.pattern,
664
+ flags: value.flags ?? "",
665
+ raw: JSON.stringify(value),
666
+ returnMessage: value.return_message
667
+ };
668
+ }
669
+ function normalizeBuiltInValidator(value) {
670
+ if (value === void 0 || value === false) {
671
+ return void 0;
672
+ }
673
+ if (value === true) {
674
+ return {};
675
+ }
676
+ return {
677
+ returnMessage: value.return_message
678
+ };
679
+ }
680
+ function parseRegexLiteral(value) {
681
+ if (!value.startsWith("/")) {
682
+ return void 0;
683
+ }
684
+ for (let index = value.length - 1; index > 0; index -= 1) {
685
+ if (value[index] !== "/") {
686
+ continue;
687
+ }
688
+ let backslashCount = 0;
689
+ for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
690
+ backslashCount += 1;
691
+ }
692
+ if (backslashCount % 2 === 1) {
693
+ continue;
694
+ }
695
+ return {
696
+ pattern: value.slice(1, index),
697
+ flags: value.slice(index + 1)
698
+ };
699
+ }
700
+ return void 0;
701
+ }
702
+ function formatInvalidContextRegexMessage(details) {
703
+ return [
704
+ `Invalid context regex for prompt "${details.promptId}"`,
705
+ `variable "${details.variable}"`,
706
+ `field "${details.field}"`,
707
+ `value ${JSON.stringify(details.raw)}: ${details.reason}`
708
+ ].join(", ");
709
+ }
710
+ function compileContextRegex(regex, details) {
711
+ if (regex.invalidLiteral) {
712
+ throw new Error(
713
+ `POK013: ${formatInvalidContextRegexMessage({
714
+ ...details,
715
+ raw: regex.raw,
716
+ reason: "Malformed regex literal. Use /pattern/flags or { pattern, flags }."
717
+ })}`
718
+ );
719
+ }
720
+ try {
721
+ return new RegExp(regex.pattern, regex.flags);
722
+ } catch (error) {
723
+ const reason = error instanceof Error ? error.message : String(error);
724
+ throw new Error(`POK013: ${formatInvalidContextRegexMessage({ ...details, raw: regex.raw, reason })}`);
725
+ }
726
+ }
727
+ function getRejectSecretsRegex() {
728
+ return {
729
+ pattern: REJECT_SECRETS_PATTERN,
730
+ flags: REJECT_SECRETS_FLAGS,
731
+ raw: JSON.stringify({ pattern: REJECT_SECRETS_PATTERN, flags: REJECT_SECRETS_FLAGS })
620
732
  };
621
733
  }
622
734
  function isTrimEnabled(mode) {
@@ -688,8 +800,23 @@ function sanitizeContextVariables(asset, variables = {}, options = {}) {
688
800
  sanitized[input.name] = candidate;
689
801
  if (input.allow_regex) {
690
802
  const candidate2 = sanitized[input.name];
691
- const matcher = new RegExp(input.allow_regex);
803
+ const matcher = compileContextRegex(input.allow_regex, {
804
+ promptId: asset.id,
805
+ variable: input.name,
806
+ field: "allow_regex"
807
+ });
692
808
  if (!matcher.test(candidate2)) {
809
+ if (input.allow_regex.returnMessage) {
810
+ return {
811
+ variables: sanitized,
812
+ shortCircuit: {
813
+ returnMessage: input.allow_regex.returnMessage,
814
+ code: "POK031",
815
+ variable: input.name,
816
+ field: "allow_regex"
817
+ }
818
+ };
819
+ }
693
820
  throw new Error(
694
821
  `POK031: Context variable "${input.name}" failed allow_regex validation for prompt "${asset.id}".`
695
822
  );
@@ -697,15 +824,69 @@ function sanitizeContextVariables(asset, variables = {}, options = {}) {
697
824
  }
698
825
  if (input.deny_regex) {
699
826
  const candidate2 = sanitized[input.name];
700
- const matcher = new RegExp(input.deny_regex);
827
+ const matcher = compileContextRegex(input.deny_regex, {
828
+ promptId: asset.id,
829
+ variable: input.name,
830
+ field: "deny_regex"
831
+ });
701
832
  if (matcher.test(candidate2)) {
833
+ if (input.deny_regex.returnMessage) {
834
+ return {
835
+ variables: sanitized,
836
+ shortCircuit: {
837
+ returnMessage: input.deny_regex.returnMessage,
838
+ code: "POK032",
839
+ variable: input.name,
840
+ field: "deny_regex"
841
+ }
842
+ };
843
+ }
702
844
  throw new Error(
703
845
  `POK032: Context variable "${input.name}" matched deny_regex for prompt "${asset.id}".`
704
846
  );
705
847
  }
706
848
  }
849
+ if (input.non_empty && candidate.trim().length === 0) {
850
+ if (input.non_empty.returnMessage) {
851
+ return {
852
+ variables: sanitized,
853
+ shortCircuit: {
854
+ returnMessage: input.non_empty.returnMessage,
855
+ code: "POK033",
856
+ variable: input.name,
857
+ field: "non_empty"
858
+ }
859
+ };
860
+ }
861
+ throw new Error(
862
+ `POK033: Context variable "${input.name}" failed non_empty validation for prompt "${asset.id}".`
863
+ );
864
+ }
865
+ if (input.reject_secrets) {
866
+ const matcher = compileContextRegex(getRejectSecretsRegex(), {
867
+ promptId: asset.id,
868
+ variable: input.name,
869
+ field: "reject_secrets"
870
+ });
871
+ if (matcher.test(candidate)) {
872
+ if (input.reject_secrets.returnMessage) {
873
+ return {
874
+ variables: sanitized,
875
+ shortCircuit: {
876
+ returnMessage: input.reject_secrets.returnMessage,
877
+ code: "POK034",
878
+ variable: input.name,
879
+ field: "reject_secrets"
880
+ }
881
+ };
882
+ }
883
+ throw new Error(
884
+ `POK034: Context variable "${input.name}" matched reject_secrets validation for prompt "${asset.id}".`
885
+ );
886
+ }
887
+ }
707
888
  }
708
- return sanitized;
889
+ return { variables: sanitized };
709
890
  }
710
891
  function measureContextValueSize(value) {
711
892
  return textEncoder.encode(value).length;
@@ -755,12 +936,19 @@ function withPromptInputSupport(adapter) {
755
936
  };
756
937
  const renderPrompt2 = async (input, runtime) => {
757
938
  const resolved = await resolveProviderPromptInput(input, runtime);
758
- const variables = sanitizeContextVariables(resolved, runtime.variables, {
939
+ const sanitization = sanitizeContextVariables(resolved, runtime.variables, {
759
940
  onContextOverflow: runtime.onContextOverflow
760
941
  });
942
+ if (sanitization.shortCircuit) {
943
+ return {
944
+ provider: adapter.name,
945
+ model: resolved.model ?? "",
946
+ returnMessage: sanitization.shortCircuit.returnMessage
947
+ };
948
+ }
761
949
  return adapter.render(resolved, {
762
950
  ...runtime,
763
- variables
951
+ variables: sanitization.variables
764
952
  });
765
953
  };
766
954
  return {
@@ -1168,16 +1356,20 @@ function validateAsset(asset, frontMatterKeys, filePath) {
1168
1356
  });
1169
1357
  }
1170
1358
  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" });
1359
+ if (input.allow_regex) checks.push({ regex: input.allow_regex, kind: "allow_regex" });
1360
+ if (input.deny_regex) checks.push({ regex: input.deny_regex, kind: "deny_regex" });
1173
1361
  for (const check of checks) {
1174
1362
  try {
1175
- new RegExp(check.pattern);
1363
+ compileContextRegex(check.regex, {
1364
+ promptId: asset.id,
1365
+ variable: input.name,
1366
+ field: check.kind
1367
+ });
1176
1368
  } catch (error) {
1177
- const reason = error instanceof Error ? error.message : String(error);
1369
+ const reason = error instanceof Error ? error.message.replace(/^POK013:\s*/, "") : String(error);
1178
1370
  errors.push({
1179
1371
  code: "POK013",
1180
- message: `Invalid context ${check.kind} for "${input.name}": ${reason}`,
1372
+ message: reason,
1181
1373
  filePath
1182
1374
  });
1183
1375
  }
@@ -1664,10 +1856,17 @@ var PromptOpsKit = class {
1664
1856
  ` + validation.errors.map((e) => ` - ${e}`).join("\n")
1665
1857
  );
1666
1858
  }
1667
- const sanitizedVariables = sanitizeContextVariables(resolved, options.variables, {
1859
+ const sanitization = sanitizeContextVariables(resolved, options.variables, {
1668
1860
  onContextOverflow: options.onContextOverflow
1669
1861
  });
1670
- const contextSizeWarnings = collectContextSizeWarnings(resolved, sanitizedVariables).map(
1862
+ if (sanitization.shortCircuit) {
1863
+ return {
1864
+ resolved,
1865
+ returnMessage: sanitization.shortCircuit.returnMessage,
1866
+ warnings: validation.warnings
1867
+ };
1868
+ }
1869
+ const contextSizeWarnings = collectContextSizeWarnings(resolved, sanitization.variables).map(
1671
1870
  (warning) => formatContextSizeWarning(resolved, warning)
1672
1871
  );
1673
1872
  const contextWarningPolicy = this.config.warnings?.contextSize;
@@ -1677,7 +1876,7 @@ var PromptOpsKit = class {
1677
1876
  }
1678
1877
  }
1679
1878
  const request = adapter.render(resolved, {
1680
- variables: sanitizedVariables,
1879
+ variables: sanitization.variables,
1681
1880
  history: options.history,
1682
1881
  toolRegistry: options.toolRegistry,
1683
1882
  strict: options.strict