promptopskit 0.8.2 → 0.9.0

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 (69) hide show
  1. package/README.md +2 -1
  2. package/SKILL.md +10 -4
  3. package/dist/{chunk-ZVCKP4EM.js → chunk-AAQNCAVA.js} +3 -3
  4. package/dist/{chunk-5XH2GROP.js → chunk-E2AIIPQC.js} +2 -2
  5. package/dist/{chunk-UQLAWU67.js → chunk-FJ3D76IV.js} +2 -2
  6. package/dist/{chunk-RVAFVWR2.js → chunk-NS6OTKY2.js} +115 -34
  7. package/dist/chunk-NS6OTKY2.js.map +1 -0
  8. package/dist/{chunk-Z3DPPJNU.js → chunk-Q67E2GGD.js} +2 -2
  9. package/dist/{chunk-PDVUVZAU.js → chunk-SVNQNMMV.js} +2 -2
  10. package/dist/{chunk-E4GEKWVP.js → chunk-VOXMOGU5.js} +5 -2
  11. package/dist/chunk-VOXMOGU5.js.map +1 -0
  12. package/dist/{chunk-DI7Q4T7A.js → chunk-W6XHGSPJ.js} +3 -3
  13. package/dist/cli/index.js +8 -2
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/index.cjs +117 -33
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +4 -4
  18. package/dist/index.d.ts +4 -4
  19. package/dist/index.js +8 -8
  20. package/dist/providers/anthropic.cjs +117 -33
  21. package/dist/providers/anthropic.cjs.map +1 -1
  22. package/dist/providers/anthropic.d.cts +2 -2
  23. package/dist/providers/anthropic.d.ts +2 -2
  24. package/dist/providers/anthropic.js +3 -3
  25. package/dist/providers/gemini.cjs +117 -33
  26. package/dist/providers/gemini.cjs.map +1 -1
  27. package/dist/providers/gemini.d.cts +2 -2
  28. package/dist/providers/gemini.d.ts +2 -2
  29. package/dist/providers/gemini.js +3 -3
  30. package/dist/providers/llmasaservice.cjs +117 -33
  31. package/dist/providers/llmasaservice.cjs.map +1 -1
  32. package/dist/providers/llmasaservice.d.cts +2 -2
  33. package/dist/providers/llmasaservice.d.ts +2 -2
  34. package/dist/providers/llmasaservice.js +4 -4
  35. package/dist/providers/openai-responses.cjs +117 -33
  36. package/dist/providers/openai-responses.cjs.map +1 -1
  37. package/dist/providers/openai-responses.d.cts +2 -2
  38. package/dist/providers/openai-responses.d.ts +2 -2
  39. package/dist/providers/openai-responses.js +3 -3
  40. package/dist/providers/openai.cjs +117 -33
  41. package/dist/providers/openai.cjs.map +1 -1
  42. package/dist/providers/openai.d.cts +2 -2
  43. package/dist/providers/openai.d.ts +2 -2
  44. package/dist/providers/openai.js +3 -3
  45. package/dist/providers/openrouter.cjs +117 -33
  46. package/dist/providers/openrouter.cjs.map +1 -1
  47. package/dist/providers/openrouter.d.cts +2 -2
  48. package/dist/providers/openrouter.d.ts +2 -2
  49. package/dist/providers/openrouter.js +4 -4
  50. package/dist/{schema-BgVLZ2u5.d.cts → schema-BkOMklgI.d.cts} +129 -0
  51. package/dist/{schema-BgVLZ2u5.d.ts → schema-BkOMklgI.d.ts} +129 -0
  52. package/dist/testing.cjs +4 -1
  53. package/dist/testing.cjs.map +1 -1
  54. package/dist/testing.d.cts +1 -1
  55. package/dist/testing.d.ts +1 -1
  56. package/dist/testing.js +1 -1
  57. package/dist/{types-2hnZmCkH.d.cts → types-B4TWRzUY.d.cts} +1 -1
  58. package/dist/{types-DgAT4jSR.d.ts → types-D6VJJo1x.d.ts} +1 -1
  59. package/dist/usagetap/index.d.cts +2 -2
  60. package/dist/usagetap/index.d.ts +2 -2
  61. package/package.json +1 -1
  62. package/dist/chunk-E4GEKWVP.js.map +0 -1
  63. package/dist/chunk-RVAFVWR2.js.map +0 -1
  64. /package/dist/{chunk-ZVCKP4EM.js.map → chunk-AAQNCAVA.js.map} +0 -0
  65. /package/dist/{chunk-5XH2GROP.js.map → chunk-E2AIIPQC.js.map} +0 -0
  66. /package/dist/{chunk-UQLAWU67.js.map → chunk-FJ3D76IV.js.map} +0 -0
  67. /package/dist/{chunk-Z3DPPJNU.js.map → chunk-Q67E2GGD.js.map} +0 -0
  68. /package/dist/{chunk-PDVUVZAU.js.map → chunk-SVNQNMMV.js.map} +0 -0
  69. /package/dist/{chunk-DI7Q4T7A.js.map → chunk-W6XHGSPJ.js.map} +0 -0
@@ -1,5 +1,5 @@
1
- import { P as ProviderAdapter } from '../types-2hnZmCkH.cjs';
2
- import '../schema-BgVLZ2u5.cjs';
1
+ import { P as ProviderAdapter } from '../types-B4TWRzUY.cjs';
2
+ import '../schema-BkOMklgI.cjs';
3
3
  import 'zod';
4
4
 
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { P as ProviderAdapter } from '../types-DgAT4jSR.js';
2
- import '../schema-BgVLZ2u5.js';
1
+ import { P as ProviderAdapter } from '../types-D6VJJo1x.js';
2
+ import '../schema-BkOMklgI.js';
3
3
  import 'zod';
4
4
 
5
5
  /**
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  openaiResponsesAdapter
3
- } from "../chunk-5XH2GROP.js";
4
- import "../chunk-RVAFVWR2.js";
5
- import "../chunk-E4GEKWVP.js";
3
+ } from "../chunk-E2AIIPQC.js";
4
+ import "../chunk-NS6OTKY2.js";
5
+ import "../chunk-VOXMOGU5.js";
6
6
  export {
7
7
  openaiResponsesAdapter
8
8
  };
@@ -101,7 +101,10 @@ function normalizeContextInputCompression(value) {
101
101
  target_reduction: value.heuristic.target_reduction,
102
102
  query: value.heuristic.query,
103
103
  query_variable: value.heuristic.query_variable,
104
- json_to_toon: value.heuristic.json_to_toon
104
+ json_to_toon: value.heuristic.json_to_toon,
105
+ mode: value.heuristic.mode,
106
+ preserve_neighbors: value.heuristic.preserve_neighbors,
107
+ fail_on_low_confidence: value.heuristic.fail_on_low_confidence
105
108
  }
106
109
  };
107
110
  const code = normalizeCodeCompression(value.code);
@@ -579,7 +582,10 @@ function line(depth, content, indent) {
579
582
  var TOKEN_REGEX = /[\p{L}\p{N}]+|[^\s]/gu;
580
583
  var TOKEN_NORMALIZE_REGEX = /[^\p{L}\p{N}]/gu;
581
584
  var DEDUPE_NORMALIZE_REGEX = /[^\p{L}\p{N}\s]/gu;
582
- var BOILERPLATE_REGEX = /copyright|all rights reserved|disclaimer|confidential/i;
585
+ var BOILERPLATE_REGEX = /copyright|all rights reserved|disclaimer/i;
586
+ var STRUCTURED_BLOCK_REGEX = /(^|\n)\s*```|(^|\n)\s*\|.+\|\s*(\n|$)/;
587
+ var PROTECTED_SIGNAL_REGEX = /\b(?:must|shall|should|required|requires|requirement|never|do not|don't|only|except|unless|however|but|constraint|constraints|safety|security|deadline|sla)\b|output\s+format/i;
588
+ var EVIDENCE_SIGNAL_REGEX = /https?:\/\/|\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b|[$€£]\s?\d|\b\d+(?:[.,:/-]\d+)*%?\b|\b[A-Z]{2,}[-_A-Z0-9]*\b|\b[A-Z]\d\b/i;
583
589
  var MAX_SEGMENT_TOKENS = 120;
584
590
  var STOP_WORDS = /* @__PURE__ */ new Set([
585
591
  "a",
@@ -613,7 +619,8 @@ var STOP_WORDS = /* @__PURE__ */ new Set([
613
619
  var DEFAULT_OPTIONS = {
614
620
  min_tokens: 80,
615
621
  max_sentences: 10,
616
- target_reduction: 0.45
622
+ target_reduction: 0.45,
623
+ mode: "conservative"
617
624
  };
618
625
  function tokenizeForHeuristicCompression(text) {
619
626
  if (!text) {
@@ -647,25 +654,46 @@ function compressHeuristicText(input, options = {}) {
647
654
  warnings: ["JSON-to-TOON skipped because the input is not a complete valid JSON object or array."]
648
655
  };
649
656
  }
650
- const analysis = preprocessContext(inputText);
651
657
  if (inputTokens === 0) {
652
658
  return toCompressionOutput(inputText, inputTokens);
653
659
  }
660
+ const mode = options.mode ?? DEFAULT_OPTIONS.mode;
661
+ const isConservative = mode === "conservative";
662
+ const failOnLowConfidence = options.fail_on_low_confidence ?? isConservative;
663
+ const preserveNeighbors = options.preserve_neighbors ?? isConservative;
654
664
  const minTokens = options.min_tokens ?? DEFAULT_OPTIONS.min_tokens;
655
665
  if (inputTokens <= minTokens) {
656
666
  return toCompressionOutput(inputText, inputTokens);
657
667
  }
668
+ if (isConservative && looksStructured(inputText)) {
669
+ return toCompressionOutput(inputText, inputTokens, [
670
+ "Heuristic compression skipped because the input appears to contain structured blocks; use TOON or code compaction for structured content."
671
+ ]);
672
+ }
673
+ const analysis = preprocessContext(inputText);
658
674
  const targetReduction = options.target_reduction ?? DEFAULT_OPTIONS.target_reduction;
659
675
  const targetTokens = Math.max(1, Math.max(minTokens, Math.floor(inputTokens * (1 - targetReduction))));
660
676
  const maxSentences = options.max_sentences ?? DEFAULT_OPTIONS.max_sentences;
661
677
  const query = options.query ?? "";
662
678
  const terms = queryTerms(query);
679
+ if (failOnLowConfidence && terms.size === 0) {
680
+ return toCompressionOutput(inputText, inputTokens, [
681
+ "Heuristic compression skipped because no usable relevance query terms were available."
682
+ ]);
683
+ }
663
684
  const scoredSentences = analysis.candidates.map((candidate) => ({
664
685
  sentence: candidate.sentence,
665
686
  index: candidate.index,
666
687
  ...scoreSentenceCandidate(candidate, terms),
667
- tokens: candidate.tokenCount
688
+ tokens: candidate.tokenCount,
689
+ isProtected: candidate.isProtected,
690
+ hasEvidence: candidate.hasEvidence
668
691
  }));
692
+ if (failOnLowConfidence && terms.size > 0 && !scoredSentences.some((candidate) => candidate.overlapCount > 0)) {
693
+ return toCompressionOutput(inputText, inputTokens, [
694
+ "Heuristic compression skipped because no sentence matched the relevance query."
695
+ ]);
696
+ }
669
697
  const selected = [];
670
698
  const selectedIndices = /* @__PURE__ */ new Set();
671
699
  const coveredTerms = /* @__PURE__ */ new Set();
@@ -705,19 +733,15 @@ function compressHeuristicText(input, options = {}) {
705
733
  coveredTerms.add(term);
706
734
  }
707
735
  }
708
- selected.sort((left, right) => left.index - right.index);
709
- let output = selected.map((item) => item.sentence).join(" ");
736
+ const finalSelection = preserveNeighbors ? expandSelectionWithNeighbors(selected, scoredSentences, maxSentences) : selected;
737
+ finalSelection.sort((left, right) => left.index - right.index);
738
+ let output = finalSelection.map((item) => item.sentence).join(" ");
710
739
  if (!output) {
711
- output = tokenizeForHeuristicCompression(inputText).slice(0, targetTokens).join(" ");
712
- } else {
713
- const outputTokens = tokenizeForHeuristicCompression(output);
714
- if (outputTokens.length > targetTokens) {
715
- output = outputTokens.slice(0, targetTokens).join(" ");
716
- }
740
+ output = takeWholeCandidatesWithinBudget(analysis.candidates, targetTokens) || inputText;
717
741
  }
718
742
  return toCompressionOutput(output, inputTokens);
719
743
  }
720
- function toCompressionOutput(output, inputTokens) {
744
+ function toCompressionOutput(output, inputTokens, warnings = []) {
721
745
  const outputTokens = estimateHeuristicTokens(output);
722
746
  const tokensSaved = Math.max(0, inputTokens - outputTokens);
723
747
  return {
@@ -725,7 +749,8 @@ function toCompressionOutput(output, inputTokens) {
725
749
  inputTokens,
726
750
  outputTokens,
727
751
  tokensSaved,
728
- compressionRatio: outputTokens === 0 ? 0 : inputTokens / outputTokens
752
+ compressionRatio: outputTokens === 0 ? 0 : inputTokens / outputTokens,
753
+ ...warnings.length > 0 ? { warnings } : {}
729
754
  };
730
755
  }
731
756
  function isBetterTieBreak(candidate, bestCandidate) {
@@ -743,13 +768,6 @@ function normalizeForDeduping(sentence) {
743
768
  function splitIntoSentences(text) {
744
769
  return text.split(/(?<=[.!?])\s+|\n+/g).map((sentence) => sentence.trim()).filter(Boolean);
745
770
  }
746
- function chunkTokens(tokens, chunkSize) {
747
- const chunks = [];
748
- for (let index = 0; index < tokens.length; index += chunkSize) {
749
- chunks.push(tokens.slice(index, index + chunkSize));
750
- }
751
- return chunks;
752
- }
753
771
  function splitOversizedSentence(sentence, maxTokens = MAX_SEGMENT_TOKENS) {
754
772
  const rawTokens = tokenizeForHeuristicCompression(sentence);
755
773
  if (rawTokens.length <= maxTokens) {
@@ -761,10 +779,10 @@ function splitOversizedSentence(sentence, maxTokens = MAX_SEGMENT_TOKENS) {
761
779
  if (estimateHeuristicTokens(segment) <= maxTokens) {
762
780
  return [segment];
763
781
  }
764
- return chunkTokens(tokenizeForHeuristicCompression(segment), maxTokens).map((chunk) => chunk.join(" "));
782
+ return [segment];
765
783
  });
766
784
  }
767
- return chunkTokens(rawTokens, maxTokens).map((chunk) => chunk.join(" "));
785
+ return [sentence];
768
786
  }
769
787
  function normalizeToken(token) {
770
788
  return token.replace(TOKEN_NORMALIZE_REGEX, "").trim();
@@ -773,19 +791,24 @@ function tokenizeNormalized(text) {
773
791
  return tokenizeForHeuristicCompression(text.toLowerCase()).map(normalizeToken).filter(Boolean);
774
792
  }
775
793
  function queryTerms(query) {
776
- return new Set(tokenizeNormalized(query).filter((term) => term.length >= 3 && !STOP_WORDS.has(term)));
794
+ return new Set(tokenizeNormalized(query).filter((term) => {
795
+ if (STOP_WORDS.has(term)) {
796
+ return false;
797
+ }
798
+ return term.length >= 3 || /^(?:[a-z]\d|\d+[a-z]?|[a-z]{2})$/i.test(term);
799
+ }));
777
800
  }
778
801
  function preprocessContext(context) {
779
802
  const originalTokens = estimateHeuristicTokens(context);
780
- const dedupeSet = /* @__PURE__ */ new Set();
781
803
  const candidates = [];
804
+ let previousNormalized = "";
782
805
  for (const sentence of splitIntoSentences(context)) {
783
806
  for (const segment of splitOversizedSentence(sentence)) {
784
807
  const normalized = normalizeForDeduping(segment);
785
- if (!normalized || dedupeSet.has(normalized)) {
808
+ if (!normalized || normalized === previousNormalized) {
786
809
  continue;
787
810
  }
788
- dedupeSet.add(normalized);
811
+ previousNormalized = normalized;
789
812
  const rawTokens = tokenizeForHeuristicCompression(segment);
790
813
  const normalizedTerms = rawTokens.map((token) => normalizeToken(token.toLowerCase())).filter(Boolean);
791
814
  const lowered = segment.toLowerCase();
@@ -794,7 +817,9 @@ function preprocessContext(context) {
794
817
  index: candidates.length,
795
818
  tokenCount: rawTokens.length,
796
819
  uniqueTerms: new Set(normalizedTerms),
797
- isBoilerplate: BOILERPLATE_REGEX.test(lowered)
820
+ isBoilerplate: BOILERPLATE_REGEX.test(lowered),
821
+ isProtected: PROTECTED_SIGNAL_REGEX.test(segment),
822
+ hasEvidence: EVIDENCE_SIGNAL_REGEX.test(segment)
798
823
  });
799
824
  }
800
825
  }
@@ -820,12 +845,62 @@ function scoreSentenceCandidate(candidate, terms) {
820
845
  const densityScore = terms.size > 0 ? overlap / terms.size : 0;
821
846
  const lengthScore = Math.min(candidate.tokenCount, 40) / 40;
822
847
  const boilerplatePenalty = candidate.isBoilerplate ? 0.5 : 0;
848
+ const protectedScore = candidate.isProtected ? 0.9 : 0;
849
+ const evidenceScore = candidate.hasEvidence ? 0.4 : 0;
823
850
  return {
824
- score: overlapScore + densityScore + lengthScore - boilerplatePenalty,
851
+ score: overlapScore + densityScore + lengthScore + protectedScore + evidenceScore - boilerplatePenalty,
825
852
  overlapCount: overlap,
826
853
  overlapTerms
827
854
  };
828
855
  }
856
+ function looksStructured(text) {
857
+ if (STRUCTURED_BLOCK_REGEX.test(text)) {
858
+ return true;
859
+ }
860
+ const lines = text.split(/\r?\n/).map((line2) => line2.trim()).filter(Boolean);
861
+ if (lines.length < 3) {
862
+ return false;
863
+ }
864
+ const listLikeLines = lines.filter((line2) => /^[-*+] |\d+[.)] /.test(line2)).length;
865
+ return listLikeLines >= 3 && listLikeLines / lines.length >= 0.6;
866
+ }
867
+ function expandSelectionWithNeighbors(selected, scoredSentences, maxSentences) {
868
+ if (selected.length === 0 || selected.length >= maxSentences) {
869
+ return selected;
870
+ }
871
+ const byIndex = new Map(scoredSentences.map((candidate) => [candidate.index, candidate]));
872
+ const expanded = new Map(selected.map((candidate) => [candidate.index, candidate]));
873
+ for (const candidate of selected) {
874
+ if (expanded.size >= maxSentences) {
875
+ break;
876
+ }
877
+ if (candidate.overlapCount === 0 && !candidate.isProtected && !candidate.hasEvidence) {
878
+ continue;
879
+ }
880
+ for (const neighborIndex of [candidate.index - 1, candidate.index + 1]) {
881
+ if (expanded.size >= maxSentences) {
882
+ break;
883
+ }
884
+ const neighbor = byIndex.get(neighborIndex);
885
+ if (neighbor && !expanded.has(neighbor.index)) {
886
+ expanded.set(neighbor.index, neighbor);
887
+ }
888
+ }
889
+ }
890
+ return [...expanded.values()];
891
+ }
892
+ function takeWholeCandidatesWithinBudget(candidates, targetTokens) {
893
+ const selected = [];
894
+ let tokens = 0;
895
+ for (const candidate of candidates) {
896
+ if (tokens + candidate.tokenCount > targetTokens) {
897
+ break;
898
+ }
899
+ selected.push(candidate.sentence);
900
+ tokens += candidate.tokenCount;
901
+ }
902
+ return selected.join(" ");
903
+ }
829
904
 
830
905
  // src/code-compaction.ts
831
906
  function compactCode(input, options = {}) {
@@ -991,7 +1066,10 @@ function renderSections(asset, options = {}) {
991
1066
  max_sentences: configuredHeuristic?.max_sentences,
992
1067
  target_reduction: configuredHeuristic?.target_reduction,
993
1068
  query,
994
- json_to_toon: configuredHeuristic?.json_to_toon
1069
+ json_to_toon: configuredHeuristic?.json_to_toon,
1070
+ mode: configuredHeuristic?.mode,
1071
+ preserve_neighbors: configuredHeuristic?.preserve_neighbors,
1072
+ fail_on_low_confidence: configuredHeuristic?.fail_on_low_confidence
995
1073
  };
996
1074
  const cacheKey = JSON.stringify([name, value, compressionOptions]);
997
1075
  const cached = compressionCache.get(cacheKey);
@@ -1357,7 +1435,10 @@ var HeuristicCompressionSchema = import_zod.z.object({
1357
1435
  target_reduction: import_zod.z.number().min(0).max(1).optional(),
1358
1436
  query: import_zod.z.string().optional(),
1359
1437
  query_variable: import_zod.z.string().min(1).optional(),
1360
- json_to_toon: import_zod.z.boolean().optional()
1438
+ json_to_toon: import_zod.z.boolean().optional(),
1439
+ mode: import_zod.z.enum(["conservative", "balanced"]).optional(),
1440
+ preserve_neighbors: import_zod.z.boolean().optional(),
1441
+ fail_on_low_confidence: import_zod.z.boolean().optional()
1361
1442
  });
1362
1443
  var CodeCompactionSchema = import_zod.z.object({
1363
1444
  enabled: import_zod.z.boolean().optional(),
@@ -2342,7 +2423,10 @@ async function applyPromptCompressionForRender(asset, runtime) {
2342
2423
  max_sentences: heuristicConfig?.max_sentences,
2343
2424
  target_reduction: heuristicConfig?.target_reduction,
2344
2425
  query: resolveHeuristicPromptQuery(heuristicConfig, runtime.variables, sections.system_instructions),
2345
- json_to_toon: heuristicConfig?.json_to_toon
2426
+ json_to_toon: heuristicConfig?.json_to_toon,
2427
+ mode: heuristicConfig?.mode,
2428
+ preserve_neighbors: heuristicConfig?.preserve_neighbors,
2429
+ fail_on_low_confidence: heuristicConfig?.fail_on_low_confidence
2346
2430
  });
2347
2431
  promptTemplate = result.output;
2348
2432
  reportHeuristicCompressionWarnings2(warnings, result.warnings, "prompt template");