@promptbook/utils 0.107.0-0 → 0.108.0-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.
package/esm/index.es.js CHANGED
@@ -18,7 +18,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
18
18
  * @generated
19
19
  * @see https://github.com/webgptorg/promptbook
20
20
  */
21
- const PROMPTBOOK_ENGINE_VERSION = '0.107.0-0';
21
+ const PROMPTBOOK_ENGINE_VERSION = '0.108.0-0';
22
22
  /**
23
23
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
24
24
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -2804,13 +2804,125 @@ function escapePromptParameterValue(value, options) {
2804
2804
  return value.replace(pattern, '\\$&');
2805
2805
  }
2806
2806
  /**
2807
- * Builds the parameter name used in prompt placeholders.
2807
+ * Builds numeric parameter name used in prompt placeholders.
2808
2808
  *
2809
2809
  * @param index Zero-based parameter index.
2810
2810
  */
2811
- function buildParameterName(index) {
2811
+ function buildNumericParameterName(index) {
2812
2812
  return `${index + 1}`;
2813
2813
  }
2814
+ /**
2815
+ * Builds alphabetic parameter name used in prompt placeholders.
2816
+ *
2817
+ * @param index Zero-based parameter index.
2818
+ */
2819
+ function buildAlphabeticParameterName(index) {
2820
+ const alphabet = 'abcdefghijklmnopqrstuvwxyz';
2821
+ let result = '';
2822
+ let remaining = index;
2823
+ while (remaining >= 0) {
2824
+ result = alphabet[remaining % alphabet.length] + result;
2825
+ remaining = Math.floor(remaining / alphabet.length) - 1;
2826
+ }
2827
+ return result;
2828
+ }
2829
+ /**
2830
+ * Converts a positive integer into a Roman numeral string.
2831
+ *
2832
+ * @param value Positive integer value.
2833
+ */
2834
+ function toRomanNumeral(value) {
2835
+ const romanTable = [
2836
+ { symbol: 'M', value: 1000 },
2837
+ { symbol: 'CM', value: 900 },
2838
+ { symbol: 'D', value: 500 },
2839
+ { symbol: 'CD', value: 400 },
2840
+ { symbol: 'C', value: 100 },
2841
+ { symbol: 'XC', value: 90 },
2842
+ { symbol: 'L', value: 50 },
2843
+ { symbol: 'XL', value: 40 },
2844
+ { symbol: 'X', value: 10 },
2845
+ { symbol: 'IX', value: 9 },
2846
+ { symbol: 'V', value: 5 },
2847
+ { symbol: 'IV', value: 4 },
2848
+ { symbol: 'I', value: 1 },
2849
+ ];
2850
+ let remaining = Math.max(1, Math.floor(value));
2851
+ let result = '';
2852
+ for (const entry of romanTable) {
2853
+ while (remaining >= entry.value) {
2854
+ result += entry.symbol;
2855
+ remaining -= entry.value;
2856
+ }
2857
+ }
2858
+ return result;
2859
+ }
2860
+ /**
2861
+ * Builds Roman numeral parameter name used in prompt placeholders.
2862
+ *
2863
+ * @param index Zero-based parameter index.
2864
+ */
2865
+ function buildRomanParameterName(index) {
2866
+ return toRomanNumeral(index + 1);
2867
+ }
2868
+ /**
2869
+ * Creates a parameter name builder that prefixes another builder.
2870
+ *
2871
+ * @param prefix Prefix to add.
2872
+ * @param builder Base builder to wrap.
2873
+ */
2874
+ function buildPrefixedParameterName(prefix, builder) {
2875
+ return (index) => `${prefix}${builder(index)}`;
2876
+ }
2877
+ /**
2878
+ * Ordered list of strategies for parameter naming.
2879
+ */
2880
+ const PARAMETER_NAME_STRATEGIES = [
2881
+ { buildName: buildNumericParameterName },
2882
+ { buildName: buildAlphabeticParameterName },
2883
+ { buildName: buildRomanParameterName },
2884
+ { buildName: buildPrefixedParameterName('p', buildNumericParameterName) },
2885
+ { buildName: buildPrefixedParameterName('p', buildAlphabeticParameterName) },
2886
+ ];
2887
+ /**
2888
+ * Collects bracketed tokens from parameter values to avoid placeholder collisions.
2889
+ *
2890
+ * @param values Parameter values to scan.
2891
+ */
2892
+ function collectBracketedParameterTokens(values) {
2893
+ const tokens = new Set();
2894
+ for (const value of values) {
2895
+ const pattern = /{(\w+)}/g;
2896
+ let match;
2897
+ while ((match = pattern.exec(value)) !== null) {
2898
+ const token = match[1];
2899
+ if (token) {
2900
+ tokens.add(token);
2901
+ }
2902
+ }
2903
+ }
2904
+ return tokens;
2905
+ }
2906
+ /**
2907
+ * Builds parameter names used in prompt placeholders while avoiding collisions.
2908
+ *
2909
+ * @param values Parameter values to scan for conflicting tokens.
2910
+ */
2911
+ function buildParameterNames(values) {
2912
+ const count = values.length;
2913
+ if (count === 0) {
2914
+ return [];
2915
+ }
2916
+ const conflicts = collectBracketedParameterTokens(values);
2917
+ for (const strategy of PARAMETER_NAME_STRATEGIES) {
2918
+ const names = Array.from({ length: count }, (_, index) => strategy.buildName(index));
2919
+ const hasConflict = names.some((name) => conflicts.has(name));
2920
+ if (!hasConflict) {
2921
+ return names;
2922
+ }
2923
+ }
2924
+ return Array.from({ length: count }, (_, index) => `${REPLACING_NONCE}${index + 1}`);
2925
+ }
2814
2926
  /**
2815
2927
  * Formats the placeholder used in the prompt body for a parameter.
2816
2928
  *
@@ -2865,26 +2977,40 @@ function prompt(strings, ...values) {
2865
2977
  return new PromptString(spaceTrim$2(strings.join('')));
2866
2978
  }
2867
2979
  const stringsWithHiddenParameters = strings.map((stringsItem) => hideBrackets(stringsItem));
2868
- const parameterEntries = values.map((value, index) => {
2869
- const name = buildParameterName(index);
2980
+ const parameterMetadata = values.map((value) => {
2870
2981
  const isPrompt = isPromptString(value);
2871
2982
  const stringValue = isPrompt ? value.toString() : valueToString(value);
2872
2983
  const isInline = isPrompt ? true : shouldInlineParameterValue(stringValue);
2873
2984
  const jsonValue = !isPrompt && !isInline ? normalizeJsonString(stringValue) : null;
2985
+ return { isPrompt, stringValue, isInline, jsonValue };
2986
+ });
2987
+ const parameterNames = buildParameterNames(parameterMetadata.map((entry) => entry.stringValue));
2988
+ const parameterEntries = parameterMetadata.map((entry, index) => {
2989
+ var _a;
2990
+ const name = (_a = parameterNames[index]) !== null && _a !== void 0 ? _a : buildNumericParameterName(index);
2874
2991
  const promptMarker = `${REPLACING_NONCE}prompt-${index}`;
2875
2992
  const parameterMarker = `${REPLACING_NONCE}parameter-${index}`;
2876
- const templateValue = isPrompt
2993
+ const templateValue = entry.isPrompt
2877
2994
  ? promptMarker
2878
- : isInline
2879
- ? escapePromptParameterValue(stringValue, { includeBraces: false })
2995
+ : entry.isInline
2996
+ ? escapePromptParameterValue(entry.stringValue, { includeBraces: false })
2880
2997
  : parameterMarker;
2881
- return { name, stringValue, jsonValue, isPrompt, isInline, promptMarker, parameterMarker, templateValue };
2998
+ return {
2999
+ name,
3000
+ stringValue: entry.stringValue,
3001
+ jsonValue: entry.jsonValue,
3002
+ isPrompt: entry.isPrompt,
3003
+ isInline: entry.isInline,
3004
+ promptMarker,
3005
+ parameterMarker,
3006
+ templateValue,
3007
+ };
2882
3008
  });
2883
3009
  const parameters = Object.fromEntries(parameterEntries.map((entry) => [entry.name, entry.templateValue]));
2884
- const parameterNames = parameterEntries.map((entry) => entry.name);
3010
+ const parameterNamesOrdered = parameterEntries.map((entry) => entry.name);
2885
3011
  // Combine strings and values
2886
3012
  let pipelineString = stringsWithHiddenParameters.reduce((result, stringsItem, i) => {
2887
- const parameterName = parameterNames[i];
3013
+ const parameterName = parameterNamesOrdered[i];
2888
3014
  return parameterName === undefined
2889
3015
  ? `${result}${stringsItem}`
2890
3016
  : `${result}${stringsItem}${formatParameterPlaceholder(parameterName)}`;
@@ -2897,7 +3023,7 @@ function prompt(strings, ...values) {
2897
3023
  if (!(error instanceof PipelineExecutionError)) {
2898
3024
  throw error;
2899
3025
  }
2900
- console.error({ pipelineString, parameters, parameterNames, error });
3026
+ console.error({ pipelineString, parameters, parameterNames: parameterNamesOrdered, error });
2901
3027
  throw new UnexpectedError(spaceTrim$2((block) => `
2902
3028
  Internal error in prompt template literal
2903
3029
 
@@ -2912,9 +3038,7 @@ function prompt(strings, ...values) {
2912
3038
  continue;
2913
3039
  }
2914
3040
  if (!entry.isInline) {
2915
- pipelineString = pipelineString
2916
- .split(entry.parameterMarker)
2917
- .join(formatParameterPlaceholder(entry.name));
3041
+ pipelineString = pipelineString.split(entry.parameterMarker).join(formatParameterPlaceholder(entry.name));
2918
3042
  }
2919
3043
  }
2920
3044
  const structuredParameters = parameterEntries.filter((entry) => !entry.isPrompt && !entry.isInline);