@promptbook/core 0.107.0-0 → 0.110.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.
Files changed (28) hide show
  1. package/esm/index.es.js +434 -101
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/typings/src/_packages/markdown-utils.index.d.ts +2 -0
  4. package/esm/typings/src/_packages/types.index.d.ts +8 -0
  5. package/esm/typings/src/book-components/AvatarProfile/AvatarProfile/AvatarProfile.d.ts +1 -1
  6. package/esm/typings/src/book-components/Chat/Chat/ChatActionsBar.d.ts +32 -0
  7. package/esm/typings/src/book-components/Chat/Chat/ChatCitationModal.d.ts +21 -0
  8. package/esm/typings/src/book-components/Chat/Chat/ChatInputArea.d.ts +48 -0
  9. package/esm/typings/src/book-components/Chat/Chat/ChatMessageList.d.ts +40 -0
  10. package/esm/typings/src/book-components/Chat/Chat/ChatRatingModal.d.ts +30 -0
  11. package/esm/typings/src/book-components/Chat/Chat/ChatSelfLearningSummary.d.ts +24 -0
  12. package/esm/typings/src/book-components/Chat/Chat/ChatToolCallModal.d.ts +23 -0
  13. package/esm/typings/src/book-components/Chat/Chat/ChatToolCallModalComponents.d.ts +39 -0
  14. package/esm/typings/src/book-components/Chat/hooks/useChatActionsOverlap.d.ts +55 -0
  15. package/esm/typings/src/book-components/Chat/hooks/useChatRatings.d.ts +67 -0
  16. package/esm/typings/src/book-components/Chat/utils/getToolCallChipletInfo.d.ts +7 -0
  17. package/esm/typings/src/book-components/icons/TeacherIcon.d.ts +15 -0
  18. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +18 -1
  19. package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentsDatabaseSchema.d.ts +40 -3
  20. package/esm/typings/src/types/ToolCall.d.ts +67 -0
  21. package/esm/typings/src/utils/linguistic-hash/linguisticHash.d.ts +1 -24
  22. package/esm/typings/src/utils/linguistic-hash/linguisticHashWordCount.d.ts +31 -0
  23. package/esm/typings/src/utils/linguistic-hash/linguisticHashWordSelection.d.ts +22 -0
  24. package/esm/typings/src/utils/markdown/humanizeAiTextSources.d.ts +13 -0
  25. package/esm/typings/src/version.d.ts +1 -1
  26. package/package.json +1 -1
  27. package/umd/index.umd.js +434 -101
  28. package/umd/index.umd.js.map +1 -1
package/esm/index.es.js CHANGED
@@ -27,7 +27,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
27
27
  * @generated
28
28
  * @see https://github.com/webgptorg/promptbook
29
29
  */
30
- const PROMPTBOOK_ENGINE_VERSION = '0.107.0-0';
30
+ const PROMPTBOOK_ENGINE_VERSION = '0.110.0-0';
31
31
  /**
32
32
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
33
33
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -8593,13 +8593,125 @@ function escapePromptParameterValue(value, options) {
8593
8593
  return value.replace(pattern, '\\$&');
8594
8594
  }
8595
8595
  /**
8596
- * Builds the parameter name used in prompt placeholders.
8596
+ * Builds numeric parameter name used in prompt placeholders.
8597
8597
  *
8598
8598
  * @param index Zero-based parameter index.
8599
8599
  */
8600
- function buildParameterName(index) {
8600
+ function buildNumericParameterName(index) {
8601
8601
  return `${index + 1}`;
8602
8602
  }
8603
+ /**
8604
+ * Builds alphabetic parameter name used in prompt placeholders.
8605
+ *
8606
+ * @param index Zero-based parameter index.
8607
+ */
8608
+ function buildAlphabeticParameterName(index) {
8609
+ const alphabet = 'abcdefghijklmnopqrstuvwxyz';
8610
+ let result = '';
8611
+ let remaining = index;
8612
+ while (remaining >= 0) {
8613
+ result = alphabet[remaining % alphabet.length] + result;
8614
+ remaining = Math.floor(remaining / alphabet.length) - 1;
8615
+ }
8616
+ return result;
8617
+ }
8618
+ /**
8619
+ * Converts a positive integer into a Roman numeral string.
8620
+ *
8621
+ * @param value Positive integer value.
8622
+ */
8623
+ function toRomanNumeral(value) {
8624
+ const romanTable = [
8625
+ { symbol: 'M', value: 1000 },
8626
+ { symbol: 'CM', value: 900 },
8627
+ { symbol: 'D', value: 500 },
8628
+ { symbol: 'CD', value: 400 },
8629
+ { symbol: 'C', value: 100 },
8630
+ { symbol: 'XC', value: 90 },
8631
+ { symbol: 'L', value: 50 },
8632
+ { symbol: 'XL', value: 40 },
8633
+ { symbol: 'X', value: 10 },
8634
+ { symbol: 'IX', value: 9 },
8635
+ { symbol: 'V', value: 5 },
8636
+ { symbol: 'IV', value: 4 },
8637
+ { symbol: 'I', value: 1 },
8638
+ ];
8639
+ let remaining = Math.max(1, Math.floor(value));
8640
+ let result = '';
8641
+ for (const entry of romanTable) {
8642
+ while (remaining >= entry.value) {
8643
+ result += entry.symbol;
8644
+ remaining -= entry.value;
8645
+ }
8646
+ }
8647
+ return result;
8648
+ }
8649
+ /**
8650
+ * Builds Roman numeral parameter name used in prompt placeholders.
8651
+ *
8652
+ * @param index Zero-based parameter index.
8653
+ */
8654
+ function buildRomanParameterName(index) {
8655
+ return toRomanNumeral(index + 1);
8656
+ }
8657
+ /**
8658
+ * Creates a parameter name builder that prefixes another builder.
8659
+ *
8660
+ * @param prefix Prefix to add.
8661
+ * @param builder Base builder to wrap.
8662
+ */
8663
+ function buildPrefixedParameterName(prefix, builder) {
8664
+ return (index) => `${prefix}${builder(index)}`;
8665
+ }
8666
+ /**
8667
+ * Ordered list of strategies for parameter naming.
8668
+ */
8669
+ const PARAMETER_NAME_STRATEGIES = [
8670
+ { buildName: buildNumericParameterName },
8671
+ { buildName: buildAlphabeticParameterName },
8672
+ { buildName: buildRomanParameterName },
8673
+ { buildName: buildPrefixedParameterName('p', buildNumericParameterName) },
8674
+ { buildName: buildPrefixedParameterName('p', buildAlphabeticParameterName) },
8675
+ ];
8676
+ /**
8677
+ * Collects bracketed tokens from parameter values to avoid placeholder collisions.
8678
+ *
8679
+ * @param values Parameter values to scan.
8680
+ */
8681
+ function collectBracketedParameterTokens(values) {
8682
+ const tokens = new Set();
8683
+ for (const value of values) {
8684
+ const pattern = /{(\w+)}/g;
8685
+ let match;
8686
+ while ((match = pattern.exec(value)) !== null) {
8687
+ const token = match[1];
8688
+ if (token) {
8689
+ tokens.add(token);
8690
+ }
8691
+ }
8692
+ }
8693
+ return tokens;
8694
+ }
8695
+ /**
8696
+ * Builds parameter names used in prompt placeholders while avoiding collisions.
8697
+ *
8698
+ * @param values Parameter values to scan for conflicting tokens.
8699
+ */
8700
+ function buildParameterNames(values) {
8701
+ const count = values.length;
8702
+ if (count === 0) {
8703
+ return [];
8704
+ }
8705
+ const conflicts = collectBracketedParameterTokens(values);
8706
+ for (const strategy of PARAMETER_NAME_STRATEGIES) {
8707
+ const names = Array.from({ length: count }, (_, index) => strategy.buildName(index));
8708
+ const hasConflict = names.some((name) => conflicts.has(name));
8709
+ if (!hasConflict) {
8710
+ return names;
8711
+ }
8712
+ }
8713
+ return Array.from({ length: count }, (_, index) => `${REPLACING_NONCE}${index + 1}`);
8714
+ }
8603
8715
  /**
8604
8716
  * Formats the placeholder used in the prompt body for a parameter.
8605
8717
  *
@@ -8654,26 +8766,40 @@ function prompt(strings, ...values) {
8654
8766
  return new PromptString(spaceTrim$2(strings.join('')));
8655
8767
  }
8656
8768
  const stringsWithHiddenParameters = strings.map((stringsItem) => hideBrackets(stringsItem));
8657
- const parameterEntries = values.map((value, index) => {
8658
- const name = buildParameterName(index);
8769
+ const parameterMetadata = values.map((value) => {
8659
8770
  const isPrompt = isPromptString(value);
8660
8771
  const stringValue = isPrompt ? value.toString() : valueToString(value);
8661
8772
  const isInline = isPrompt ? true : shouldInlineParameterValue(stringValue);
8662
8773
  const jsonValue = !isPrompt && !isInline ? normalizeJsonString(stringValue) : null;
8774
+ return { isPrompt, stringValue, isInline, jsonValue };
8775
+ });
8776
+ const parameterNames = buildParameterNames(parameterMetadata.map((entry) => entry.stringValue));
8777
+ const parameterEntries = parameterMetadata.map((entry, index) => {
8778
+ var _a;
8779
+ const name = (_a = parameterNames[index]) !== null && _a !== void 0 ? _a : buildNumericParameterName(index);
8663
8780
  const promptMarker = `${REPLACING_NONCE}prompt-${index}`;
8664
8781
  const parameterMarker = `${REPLACING_NONCE}parameter-${index}`;
8665
- const templateValue = isPrompt
8782
+ const templateValue = entry.isPrompt
8666
8783
  ? promptMarker
8667
- : isInline
8668
- ? escapePromptParameterValue(stringValue, { includeBraces: false })
8784
+ : entry.isInline
8785
+ ? escapePromptParameterValue(entry.stringValue, { includeBraces: false })
8669
8786
  : parameterMarker;
8670
- return { name, stringValue, jsonValue, isPrompt, isInline, promptMarker, parameterMarker, templateValue };
8787
+ return {
8788
+ name,
8789
+ stringValue: entry.stringValue,
8790
+ jsonValue: entry.jsonValue,
8791
+ isPrompt: entry.isPrompt,
8792
+ isInline: entry.isInline,
8793
+ promptMarker,
8794
+ parameterMarker,
8795
+ templateValue,
8796
+ };
8671
8797
  });
8672
8798
  const parameters = Object.fromEntries(parameterEntries.map((entry) => [entry.name, entry.templateValue]));
8673
- const parameterNames = parameterEntries.map((entry) => entry.name);
8799
+ const parameterNamesOrdered = parameterEntries.map((entry) => entry.name);
8674
8800
  // Combine strings and values
8675
8801
  let pipelineString = stringsWithHiddenParameters.reduce((result, stringsItem, i) => {
8676
- const parameterName = parameterNames[i];
8802
+ const parameterName = parameterNamesOrdered[i];
8677
8803
  return parameterName === undefined
8678
8804
  ? `${result}${stringsItem}`
8679
8805
  : `${result}${stringsItem}${formatParameterPlaceholder(parameterName)}`;
@@ -8686,7 +8812,7 @@ function prompt(strings, ...values) {
8686
8812
  if (!(error instanceof PipelineExecutionError)) {
8687
8813
  throw error;
8688
8814
  }
8689
- console.error({ pipelineString, parameters, parameterNames, error });
8815
+ console.error({ pipelineString, parameters, parameterNames: parameterNamesOrdered, error });
8690
8816
  throw new UnexpectedError(spaceTrim$2((block) => `
8691
8817
  Internal error in prompt template literal
8692
8818
 
@@ -8701,9 +8827,7 @@ function prompt(strings, ...values) {
8701
8827
  continue;
8702
8828
  }
8703
8829
  if (!entry.isInline) {
8704
- pipelineString = pipelineString
8705
- .split(entry.parameterMarker)
8706
- .join(formatParameterPlaceholder(entry.name));
8830
+ pipelineString = pipelineString.split(entry.parameterMarker).join(formatParameterPlaceholder(entry.name));
8707
8831
  }
8708
8832
  }
8709
8833
  const structuredParameters = parameterEntries.filter((entry) => !entry.isPrompt && !entry.isInline);
@@ -10118,60 +10242,12 @@ function getLinguisticHashLanguageConfig(language) {
10118
10242
  return LANGUAGE_CONFIGS[normalized];
10119
10243
  }
10120
10244
 
10121
- // <- TODO: !!!! Remove re-exports
10122
- /**
10123
- * Creates a human-readable hash as a short, story-like phrase.
10124
- *
10125
- * @param wordCount how many words to include (defaults to {@link DEFAULT_LINGUISTIC_HASH_WORD_COUNT}, clamped to
10126
- * {@link MIN_LINGUISTIC_HASH_WORD_COUNT}..{@link MAX_LINGUISTIC_HASH_WORD_COUNT})
10127
- * @param language optional language code (defaults to {@link DEFAULT_LINGUISTIC_HASH_LANGUAGE})
10128
- *
10129
- * @public exported from `@promptbook/utils`
10130
- */
10131
- async function linguisticHash(input, wordCount, language) {
10132
- const hash = computeHash(input);
10133
- const normalizedWordCount = normalizeLinguisticHashWordCount(wordCount);
10134
- const languageConfig = getLinguisticHashLanguageConfig(language);
10135
- const words = createLinguisticHashWords(hash, normalizedWordCount, languageConfig.wordLists);
10136
- return capitalize(words.join(' '));
10137
- }
10138
10245
  /**
10139
10246
  * @@@
10140
10247
  *
10141
10248
  * @private utility of `linguisticHash`
10142
10249
  */
10143
10250
  const HASH_SEGMENT_LENGTH = 8;
10144
- /**
10145
- * The minimum number of words for a linguistic hash.
10146
- *
10147
- * @private utility of `linguisticHash`
10148
- */
10149
- const MIN_LINGUISTIC_HASH_WORD_COUNT = 1;
10150
- /**
10151
- * The default number of words for a linguistic hash.
10152
- *
10153
- * @private utility of `linguisticHash`
10154
- */
10155
- const DEFAULT_LINGUISTIC_HASH_WORD_COUNT = 7;
10156
- /**
10157
- * Extracts a deterministic numeric seed from a SHA-256 hash.
10158
- *
10159
- * @private utility of `linguisticHash`
10160
- */
10161
- function getHashSeed(hash, segmentIndex) {
10162
- const expandedHash = `${hash}${hash}`;
10163
- const start = (segmentIndex * HASH_SEGMENT_LENGTH + segmentIndex) % hash.length;
10164
- return parseInt(expandedHash.substring(start, start + HASH_SEGMENT_LENGTH), 16);
10165
- }
10166
- /**
10167
- * Picks a deterministic item from a list based on the hash seed.
10168
- *
10169
- * @private utility of `linguisticHash`
10170
- */
10171
- function pickFromHash(hash, segmentIndex, list) {
10172
- const seed = getHashSeed(hash, segmentIndex);
10173
- return list[seed % list.length];
10174
- }
10175
10251
  /**
10176
10252
  * Ordered word kinds used to build the linguistic hash output.
10177
10253
  *
@@ -10212,16 +10288,23 @@ const MAX_LINGUISTIC_HASH_WORD_COUNT = WORD_SEQUENCE.length;
10212
10288
  */
10213
10289
  const SINGLE_WORD_INDEX = 1;
10214
10290
  /**
10215
- * Normalizes the word count to a supported integer range.
10291
+ * Extracts a deterministic numeric seed from a SHA-256 hash.
10216
10292
  *
10217
10293
  * @private utility of `linguisticHash`
10218
10294
  */
10219
- function normalizeLinguisticHashWordCount(wordCount) {
10220
- if (typeof wordCount !== 'number' || !Number.isFinite(wordCount)) {
10221
- return DEFAULT_LINGUISTIC_HASH_WORD_COUNT;
10222
- }
10223
- const rounded = Math.round(wordCount);
10224
- return Math.min(MAX_LINGUISTIC_HASH_WORD_COUNT, Math.max(MIN_LINGUISTIC_HASH_WORD_COUNT, rounded));
10295
+ function getHashSeed(hash, segmentIndex) {
10296
+ const expandedHash = `${hash}${hash}`;
10297
+ const start = (segmentIndex * HASH_SEGMENT_LENGTH + segmentIndex) % hash.length;
10298
+ return parseInt(expandedHash.substring(start, start + HASH_SEGMENT_LENGTH), 16);
10299
+ }
10300
+ /**
10301
+ * Picks a deterministic item from a list based on the hash seed.
10302
+ *
10303
+ * @private utility of `linguisticHash`
10304
+ */
10305
+ function pickFromHash(hash, segmentIndex, list) {
10306
+ const seed = getHashSeed(hash, segmentIndex);
10307
+ return list[seed % list.length];
10225
10308
  }
10226
10309
  /**
10227
10310
  * Picks a deterministic word from the hash by kind.
@@ -10252,6 +10335,49 @@ function createLinguisticHashWords(hash, wordCount, wordLists) {
10252
10335
  return words.slice(0, wordCount);
10253
10336
  }
10254
10337
 
10338
+ /**
10339
+ * The minimum number of words for a linguistic hash.
10340
+ *
10341
+ * @private utility of `linguisticHash`
10342
+ */
10343
+ const MIN_LINGUISTIC_HASH_WORD_COUNT = 1;
10344
+ /**
10345
+ * The default number of words for a linguistic hash.
10346
+ *
10347
+ * @private utility of `linguisticHash`
10348
+ */
10349
+ const DEFAULT_LINGUISTIC_HASH_WORD_COUNT = 7;
10350
+ /**
10351
+ * Normalizes the word count to a supported integer range.
10352
+ *
10353
+ * @private utility of `linguisticHash`
10354
+ */
10355
+ function normalizeLinguisticHashWordCount(wordCount) {
10356
+ if (typeof wordCount !== 'number' || !Number.isFinite(wordCount)) {
10357
+ return DEFAULT_LINGUISTIC_HASH_WORD_COUNT;
10358
+ }
10359
+ const rounded = Math.round(wordCount);
10360
+ return Math.min(MAX_LINGUISTIC_HASH_WORD_COUNT, Math.max(MIN_LINGUISTIC_HASH_WORD_COUNT, rounded));
10361
+ }
10362
+
10363
+ // <- TODO: !!!! Remove re-exports
10364
+ /**
10365
+ * Creates a human-readable hash as a short, story-like phrase.
10366
+ *
10367
+ * @param wordCount how many words to include (defaults to {@link DEFAULT_LINGUISTIC_HASH_WORD_COUNT}, clamped to
10368
+ * {@link MIN_LINGUISTIC_HASH_WORD_COUNT}..{@link MAX_LINGUISTIC_HASH_WORD_COUNT})
10369
+ * @param language optional language code (defaults to {@link DEFAULT_LINGUISTIC_HASH_LANGUAGE})
10370
+ *
10371
+ * @public exported from `@promptbook/utils`
10372
+ */
10373
+ async function linguisticHash(input, wordCount, language) {
10374
+ const hash = computeHash(input);
10375
+ const normalizedWordCount = normalizeLinguisticHashWordCount(wordCount);
10376
+ const languageConfig = getLinguisticHashLanguageConfig(language);
10377
+ const words = createLinguisticHashWords(hash, normalizedWordCount, languageConfig.wordLists);
10378
+ return capitalize(words.join(' '));
10379
+ }
10380
+
10255
10381
  /**
10256
10382
  * Simple wrapper `new Date().toISOString()`
10257
10383
  *
@@ -15835,8 +15961,6 @@ function $randomBase58(length) {
15835
15961
  return result;
15836
15962
  }
15837
15963
 
15838
- // import { getTableName } from '../../../../../apps/agents-server/src/database/getTableName';
15839
- // <- TODO: [🐱‍🚀] Prevent imports from `/apps` -> `/src`
15840
15964
  /**
15841
15965
  * Agent collection stored in a Supabase table.
15842
15966
  *
@@ -15941,8 +16065,11 @@ class AgentCollectionInSupabase /* TODO: [🌈][🐱‍🚀] implements AgentCol
15941
16065
  * Creates a new agent in the collection
15942
16066
  *
15943
16067
  * Note: You can set 'PARENT' in the agent source to inherit from another agent in the collection.
16068
+ *
16069
+ * @param agentSource - Source content of the agent.
16070
+ * @param options - Optional folder placement and ordering data.
15944
16071
  */
15945
- async createAgent(agentSource) {
16072
+ async createAgent(agentSource, options = {}) {
15946
16073
  let agentProfile = parseAgentSource(agentSource);
15947
16074
  // <- TODO: [🕛]
15948
16075
  // 1. Extract permanentId from the source if present
@@ -15959,7 +16086,7 @@ class AgentCollectionInSupabase /* TODO: [🌈][🐱‍🚀] implements AgentCol
15959
16086
  if (!permanentId) {
15960
16087
  permanentId = $randomBase58(14);
15961
16088
  }
15962
- const insertAgentResult = await this.supabaseClient.from(this.getTableName('Agent')).insert({
16089
+ const insertPayload = {
15963
16090
  agentName,
15964
16091
  agentHash,
15965
16092
  permanentId,
@@ -15969,7 +16096,14 @@ class AgentCollectionInSupabase /* TODO: [🌈][🐱‍🚀] implements AgentCol
15969
16096
  promptbookEngineVersion: PROMPTBOOK_ENGINE_VERSION,
15970
16097
  usage: ZERO_USAGE,
15971
16098
  agentSource: agentSource,
15972
- });
16099
+ };
16100
+ if (options.folderId !== undefined) {
16101
+ insertPayload.folderId = options.folderId;
16102
+ }
16103
+ if (options.sortOrder !== undefined) {
16104
+ insertPayload.sortOrder = options.sortOrder;
16105
+ }
16106
+ const insertAgentResult = await this.supabaseClient.from(this.getTableName('Agent')).insert(insertPayload);
15973
16107
  if (insertAgentResult.error) {
15974
16108
  throw new DatabaseError(spaceTrim((block) => `
15975
16109
  Error creating agent "${agentProfile.agentName}" in Supabase:
@@ -16036,7 +16170,7 @@ class AgentCollectionInSupabase /* TODO: [🌈][🐱‍🚀] implements AgentCol
16036
16170
  const updateAgentResult = await this.supabaseClient
16037
16171
  .from(this.getTableName('Agent'))
16038
16172
  .update({
16039
- // TODO: [🐱‍🚀] Compare not update> agentName: agentProfile.agentName || '[🐱‍🚀]' /* <- TODO: [🐱‍🚀] Remove */,
16173
+ agentName,
16040
16174
  permanentId,
16041
16175
  agentProfile,
16042
16176
  updatedAt: new Date().toISOString(),
@@ -20975,14 +21109,27 @@ function humanizeAiTextEmdashed(aiText) {
20975
21109
  * @public exported from `@promptbook/markdown-utils`
20976
21110
  */
20977
21111
  function humanizeAiTextQuotes(aiText) {
20978
- return aiText
20979
- .replace(/[“”„‟«»❝❞〝〞〟"]/g, '"')
20980
- .replace(/[‚‘’‛‹›❛❜'ʼ]/g, "'");
21112
+ return aiText.replace(/[“”„‟«»❝❞〝〞〟"]/g, '"').replace(/[‚‘’‛‹›❛❜'ʼ]/g, "'");
20981
21113
  }
20982
21114
  /**
20983
21115
  * Note: [🏂] This function is not tested by itself but together with other cleanup functions with `humanizeAiText`
20984
21116
  */
20985
21117
 
21118
+ /**
21119
+ * Remove bracketed source citation artifacts like `\u30105:1\u2020source\u3011`.
21120
+ *
21121
+ * Note: [??] This function is idempotent.
21122
+ * Tip: If you want to do the full cleanup, look for `humanizeAiText` exported `@promptbook/markdown-utils`
21123
+ *
21124
+ * @public exported from `@promptbook/markdown-utils`
21125
+ */
21126
+ function humanizeAiTextSources(aiText) {
21127
+ return aiText.replace(/[ \t]*\u3010\s*\d+(?:\s*:\s*\d+)?\s*\u2020source\s*\u3011/g, '');
21128
+ }
21129
+ /**
21130
+ * Note: [??] This function is not tested by itself but together with other cleanup functions with `humanizeAiText`
21131
+ */
21132
+
20986
21133
  /**
20987
21134
  * Change unprintable hard spaces to regular spaces and drop zero-width spaces
20988
21135
  *
@@ -20992,9 +21139,7 @@ function humanizeAiTextQuotes(aiText) {
20992
21139
  * @public exported from `@promptbook/markdown-utils`
20993
21140
  */
20994
21141
  function humanizeAiTextWhitespace(aiText) {
20995
- return aiText
20996
- .replace(/[\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000]/g, ' ')
20997
- .replace(/[\u200B\uFEFF\u2060]/g, '');
21142
+ return aiText.replace(/[\u00A0\u1680\u2000-\u200A\u202F\u205F\u3000]/g, ' ').replace(/[\u200B\uFEFF\u2060]/g, '');
20998
21143
  }
20999
21144
  /**
21000
21145
  * Note: [🏂] This function is not tested by itself but together with other cleanup functions with `humanizeAiText`
@@ -21013,6 +21158,7 @@ function humanizeAiText(aiText) {
21013
21158
  cleanedText = humanizeAiTextEllipsis(cleanedText);
21014
21159
  cleanedText = humanizeAiTextEmdashed(cleanedText);
21015
21160
  cleanedText = humanizeAiTextQuotes(cleanedText);
21161
+ cleanedText = humanizeAiTextSources(cleanedText);
21016
21162
  cleanedText = humanizeAiTextWhitespace(cleanedText);
21017
21163
  return cleanedText;
21018
21164
  }
@@ -23503,17 +23649,32 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
23503
23649
  });
23504
23650
  }
23505
23651
  async createNewAssistant(options) {
23652
+ var _a, _b, _c;
23506
23653
  if (!this.isCreatingNewAssistantsAllowed) {
23507
23654
  throw new NotAllowed(`Creating new assistants is not allowed. Set \`isCreatingNewAssistantsAllowed: true\` in options to enable this feature.`);
23508
23655
  }
23509
23656
  // await this.playground();
23510
23657
  const { name, instructions, knowledgeSources, tools } = options;
23658
+ const preparationStartedAtMs = Date.now();
23659
+ const knowledgeSourcesCount = (_a = knowledgeSources === null || knowledgeSources === void 0 ? void 0 : knowledgeSources.length) !== null && _a !== void 0 ? _a : 0;
23660
+ const toolsCount = (_b = tools === null || tools === void 0 ? void 0 : tools.length) !== null && _b !== void 0 ? _b : 0;
23661
+ if (this.options.isVerbose) {
23662
+ console.info('[🤰]', 'Starting OpenAI assistant creation', {
23663
+ name,
23664
+ knowledgeSourcesCount,
23665
+ toolsCount,
23666
+ instructionsLength: instructions.length,
23667
+ });
23668
+ }
23511
23669
  const client = await this.getClient();
23512
23670
  let vectorStoreId;
23513
23671
  // If knowledge sources are provided, create a vector store with them
23514
23672
  if (knowledgeSources && knowledgeSources.length > 0) {
23515
23673
  if (this.options.isVerbose) {
23516
- console.info(`📚 Creating vector store with ${knowledgeSources.length} knowledge sources...`);
23674
+ console.info('[🤰]', 'Creating vector store with knowledge sources', {
23675
+ name,
23676
+ knowledgeSourcesCount,
23677
+ });
23517
23678
  }
23518
23679
  // Create a vector store
23519
23680
  const vectorStore = await client.beta.vectorStores.create({
@@ -23521,12 +23682,22 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
23521
23682
  });
23522
23683
  vectorStoreId = vectorStore.id;
23523
23684
  if (this.options.isVerbose) {
23524
- console.info(`✅ Vector store created: ${vectorStoreId}`);
23685
+ console.info('[🤰]', 'Vector store created', {
23686
+ vectorStoreId,
23687
+ });
23525
23688
  }
23526
23689
  // Upload files from knowledge sources to the vector store
23527
23690
  const fileStreams = [];
23528
- for (const source of knowledgeSources) {
23691
+ for (const [index, source] of knowledgeSources.entries()) {
23529
23692
  try {
23693
+ if (this.options.isVerbose) {
23694
+ console.info('[🤰]', 'Processing knowledge source', {
23695
+ index: index + 1,
23696
+ total: knowledgeSources.length,
23697
+ source,
23698
+ sourceType: source.startsWith('http') || source.startsWith('https') ? 'url' : 'file',
23699
+ });
23700
+ }
23530
23701
  // Check if it's a URL
23531
23702
  if (source.startsWith('http://') || source.startsWith('https://')) {
23532
23703
  // Download the file
@@ -23571,7 +23742,10 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
23571
23742
  files: fileStreams,
23572
23743
  });
23573
23744
  if (this.options.isVerbose) {
23574
- console.info(`✅ Uploaded ${fileStreams.length} files to vector store`);
23745
+ console.info('[🤰]', 'Uploaded files to vector store', {
23746
+ vectorStoreId,
23747
+ fileCount: fileStreams.length,
23748
+ });
23575
23749
  }
23576
23750
  }
23577
23751
  catch (error) {
@@ -23599,8 +23773,21 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
23599
23773
  },
23600
23774
  };
23601
23775
  }
23776
+ if (this.options.isVerbose) {
23777
+ console.info('[🤰]', 'Creating OpenAI assistant', {
23778
+ name,
23779
+ model: assistantConfig.model,
23780
+ toolCount: (_c = assistantConfig === null || assistantConfig === void 0 ? void 0 : assistantConfig.tools) === null || _c === void 0 ? void 0 : _c.length,
23781
+ hasVectorStore: Boolean(vectorStoreId),
23782
+ });
23783
+ }
23602
23784
  const assistant = await client.beta.assistants.create(assistantConfig);
23603
- console.log(`✅ Assistant created: ${assistant.id}`);
23785
+ if (this.options.isVerbose) {
23786
+ console.info('[🤰]', 'OpenAI assistant created', {
23787
+ assistantId: assistant.id,
23788
+ elapsedMs: Date.now() - preparationStartedAtMs,
23789
+ });
23790
+ }
23604
23791
  // TODO: [🐱‍🚀] Try listing existing assistants
23605
23792
  // TODO: [🐱‍🚀] Try marking existing assistants by DISCRIMINANT
23606
23793
  // TODO: [🐱‍🚀] Allow to update and reconnect to existing assistants
@@ -23611,17 +23798,34 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
23611
23798
  });
23612
23799
  }
23613
23800
  async updateAssistant(options) {
23801
+ var _a, _b, _c, _d;
23614
23802
  if (!this.isCreatingNewAssistantsAllowed) {
23615
23803
  throw new NotAllowed(`Updating assistants is not allowed. Set \`isCreatingNewAssistantsAllowed: true\` in options to enable this feature.`);
23616
23804
  }
23617
23805
  const { assistantId, name, instructions, knowledgeSources, tools } = options;
23806
+ const preparationStartedAtMs = Date.now();
23807
+ const knowledgeSourcesCount = (_a = knowledgeSources === null || knowledgeSources === void 0 ? void 0 : knowledgeSources.length) !== null && _a !== void 0 ? _a : 0;
23808
+ const toolsCount = (_b = tools === null || tools === void 0 ? void 0 : tools.length) !== null && _b !== void 0 ? _b : 0;
23809
+ if (this.options.isVerbose) {
23810
+ console.info('[🤰]', 'Starting OpenAI assistant update', {
23811
+ assistantId,
23812
+ name,
23813
+ knowledgeSourcesCount,
23814
+ toolsCount,
23815
+ instructionsLength: (_c = instructions === null || instructions === void 0 ? void 0 : instructions.length) !== null && _c !== void 0 ? _c : 0,
23816
+ });
23817
+ }
23618
23818
  const client = await this.getClient();
23619
23819
  let vectorStoreId;
23620
23820
  // If knowledge sources are provided, create a vector store with them
23621
23821
  // TODO: [🧠] Reuse vector store creation logic from createNewAssistant
23622
23822
  if (knowledgeSources && knowledgeSources.length > 0) {
23623
23823
  if (this.options.isVerbose) {
23624
- console.info(`📚 Creating vector store for update with ${knowledgeSources.length} knowledge sources...`);
23824
+ console.info('[🤰]', 'Creating vector store for assistant update', {
23825
+ assistantId,
23826
+ name,
23827
+ knowledgeSourcesCount,
23828
+ });
23625
23829
  }
23626
23830
  // Create a vector store
23627
23831
  const vectorStore = await client.beta.vectorStores.create({
@@ -23629,12 +23833,22 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
23629
23833
  });
23630
23834
  vectorStoreId = vectorStore.id;
23631
23835
  if (this.options.isVerbose) {
23632
- console.info(`✅ Vector store created: ${vectorStoreId}`);
23836
+ console.info('[🤰]', 'Vector store created for assistant update', {
23837
+ vectorStoreId,
23838
+ });
23633
23839
  }
23634
23840
  // Upload files from knowledge sources to the vector store
23635
23841
  const fileStreams = [];
23636
- for (const source of knowledgeSources) {
23842
+ for (const [index, source] of knowledgeSources.entries()) {
23637
23843
  try {
23844
+ if (this.options.isVerbose) {
23845
+ console.info('[🤰]', 'Processing knowledge source for update', {
23846
+ index: index + 1,
23847
+ total: knowledgeSources.length,
23848
+ source,
23849
+ sourceType: source.startsWith('http') || source.startsWith('https') ? 'url' : 'file',
23850
+ });
23851
+ }
23638
23852
  // Check if it's a URL
23639
23853
  if (source.startsWith('http://') || source.startsWith('https://')) {
23640
23854
  // Download the file
@@ -23679,7 +23893,10 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
23679
23893
  files: fileStreams,
23680
23894
  });
23681
23895
  if (this.options.isVerbose) {
23682
- console.info(`✅ Uploaded ${fileStreams.length} files to vector store`);
23896
+ console.info('[🤰]', 'Uploaded files to vector store for update', {
23897
+ vectorStoreId,
23898
+ fileCount: fileStreams.length,
23899
+ });
23683
23900
  }
23684
23901
  }
23685
23902
  catch (error) {
@@ -23703,9 +23920,20 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
23703
23920
  },
23704
23921
  };
23705
23922
  }
23923
+ if (this.options.isVerbose) {
23924
+ console.info('[🤰]', 'Updating OpenAI assistant', {
23925
+ assistantId,
23926
+ name,
23927
+ toolCount: (_d = assistantUpdate === null || assistantUpdate === void 0 ? void 0 : assistantUpdate.tools) === null || _d === void 0 ? void 0 : _d.length,
23928
+ hasVectorStore: Boolean(vectorStoreId),
23929
+ });
23930
+ }
23706
23931
  const assistant = await client.beta.assistants.update(assistantId, assistantUpdate);
23707
23932
  if (this.options.isVerbose) {
23708
- console.log(`✅ Assistant updated: ${assistant.id}`);
23933
+ console.info('[🤰]', 'OpenAI assistant updated', {
23934
+ assistantId: assistant.id,
23935
+ elapsedMs: Date.now() - preparationStartedAtMs,
23936
+ });
23709
23937
  }
23710
23938
  return new OpenAiAssistantExecutionTools({
23711
23939
  ...this.options,
@@ -23764,7 +23992,7 @@ function emitAssistantPreparationProgress(options) {
23764
23992
  toolCalls: [
23765
23993
  {
23766
23994
  name: ASSISTANT_PREPARATION_TOOL_CALL_NAME,
23767
- arguments: {},
23995
+ arguments: options.phase ? { phase: options.phase } : {},
23768
23996
  createdAt: startedAt,
23769
23997
  },
23770
23998
  ],
@@ -23828,10 +24056,32 @@ class AgentLlmExecutionTools {
23828
24056
  */
23829
24057
  async getModelRequirements() {
23830
24058
  if (this._cachedModelRequirements === null) {
24059
+ const preparationStartedAtMs = Date.now();
24060
+ if (this.options.isVerbose) {
24061
+ console.info('[🤰]', 'Preparing agent model requirements', {
24062
+ agent: this.title,
24063
+ });
24064
+ }
23831
24065
  // Get available models from underlying LLM tools for best model selection
24066
+ const availableModelsStartedAtMs = Date.now();
23832
24067
  const availableModels = await this.options.llmTools.listModels();
24068
+ if (this.options.isVerbose) {
24069
+ console.info('[🤰]', 'Available models resolved for agent', {
24070
+ agent: this.title,
24071
+ modelCount: availableModels.length,
24072
+ elapsedMs: Date.now() - availableModelsStartedAtMs,
24073
+ });
24074
+ }
24075
+ const requirementsStartedAtMs = Date.now();
23833
24076
  this._cachedModelRequirements = await createAgentModelRequirements(this.options.agentSource, undefined, // Let the function pick the best model
23834
24077
  availableModels);
24078
+ if (this.options.isVerbose) {
24079
+ console.info('[🤰]', 'Agent model requirements ready', {
24080
+ agent: this.title,
24081
+ elapsedMs: Date.now() - requirementsStartedAtMs,
24082
+ totalElapsedMs: Date.now() - preparationStartedAtMs,
24083
+ });
24084
+ }
23835
24085
  }
23836
24086
  return this._cachedModelRequirements;
23837
24087
  }
@@ -23985,18 +24235,25 @@ class AgentLlmExecutionTools {
23985
24235
  if (cached) {
23986
24236
  if (cached.requirementsHash === requirementsHash) {
23987
24237
  if (this.options.isVerbose) {
23988
- console.log(`1️⃣ Using cached OpenAI Assistant for agent ${this.title}...`);
24238
+ console.info('[🤰]', 'Using cached OpenAI Assistant', {
24239
+ agent: this.title,
24240
+ assistantId: cached.assistantId,
24241
+ });
23989
24242
  }
23990
24243
  assistant = this.options.llmTools.getAssistant(cached.assistantId);
23991
24244
  }
23992
24245
  else {
23993
24246
  if (this.options.isVerbose) {
23994
- console.log(`1️⃣ Updating OpenAI Assistant for agent ${this.title}...`);
24247
+ console.info('[🤰]', 'Updating OpenAI Assistant', {
24248
+ agent: this.title,
24249
+ assistantId: cached.assistantId,
24250
+ });
23995
24251
  }
23996
24252
  emitAssistantPreparationProgress({
23997
24253
  onProgress,
23998
24254
  prompt,
23999
24255
  modelName: this.modelName,
24256
+ phase: 'Updating assistant',
24000
24257
  });
24001
24258
  assistant = await this.options.llmTools.updateAssistant({
24002
24259
  assistantId: cached.assistantId,
@@ -24013,13 +24270,16 @@ class AgentLlmExecutionTools {
24013
24270
  }
24014
24271
  else {
24015
24272
  if (this.options.isVerbose) {
24016
- console.log(`1️⃣ Creating new OpenAI Assistant for agent ${this.title}...`);
24273
+ console.info('[🤰]', 'Creating new OpenAI Assistant', {
24274
+ agent: this.title,
24275
+ });
24017
24276
  }
24018
24277
  // <- TODO: [🐱‍🚀] Check also `isCreatingNewAssistantsAllowed` and warn about it
24019
24278
  emitAssistantPreparationProgress({
24020
24279
  onProgress,
24021
24280
  prompt,
24022
24281
  modelName: this.modelName,
24282
+ phase: 'Creating assistant',
24023
24283
  });
24024
24284
  assistant = await this.options.llmTools.createNewAssistant({
24025
24285
  name: this.title,
@@ -24093,6 +24353,65 @@ AgentLlmExecutionTools.vectorStoreCache = new Map();
24093
24353
  */
24094
24354
 
24095
24355
  var _Agent_instances, _Agent_selfLearnNonce, _Agent_selfLearnSamples, _Agent_selfLearnTeacher;
24356
+ /**
24357
+ * Creates an empty commitment breakdown for self-learning summaries.
24358
+ */
24359
+ function createEmptySelfLearningCommitmentCounts() {
24360
+ return {
24361
+ total: 0,
24362
+ knowledge: 0,
24363
+ rule: 0,
24364
+ persona: 0,
24365
+ other: 0,
24366
+ };
24367
+ }
24368
+ /**
24369
+ * Normalizes teacher commitments into trimmed, display-ready lines.
24370
+ */
24371
+ function getTeacherCommitmentLines(commitments) {
24372
+ return commitments
24373
+ .split(/\r?\n/)
24374
+ .map((line) => line.trim())
24375
+ .filter((line) => line.length > 0 && line !== '---' && !line.startsWith('```'));
24376
+ }
24377
+ /**
24378
+ * Summarizes teacher commitment lines into user-friendly counts for self-learning.
24379
+ */
24380
+ function summarizeTeacherCommitmentLines(lines) {
24381
+ var _a, _b;
24382
+ const counts = createEmptySelfLearningCommitmentCounts();
24383
+ for (const line of lines) {
24384
+ const keyword = (_b = (_a = line.split(/\s+/)[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase()) !== null && _b !== void 0 ? _b : '';
24385
+ if (!/^[A-Z][A-Z_-]*$/.test(keyword)) {
24386
+ continue;
24387
+ }
24388
+ counts.total += 1;
24389
+ if (keyword === 'KNOWLEDGE') {
24390
+ counts.knowledge += 1;
24391
+ }
24392
+ else if (keyword === 'RULE') {
24393
+ counts.rule += 1;
24394
+ }
24395
+ else if (keyword === 'PERSONA') {
24396
+ counts.persona += 1;
24397
+ }
24398
+ else {
24399
+ counts.other += 1;
24400
+ }
24401
+ }
24402
+ return counts;
24403
+ }
24404
+ /**
24405
+ * Builds the teacher summary payload for the self-learning tool call.
24406
+ */
24407
+ function buildTeacherSummary(commitments, used) {
24408
+ const commitmentLines = getTeacherCommitmentLines(commitments);
24409
+ return {
24410
+ used,
24411
+ commitmentTypes: summarizeTeacherCommitmentLines(commitmentLines),
24412
+ commitments: commitmentLines.length > 0 ? commitmentLines : undefined,
24413
+ };
24414
+ }
24096
24415
  /**
24097
24416
  * Represents one AI Agent
24098
24417
  *
@@ -24267,16 +24586,29 @@ class Agent extends AgentLlmExecutionTools {
24267
24586
  // Note: [2] Do the append of the samples
24268
24587
  await __classPrivateFieldGet(this, _Agent_instances, "m", _Agent_selfLearnSamples).call(this, prompt, result);
24269
24588
  // Note: [3] Asynchronously call the teacher agent and invoke the silver link. When the teacher fails, keep just the samples
24270
- await __classPrivateFieldGet(this, _Agent_instances, "m", _Agent_selfLearnTeacher).call(this, prompt, result).catch((error) => {
24589
+ let teacherSummary = null;
24590
+ try {
24591
+ teacherSummary = await __classPrivateFieldGet(this, _Agent_instances, "m", _Agent_selfLearnTeacher).call(this, prompt, result);
24592
+ }
24593
+ catch (error) {
24271
24594
  // !!!!! if (this.options.isVerbose) {
24272
24595
  console.error(colors.bgCyan('[Self-learning]') + colors.red(' Failed to learn from teacher agent'));
24273
24596
  console.error(error);
24274
24597
  // }
24275
- });
24598
+ teacherSummary = this.teacherAgent ? buildTeacherSummary('', true) : null;
24599
+ }
24276
24600
  // Note: [4] Notify end of self-learning
24601
+ const completedAt = new Date().toISOString();
24602
+ const selfLearningResult = {
24603
+ success: true,
24604
+ startedAt: selfLearningToolCall.createdAt,
24605
+ completedAt,
24606
+ samplesAdded: 1,
24607
+ teacher: teacherSummary || undefined,
24608
+ };
24277
24609
  const completedSelfLearningToolCall = {
24278
24610
  ...selfLearningToolCall,
24279
- result: { success: true },
24611
+ result: selfLearningResult,
24280
24612
  };
24281
24613
  const finalResult = {
24282
24614
  ...result,
@@ -24325,7 +24657,7 @@ async function _Agent_selfLearnNonce() {
24325
24657
  async function _Agent_selfLearnTeacher(prompt, result) {
24326
24658
  // [1] Call the teacher agent // <- !!!!! Emojis
24327
24659
  if (this.teacherAgent === null) {
24328
- return;
24660
+ return null;
24329
24661
  }
24330
24662
  console.info(colors.bgCyan('[Self-learning]') + colors.cyan(' Teacher'));
24331
24663
  const teacherResult = await this.teacherAgent.callChatModel({
@@ -24380,7 +24712,7 @@ async function _Agent_selfLearnTeacher(prompt, result) {
24380
24712
  if (teacherCommitments === '') {
24381
24713
  console.info(colors.bgCyan('[Self-learning]') +
24382
24714
  colors.cyan(' Teacher agent did not provide new commitments to learn'));
24383
- return;
24715
+ return buildTeacherSummary('', true);
24384
24716
  }
24385
24717
  // [2] Append to the current source
24386
24718
  const currentSource = this.agentSource.value;
@@ -24388,6 +24720,7 @@ async function _Agent_selfLearnTeacher(prompt, result) {
24388
24720
  // <- TODO: [🈲] Use some object-based way how to append on book (with sections `---`)
24389
24721
  // [3] Update the source
24390
24722
  this.agentSource.next(newSource);
24723
+ return buildTeacherSummary(teacherCommitments, true);
24391
24724
  };
24392
24725
  /**
24393
24726
  * TODO: [🧠][😰]Agent is not working with the parameters, should it be?