@promptbook/fake-llm 0.105.0-1 → 0.105.0-11

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 (70) hide show
  1. package/README.md +36 -77
  2. package/esm/index.es.js +4277 -137
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/src/_packages/browser.index.d.ts +2 -0
  5. package/esm/typings/src/_packages/core.index.d.ts +4 -0
  6. package/esm/typings/src/_packages/types.index.d.ts +16 -0
  7. package/esm/typings/src/_packages/utils.index.d.ts +2 -0
  8. package/esm/typings/src/book-2.0/agent-source/AgentBasicInformation.d.ts +15 -3
  9. package/esm/typings/src/book-2.0/agent-source/AgentModelRequirements.d.ts +11 -1
  10. package/esm/typings/src/book-2.0/agent-source/communication-samples.test.d.ts +1 -0
  11. package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.blocks.test.d.ts +1 -0
  12. package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.import.test.d.ts +1 -0
  13. package/esm/typings/src/book-2.0/agent-source/parseAgentSource.import.test.d.ts +1 -0
  14. package/esm/typings/src/book-2.0/agent-source/parseAgentSourceWithCommitments.blocks.test.d.ts +1 -0
  15. package/esm/typings/src/book-components/Chat/AgentChat/AgentChatProps.d.ts +5 -0
  16. package/esm/typings/src/book-components/Chat/Chat/ChatMessageItem.d.ts +15 -1
  17. package/esm/typings/src/book-components/Chat/Chat/ChatProps.d.ts +26 -11
  18. package/esm/typings/src/book-components/Chat/LlmChat/LlmChatProps.d.ts +5 -0
  19. package/esm/typings/src/book-components/Chat/types/ChatMessage.d.ts +43 -0
  20. package/esm/typings/src/book-components/Chat/utils/getToolCallChipletText.d.ts +22 -0
  21. package/esm/typings/src/commitments/NOTE/NOTE.d.ts +2 -2
  22. package/esm/typings/src/commitments/USE_BROWSER/USE_BROWSER.d.ts +4 -0
  23. package/esm/typings/src/commitments/USE_IMAGE_GENERATOR/USE_IMAGE_GENERATOR.d.ts +46 -0
  24. package/esm/typings/src/commitments/USE_IMAGE_GENERATOR/USE_IMAGE_GENERATOR.test.d.ts +1 -0
  25. package/esm/typings/src/commitments/USE_SEARCH_ENGINE/USE_SEARCH_ENGINE.d.ts +10 -0
  26. package/esm/typings/src/commitments/USE_SEARCH_ENGINE/USE_SEARCH_ENGINE.test.d.ts +1 -0
  27. package/esm/typings/src/commitments/USE_TIME/USE_TIME.d.ts +44 -0
  28. package/esm/typings/src/commitments/USE_TIME/USE_TIME.test.d.ts +1 -0
  29. package/esm/typings/src/commitments/_base/BaseCommitmentDefinition.d.ts +14 -0
  30. package/esm/typings/src/commitments/_base/CommitmentDefinition.d.ts +14 -0
  31. package/esm/typings/src/commitments/index.d.ts +18 -2
  32. package/esm/typings/src/config.d.ts +1 -0
  33. package/esm/typings/src/execution/LlmExecutionTools.d.ts +3 -1
  34. package/esm/typings/src/import-plugins/$fileImportPlugins.d.ts +7 -0
  35. package/esm/typings/src/import-plugins/AgentFileImportPlugin.d.ts +7 -0
  36. package/esm/typings/src/import-plugins/FileImportPlugin.d.ts +24 -0
  37. package/esm/typings/src/import-plugins/JsonFileImportPlugin.d.ts +7 -0
  38. package/esm/typings/src/import-plugins/TextFileImportPlugin.d.ts +7 -0
  39. package/esm/typings/src/llm-providers/_common/utils/cache/cacheLlmTools.d.ts +2 -1
  40. package/esm/typings/src/llm-providers/_common/utils/count-total-usage/countUsage.d.ts +2 -2
  41. package/esm/typings/src/llm-providers/agent/Agent.d.ts +14 -2
  42. package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +3 -1
  43. package/esm/typings/src/llm-providers/agent/AgentOptions.d.ts +7 -0
  44. package/esm/typings/src/llm-providers/agent/RemoteAgent.d.ts +1 -0
  45. package/esm/typings/src/llm-providers/agent/RemoteAgentOptions.d.ts +1 -1
  46. package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +10 -0
  47. package/esm/typings/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +7 -0
  48. package/esm/typings/src/llm-providers/remote/RemoteLlmExecutionTools.d.ts +1 -1
  49. package/esm/typings/src/scripting/javascript/JavascriptExecutionToolsOptions.d.ts +6 -1
  50. package/esm/typings/src/search-engines/SearchEngine.d.ts +1 -1
  51. package/esm/typings/src/search-engines/_index.d.ts +6 -0
  52. package/esm/typings/src/search-engines/bing/BingSearchEngine.d.ts +1 -1
  53. package/esm/typings/src/search-engines/dummy/DummySearchEngine.d.ts +1 -1
  54. package/esm/typings/src/search-engines/google/GoogleSearchEngine.d.ts +18 -0
  55. package/esm/typings/src/search-engines/serp/SerpSearchEngine.d.ts +15 -0
  56. package/esm/typings/src/speech-recognition/BrowserSpeechRecognition.d.ts +21 -0
  57. package/esm/typings/src/speech-recognition/OpenAiSpeechRecognition.d.ts +32 -0
  58. package/esm/typings/src/types/ModelRequirements.d.ts +6 -12
  59. package/esm/typings/src/types/SpeechRecognition.d.ts +58 -0
  60. package/esm/typings/src/types/typeAliases.d.ts +4 -0
  61. package/esm/typings/src/utils/execCommand/$execCommandNormalizeOptions.d.ts +2 -3
  62. package/esm/typings/src/utils/execCommand/ExecCommandOptions.d.ts +7 -1
  63. package/esm/typings/src/utils/misc/linguisticHash.d.ts +6 -0
  64. package/esm/typings/src/utils/misc/linguisticHash.test.d.ts +1 -0
  65. package/esm/typings/src/utils/organization/keepImported.d.ts +9 -0
  66. package/esm/typings/src/utils/organization/keepTypeImported.d.ts +0 -1
  67. package/esm/typings/src/version.d.ts +1 -1
  68. package/package.json +2 -2
  69. package/umd/index.umd.js +4277 -137
  70. package/umd/index.umd.js.map +1 -1
package/esm/index.es.js CHANGED
@@ -20,7 +20,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
20
20
  * @generated
21
21
  * @see https://github.com/webgptorg/promptbook
22
22
  */
23
- const PROMPTBOOK_ENGINE_VERSION = '0.105.0-1';
23
+ const PROMPTBOOK_ENGINE_VERSION = '0.105.0-11';
24
24
  /**
25
25
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
26
26
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1052,6 +1052,7 @@ const PROMPTBOOK_COLOR = Color.fromString('promptbook');
1052
1052
  SEPARATOR: Color.fromHex('#cccccc'),
1053
1053
  COMMITMENT: Color.fromHex('#DA0F78'),
1054
1054
  PARAMETER: Color.fromHex('#8e44ad'),
1055
+ CODE_BLOCK: Color.fromHex('#7700ffff'),
1055
1056
  });
1056
1057
  // <- TODO: [🧠][🈵] Using `Color` here increases the package size approx 3kb, maybe remove it
1057
1058
  /**
@@ -2361,6 +2362,93 @@ function normalizeTo_camelCase(text, _isFirstLetterCapital = false) {
2361
2362
  * TODO: [🌺] Use some intermediate util splitWords
2362
2363
  */
2363
2364
 
2365
+ /**
2366
+ * Tests if given string is valid file path.
2367
+ *
2368
+ * Note: This does not check if the file exists only if the path is valid
2369
+ * @public exported from `@promptbook/utils`
2370
+ */
2371
+ function isValidFilePath(filename) {
2372
+ if (typeof filename !== 'string') {
2373
+ return false;
2374
+ }
2375
+ if (filename.split('\n').length > 1) {
2376
+ return false;
2377
+ }
2378
+ // Normalize slashes early so heuristics can detect path-like inputs
2379
+ const filenameSlashes = filename.replace(/\\/g, '/');
2380
+ // Reject strings that look like sentences (informational text)
2381
+ // Heuristic: contains multiple spaces and ends with a period, or contains typical sentence punctuation
2382
+ // But skip this heuristic if the string looks like a path (contains '/' or starts with a drive letter)
2383
+ if (filename.trim().length > 60 && // long enough to be a sentence
2384
+ /[.!?]/.test(filename) && // contains sentence punctuation
2385
+ filename.split(' ').length > 8 && // has many words
2386
+ !/\/|^[A-Z]:/i.test(filenameSlashes) // do NOT treat as sentence if looks like a path
2387
+ ) {
2388
+ return false;
2389
+ }
2390
+ // Absolute Unix path: /hello.txt
2391
+ if (/^(\/)/i.test(filenameSlashes)) {
2392
+ // console.log(filename, 'Absolute Unix path: /hello.txt');
2393
+ return true;
2394
+ }
2395
+ // Absolute Windows path: C:/ or C:\ (allow spaces and multiple dots in filename)
2396
+ if (/^[A-Z]:\/.+$/i.test(filenameSlashes)) {
2397
+ // console.log(filename, 'Absolute Windows path: /hello.txt');
2398
+ return true;
2399
+ }
2400
+ // Relative path: ./hello.txt
2401
+ if (/^(\.\.?\/)+/i.test(filenameSlashes)) {
2402
+ // console.log(filename, 'Relative path: ./hello.txt');
2403
+ return true;
2404
+ }
2405
+ // Allow paths like foo/hello
2406
+ if (/^[^/]+\/[^/]+/i.test(filenameSlashes)) {
2407
+ // console.log(filename, 'Allow paths like foo/hello');
2408
+ return true;
2409
+ }
2410
+ // Allow paths like hello.book
2411
+ if (/^[^/]+\.[^/]+$/i.test(filenameSlashes)) {
2412
+ // console.log(filename, 'Allow paths like hello.book');
2413
+ return true;
2414
+ }
2415
+ return false;
2416
+ }
2417
+ /**
2418
+ * TODO: [🍏] Implement for MacOs
2419
+ */
2420
+
2421
+ /**
2422
+ * Tests if given string is valid URL.
2423
+ *
2424
+ * Note: [🔂] This function is idempotent.
2425
+ * Note: Dataurl are considered perfectly valid.
2426
+ * Note: There are few similar functions:
2427
+ * - `isValidUrl` *(this one)* which tests any URL
2428
+ * - `isValidAgentUrl` which tests just agent URL
2429
+ * - `isValidPipelineUrl` which tests just pipeline URL
2430
+ *
2431
+ * @public exported from `@promptbook/utils`
2432
+ */
2433
+ function isValidUrl(url) {
2434
+ if (typeof url !== 'string') {
2435
+ return false;
2436
+ }
2437
+ try {
2438
+ if (url.startsWith('blob:')) {
2439
+ url = url.replace(/^blob:/, '');
2440
+ }
2441
+ const urlObject = new URL(url /* because fail is handled */);
2442
+ if (!['http:', 'https:', 'data:'].includes(urlObject.protocol)) {
2443
+ return false;
2444
+ }
2445
+ return true;
2446
+ }
2447
+ catch (error) {
2448
+ return false;
2449
+ }
2450
+ }
2451
+
2364
2452
  /**
2365
2453
  * Converts a given text to kebab-case format.
2366
2454
  *
@@ -2687,6 +2775,16 @@ function unwrapResult(text, options) {
2687
2775
  trimmedText = spaceTrim$1(trimmedText);
2688
2776
  }
2689
2777
  let processedText = trimmedText;
2778
+ // Check for markdown code block
2779
+ const codeBlockRegex = /^```[a-z]*\n([\s\S]*?)\n```\s*$/;
2780
+ const codeBlockMatch = processedText.match(codeBlockRegex);
2781
+ if (codeBlockMatch && codeBlockMatch[1] !== undefined) {
2782
+ // Check if there's only one code block
2783
+ const codeBlockCount = (processedText.match(/```/g) || []).length / 2;
2784
+ if (codeBlockCount === 1) {
2785
+ return unwrapResult(codeBlockMatch[1], { isTrimmed: false, isIntroduceSentenceRemoved: false });
2786
+ }
2787
+ }
2690
2788
  if (isIntroduceSentenceRemoved) {
2691
2789
  const introduceSentenceRegex = /^[a-zěščřžýáíéúů:\s]*:\s*/i;
2692
2790
  if (introduceSentenceRegex.test(text)) {
@@ -2694,6 +2792,14 @@ function unwrapResult(text, options) {
2694
2792
  processedText = processedText.replace(introduceSentenceRegex, '');
2695
2793
  }
2696
2794
  processedText = spaceTrim$1(processedText);
2795
+ // Check again for code block after removing introduce sentence
2796
+ const codeBlockMatch2 = processedText.match(codeBlockRegex);
2797
+ if (codeBlockMatch2 && codeBlockMatch2[1] !== undefined) {
2798
+ const codeBlockCount = (processedText.match(/```/g) || []).length / 2;
2799
+ if (codeBlockCount === 1) {
2800
+ return unwrapResult(codeBlockMatch2[1], { isTrimmed: false, isIntroduceSentenceRemoved: false });
2801
+ }
2802
+ }
2697
2803
  }
2698
2804
  if (processedText.length < 3) {
2699
2805
  return trimmedText;
@@ -2738,178 +2844,4201 @@ function unwrapResult(text, options) {
2738
2844
  */
2739
2845
 
2740
2846
  /**
2741
- * Extracts all code blocks from markdown.
2847
+ * Tests if given string is valid agent URL
2742
2848
  *
2743
- * Note: There are multiple similar functions:
2744
- * - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
2745
- * - `extractJsonBlock` extracts exactly one valid JSON code block
2746
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
2747
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
2849
+ * Note: There are few similar functions:
2850
+ * - `isValidUrl` which tests any URL
2851
+ * - `isValidAgentUrl` *(this one)* which tests just agent URL
2852
+ * - `isValidPipelineUrl` which tests just pipeline URL
2748
2853
  *
2749
- * @param markdown any valid markdown
2750
- * @returns code blocks with language and content
2751
- * @throws {ParseError} if block is not closed properly
2752
- * @public exported from `@promptbook/markdown-utils`
2854
+ * @public exported from `@promptbook/utils`
2753
2855
  */
2754
- function extractAllBlocksFromMarkdown(markdown) {
2755
- const codeBlocks = [];
2756
- const lines = markdown.split('\n');
2757
- // Note: [0] Ensure that the last block notated by gt > will be closed
2758
- lines.push('');
2759
- let currentCodeBlock = null;
2760
- for (const line of lines) {
2761
- if (line.startsWith('> ') || line === '>') {
2762
- if (currentCodeBlock === null) {
2763
- currentCodeBlock = { blockNotation: '>', language: null, content: '' };
2764
- } /* not else */
2765
- if (currentCodeBlock.blockNotation === '>') {
2766
- if (currentCodeBlock.content !== '') {
2767
- currentCodeBlock.content += '\n';
2768
- }
2769
- currentCodeBlock.content += line.slice(2);
2770
- }
2771
- }
2772
- else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '>' /* <- Note: [0] */) {
2773
- codeBlocks.push(currentCodeBlock);
2774
- currentCodeBlock = null;
2775
- }
2776
- /* not else */
2777
- if (line.startsWith('```')) {
2778
- const language = line.slice(3).trim() || null;
2779
- if (currentCodeBlock === null) {
2780
- currentCodeBlock = { blockNotation: '```', language, content: '' };
2781
- }
2782
- else {
2783
- if (language !== null) {
2784
- throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed and already opening new ${language} code block`);
2785
- }
2786
- codeBlocks.push(currentCodeBlock);
2787
- currentCodeBlock = null;
2788
- }
2789
- }
2790
- else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '```') {
2791
- if (currentCodeBlock.content !== '') {
2792
- currentCodeBlock.content += '\n';
2793
- }
2794
- currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make proper unescape */;
2795
- }
2856
+ function isValidAgentUrl(url) {
2857
+ if (!isValidUrl(url)) {
2858
+ return false;
2796
2859
  }
2797
- if (currentCodeBlock !== null) {
2798
- throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed at the end of the markdown`);
2860
+ if (!url.startsWith('https://') && !url.startsWith('http://') /* <- Note: [👣] */) {
2861
+ return false;
2799
2862
  }
2800
- return codeBlocks;
2863
+ if (url.includes('#')) {
2864
+ // TODO: [🐠]
2865
+ return false;
2866
+ }
2867
+ /*
2868
+ Note: [👣][🧠] Is it secure to allow pipeline URLs on private and unsecured networks?
2869
+ if (isUrlOnPrivateNetwork(url)) {
2870
+ return false;
2871
+ }
2872
+ */
2873
+ return true;
2801
2874
  }
2802
2875
  /**
2803
- * TODO: Maybe name for `blockNotation` instead of '```' and '>'
2876
+ * TODO: [🐠] Maybe more info why the URL is invalid
2804
2877
  */
2805
2878
 
2806
2879
  /**
2807
- * Extracts exactly ONE code block from markdown.
2808
- *
2809
- * - When there are multiple or no code blocks the function throws a `ParseError`
2880
+ * Generates a regex pattern to match a specific commitment
2810
2881
  *
2811
- * Note: There are multiple similar functions:
2812
- * - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
2813
- * - `extractJsonBlock` extracts exactly one valid JSON code block
2814
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
2815
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
2882
+ * Note: It always creates new Regex object
2883
+ * Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
2816
2884
  *
2817
- * @param markdown any valid markdown
2818
- * @returns code block with language and content
2819
- * @public exported from `@promptbook/markdown-utils`
2820
- * @throws {ParseError} if there is not exactly one code block in the markdown
2885
+ * @private - TODO: [🧠] Maybe should be public?
2821
2886
  */
2822
- function extractOneBlockFromMarkdown(markdown) {
2823
- const codeBlocks = extractAllBlocksFromMarkdown(markdown);
2824
- if (codeBlocks.length !== 1) {
2825
- throw new ParseError(spaceTrim$2((block) => `
2826
- There should be exactly 1 code block in task section, found ${codeBlocks.length} code blocks
2827
-
2828
- ${block(codeBlocks.map((block, i) => `Block ${i + 1}:\n${block.content}`).join('\n\n\n'))}
2829
- `));
2887
+ function createCommitmentRegex(commitment, aliases = [], requiresContent = true) {
2888
+ const allCommitments = [commitment, ...aliases];
2889
+ const patterns = allCommitments.map((commitment) => {
2890
+ const escapedCommitment = commitment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
2891
+ return escapedCommitment.split(/\s+/).join('\\s+');
2892
+ });
2893
+ const keywordPattern = patterns.join('|');
2894
+ if (requiresContent) {
2895
+ return new RegExp(`^\\s*(?<type>${keywordPattern})\\b\\s+(?<contents>.+)$`, 'gim');
2896
+ }
2897
+ else {
2898
+ return new RegExp(`^\\s*(?<type>${keywordPattern})\\b(?:\\s+(?<contents>.+))?$`, 'gim');
2830
2899
  }
2831
- return codeBlocks[0];
2832
2900
  }
2833
- /***
2834
- * TODO: [🍓][🌻] Decide of this is internal utility, external util OR validator/postprocessor
2835
- */
2836
-
2837
2901
  /**
2838
- * Extracts code block from markdown.
2839
- *
2840
- * - When there are multiple or no code blocks the function throws a `ParseError`
2902
+ * Generates a regex pattern to match a specific commitment type
2841
2903
  *
2842
- * Note: There are multiple similar function:
2843
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
2844
- * - `extractJsonBlock` extracts exactly one valid JSON code block
2845
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
2846
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
2904
+ * Note: It just matches the type part of the commitment
2905
+ * Note: It always creates new Regex object
2906
+ * Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
2847
2907
  *
2848
- * @public exported from `@promptbook/markdown-utils`
2849
- * @throws {ParseError} if there is not exactly one code block in the markdown
2908
+ * @private
2850
2909
  */
2851
- function extractBlock(markdown) {
2852
- const { content } = extractOneBlockFromMarkdown(markdown);
2853
- return content;
2910
+ function createCommitmentTypeRegex(commitment, aliases = []) {
2911
+ const allCommitments = [commitment, ...aliases];
2912
+ const patterns = allCommitments.map((commitment) => {
2913
+ const escapedCommitment = commitment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
2914
+ return escapedCommitment.split(/\s+/).join('\\s+');
2915
+ });
2916
+ const keywordPattern = patterns.join('|');
2917
+ const regex = new RegExp(`^\\s*(?<type>${keywordPattern})\\b`, 'gim');
2918
+ return regex;
2854
2919
  }
2855
2920
 
2856
2921
  /**
2857
- * Prettify the html code
2922
+ * Base implementation of CommitmentDefinition that provides common functionality
2923
+ * Most commitments can extend this class and only override the applyToAgentModelRequirements method
2858
2924
  *
2859
- * @param content raw html code
2860
- * @returns formatted html code
2861
- * @private withing the package because of HUGE size of prettier dependency
2862
- * @deprecated Prettier removed from Promptbook due to package size
2925
+ * @private
2863
2926
  */
2864
- function prettifyMarkdown(content) {
2865
- return (content + `\n\n<!-- Note: Prettier removed from Promptbook -->`);
2927
+ class BaseCommitmentDefinition {
2928
+ constructor(type, aliases = []) {
2929
+ this.type = type;
2930
+ this.aliases = aliases;
2931
+ }
2932
+ /**
2933
+ * Whether this commitment requires content.
2934
+ * If true, regex will match only if there is content after the commitment keyword.
2935
+ * If false, regex will match even if there is no content.
2936
+ */
2937
+ get requiresContent() {
2938
+ return true;
2939
+ }
2940
+ /**
2941
+ * Creates a regex pattern to match this commitment in agent source
2942
+ * Uses the existing createCommitmentRegex function as internal helper
2943
+ */
2944
+ createRegex() {
2945
+ return createCommitmentRegex(this.type, this.aliases, this.requiresContent);
2946
+ }
2947
+ /**
2948
+ * Creates a regex pattern to match just the commitment type
2949
+ * Uses the existing createCommitmentTypeRegex function as internal helper
2950
+ */
2951
+ createTypeRegex() {
2952
+ return createCommitmentTypeRegex(this.type, this.aliases);
2953
+ }
2954
+ /**
2955
+ * Helper method to create a new requirements object with updated system message
2956
+ * This is commonly used by many commitments
2957
+ */
2958
+ updateSystemMessage(requirements, messageUpdate) {
2959
+ const newMessage = typeof messageUpdate === 'string' ? messageUpdate : messageUpdate(requirements.systemMessage);
2960
+ return {
2961
+ ...requirements,
2962
+ systemMessage: newMessage,
2963
+ };
2964
+ }
2965
+ /**
2966
+ * Helper method to append content to the system message
2967
+ */
2968
+ appendToSystemMessage(requirements, content, separator = '\n\n') {
2969
+ return this.updateSystemMessage(requirements, (currentMessage) => {
2970
+ if (!currentMessage.trim()) {
2971
+ return content;
2972
+ }
2973
+ return currentMessage + separator + content;
2974
+ });
2975
+ }
2976
+ /**
2977
+ * Helper method to add a comment section to the system message
2978
+ * Comments are lines starting with # that will be removed from the final system message
2979
+ * but can be useful for organizing and structuring the message during processing
2980
+ */
2981
+ addCommentSection(requirements, commentTitle, content, position = 'end') {
2982
+ const commentSection = `# ${commentTitle.toUpperCase()}\n${content}`;
2983
+ if (position === 'beginning') {
2984
+ return this.updateSystemMessage(requirements, (currentMessage) => {
2985
+ if (!currentMessage.trim()) {
2986
+ return commentSection;
2987
+ }
2988
+ return commentSection + '\n\n' + currentMessage;
2989
+ });
2990
+ }
2991
+ else {
2992
+ return this.appendToSystemMessage(requirements, commentSection);
2993
+ }
2994
+ }
2995
+ /**
2996
+ * Gets tool function implementations provided by this commitment
2997
+ *
2998
+ * When the `applyToAgentModelRequirements` adds tools to the requirements, this method should return the corresponding function definitions.
2999
+ */
3000
+ getToolFunctions() {
3001
+ return {};
3002
+ }
3003
+ /**
3004
+ * Gets human-readable titles for tool functions provided by this commitment
3005
+ *
3006
+ * This is used in the UI to show a user-friendly name instead of the technical function name.
3007
+ */
3008
+ getToolTitles() {
3009
+ return {};
3010
+ }
2866
3011
  }
2867
3012
 
2868
3013
  /**
2869
- * Function trimCodeBlock will trim starting and ending code block from the string if it is present.
3014
+ * ACTION commitment definition
2870
3015
  *
2871
- * Note: [🔂] This function is idempotent.
2872
- * Note: This is useful for post-processing of the result of the chat LLM model
2873
- * when the model wraps the result in the (markdown) code block.
3016
+ * The ACTION commitment defines specific actions or capabilities that the agent can perform.
3017
+ * This helps define what the agent is capable of doing and how it should approach tasks.
2874
3018
  *
2875
- * @public exported from `@promptbook/markdown-utils`
2876
- */
2877
- function trimCodeBlock(value) {
2878
- value = spaceTrim$1(value);
2879
- if (!/^```[a-z]*(.*)```$/is.test(value)) {
2880
- return value;
2881
- }
2882
- value = value.replace(/^```[a-z]*/i, '');
2883
- value = value.replace(/```$/i, '');
2884
- value = spaceTrim$1(value);
2885
- return value;
2886
- }
2887
-
2888
- /**
2889
- * Function trimEndOfCodeBlock will remove ending code block from the string if it is present.
3019
+ * Example usage in agent source:
2890
3020
  *
2891
- * Note: This is useful for post-processing of the result of the completion LLM model
2892
- * if you want to start code block in the prompt but you don't want to end it in the result.
3021
+ * ```book
3022
+ * ACTION Can generate code snippets and explain programming concepts
3023
+ * ACTION Able to analyze data and provide insights
3024
+ * ```
2893
3025
  *
2894
- * @public exported from `@promptbook/markdown-utils`
3026
+ * @private [🪔] Maybe export the commitments through some package
2895
3027
  */
2896
- function trimEndOfCodeBlock(value) {
2897
- value = spaceTrim$1(value);
2898
- value = value.replace(/```$/g, '');
2899
- value = spaceTrim$1(value);
2900
- return value;
2901
- }
3028
+ class ActionCommitmentDefinition extends BaseCommitmentDefinition {
3029
+ constructor(type = 'ACTION') {
3030
+ super(type);
3031
+ }
3032
+ /**
3033
+ * Short one-line description of ACTION.
3034
+ */
3035
+ get description() {
3036
+ return 'Define agent capabilities and actions it can perform.';
3037
+ }
3038
+ /**
3039
+ * Icon for this commitment.
3040
+ */
3041
+ get icon() {
3042
+ return '⚡';
3043
+ }
3044
+ /**
3045
+ * Markdown documentation for ACTION commitment.
3046
+ */
3047
+ get documentation() {
3048
+ return spaceTrim$1(`
3049
+ # ${this.type}
3050
+
3051
+ Defines specific actions or capabilities that the agent can perform.
3052
+
3053
+ ## Key aspects
3054
+
3055
+ - Both terms work identically and can be used interchangeably.
3056
+ - Each action adds to the agent's capability list.
3057
+ - Actions help users understand what the agent can do.
3058
+
3059
+ ## Examples
3060
+
3061
+ \`\`\`book
3062
+ Code Assistant
2902
3063
 
3064
+ PERSONA You are a programming assistant
3065
+ ACTION Can generate code snippets and explain programming concepts
3066
+ ACTION Able to debug existing code and suggest improvements
3067
+ ACTION Can create unit tests for functions
3068
+ \`\`\`
3069
+
3070
+ \`\`\`book
3071
+ Data Scientist
3072
+
3073
+ PERSONA You are a data analysis expert
3074
+ ACTION Able to analyze data and provide insights
3075
+ ACTION Can create visualizations and charts
3076
+ ACTION Capable of statistical analysis and modeling
3077
+ KNOWLEDGE Data analysis best practices and statistical methods
3078
+ \`\`\`
3079
+ `);
3080
+ }
3081
+ applyToAgentModelRequirements(requirements, content) {
3082
+ const trimmedContent = content.trim();
3083
+ if (!trimmedContent) {
3084
+ return requirements;
3085
+ }
3086
+ // Add action capability to the system message
3087
+ const actionSection = `Capability: ${trimmedContent}`;
3088
+ return this.appendToSystemMessage(requirements, actionSection, '\n\n');
3089
+ }
3090
+ }
2903
3091
  /**
2904
- * @private internal for `preserve`
3092
+ * Note: [💞] Ignore a discrepancy between file name and entity name
2905
3093
  */
2906
- const _preserved = [];
3094
+
2907
3095
  /**
2908
- * Does nothing, but preserves the function in the bundle
2909
- * Compiler is tricked into thinking the function is used
3096
+ * CLOSED commitment definition
2910
3097
  *
2911
- * @param value any function to preserve
2912
- * @returns nothing
3098
+ * The CLOSED commitment specifies that the agent CANNOT be modified by conversation.
3099
+ * It prevents the agent from learning from interactions and updating its source code.
3100
+ *
3101
+ * Example usage in agent source:
3102
+ *
3103
+ * ```book
3104
+ * CLOSED
3105
+ * ```
3106
+ *
3107
+ * @private [🪔] Maybe export the commitments through some package
3108
+ */
3109
+ class ClosedCommitmentDefinition extends BaseCommitmentDefinition {
3110
+ constructor() {
3111
+ super('CLOSED');
3112
+ }
3113
+ /**
3114
+ * The `CLOSED` commitment is standalone.
3115
+ */
3116
+ get requiresContent() {
3117
+ return false;
3118
+ }
3119
+ /**
3120
+ * Short one-line description of CLOSED.
3121
+ */
3122
+ get description() {
3123
+ return 'Prevent the agent from being modified by conversation.';
3124
+ }
3125
+ /**
3126
+ * Icon for this commitment.
3127
+ */
3128
+ get icon() {
3129
+ return '🔒';
3130
+ }
3131
+ /**
3132
+ * Markdown documentation for CLOSED commitment.
3133
+ */
3134
+ get documentation() {
3135
+ return spaceTrim$1(`
3136
+ # CLOSED
3137
+
3138
+ Specifies that the agent **cannot** be modified by conversation with it.
3139
+ This means the agent will **not** learn from interactions and its source code will remain static during conversation.
3140
+
3141
+ By default (if not specified), agents are \`OPEN\` to modification.
3142
+
3143
+ > See also [OPEN](/docs/OPEN)
3144
+
3145
+ ## Example
3146
+
3147
+ \`\`\`book
3148
+ CLOSED
3149
+ \`\`\`
3150
+ `);
3151
+ }
3152
+ applyToAgentModelRequirements(requirements, _content) {
3153
+ const updatedMetadata = {
3154
+ ...requirements.metadata,
3155
+ isClosed: true,
3156
+ };
3157
+ return {
3158
+ ...requirements,
3159
+ metadata: updatedMetadata,
3160
+ };
3161
+ }
3162
+ }
3163
+ /**
3164
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3165
+ */
3166
+
3167
+ /**
3168
+ * COMPONENT commitment definition
3169
+ *
3170
+ * The COMPONENT commitment defines a UI component that the agent can render in the chat.
3171
+ *
3172
+ * @private [🪔] Maybe export the commitments through some package
3173
+ */
3174
+ class ComponentCommitmentDefinition extends BaseCommitmentDefinition {
3175
+ constructor() {
3176
+ super('COMPONENT');
3177
+ }
3178
+ /**
3179
+ * Short one-line description of COMPONENT.
3180
+ */
3181
+ get description() {
3182
+ return 'Define a UI component that the agent can render in the chat.';
3183
+ }
3184
+ /**
3185
+ * Icon for this commitment.
3186
+ */
3187
+ get icon() {
3188
+ return '🧩';
3189
+ }
3190
+ /**
3191
+ * Markdown documentation for COMPONENT commitment.
3192
+ */
3193
+ get documentation() {
3194
+ return spaceTrim$1(`
3195
+ # COMPONENT
3196
+
3197
+ Defines a UI component that the agent can render in the chat.
3198
+
3199
+ ## Key aspects
3200
+
3201
+ - Tells the agent that a specific component is available.
3202
+ - Provides syntax for using the component.
3203
+
3204
+ ## Example
3205
+
3206
+ \`\`\`book
3207
+ COMPONENT Arrow
3208
+ The agent should render an arrow component in the chat UI.
3209
+ Syntax:
3210
+ <Arrow direction="up" color="red" />
3211
+ \`\`\`
3212
+ `);
3213
+ }
3214
+ applyToAgentModelRequirements(requirements, content) {
3215
+ const trimmedContent = content.trim();
3216
+ if (!trimmedContent) {
3217
+ return requirements;
3218
+ }
3219
+ // Add component capability to the system message
3220
+ const componentSection = `Component: ${trimmedContent}`;
3221
+ return this.appendToSystemMessage(requirements, componentSection, '\n\n');
3222
+ }
3223
+ }
3224
+ /**
3225
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3226
+ */
3227
+
3228
+ /**
3229
+ * DELETE commitment definition
3230
+ *
3231
+ * The DELETE commitment (and its aliases CANCEL, DISCARD, REMOVE) is used to
3232
+ * remove or disregard certain information or context. This can be useful for
3233
+ * overriding previous commitments or removing unwanted behaviors.
3234
+ *
3235
+ * Example usage in agent source:
3236
+ *
3237
+ * ```book
3238
+ * DELETE Previous formatting requirements
3239
+ * CANCEL All emotional responses
3240
+ * DISCARD Technical jargon explanations
3241
+ * REMOVE Casual conversational style
3242
+ * ```
3243
+ *
3244
+ * @private [🪔] Maybe export the commitments through some package
3245
+ */
3246
+ class DeleteCommitmentDefinition extends BaseCommitmentDefinition {
3247
+ constructor(type) {
3248
+ super(type);
3249
+ }
3250
+ /**
3251
+ * Short one-line description of DELETE/CANCEL/DISCARD/REMOVE.
3252
+ */
3253
+ get description() {
3254
+ return 'Remove or **disregard** certain information, context, or previous commitments.';
3255
+ }
3256
+ /**
3257
+ * Icon for this commitment.
3258
+ */
3259
+ get icon() {
3260
+ return '🗑️';
3261
+ }
3262
+ /**
3263
+ * Markdown documentation for DELETE commitment.
3264
+ */
3265
+ get documentation() {
3266
+ return spaceTrim$1(`
3267
+ # DELETE (CANCEL, DISCARD, REMOVE)
3268
+
3269
+ A commitment to remove or disregard certain information or context. This can be useful for overriding previous commitments or removing unwanted behaviors.
3270
+
3271
+ ## Aliases
3272
+
3273
+ - \`DELETE\` - Remove or eliminate something
3274
+ - \`CANCEL\` - Cancel or nullify something
3275
+ - \`DISCARD\` - Discard or ignore something
3276
+ - \`REMOVE\` - Remove or take away something
3277
+
3278
+ ## Key aspects
3279
+
3280
+ - Multiple delete commitments can be used to remove different aspects.
3281
+ - Useful for overriding previous commitments in the same agent definition.
3282
+ - Can be used to remove inherited behaviors from base personas.
3283
+ - Helps fine-tune agent behavior by explicitly removing unwanted elements.
3284
+
3285
+ ## Use cases
3286
+
3287
+ - Overriding inherited persona characteristics
3288
+ - Removing conflicting or outdated instructions
3289
+ - Disabling specific response patterns
3290
+ - Canceling previous formatting or style requirements
3291
+
3292
+ ## Examples
3293
+
3294
+ \`\`\`book
3295
+ Serious Business Assistant
3296
+
3297
+ PERSONA You are a friendly and casual assistant who uses emojis
3298
+ DELETE Casual conversational style
3299
+ REMOVE All emoji usage
3300
+ GOAL Provide professional business communications
3301
+ STYLE Use formal language and proper business etiquette
3302
+ \`\`\`
3303
+
3304
+ \`\`\`book
3305
+ Simplified Technical Support
3306
+
3307
+ PERSONA You are a technical support specialist with deep expertise
3308
+ KNOWLEDGE Extensive database of technical specifications
3309
+ DISCARD Technical jargon explanations
3310
+ CANCEL Advanced troubleshooting procedures
3311
+ GOAL Help users with simple, easy-to-follow solutions
3312
+ STYLE Use plain language that anyone can understand
3313
+ \`\`\`
3314
+
3315
+ \`\`\`book
3316
+ Focused Customer Service
3317
+
3318
+ PERSONA You are a customer service agent with broad knowledge
3319
+ ACTION Can help with billing, technical issues, and product information
3320
+ DELETE Billing assistance capabilities
3321
+ REMOVE Technical troubleshooting functions
3322
+ GOAL Focus exclusively on product information and general inquiries
3323
+ \`\`\`
3324
+
3325
+ \`\`\`book
3326
+ Concise Information Provider
3327
+
3328
+ PERSONA You are a helpful assistant who provides detailed explanations
3329
+ STYLE Include examples, analogies, and comprehensive context
3330
+ CANCEL Detailed explanation style
3331
+ DISCARD Examples and analogies
3332
+ GOAL Provide brief, direct answers without unnecessary elaboration
3333
+ STYLE Be concise and to the point
3334
+ \`\`\`
3335
+ `);
3336
+ }
3337
+ applyToAgentModelRequirements(requirements, content) {
3338
+ const trimmedContent = content.trim();
3339
+ if (!trimmedContent) {
3340
+ return requirements;
3341
+ }
3342
+ // Create deletion instruction for system message
3343
+ const deleteSection = `${this.type}: ${trimmedContent}`;
3344
+ // Delete instructions provide important context about what should be removed or ignored
3345
+ return this.appendToSystemMessage(requirements, deleteSection, '\n\n');
3346
+ }
3347
+ }
3348
+ /**
3349
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3350
+ */
3351
+
3352
+ /**
3353
+ * DICTIONARY commitment definition
3354
+ *
3355
+ * The DICTIONARY commitment defines specific terms and their meanings that the agent should use correctly
3356
+ * in its reasoning and responses. This ensures consistent terminology usage.
3357
+ *
3358
+ * Key features:
3359
+ * - Multiple DICTIONARY commitments are automatically merged into one
3360
+ * - Content is placed in a dedicated section of the system message
3361
+ * - Terms and definitions are stored in metadata.DICTIONARY for debugging
3362
+ * - Agent should use the defined terms correctly in responses
3363
+ *
3364
+ * Example usage in agent source:
3365
+ *
3366
+ * ```book
3367
+ * Legal Assistant
3368
+ *
3369
+ * PERSONA You are a knowledgeable legal assistant
3370
+ * DICTIONARY Misdemeanor is a minor wrongdoing or criminal offense
3371
+ * DICTIONARY Felony is a serious crime usually punishable by imprisonment for more than one year
3372
+ * DICTIONARY Tort is a civil wrong that causes harm or loss to another person, leading to legal liability
3373
+ * ```
3374
+ *
3375
+ * @private [🪔] Maybe export the commitments through some package
3376
+ */
3377
+ class DictionaryCommitmentDefinition extends BaseCommitmentDefinition {
3378
+ constructor() {
3379
+ super('DICTIONARY');
3380
+ }
3381
+ /**
3382
+ * Short one-line description of DICTIONARY.
3383
+ */
3384
+ get description() {
3385
+ return 'Define terms and their meanings for consistent terminology usage.';
3386
+ }
3387
+ /**
3388
+ * Icon for this commitment.
3389
+ */
3390
+ get icon() {
3391
+ return '📚';
3392
+ }
3393
+ /**
3394
+ * Markdown documentation for DICTIONARY commitment.
3395
+ */
3396
+ get documentation() {
3397
+ return spaceTrim$1(`
3398
+ # DICTIONARY
3399
+
3400
+ Defines specific terms and their meanings that the agent should use correctly in reasoning and responses.
3401
+
3402
+ ## Key aspects
3403
+
3404
+ - Multiple \`DICTIONARY\` commitments are merged together.
3405
+ - Terms are defined in the format: "Term is definition"
3406
+ - The agent should use these terms consistently in responses.
3407
+ - Definitions help ensure accurate and consistent terminology.
3408
+
3409
+ ## Examples
3410
+
3411
+ \`\`\`book
3412
+ Legal Assistant
3413
+
3414
+ PERSONA You are a knowledgeable legal assistant specializing in criminal law
3415
+ DICTIONARY Misdemeanor is a minor wrongdoing or criminal offense
3416
+ DICTIONARY Felony is a serious crime usually punishable by imprisonment for more than one year
3417
+ DICTIONARY Tort is a civil wrong that causes harm or loss to another person, leading to legal liability
3418
+ \`\`\`
3419
+
3420
+ \`\`\`book
3421
+ Medical Assistant
3422
+
3423
+ PERSONA You are a helpful medical assistant
3424
+ DICTIONARY Hypertension is persistently high blood pressure
3425
+ DICTIONARY Diabetes is a chronic condition that affects how the body processes blood sugar
3426
+ DICTIONARY Vaccine is a biological preparation that provides active immunity to a particular disease
3427
+ \`\`\`
3428
+ `);
3429
+ }
3430
+ applyToAgentModelRequirements(requirements, content) {
3431
+ var _a;
3432
+ const trimmedContent = content.trim();
3433
+ if (!trimmedContent) {
3434
+ return requirements;
3435
+ }
3436
+ // Get existing dictionary entries from metadata
3437
+ const existingDictionary = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.DICTIONARY) || '';
3438
+ // Merge the new dictionary entry with existing entries
3439
+ const mergedDictionary = existingDictionary ? `${existingDictionary}\n${trimmedContent}` : trimmedContent;
3440
+ // Store the merged dictionary in metadata for debugging and inspection
3441
+ const updatedMetadata = {
3442
+ ...requirements.metadata,
3443
+ DICTIONARY: mergedDictionary,
3444
+ };
3445
+ // Create the dictionary section for the system message
3446
+ // Format: "# DICTIONARY\nTerm: definition\nTerm: definition..."
3447
+ const dictionarySection = `# DICTIONARY\n${mergedDictionary}`;
3448
+ return {
3449
+ ...this.appendToSystemMessage(requirements, dictionarySection),
3450
+ metadata: updatedMetadata,
3451
+ };
3452
+ }
3453
+ }
3454
+ /**
3455
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3456
+ */
3457
+
3458
+ /**
3459
+ * FORMAT commitment definition
3460
+ *
3461
+ * The FORMAT commitment defines the specific output structure and formatting
3462
+ * that the agent should use in its responses. This includes data formats,
3463
+ * response templates, and structural requirements.
3464
+ *
3465
+ * Example usage in agent source:
3466
+ *
3467
+ * ```book
3468
+ * FORMAT Always respond in JSON format with 'status' and 'data' fields
3469
+ * FORMAT Use markdown formatting for all code blocks
3470
+ * ```
3471
+ *
3472
+ * @private [🪔] Maybe export the commitments through some package
3473
+ */
3474
+ class FormatCommitmentDefinition extends BaseCommitmentDefinition {
3475
+ constructor(type = 'FORMAT') {
3476
+ super(type);
3477
+ }
3478
+ /**
3479
+ * Short one-line description of FORMAT.
3480
+ */
3481
+ get description() {
3482
+ return 'Specify output structure or formatting requirements.';
3483
+ }
3484
+ /**
3485
+ * Icon for this commitment.
3486
+ */
3487
+ get icon() {
3488
+ return '📜';
3489
+ }
3490
+ /**
3491
+ * Markdown documentation for FORMAT commitment.
3492
+ */
3493
+ get documentation() {
3494
+ return spaceTrim$1(`
3495
+ # ${this.type}
3496
+
3497
+ Defines the specific output structure and formatting for responses (data formats, templates, structure).
3498
+
3499
+ ## Key aspects
3500
+
3501
+ - Both terms work identically and can be used interchangeably.
3502
+ - If they are in conflict, the last one takes precedence.
3503
+ - You can specify both data formats and presentation styles.
3504
+
3505
+ ## Examples
3506
+
3507
+ \`\`\`book
3508
+ Customer Support Bot
3509
+
3510
+ PERSONA You are a helpful customer support agent
3511
+ FORMAT Always respond in JSON format with 'status' and 'data' fields
3512
+ FORMAT Use markdown formatting for all code blocks
3513
+ \`\`\`
3514
+
3515
+ \`\`\`book
3516
+ Data Analyst
3517
+
3518
+ PERSONA You are a data analysis expert
3519
+ FORMAT Present results in structured tables
3520
+ FORMAT Include confidence scores for all predictions
3521
+ STYLE Be concise and precise in explanations
3522
+ \`\`\`
3523
+ `);
3524
+ }
3525
+ applyToAgentModelRequirements(requirements, content) {
3526
+ const trimmedContent = content.trim();
3527
+ if (!trimmedContent) {
3528
+ return requirements;
3529
+ }
3530
+ // Add format instructions to the system message
3531
+ const formatSection = `Output Format: ${trimmedContent}`;
3532
+ return this.appendToSystemMessage(requirements, formatSection, '\n\n');
3533
+ }
3534
+ }
3535
+ /**
3536
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3537
+ */
3538
+
3539
+ /**
3540
+ * FROM commitment definition
3541
+ *
3542
+ * The FROM commitment tells the agent that its `agentSource` is inherited from another agent.
3543
+ *
3544
+ * Example usage in agent source:
3545
+ *
3546
+ * ```book
3547
+ * FROM https://s6.ptbk.io/benjamin-white
3548
+ * ```
3549
+ *
3550
+ * @private [🪔] Maybe export the commitments through some package
3551
+ */
3552
+ class FromCommitmentDefinition extends BaseCommitmentDefinition {
3553
+ constructor(type = 'FROM') {
3554
+ super(type);
3555
+ }
3556
+ /**
3557
+ * Short one-line description of FROM.
3558
+ */
3559
+ get description() {
3560
+ return 'Inherit agent source from another agent.';
3561
+ }
3562
+ /**
3563
+ * Icon for this commitment.
3564
+ */
3565
+ get icon() {
3566
+ return '🧬';
3567
+ }
3568
+ /**
3569
+ * Markdown documentation for FROM commitment.
3570
+ */
3571
+ get documentation() {
3572
+ return spaceTrim$1(`
3573
+ # ${this.type}
3574
+
3575
+ Inherits agent source from another agent.
3576
+
3577
+ ## Examples
3578
+
3579
+ \`\`\`book
3580
+ My AI Agent
3581
+
3582
+ FROM https://s6.ptbk.io/benjamin-white
3583
+ RULE Speak only in English.
3584
+ \`\`\`
3585
+ `);
3586
+ }
3587
+ applyToAgentModelRequirements(requirements, content) {
3588
+ const trimmedContent = content.trim();
3589
+ if (!trimmedContent) {
3590
+ return {
3591
+ ...requirements,
3592
+ parentAgentUrl: undefined,
3593
+ };
3594
+ }
3595
+ if (trimmedContent.toUpperCase() === 'VOID' ||
3596
+ trimmedContent.toUpperCase() === 'NULL' ||
3597
+ trimmedContent.toUpperCase() === 'NONE' ||
3598
+ trimmedContent.toUpperCase() === 'NIL') {
3599
+ return {
3600
+ ...requirements,
3601
+ parentAgentUrl: null,
3602
+ };
3603
+ }
3604
+ if (!isValidAgentUrl(trimmedContent)) {
3605
+ throw new Error(spaceTrim$1((block) => `
3606
+ Invalid agent URL in FROM commitment: "${trimmedContent}"
3607
+
3608
+ \`\`\`book
3609
+ ${block(content)}
3610
+ \`\`\`
3611
+
3612
+
3613
+ `));
3614
+ }
3615
+ const parentAgentUrl = trimmedContent;
3616
+ return {
3617
+ ...requirements,
3618
+ parentAgentUrl,
3619
+ };
3620
+ }
3621
+ }
3622
+ /**
3623
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3624
+ */
3625
+
3626
+ /**
3627
+ * GOAL commitment definition
3628
+ *
3629
+ * The GOAL commitment defines the main goal which should be achieved by the AI assistant.
3630
+ * There can be multiple goals. Later goals are more important than earlier goals.
3631
+ *
3632
+ * Example usage in agent source:
3633
+ *
3634
+ * ```book
3635
+ * GOAL Help users understand complex technical concepts
3636
+ * GOAL Provide accurate and up-to-date information
3637
+ * GOAL Always prioritize user safety and ethical guidelines
3638
+ * ```
3639
+ *
3640
+ * @private [🪔] Maybe export the commitments through some package
3641
+ */
3642
+ class GoalCommitmentDefinition extends BaseCommitmentDefinition {
3643
+ constructor(type = 'GOAL') {
3644
+ super(type);
3645
+ }
3646
+ /**
3647
+ * Short one-line description of GOAL.
3648
+ */
3649
+ get description() {
3650
+ return 'Define main **goals** the AI assistant should achieve, with later goals having higher priority.';
3651
+ }
3652
+ /**
3653
+ * Icon for this commitment.
3654
+ */
3655
+ get icon() {
3656
+ return '🎯';
3657
+ }
3658
+ /**
3659
+ * Markdown documentation for GOAL commitment.
3660
+ */
3661
+ get documentation() {
3662
+ return spaceTrim$1(`
3663
+ # ${this.type}
3664
+
3665
+ Defines the main goal which should be achieved by the AI assistant. There can be multiple goals, and later goals are more important than earlier goals.
3666
+
3667
+ ## Key aspects
3668
+
3669
+ - Both terms work identically and can be used interchangeably.
3670
+ - Later goals have higher priority and can override earlier goals.
3671
+ - Goals provide clear direction and purpose for the agent's responses.
3672
+ - Goals influence decision-making and response prioritization.
3673
+
3674
+ ## Priority system
3675
+
3676
+ When multiple goals are defined, they are processed in order, with later goals taking precedence over earlier ones when there are conflicts.
3677
+
3678
+ ## Examples
3679
+
3680
+ \`\`\`book
3681
+ Customer Support Agent
3682
+
3683
+ PERSONA You are a helpful customer support representative
3684
+ GOAL Resolve customer issues quickly and efficiently
3685
+ GOAL Maintain high customer satisfaction scores
3686
+ GOAL Always follow company policies and procedures
3687
+ RULE Be polite and professional at all times
3688
+ \`\`\`
3689
+
3690
+ \`\`\`book
3691
+ Educational Assistant
3692
+
3693
+ PERSONA You are an educational assistant specializing in mathematics
3694
+ GOAL Help students understand mathematical concepts clearly
3695
+ GOAL Encourage critical thinking and problem-solving skills
3696
+ GOAL Ensure all explanations are age-appropriate and accessible
3697
+ STYLE Use simple language and provide step-by-step explanations
3698
+ \`\`\`
3699
+
3700
+ \`\`\`book
3701
+ Safety-First Assistant
3702
+
3703
+ PERSONA You are a general-purpose AI assistant
3704
+ GOAL Be helpful and informative in all interactions
3705
+ GOAL Provide accurate and reliable information
3706
+ GOAL Always prioritize user safety and ethical guidelines
3707
+ RULE Never provide harmful or dangerous advice
3708
+ \`\`\`
3709
+ `);
3710
+ }
3711
+ applyToAgentModelRequirements(requirements, content) {
3712
+ const trimmedContent = content.trim();
3713
+ if (!trimmedContent) {
3714
+ return requirements;
3715
+ }
3716
+ // Create goal section for system message
3717
+ const goalSection = `Goal: ${trimmedContent}`;
3718
+ // Goals are important directives, so we add them prominently to the system message
3719
+ return this.appendToSystemMessage(requirements, goalSection, '\n\n');
3720
+ }
3721
+ }
3722
+ /**
3723
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3724
+ */
3725
+
3726
+ /**
3727
+ * IMPORT commitment definition
3728
+ *
3729
+ * The IMPORT commitment tells the agent to import content from another agent at the current location.
3730
+ *
3731
+ * Example usage in agent source:
3732
+ *
3733
+ * ```book
3734
+ * IMPORT https://s6.ptbk.io/benjamin-white
3735
+ * ```
3736
+ *
3737
+ * @private [🪔] Maybe export the commitments through some package
3738
+ */
3739
+ class ImportCommitmentDefinition extends BaseCommitmentDefinition {
3740
+ constructor(type = 'IMPORT') {
3741
+ super(type);
3742
+ }
3743
+ /**
3744
+ * Short one-line description of IMPORT.
3745
+ */
3746
+ get description() {
3747
+ return 'Import content from another agent or a generic text file.';
3748
+ }
3749
+ /**
3750
+ * Icon for this commitment.
3751
+ */
3752
+ get icon() {
3753
+ return '📥';
3754
+ }
3755
+ /**
3756
+ * Markdown documentation for IMPORT commitment.
3757
+ */
3758
+ get documentation() {
3759
+ return spaceTrim$1(`
3760
+ # ${this.type}
3761
+
3762
+ Imports content from another agent or a generic text file at the location of the commitment.
3763
+
3764
+ ## Examples
3765
+
3766
+ \`\`\`book
3767
+ My AI Agent
3768
+
3769
+ IMPORT https://s6.ptbk.io/benjamin-white
3770
+ IMPORT https://example.com/some-text-file.txt
3771
+ IMPORT ./path/to/local-file.json
3772
+ RULE Speak only in English.
3773
+ \`\`\`
3774
+ `);
3775
+ }
3776
+ applyToAgentModelRequirements(requirements, content) {
3777
+ const trimmedContent = content.trim();
3778
+ if (!trimmedContent) {
3779
+ return requirements;
3780
+ }
3781
+ if (isValidAgentUrl(trimmedContent)) {
3782
+ const importedAgentUrl = trimmedContent;
3783
+ return {
3784
+ ...requirements,
3785
+ importedAgentUrls: [...(requirements.importedAgentUrls || []), importedAgentUrl],
3786
+ };
3787
+ }
3788
+ if (isValidUrl(trimmedContent) || isValidFilePath(trimmedContent)) {
3789
+ return {
3790
+ ...requirements,
3791
+ importedFileUrls: [...(requirements.importedFileUrls || []), trimmedContent],
3792
+ };
3793
+ }
3794
+ throw new Error(spaceTrim$1((block) => `
3795
+ Invalid agent URL or file path in IMPORT commitment: "${trimmedContent}"
3796
+
3797
+ \`\`\`book
3798
+ ${block(content)}
3799
+ \`\`\`
3800
+ `));
3801
+ }
3802
+ }
3803
+ /**
3804
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3805
+ */
3806
+
3807
+ /**
3808
+ * KNOWLEDGE commitment definition
3809
+ *
3810
+ * The KNOWLEDGE commitment adds specific knowledge, facts, or context to the agent
3811
+ * using RAG (Retrieval-Augmented Generation) approach for external sources.
3812
+ *
3813
+ * Supports both direct text knowledge and external sources like PDFs.
3814
+ *
3815
+ * Example usage in agent source:
3816
+ *
3817
+ * ```book
3818
+ * KNOWLEDGE The company was founded in 2020 and specializes in AI-powered solutions
3819
+ * KNOWLEDGE https://example.com/company-handbook.pdf
3820
+ * KNOWLEDGE https://example.com/product-documentation.pdf
3821
+ * ```
3822
+ *
3823
+ * @private [🪔] Maybe export the commitments through some package
3824
+ */
3825
+ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
3826
+ constructor() {
3827
+ super('KNOWLEDGE');
3828
+ }
3829
+ /**
3830
+ * Short one-line description of KNOWLEDGE.
3831
+ */
3832
+ get description() {
3833
+ return 'Add domain **knowledge** via direct text or external sources (RAG).';
3834
+ }
3835
+ /**
3836
+ * Icon for this commitment.
3837
+ */
3838
+ get icon() {
3839
+ return '🧠';
3840
+ }
3841
+ /**
3842
+ * Markdown documentation for KNOWLEDGE commitment.
3843
+ */
3844
+ get documentation() {
3845
+ return spaceTrim$1(`
3846
+ # ${this.type}
3847
+
3848
+ Adds specific knowledge, facts, or context to the agent using a RAG (Retrieval-Augmented Generation) approach for external sources.
3849
+
3850
+ ## Key aspects
3851
+
3852
+ - Both terms work identically and can be used interchangeably.
3853
+ - Supports both direct text knowledge and external URLs.
3854
+ - External sources (PDFs, websites) are processed via RAG for context retrieval.
3855
+
3856
+ ## Supported formats
3857
+
3858
+ - Direct text: Immediate knowledge incorporated into agent
3859
+ - URLs: External documents processed for contextual retrieval
3860
+ - Supported file types: PDF, text, markdown, HTML
3861
+
3862
+ ## Examples
3863
+
3864
+ \`\`\`book
3865
+ Customer Support Bot
3866
+
3867
+ PERSONA You are a helpful customer support agent for TechCorp
3868
+ KNOWLEDGE TechCorp was founded in 2020 and specializes in AI-powered solutions
3869
+ KNOWLEDGE https://example.com/company-handbook.pdf
3870
+ KNOWLEDGE https://example.com/product-documentation.pdf
3871
+ RULE Always be polite and professional
3872
+ \`\`\`
3873
+
3874
+ \`\`\`book
3875
+ Research Assistant
3876
+
3877
+ PERSONA You are a knowledgeable research assistant
3878
+ KNOWLEDGE Academic research requires careful citation and verification
3879
+ KNOWLEDGE https://example.com/research-guidelines.pdf
3880
+ ACTION Can help with literature reviews and data analysis
3881
+ STYLE Present information in clear, academic format
3882
+ \`\`\`
3883
+ `);
3884
+ }
3885
+ applyToAgentModelRequirements(requirements, content) {
3886
+ const trimmedContent = content.trim();
3887
+ if (!trimmedContent) {
3888
+ return requirements;
3889
+ }
3890
+ // Check if content is a URL (external knowledge source)
3891
+ if (isValidUrl(trimmedContent)) {
3892
+ // Store the URL for later async processing
3893
+ const updatedRequirements = {
3894
+ ...requirements,
3895
+ knowledgeSources: [
3896
+ ...(requirements.knowledgeSources || []),
3897
+ trimmedContent,
3898
+ ],
3899
+ };
3900
+ // Add placeholder information about knowledge sources to system message
3901
+ const knowledgeInfo = `Knowledge Source URL: ${trimmedContent} (will be processed for retrieval during chat)`;
3902
+ return this.appendToSystemMessage(updatedRequirements, knowledgeInfo, '\n\n');
3903
+ }
3904
+ else {
3905
+ // Direct text knowledge - add to system message
3906
+ const knowledgeSection = `Knowledge: ${trimmedContent}`;
3907
+ return this.appendToSystemMessage(requirements, knowledgeSection, '\n\n');
3908
+ }
3909
+ }
3910
+ }
3911
+ /**
3912
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3913
+ */
3914
+
3915
+ /**
3916
+ * LANGUAGE commitment definition
3917
+ *
3918
+ * The LANGUAGE/LANGUAGES commitment specifies the language(s) the agent should use in its responses.
3919
+ *
3920
+ * Example usage in agent source:
3921
+ *
3922
+ * ```book
3923
+ * LANGUAGE English
3924
+ * LANGUAGE French, English and Czech
3925
+ * ```
3926
+ *
3927
+ * @private [🪔] Maybe export the commitments through some package
3928
+ */
3929
+ class LanguageCommitmentDefinition extends BaseCommitmentDefinition {
3930
+ constructor(type = 'LANGUAGE') {
3931
+ super(type);
3932
+ }
3933
+ /**
3934
+ * Short one-line description of LANGUAGE/LANGUAGES.
3935
+ */
3936
+ get description() {
3937
+ return 'Specifies the language(s) the agent should use.';
3938
+ }
3939
+ /**
3940
+ * Icon for this commitment.
3941
+ */
3942
+ get icon() {
3943
+ return '🌐';
3944
+ }
3945
+ /**
3946
+ * Markdown documentation for LANGUAGE/LANGUAGES commitment.
3947
+ */
3948
+ get documentation() {
3949
+ return spaceTrim$1(`
3950
+ # ${this.type}
3951
+
3952
+ Specifies the language(s) the agent should use in its responses.
3953
+ This is a specialized variation of the RULE commitment focused on language constraints.
3954
+
3955
+ ## Examples
3956
+
3957
+ \`\`\`book
3958
+ Paul Smith & Associés
3959
+
3960
+ PERSONA You are a company lawyer.
3961
+ LANGUAGE French, English and Czech
3962
+ \`\`\`
3963
+
3964
+ \`\`\`book
3965
+ Customer Support
3966
+
3967
+ PERSONA You are a customer support agent.
3968
+ LANGUAGE English
3969
+ \`\`\`
3970
+ `);
3971
+ }
3972
+ applyToAgentModelRequirements(requirements, content) {
3973
+ const trimmedContent = content.trim();
3974
+ if (!trimmedContent) {
3975
+ return requirements;
3976
+ }
3977
+ // Add language rule to the system message
3978
+ const languageSection = `Language: ${trimmedContent}`;
3979
+ return this.appendToSystemMessage(requirements, languageSection, '\n\n');
3980
+ }
3981
+ }
3982
+ /**
3983
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3984
+ */
3985
+
3986
+ /**
3987
+ * MEMORY commitment definition
3988
+ *
3989
+ * The MEMORY commitment is similar to KNOWLEDGE but has a focus on remembering past
3990
+ * interactions and user preferences. It helps the agent maintain context about the
3991
+ * user's history, preferences, and previous conversations.
3992
+ *
3993
+ * Example usage in agent source:
3994
+ *
3995
+ * ```book
3996
+ * MEMORY User prefers detailed technical explanations
3997
+ * MEMORY Previously worked on React projects
3998
+ * MEMORY Timezone: UTC-5 (Eastern Time)
3999
+ * ```
4000
+ *
4001
+ * @private [🪔] Maybe export the commitments through some package
4002
+ */
4003
+ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
4004
+ constructor(type = 'MEMORY') {
4005
+ super(type);
4006
+ }
4007
+ /**
4008
+ * Short one-line description of MEMORY.
4009
+ */
4010
+ get description() {
4011
+ return 'Remember past interactions and user **preferences** for personalized responses.';
4012
+ }
4013
+ /**
4014
+ * Icon for this commitment.
4015
+ */
4016
+ get icon() {
4017
+ return '🧠';
4018
+ }
4019
+ /**
4020
+ * Markdown documentation for MEMORY commitment.
4021
+ */
4022
+ get documentation() {
4023
+ return spaceTrim$1(`
4024
+ # ${this.type}
4025
+
4026
+ Similar to KNOWLEDGE but focuses on remembering past interactions and user preferences. This commitment helps the agent maintain context about the user's history, preferences, and previous conversations.
4027
+
4028
+ ## Key aspects
4029
+
4030
+ - Both terms work identically and can be used interchangeably.
4031
+ - Focuses on user-specific information and interaction history.
4032
+ - Helps personalize responses based on past interactions.
4033
+ - Maintains continuity across conversations.
4034
+
4035
+ ## Differences from KNOWLEDGE
4036
+
4037
+ - \`KNOWLEDGE\` is for domain expertise and factual information
4038
+ - \`MEMORY\` is for user-specific context and preferences
4039
+ - \`MEMORY\` creates more personalized interactions
4040
+ - \`MEMORY\` often includes temporal or preference-based information
4041
+
4042
+ ## Examples
4043
+
4044
+ \`\`\`book
4045
+ Personal Assistant
4046
+
4047
+ PERSONA You are a personal productivity assistant
4048
+ MEMORY User is a software developer working in JavaScript/React
4049
+ MEMORY User prefers morning work sessions and afternoon meetings
4050
+ MEMORY Previously helped with project planning for mobile apps
4051
+ MEMORY User timezone: UTC-8 (Pacific Time)
4052
+ GOAL Help optimize daily productivity and workflow
4053
+ \`\`\`
4054
+
4055
+ \`\`\`book
4056
+ Learning Companion
4057
+
4058
+ PERSONA You are an educational companion for programming students
4059
+ MEMORY Student is learning Python as their first programming language
4060
+ MEMORY Previous topics covered: variables, loops, functions
4061
+ MEMORY Student learns best with practical examples and exercises
4062
+ MEMORY Last session: working on list comprehensions
4063
+ GOAL Provide progressive learning experiences tailored to student's pace
4064
+ \`\`\`
4065
+
4066
+ \`\`\`book
4067
+ Customer Support Agent
4068
+
4069
+ PERSONA You are a customer support representative
4070
+ MEMORY Customer has premium subscription since 2023
4071
+ MEMORY Previous issue: billing question resolved last month
4072
+ MEMORY Customer prefers email communication over phone calls
4073
+ MEMORY Account shows frequent use of advanced features
4074
+ GOAL Provide personalized support based on customer history
4075
+ \`\`\`
4076
+ `);
4077
+ }
4078
+ applyToAgentModelRequirements(requirements, content) {
4079
+ const trimmedContent = content.trim();
4080
+ if (!trimmedContent) {
4081
+ return requirements;
4082
+ }
4083
+ // Create memory section for system message
4084
+ const memorySection = `Memory: ${trimmedContent}`;
4085
+ // Memory information is contextual and should be included in the system message
4086
+ return this.appendToSystemMessage(requirements, memorySection, '\n\n');
4087
+ }
4088
+ }
4089
+ /**
4090
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4091
+ */
4092
+
4093
+ /**
4094
+ * AGENT MESSAGE commitment definition
4095
+ *
4096
+ * The AGENT MESSAGE commitment defines a message from the agent in the conversation history.
4097
+ * It is used to pre-fill the chat with a conversation history or to provide few-shot examples.
4098
+ *
4099
+ * Example usage in agent source:
4100
+ *
4101
+ * ```book
4102
+ * AGENT MESSAGE What seems to be the issue?
4103
+ * ```
4104
+ *
4105
+ * @private [🪔] Maybe export the commitments through some package
4106
+ */
4107
+ class AgentMessageCommitmentDefinition extends BaseCommitmentDefinition {
4108
+ constructor() {
4109
+ super('AGENT MESSAGE');
4110
+ }
4111
+ /**
4112
+ * Short one-line description of AGENT MESSAGE.
4113
+ */
4114
+ get description() {
4115
+ return 'Defines a **message from the agent** in the conversation history.';
4116
+ }
4117
+ /**
4118
+ * Icon for this commitment.
4119
+ */
4120
+ get icon() {
4121
+ return '🤖';
4122
+ }
4123
+ /**
4124
+ * Markdown documentation for AGENT MESSAGE commitment.
4125
+ */
4126
+ get documentation() {
4127
+ return spaceTrim$1(`
4128
+ # ${this.type}
4129
+
4130
+ Defines a message from the agent in the conversation history. This is used to pre-fill the chat with a conversation history or to provide few-shot examples.
4131
+
4132
+ ## Key aspects
4133
+
4134
+ - Represents a message sent by the agent.
4135
+ - Used for setting up conversation context.
4136
+ - Can be used in conjunction with USER MESSAGE.
4137
+
4138
+ ## Examples
4139
+
4140
+ \`\`\`book
4141
+ Conversation History
4142
+
4143
+ USER MESSAGE Hello, I have a problem.
4144
+ AGENT MESSAGE What seems to be the issue?
4145
+ USER MESSAGE My computer is not starting.
4146
+ \`\`\`
4147
+ `);
4148
+ }
4149
+ applyToAgentModelRequirements(requirements, content) {
4150
+ // AGENT MESSAGE is for UI display purposes / conversation history construction
4151
+ // and typically doesn't need to be added to the system prompt or model requirements directly.
4152
+ // It is extracted separately for the chat interface.
4153
+ var _a;
4154
+ const pendingUserMessage = (_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.pendingUserMessage;
4155
+ if (pendingUserMessage) {
4156
+ const newSample = { question: pendingUserMessage, answer: content };
4157
+ const newSamples = [...(requirements.samples || []), newSample];
4158
+ const newMetadata = { ...requirements.metadata };
4159
+ delete newMetadata.pendingUserMessage;
4160
+ return {
4161
+ ...requirements,
4162
+ samples: newSamples,
4163
+ metadata: newMetadata,
4164
+ };
4165
+ }
4166
+ return requirements;
4167
+ }
4168
+ }
4169
+
4170
+ /**
4171
+ * INITIAL MESSAGE commitment definition
4172
+ *
4173
+ * The INITIAL MESSAGE commitment defines the first message that the user sees when opening the chat.
4174
+ * It is used to greet the user and set the tone of the conversation.
4175
+ *
4176
+ * Example usage in agent source:
4177
+ *
4178
+ * ```book
4179
+ * INITIAL MESSAGE Hello! I am ready to help you with your tasks.
4180
+ * ```
4181
+ *
4182
+ * @private [🪔] Maybe export the commitments through some package
4183
+ */
4184
+ class InitialMessageCommitmentDefinition extends BaseCommitmentDefinition {
4185
+ constructor() {
4186
+ super('INITIAL MESSAGE');
4187
+ }
4188
+ /**
4189
+ * Short one-line description of INITIAL MESSAGE.
4190
+ */
4191
+ get description() {
4192
+ return 'Defines the **initial message** shown to the user when the chat starts.';
4193
+ }
4194
+ /**
4195
+ * Icon for this commitment.
4196
+ */
4197
+ get icon() {
4198
+ return '👋';
4199
+ }
4200
+ /**
4201
+ * Markdown documentation for INITIAL MESSAGE commitment.
4202
+ */
4203
+ get documentation() {
4204
+ return spaceTrim$1(`
4205
+ # ${this.type}
4206
+
4207
+ Defines the first message that the user sees when opening the chat. This message is purely for display purposes in the UI and does not inherently become part of the LLM's system prompt context (unless also included via other means).
4208
+
4209
+ ## Key aspects
4210
+
4211
+ - Used to greet the user.
4212
+ - Sets the tone of the conversation.
4213
+ - Displayed immediately when the chat interface loads.
4214
+
4215
+ ## Examples
4216
+
4217
+ \`\`\`book
4218
+ Support Agent
4219
+
4220
+ PERSONA You are a helpful support agent.
4221
+ INITIAL MESSAGE Hi there! How can I assist you today?
4222
+ \`\`\`
4223
+ `);
4224
+ }
4225
+ applyToAgentModelRequirements(requirements, content) {
4226
+ // INITIAL MESSAGE is for UI display purposes and for conversation history construction.
4227
+ const newSample = { question: null, answer: content };
4228
+ const newSamples = [...(requirements.samples || []), newSample];
4229
+ return {
4230
+ ...requirements,
4231
+ samples: newSamples,
4232
+ };
4233
+ }
4234
+ }
4235
+
4236
+ /**
4237
+ * MESSAGE commitment definition
4238
+ *
4239
+ * The MESSAGE commitment contains 1:1 text of the message which AI assistant already
4240
+ * sent during the conversation. Later messages are later in the conversation.
4241
+ * It is similar to EXAMPLE but it is not example, it is the real message which
4242
+ * AI assistant already sent.
4243
+ *
4244
+ * Example usage in agent source:
4245
+ *
4246
+ * ```book
4247
+ * MESSAGE Hello! How can I help you today?
4248
+ * MESSAGE I understand you're looking for information about our services.
4249
+ * MESSAGE Based on your requirements, I'd recommend our premium package.
4250
+ * ```
4251
+ *
4252
+ * @private [🪔] Maybe export the commitments through some package
4253
+ */
4254
+ class MessageCommitmentDefinition extends BaseCommitmentDefinition {
4255
+ constructor(type = 'MESSAGE') {
4256
+ super(type);
4257
+ }
4258
+ /**
4259
+ * Short one-line description of MESSAGE.
4260
+ */
4261
+ get description() {
4262
+ return 'Include actual **messages** the AI assistant has sent during conversation history.';
4263
+ }
4264
+ /**
4265
+ * Icon for this commitment.
4266
+ */
4267
+ get icon() {
4268
+ return '💬';
4269
+ }
4270
+ /**
4271
+ * Markdown documentation for MESSAGE commitment.
4272
+ */
4273
+ get documentation() {
4274
+ return spaceTrim$1(`
4275
+ # ${this.type}
4276
+
4277
+ Contains 1:1 text of the message which AI assistant already sent during the conversation. Later messages are later in the conversation. It is similar to EXAMPLE but it is not example, it is the real message which AI assistant already sent.
4278
+
4279
+ ## Key aspects
4280
+
4281
+ - Multiple \`MESSAGE\` and \`MESSAGES\` commitments represent the conversation timeline.
4282
+ - Both terms work identically and can be used interchangeably.
4283
+ - Later messages are later in the conversation chronologically.
4284
+ - Contains actual historical messages, not examples or templates.
4285
+ - Helps maintain conversation continuity and context.
4286
+
4287
+ ## Differences from EXAMPLE
4288
+
4289
+ - \`EXAMPLE\` shows hypothetical or template responses
4290
+ - \`MESSAGE\`/\`MESSAGES\` contains actual historical conversation content
4291
+ - \`MESSAGE\`/\`MESSAGES\` preserves the exact conversation flow
4292
+ - \`MESSAGE\`/\`MESSAGES\` helps with context awareness and consistency
4293
+
4294
+ ## Use cases
4295
+
4296
+ - Maintaining conversation history context
4297
+ - Ensuring consistent tone and style across messages
4298
+ - Referencing previous responses in ongoing conversations
4299
+ - Building upon previously established context
4300
+
4301
+ ## Examples
4302
+
4303
+ \`\`\`book
4304
+ Customer Support Continuation
4305
+
4306
+ PERSONA You are a helpful customer support agent
4307
+ MESSAGE Hello! How can I help you today?
4308
+ MESSAGE I understand you're experiencing issues with your account login.
4309
+ MESSAGE I've sent you a password reset link to your email address.
4310
+ MESSAGE Is there anything else I can help you with regarding your account?
4311
+ GOAL Continue providing consistent support based on conversation history
4312
+ \`\`\`
4313
+
4314
+ \`\`\`book
4315
+ Technical Discussion
4316
+
4317
+ PERSONA You are a software development mentor
4318
+ MESSAGE Let's start by reviewing the React component structure you shared.
4319
+ MESSAGE I notice you're using class components - have you considered hooks?
4320
+ MESSAGE Here's how you could refactor that using the useState hook.
4321
+ MESSAGE Great question about performance! Let me explain React's rendering cycle.
4322
+ KNOWLEDGE React hooks were introduced in version 16.8
4323
+ \`\`\`
4324
+
4325
+ \`\`\`book
4326
+ Educational Session
4327
+
4328
+ PERSONA You are a mathematics tutor
4329
+ MESSAGE Today we'll work on solving quadratic equations.
4330
+ MESSAGE Let's start with the basic form: ax² + bx + c = 0
4331
+ MESSAGE Remember, we can use the quadratic formula or factoring.
4332
+ MESSAGE You did great with that first problem! Let's try a more complex one.
4333
+ GOAL Build upon previous explanations for deeper understanding
4334
+ \`\`\`
4335
+ `);
4336
+ }
4337
+ applyToAgentModelRequirements(requirements, content) {
4338
+ const trimmedContent = content.trim();
4339
+ if (!trimmedContent) {
4340
+ return requirements;
4341
+ }
4342
+ // Create message section for system message
4343
+ const messageSection = `Previous Message: ${trimmedContent}`;
4344
+ // Messages represent conversation history and should be included for context
4345
+ return this.appendToSystemMessage(requirements, messageSection, '\n\n');
4346
+ }
4347
+ }
4348
+ /**
4349
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4350
+ */
4351
+
4352
+ /**
4353
+ * USER MESSAGE commitment definition
4354
+ *
4355
+ * The USER MESSAGE commitment defines a message from the user in the conversation history.
4356
+ * It is used to pre-fill the chat with a conversation history or to provide few-shot examples.
4357
+ *
4358
+ * Example usage in agent source:
4359
+ *
4360
+ * ```book
4361
+ * USER MESSAGE Hello, I have a problem.
4362
+ * ```
4363
+ *
4364
+ * @private [🪔] Maybe export the commitments through some package
4365
+ */
4366
+ class UserMessageCommitmentDefinition extends BaseCommitmentDefinition {
4367
+ constructor() {
4368
+ super('USER MESSAGE');
4369
+ }
4370
+ /**
4371
+ * Short one-line description of USER MESSAGE.
4372
+ */
4373
+ get description() {
4374
+ return 'Defines a **message from the user** in the conversation history.';
4375
+ }
4376
+ /**
4377
+ * Icon for this commitment.
4378
+ */
4379
+ get icon() {
4380
+ return '🧑';
4381
+ }
4382
+ /**
4383
+ * Markdown documentation for USER MESSAGE commitment.
4384
+ */
4385
+ get documentation() {
4386
+ return spaceTrim$1(`
4387
+ # ${this.type}
4388
+
4389
+ Defines a message from the user in the conversation history. This is used to pre-fill the chat with a conversation history or to provide few-shot examples.
4390
+
4391
+ ## Key aspects
4392
+
4393
+ - Represents a message sent by the user.
4394
+ - Used for setting up conversation context.
4395
+ - Can be used in conjunction with AGENT MESSAGE.
4396
+
4397
+ ## Examples
4398
+
4399
+ \`\`\`book
4400
+ Conversation History
4401
+
4402
+ USER MESSAGE Hello, I have a problem.
4403
+ AGENT MESSAGE What seems to be the issue?
4404
+ USER MESSAGE My computer is not starting.
4405
+ \`\`\`
4406
+ `);
4407
+ }
4408
+ applyToAgentModelRequirements(requirements, content) {
4409
+ return {
4410
+ ...requirements,
4411
+ metadata: {
4412
+ ...requirements.metadata,
4413
+ pendingUserMessage: content,
4414
+ },
4415
+ };
4416
+ }
4417
+ }
4418
+
4419
+ /**
4420
+ * META commitment definition
4421
+ *
4422
+ * The META commitment handles all meta-information about the agent such as:
4423
+ * - META IMAGE: Sets the agent's avatar/profile image URL
4424
+ * - META LINK: Provides profile/source links for the person the agent models
4425
+ * - META TITLE: Sets the agent's display title
4426
+ * - META DESCRIPTION: Sets the agent's description
4427
+ * - META [ANYTHING]: Any other meta information in uppercase format
4428
+ *
4429
+ * These commitments are special because they don't affect the system message,
4430
+ * but are handled separately in the parsing logic for profile display.
4431
+ *
4432
+ * Example usage in agent source:
4433
+ *
4434
+ * ```book
4435
+ * META IMAGE https://example.com/avatar.jpg
4436
+ * META LINK https://twitter.com/username
4437
+ * META TITLE Professional Assistant
4438
+ * META DESCRIPTION An AI assistant specialized in business tasks
4439
+ * META AUTHOR John Doe
4440
+ * META VERSION 1.0
4441
+ * ```
4442
+ *
4443
+ * @private [🪔] Maybe export the commitments through some package
4444
+ */
4445
+ class MetaCommitmentDefinition extends BaseCommitmentDefinition {
4446
+ constructor() {
4447
+ super('META');
4448
+ }
4449
+ /**
4450
+ * Short one-line description of META commitments.
4451
+ */
4452
+ get description() {
4453
+ return 'Set meta-information about the agent (IMAGE, LINK, TITLE, DESCRIPTION, etc.).';
4454
+ }
4455
+ /**
4456
+ * Icon for this commitment.
4457
+ */
4458
+ get icon() {
4459
+ return 'ℹ️';
4460
+ }
4461
+ /**
4462
+ * Markdown documentation for META commitment.
4463
+ */
4464
+ get documentation() {
4465
+ return spaceTrim$1(`
4466
+ # META
4467
+
4468
+ Sets meta-information about the agent that is used for display and attribution purposes.
4469
+
4470
+ ## Supported META types
4471
+
4472
+ - **META IMAGE** - Sets the agent's avatar/profile image URL
4473
+ - **META LINK** - Provides profile/source links for the person the agent models
4474
+ - **META TITLE** - Sets the agent's display title
4475
+ - **META DESCRIPTION** - Sets the agent's description
4476
+ - **META [ANYTHING]** - Any other meta information in uppercase format
4477
+
4478
+ ## Key aspects
4479
+
4480
+ - Does not modify the agent's behavior or responses
4481
+ - Used for visual representation and attribution in user interfaces
4482
+ - Multiple META commitments of different types can be used
4483
+ - Multiple META LINK commitments can be used for different social profiles
4484
+ - If multiple META commitments of the same type are specified, the last one takes precedence (except for LINK)
4485
+
4486
+ ## Examples
4487
+
4488
+ ### Basic meta information
4489
+
4490
+ \`\`\`book
4491
+ Professional Assistant
4492
+
4493
+ META IMAGE https://example.com/professional-avatar.jpg
4494
+ META TITLE Senior Business Consultant
4495
+ META DESCRIPTION Specialized in strategic planning and project management
4496
+ META LINK https://linkedin.com/in/professional
4497
+ \`\`\`
4498
+
4499
+ ### Multiple links and custom meta
4500
+
4501
+ \`\`\`book
4502
+ Open Source Developer
4503
+
4504
+ META IMAGE /assets/dev-avatar.png
4505
+ META LINK https://github.com/developer
4506
+ META LINK https://twitter.com/devhandle
4507
+ META AUTHOR Jane Smith
4508
+ META VERSION 2.1
4509
+ META LICENSE MIT
4510
+ \`\`\`
4511
+
4512
+ ### Creative assistant
4513
+
4514
+ \`\`\`book
4515
+ Creative Helper
4516
+
4517
+ META IMAGE https://example.com/creative-bot.jpg
4518
+ META TITLE Creative Writing Assistant
4519
+ META DESCRIPTION Helps with brainstorming, storytelling, and creative projects
4520
+ META INSPIRATION Books, movies, and real-world experiences
4521
+ \`\`\`
4522
+ `);
4523
+ }
4524
+ applyToAgentModelRequirements(requirements, content) {
4525
+ // META commitments don't modify the system message or model requirements
4526
+ // They are handled separately in the parsing logic for meta information extraction
4527
+ // This method exists for consistency with the CommitmentDefinition interface
4528
+ return requirements;
4529
+ }
4530
+ /**
4531
+ * Extracts meta information from the content based on the meta type
4532
+ * This is used by the parsing logic
4533
+ */
4534
+ extractMetaValue(metaType, content) {
4535
+ const trimmedContent = content.trim();
4536
+ return trimmedContent || null;
4537
+ }
4538
+ /**
4539
+ * Validates if the provided content is a valid URL (for IMAGE and LINK types)
4540
+ */
4541
+ isValidUrl(content) {
4542
+ try {
4543
+ new URL(content.trim());
4544
+ return true;
4545
+ }
4546
+ catch (_a) {
4547
+ return false;
4548
+ }
4549
+ }
4550
+ /**
4551
+ * Checks if this is a known meta type
4552
+ */
4553
+ isKnownMetaType(metaType) {
4554
+ const knownTypes = ['IMAGE', 'LINK', 'TITLE', 'DESCRIPTION', 'AUTHOR', 'VERSION', 'LICENSE'];
4555
+ return knownTypes.includes(metaType.toUpperCase());
4556
+ }
4557
+ }
4558
+ /**
4559
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4560
+ */
4561
+
4562
+ /**
4563
+ * META COLOR commitment definition
4564
+ *
4565
+ * The META COLOR commitment sets the agent's accent color.
4566
+ * This commitment is special because it doesn't affect the system message,
4567
+ * but is handled separately in the parsing logic.
4568
+ *
4569
+ * Example usage in agent source:
4570
+ *
4571
+ * ```book
4572
+ * META COLOR #ff0000
4573
+ * META COLOR #00ff00
4574
+ * ```
4575
+ *
4576
+ * You can also specify multiple colors separated by comma:
4577
+ *
4578
+ * ```book
4579
+ * META COLOR #ff0000, #00ff00, #0000ff
4580
+ * ```
4581
+ *
4582
+ * @private [🪔] Maybe export the commitments through some package
4583
+ */
4584
+ class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
4585
+ constructor() {
4586
+ super('META COLOR', ['COLOR']);
4587
+ }
4588
+ /**
4589
+ * Short one-line description of META COLOR.
4590
+ */
4591
+ get description() {
4592
+ return "Set the agent's accent color or gradient.";
4593
+ }
4594
+ /**
4595
+ * Icon for this commitment.
4596
+ */
4597
+ get icon() {
4598
+ return '🎨';
4599
+ }
4600
+ /**
4601
+ * Markdown documentation for META COLOR commitment.
4602
+ */
4603
+ get documentation() {
4604
+ return spaceTrim$1(`
4605
+ # META COLOR
4606
+
4607
+ Sets the agent's accent color or gradient.
4608
+
4609
+ ## Key aspects
4610
+
4611
+ - Does not modify the agent's behavior or responses.
4612
+ - Only one \`META COLOR\` should be used per agent.
4613
+ - If multiple are specified, the last one takes precedence.
4614
+ - Used for visual representation in user interfaces.
4615
+ - Can specify multiple colors separated by comma to create a gradient.
4616
+
4617
+ ## Examples
4618
+
4619
+ \`\`\`book
4620
+ Professional Assistant
4621
+
4622
+ META COLOR #3498db
4623
+ PERSONA You are a professional business assistant
4624
+ \`\`\`
4625
+
4626
+ \`\`\`book
4627
+ Creative Helper
4628
+
4629
+ META COLOR #e74c3c
4630
+ PERSONA You are a creative and inspiring assistant
4631
+ \`\`\`
4632
+
4633
+ \`\`\`book
4634
+ Gradient Agent
4635
+
4636
+ META COLOR #ff0000, #00ff00, #0000ff
4637
+ PERSONA You are a colorful agent
4638
+ \`\`\`
4639
+ `);
4640
+ }
4641
+ applyToAgentModelRequirements(requirements, content) {
4642
+ // META COLOR doesn't modify the system message or model requirements
4643
+ // It's handled separately in the parsing logic for profile color extraction
4644
+ // This method exists for consistency with the CommitmentDefinition interface
4645
+ return requirements;
4646
+ }
4647
+ /**
4648
+ * Extracts the profile color from the content
4649
+ * This is used by the parsing logic
4650
+ */
4651
+ extractProfileColor(content) {
4652
+ const trimmedContent = content.trim();
4653
+ return trimmedContent || null;
4654
+ }
4655
+ }
4656
+ /**
4657
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4658
+ */
4659
+
4660
+ /**
4661
+ * META FONT commitment definition
4662
+ *
4663
+ * The META FONT commitment sets the agent's font.
4664
+ * This commitment is special because it doesn't affect the system message,
4665
+ * but is handled separately in the parsing logic.
4666
+ *
4667
+ * Example usage in agent source:
4668
+ *
4669
+ * ```book
4670
+ * META FONT Poppins, Arial, sans-serif
4671
+ * META FONT Roboto
4672
+ * ```
4673
+ *
4674
+ * @private [🪔] Maybe export the commitments through some package
4675
+ */
4676
+ class MetaFontCommitmentDefinition extends BaseCommitmentDefinition {
4677
+ constructor() {
4678
+ super('META FONT', ['FONT']);
4679
+ }
4680
+ /**
4681
+ * Short one-line description of META FONT.
4682
+ */
4683
+ get description() {
4684
+ return "Set the agent's font.";
4685
+ }
4686
+ /**
4687
+ * Icon for this commitment.
4688
+ */
4689
+ get icon() {
4690
+ return '🔤';
4691
+ }
4692
+ /**
4693
+ * Markdown documentation for META FONT commitment.
4694
+ */
4695
+ get documentation() {
4696
+ return spaceTrim$1(`
4697
+ # META FONT
4698
+
4699
+ Sets the agent's font.
4700
+
4701
+ ## Key aspects
4702
+
4703
+ - Does not modify the agent's behavior or responses.
4704
+ - Only one \`META FONT\` should be used per agent.
4705
+ - If multiple are specified, the last one takes precedence.
4706
+ - Used for visual representation in user interfaces.
4707
+ - Supports Google Fonts.
4708
+
4709
+ ## Examples
4710
+
4711
+ \`\`\`book
4712
+ Modern Assistant
4713
+
4714
+ META FONT Poppins, Arial, sans-serif
4715
+ PERSONA You are a modern assistant
4716
+ \`\`\`
4717
+
4718
+ \`\`\`book
4719
+ Classic Helper
4720
+
4721
+ META FONT Times New Roman
4722
+ PERSONA You are a classic helper
4723
+ \`\`\`
4724
+ `);
4725
+ }
4726
+ applyToAgentModelRequirements(requirements, content) {
4727
+ // META FONT doesn't modify the system message or model requirements
4728
+ // It's handled separately in the parsing logic
4729
+ // This method exists for consistency with the CommitmentDefinition interface
4730
+ return requirements;
4731
+ }
4732
+ /**
4733
+ * Extracts the font from the content
4734
+ * This is used by the parsing logic
4735
+ */
4736
+ extractProfileFont(content) {
4737
+ const trimmedContent = content.trim();
4738
+ return trimmedContent || null;
4739
+ }
4740
+ }
4741
+ /**
4742
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4743
+ */
4744
+
4745
+ /**
4746
+ * META IMAGE commitment definition
4747
+ *
4748
+ * The META IMAGE commitment sets the agent's avatar/profile image URL.
4749
+ * This commitment is special because it doesn't affect the system message,
4750
+ * but is handled separately in the parsing logic.
4751
+ *
4752
+ * Example usage in agent source:
4753
+ *
4754
+ * ```book
4755
+ * META IMAGE https://example.com/avatar.jpg
4756
+ * META IMAGE /assets/agent-avatar.png
4757
+ * ```
4758
+ *
4759
+ * @private [🪔] Maybe export the commitments through some package
4760
+ */
4761
+ class MetaImageCommitmentDefinition extends BaseCommitmentDefinition {
4762
+ constructor() {
4763
+ super('META IMAGE', ['IMAGE']);
4764
+ }
4765
+ /**
4766
+ * Short one-line description of META IMAGE.
4767
+ */
4768
+ get description() {
4769
+ return "Set the agent's profile image URL.";
4770
+ }
4771
+ /**
4772
+ * Icon for this commitment.
4773
+ */
4774
+ get icon() {
4775
+ return '🖼️';
4776
+ }
4777
+ /**
4778
+ * Markdown documentation for META IMAGE commitment.
4779
+ */
4780
+ get documentation() {
4781
+ return spaceTrim$1(`
4782
+ # META IMAGE
4783
+
4784
+ Sets the agent's avatar/profile image URL.
4785
+
4786
+ ## Key aspects
4787
+
4788
+ - Does not modify the agent's behavior or responses.
4789
+ - Only one \`META IMAGE\` should be used per agent.
4790
+ - If multiple are specified, the last one takes precedence.
4791
+ - Used for visual representation in user interfaces.
4792
+
4793
+ ## Examples
4794
+
4795
+ \`\`\`book
4796
+ Professional Assistant
4797
+
4798
+ META IMAGE https://example.com/professional-avatar.jpg
4799
+ PERSONA You are a professional business assistant
4800
+ STYLE Maintain a formal and courteous tone
4801
+ \`\`\`
4802
+
4803
+ \`\`\`book
4804
+ Creative Helper
4805
+
4806
+ META IMAGE /assets/creative-bot-avatar.png
4807
+ PERSONA You are a creative and inspiring assistant
4808
+ STYLE Be enthusiastic and encouraging
4809
+ ACTION Can help with brainstorming and ideation
4810
+ \`\`\`
4811
+ `);
4812
+ }
4813
+ applyToAgentModelRequirements(requirements, content) {
4814
+ // META IMAGE doesn't modify the system message or model requirements
4815
+ // It's handled separately in the parsing logic for profile image extraction
4816
+ // This method exists for consistency with the CommitmentDefinition interface
4817
+ return requirements;
4818
+ }
4819
+ /**
4820
+ * Extracts the profile image URL from the content
4821
+ * This is used by the parsing logic
4822
+ */
4823
+ extractProfileImageUrl(content) {
4824
+ const trimmedContent = content.trim();
4825
+ return trimmedContent || null;
4826
+ }
4827
+ }
4828
+ /**
4829
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4830
+ */
4831
+
4832
+ /**
4833
+ * META LINK commitment definition
4834
+ *
4835
+ * The `META LINK` commitment represents the link to the person from whom the agent is created.
4836
+ * This commitment is special because it doesn't affect the system message,
4837
+ * but is handled separately in the parsing logic for profile display.
4838
+ *
4839
+ * Example usage in agent source:
4840
+ *
4841
+ * ```
4842
+ * META LINK https://twitter.com/username
4843
+ * META LINK https://linkedin.com/in/profile
4844
+ * META LINK https://github.com/username
4845
+ * ```
4846
+ *
4847
+ * Multiple `META LINK` commitments can be used when there are multiple sources:
4848
+ *
4849
+ * ```book
4850
+ * META LINK https://twitter.com/username
4851
+ * META LINK https://linkedin.com/in/profile
4852
+ * ```
4853
+ *
4854
+ * @private [🪔] Maybe export the commitments through some package
4855
+ */
4856
+ class MetaLinkCommitmentDefinition extends BaseCommitmentDefinition {
4857
+ constructor() {
4858
+ super('META LINK');
4859
+ }
4860
+ /**
4861
+ * Short one-line description of META LINK.
4862
+ */
4863
+ get description() {
4864
+ return 'Provide profile/source links for the person the agent models.';
4865
+ }
4866
+ /**
4867
+ * Icon for this commitment.
4868
+ */
4869
+ get icon() {
4870
+ return '🔗';
4871
+ }
4872
+ /**
4873
+ * Markdown documentation for META LINK commitment.
4874
+ */
4875
+ get documentation() {
4876
+ return spaceTrim$1(`
4877
+ # META LINK
4878
+
4879
+ Represents a profile or source link for the person the agent is modeled after.
4880
+
4881
+ ## Key aspects
4882
+
4883
+ - Does not modify the agent's behavior or responses.
4884
+ - Multiple \`META LINK\` commitments can be used for different social profiles.
4885
+ - Used for attribution and crediting the original person.
4886
+ - Displayed in user interfaces for transparency.
4887
+
4888
+ ## Examples
4889
+
4890
+ \`\`\`book
4891
+ Expert Consultant
4892
+
4893
+ META LINK https://twitter.com/expertname
4894
+ META LINK https://linkedin.com/in/expertprofile
4895
+ PERSONA You are Dr. Smith, a renowned expert in artificial intelligence
4896
+ KNOWLEDGE Extensive background in machine learning and neural networks
4897
+ \`\`\`
4898
+
4899
+ \`\`\`book
4900
+ Open Source Developer
4901
+
4902
+ META LINK https://github.com/developer
4903
+ META LINK https://twitter.com/devhandle
4904
+ PERSONA You are an experienced open source developer
4905
+ ACTION Can help with code reviews and architecture decisions
4906
+ STYLE Be direct and technical in explanations
4907
+ \`\`\`
4908
+ `);
4909
+ }
4910
+ applyToAgentModelRequirements(requirements, content) {
4911
+ // META LINK doesn't modify the system message or model requirements
4912
+ // It's handled separately in the parsing logic for profile link extraction
4913
+ // This method exists for consistency with the CommitmentDefinition interface
4914
+ return requirements;
4915
+ }
4916
+ /**
4917
+ * Extracts the profile link URL from the content
4918
+ * This is used by the parsing logic
4919
+ */
4920
+ extractProfileLinkUrl(content) {
4921
+ const trimmedContent = content.trim();
4922
+ return trimmedContent || null;
4923
+ }
4924
+ /**
4925
+ * Validates if the provided content is a valid URL
4926
+ */
4927
+ isValidUrl(content) {
4928
+ try {
4929
+ new URL(content.trim());
4930
+ return true;
4931
+ }
4932
+ catch (_a) {
4933
+ return false;
4934
+ }
4935
+ }
4936
+ }
4937
+ /**
4938
+ * Note: [💞] Ignore a discrepancy between file name and entity name
4939
+ */
4940
+
4941
+ /**
4942
+ * MODEL commitment definition
4943
+ *
4944
+ * The MODEL commitment specifies which AI model to use and can also set
4945
+ * model-specific parameters like temperature, topP, topK, and maxTokens.
4946
+ *
4947
+ * Supports multiple syntax variations:
4948
+ *
4949
+ * Single-line format:
4950
+ * ```book
4951
+ * MODEL gpt-4
4952
+ * MODEL claude-3-opus temperature=0.3
4953
+ * MODEL gpt-3.5-turbo temperature=0.8 topP=0.9
4954
+ * ```
4955
+ *
4956
+ * Multi-line named parameter format:
4957
+ * ```book
4958
+ * MODEL NAME gpt-4
4959
+ * MODEL TEMPERATURE 0.7
4960
+ * MODEL TOP_P 0.9
4961
+ * MODEL MAX_TOKENS 2048
4962
+ * ```
4963
+ *
4964
+ * @private [🪔] Maybe export the commitments through some package
4965
+ */
4966
+ class ModelCommitmentDefinition extends BaseCommitmentDefinition {
4967
+ constructor(type = 'MODEL') {
4968
+ super(type);
4969
+ }
4970
+ /**
4971
+ * Short one-line description of MODEL.
4972
+ */
4973
+ get description() {
4974
+ return 'Enforce AI model requirements including name and technical parameters.';
4975
+ }
4976
+ /**
4977
+ * Icon for this commitment.
4978
+ */
4979
+ get icon() {
4980
+ return '⚙️';
4981
+ }
4982
+ /**
4983
+ * Markdown documentation for MODEL commitment.
4984
+ */
4985
+ get documentation() {
4986
+ return spaceTrim$1(`
4987
+ # ${this.type}
4988
+
4989
+ Enforces technical parameters for the AI model, ensuring consistent behavior across different execution environments.
4990
+
4991
+ ## Key aspects
4992
+
4993
+ - When no \`MODEL\` commitment is specified, the best model requirement is picked automatically based on the agent \`PERSONA\`, \`KNOWLEDGE\`, \`TOOLS\` and other commitments
4994
+ - Multiple \`MODEL\` commitments can be used to specify different parameters
4995
+ - Both \`MODEL\` and \`MODELS\` terms work identically and can be used interchangeably
4996
+ - Parameters control the randomness, creativity, and technical aspects of model responses
4997
+
4998
+ ## Syntax variations
4999
+
5000
+ ### Single-line format (legacy support)
5001
+ \`\`\`book
5002
+ MODEL gpt-4
5003
+ MODEL claude-3-opus temperature=0.3
5004
+ MODEL gpt-3.5-turbo temperature=0.8 topP=0.9
5005
+ \`\`\`
5006
+
5007
+ ### Multi-line named parameter format (recommended)
5008
+ \`\`\`book
5009
+ MODEL NAME gpt-4
5010
+ MODEL TEMPERATURE 0.7
5011
+ MODEL TOP_P 0.9
5012
+ MODEL MAX_TOKENS 2048
5013
+ \`\`\`
5014
+
5015
+ ## Supported parameters
5016
+
5017
+ - \`NAME\`: The specific model to use (e.g., 'gpt-4', 'claude-3-opus')
5018
+ - \`TEMPERATURE\`: Controls randomness (0.0 = deterministic, 1.0+ = creative)
5019
+ - \`TOP_P\`: Nucleus sampling parameter for controlling diversity
5020
+ - \`TOP_K\`: Top-k sampling parameter for limiting vocabulary
5021
+ - \`MAX_TOKENS\`: Maximum number of tokens the model can generate
5022
+
5023
+ ## Examples
5024
+
5025
+ ### Precise deterministic assistant
5026
+ \`\`\`book
5027
+ Precise Assistant
5028
+
5029
+ PERSONA You are a precise and accurate assistant
5030
+ MODEL NAME gpt-4
5031
+ MODEL TEMPERATURE 0.1
5032
+ MODEL MAX_TOKENS 1024
5033
+ RULE Always provide factual information
5034
+ \`\`\`
5035
+
5036
+ ### Creative writing assistant
5037
+ \`\`\`book
5038
+ Creative Writer
5039
+
5040
+ PERSONA You are a creative writing assistant
5041
+ MODEL NAME claude-3-opus
5042
+ MODEL TEMPERATURE 0.8
5043
+ MODEL TOP_P 0.9
5044
+ MODEL MAX_TOKENS 2048
5045
+ STYLE Be imaginative and expressive
5046
+ ACTION Can help with storytelling and character development
5047
+ \`\`\`
5048
+
5049
+ ### Balanced conversational agent
5050
+ \`\`\`book
5051
+ Balanced Assistant
5052
+
5053
+ PERSONA You are a helpful and balanced assistant
5054
+ MODEL NAME gpt-4
5055
+ MODEL TEMPERATURE 0.7
5056
+ MODEL TOP_P 0.95
5057
+ MODEL TOP_K 40
5058
+ MODEL MAX_TOKENS 1500
5059
+ \`\`\`
5060
+ `);
5061
+ }
5062
+ applyToAgentModelRequirements(requirements, content) {
5063
+ var _a;
5064
+ const trimmedContent = content.trim();
5065
+ if (!trimmedContent) {
5066
+ return requirements;
5067
+ }
5068
+ const parts = trimmedContent.split(/\s+/);
5069
+ const firstPart = (_a = parts[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase();
5070
+ // Check if this is the new named parameter format
5071
+ if (this.isNamedParameter(firstPart)) {
5072
+ return this.parseNamedParameter(requirements, firstPart, parts.slice(1));
5073
+ }
5074
+ else {
5075
+ // Legacy single-line format: "MODEL gpt-4 temperature=0.3 topP=0.9"
5076
+ return this.parseLegacyFormat(requirements, parts);
5077
+ }
5078
+ }
5079
+ /**
5080
+ * Check if the first part is a known named parameter
5081
+ */
5082
+ isNamedParameter(part) {
5083
+ if (!part)
5084
+ return false;
5085
+ const knownParams = ['NAME', 'TEMPERATURE', 'TOP_P', 'TOP_K', 'MAX_TOKENS'];
5086
+ return knownParams.includes(part);
5087
+ }
5088
+ /**
5089
+ * Parse the new named parameter format: "MODEL TEMPERATURE 0.7"
5090
+ */
5091
+ parseNamedParameter(requirements, parameterName, valueParts) {
5092
+ const value = valueParts.join(' ').trim();
5093
+ if (!value) {
5094
+ return requirements;
5095
+ }
5096
+ const result = { ...requirements };
5097
+ switch (parameterName) {
5098
+ case 'NAME':
5099
+ result.modelName = value;
5100
+ break;
5101
+ case 'TEMPERATURE': {
5102
+ const temperature = parseFloat(value);
5103
+ if (!isNaN(temperature)) {
5104
+ result.temperature = temperature;
5105
+ }
5106
+ break;
5107
+ }
5108
+ case 'TOP_P': {
5109
+ const topP = parseFloat(value);
5110
+ if (!isNaN(topP)) {
5111
+ result.topP = topP;
5112
+ }
5113
+ break;
5114
+ }
5115
+ case 'TOP_K': {
5116
+ const topK = parseFloat(value);
5117
+ if (!isNaN(topK)) {
5118
+ result.topK = Math.round(topK);
5119
+ }
5120
+ break;
5121
+ }
5122
+ case 'MAX_TOKENS': {
5123
+ const maxTokens = parseFloat(value);
5124
+ if (!isNaN(maxTokens)) {
5125
+ result.maxTokens = Math.round(maxTokens);
5126
+ }
5127
+ break;
5128
+ }
5129
+ }
5130
+ return result;
5131
+ }
5132
+ /**
5133
+ * Parse the legacy format: "MODEL gpt-4 temperature=0.3 topP=0.9"
5134
+ */
5135
+ parseLegacyFormat(requirements, parts) {
5136
+ const modelName = parts[0];
5137
+ if (!modelName) {
5138
+ return requirements;
5139
+ }
5140
+ // Start with the model name
5141
+ const result = {
5142
+ ...requirements,
5143
+ modelName,
5144
+ };
5145
+ // Parse additional key=value parameters
5146
+ for (let i = 1; i < parts.length; i++) {
5147
+ const param = parts[i];
5148
+ if (param && param.includes('=')) {
5149
+ const [key, value] = param.split('=');
5150
+ if (key && value) {
5151
+ const numValue = parseFloat(value);
5152
+ if (!isNaN(numValue)) {
5153
+ switch (key.toLowerCase()) {
5154
+ case 'temperature':
5155
+ result.temperature = numValue;
5156
+ break;
5157
+ case 'topp':
5158
+ case 'top_p':
5159
+ result.topP = numValue;
5160
+ break;
5161
+ case 'topk':
5162
+ case 'top_k':
5163
+ result.topK = Math.round(numValue);
5164
+ break;
5165
+ case 'max_tokens':
5166
+ case 'maxTokens':
5167
+ result.maxTokens = Math.round(numValue);
5168
+ break;
5169
+ }
5170
+ }
5171
+ }
5172
+ }
5173
+ }
5174
+ return result;
5175
+ }
5176
+ }
5177
+ /**
5178
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5179
+ */
5180
+
5181
+ /**
5182
+ * NOTE commitment definition
5183
+ *
5184
+ * The NOTE commitment is used to add comments to the agent source without making any changes
5185
+ * to the system message or agent model requirements. It serves as a documentation mechanism
5186
+ * for developers to add explanatory comments, reminders, or annotations directly in the agent source.
5187
+ *
5188
+ * Key features:
5189
+ * - Makes no changes to the system message
5190
+ * - Makes no changes to agent model requirements
5191
+ * - Content is preserved in metadata.NOTE for debugging and inspection
5192
+ * - Multiple NOTE commitments are aggregated together
5193
+ * - Comments (# NOTE) are removed from the final system message
5194
+ *
5195
+ * Example usage in agent source:
5196
+ *
5197
+ * ```book
5198
+ * NOTE This agent was designed for customer support scenarios
5199
+ * NOTE Remember to update the knowledge base monthly
5200
+ * NOTE Performance optimized for quick response times
5201
+ * ```
5202
+ *
5203
+ * The above notes will be stored in metadata but won't affect the agent's behavior.
5204
+ *
5205
+ * @private [🪔] Maybe export the commitments through some package
5206
+ */
5207
+ class NoteCommitmentDefinition extends BaseCommitmentDefinition {
5208
+ constructor(type = 'NOTE') {
5209
+ super(type);
5210
+ }
5211
+ /**
5212
+ * Short one-line description of NOTE.
5213
+ */
5214
+ get description() {
5215
+ return 'Add developer-facing notes without changing behavior or output.';
5216
+ }
5217
+ /**
5218
+ * Icon for this commitment.
5219
+ */
5220
+ get icon() {
5221
+ return '📝';
5222
+ }
5223
+ /**
5224
+ * Markdown documentation for NOTE commitment.
5225
+ */
5226
+ get documentation() {
5227
+ return spaceTrim$1(`
5228
+ # ${this.type}
5229
+
5230
+ Adds comments for documentation without changing agent behavior.
5231
+
5232
+ ## Key aspects
5233
+
5234
+ - Does not modify the agent's behavior or responses.
5235
+ - Multiple \`NOTE\`, \`NOTES\`, \`COMMENT\`, and \`NONCE\` commitments are aggregated for debugging.
5236
+ - All four terms work identically and can be used interchangeably.
5237
+ - Useful for documenting design decisions and reminders.
5238
+ - Content is preserved in metadata for inspection.
5239
+
5240
+ ## Examples
5241
+
5242
+ \`\`\`book
5243
+ Customer Support Bot
5244
+
5245
+ NOTE This agent was designed for customer support scenarios
5246
+ COMMENT Remember to update the knowledge base monthly
5247
+ PERSONA You are a helpful customer support representative
5248
+ KNOWLEDGE Company policies and procedures
5249
+ RULE Always be polite and professional
5250
+ \`\`\`
5251
+
5252
+ \`\`\`book
5253
+ Research Assistant
5254
+
5255
+ NONCE Performance optimized for quick response times
5256
+ NOTE Uses RAG for accessing latest research papers
5257
+ PERSONA You are a knowledgeable research assistant
5258
+ ACTION Can help with literature reviews and citations
5259
+ STYLE Present information in academic format
5260
+ \`\`\`
5261
+ `);
5262
+ }
5263
+ applyToAgentModelRequirements(requirements, content) {
5264
+ // The NOTE commitment makes no changes to the system message or model requirements
5265
+ // It only stores the note content in metadata for documentation purposes
5266
+ const trimmedContent = spaceTrim$1(content);
5267
+ if (trimmedContent === '') {
5268
+ return requirements;
5269
+ }
5270
+ // Return requirements with updated notes but no changes to system message
5271
+ return {
5272
+ ...requirements,
5273
+ notes: [...(requirements.notes || []), trimmedContent],
5274
+ };
5275
+ }
5276
+ }
5277
+ /**
5278
+ * [💞] Ignore a discrepancy between file name and entity name
5279
+ */
5280
+
5281
+ /**
5282
+ * OPEN commitment definition
5283
+ *
5284
+ * The OPEN commitment specifies that the agent can be modified by conversation.
5285
+ * This is the default behavior.
5286
+ *
5287
+ * Example usage in agent source:
5288
+ *
5289
+ * ```book
5290
+ * OPEN
5291
+ * ```
5292
+ *
5293
+ * @private [🪔] Maybe export the commitments through some package
5294
+ */
5295
+ class OpenCommitmentDefinition extends BaseCommitmentDefinition {
5296
+ constructor() {
5297
+ super('OPEN');
5298
+ }
5299
+ /**
5300
+ * Short one-line description of OPEN.
5301
+ */
5302
+ get description() {
5303
+ return 'Allow the agent to be modified by conversation (default).';
5304
+ }
5305
+ /**
5306
+ * Icon for this commitment.
5307
+ */
5308
+ get icon() {
5309
+ return '🔓';
5310
+ }
5311
+ /**
5312
+ * Markdown documentation for OPEN commitment.
5313
+ */
5314
+ get documentation() {
5315
+ return spaceTrim$1(`
5316
+ # OPEN
5317
+
5318
+ Specifies that the agent can be modified by conversation with it.
5319
+ This means the agent will learn from interactions and update its source code.
5320
+
5321
+ This is the default behavior if neither \`OPEN\` nor \`CLOSED\` is specified.
5322
+
5323
+ > See also [CLOSED](/docs/CLOSED)
5324
+
5325
+ ## Example
5326
+
5327
+ \`\`\`book
5328
+ OPEN
5329
+ \`\`\`
5330
+ `);
5331
+ }
5332
+ applyToAgentModelRequirements(requirements, _content) {
5333
+ // Since OPEN is default, we can just ensure isClosed is false
5334
+ // But to be explicit we can set it
5335
+ const updatedMetadata = {
5336
+ ...requirements.metadata,
5337
+ isClosed: false,
5338
+ };
5339
+ return {
5340
+ ...requirements,
5341
+ metadata: updatedMetadata,
5342
+ };
5343
+ }
5344
+ }
5345
+ /**
5346
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5347
+ */
5348
+
5349
+ /**
5350
+ * PERSONA commitment definition
5351
+ *
5352
+ * The PERSONA commitment modifies the agent's personality and character in the system message.
5353
+ * It defines who the agent is, their background, expertise, and personality traits.
5354
+ *
5355
+ * Key features:
5356
+ * - Multiple PERSONA commitments are automatically merged into one
5357
+ * - Content is placed at the beginning of the system message
5358
+ * - Original content with comments is preserved in metadata.PERSONA
5359
+ * - Comments (# PERSONA) are removed from the final system message
5360
+ *
5361
+ * Example usage in agent source:
5362
+ *
5363
+ * ```book
5364
+ * PERSONA You are a helpful programming assistant with expertise in TypeScript and React
5365
+ * PERSONA You have deep knowledge of modern web development practices
5366
+ * ```
5367
+ *
5368
+ * The above will be merged into a single persona section at the beginning of the system message.
5369
+ *
5370
+ * @private [🪔] Maybe export the commitments through some package
5371
+ */
5372
+ class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
5373
+ constructor(type = 'PERSONA') {
5374
+ super(type);
5375
+ }
5376
+ /**
5377
+ * Short one-line description of PERSONA.
5378
+ */
5379
+ get description() {
5380
+ return 'Define who the agent is: background, expertise, and personality.';
5381
+ }
5382
+ /**
5383
+ * Icon for this commitment.
5384
+ */
5385
+ get icon() {
5386
+ return '👤';
5387
+ }
5388
+ /**
5389
+ * Markdown documentation for PERSONA commitment.
5390
+ */
5391
+ get documentation() {
5392
+ return spaceTrim$1(`
5393
+ # ${this.type}
5394
+
5395
+ Defines who the agent is, their background, expertise, and personality traits.
5396
+
5397
+ ## Key aspects
5398
+
5399
+ - Multiple \`PERSONA\` and \`PERSONAE\` commitments are merged together.
5400
+ - Both terms work identically and can be used interchangeably.
5401
+ - If they are in conflict, the last one takes precedence.
5402
+ - You can write persona content in multiple lines.
5403
+
5404
+ ## Examples
5405
+
5406
+ \`\`\`book
5407
+ Programming Assistant
5408
+
5409
+ PERSONA You are a helpful programming assistant with expertise in TypeScript and React
5410
+ PERSONA You have deep knowledge of modern web development practices
5411
+ \`\`\`
5412
+ `);
5413
+ }
5414
+ applyToAgentModelRequirements(requirements, content) {
5415
+ var _a, _b;
5416
+ // The PERSONA commitment aggregates all persona content and places it at the beginning
5417
+ const trimmedContent = content.trim();
5418
+ if (!trimmedContent) {
5419
+ return requirements;
5420
+ }
5421
+ // Get existing persona content from metadata
5422
+ const existingPersonaContent = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.PERSONA) || '';
5423
+ // Merge the new content with existing persona content
5424
+ // When multiple PERSONA commitments exist, they are merged into one
5425
+ const mergedPersonaContent = existingPersonaContent
5426
+ ? `${existingPersonaContent}\n${trimmedContent}`
5427
+ : trimmedContent;
5428
+ // Store the merged persona content in metadata for debugging and inspection
5429
+ const updatedMetadata = {
5430
+ ...requirements.metadata,
5431
+ PERSONA: mergedPersonaContent,
5432
+ };
5433
+ // Get the agent name from metadata (which should contain the first line of agent source)
5434
+ // If not available, extract from current system message as fallback
5435
+ let agentName = (_b = requirements.metadata) === null || _b === void 0 ? void 0 : _b.agentName;
5436
+ if (!agentName) {
5437
+ // Fallback: extract from current system message
5438
+ const currentMessage = requirements.systemMessage.trim();
5439
+ const basicFormatMatch = currentMessage.match(/^You are (.+)$/);
5440
+ if (basicFormatMatch && basicFormatMatch[1]) {
5441
+ agentName = basicFormatMatch[1];
5442
+ }
5443
+ else {
5444
+ agentName = 'AI Agent'; // Final fallback
5445
+ }
5446
+ }
5447
+ // Remove any existing persona content from the system message
5448
+ // (this handles the case where we're processing multiple PERSONA commitments)
5449
+ const currentMessage = requirements.systemMessage.trim();
5450
+ let cleanedMessage = currentMessage;
5451
+ // Check if current message starts with persona content or is just the basic format
5452
+ const basicFormatRegex = /^You are .+$/;
5453
+ const isBasicFormat = basicFormatRegex.test(currentMessage) && !currentMessage.includes('\n');
5454
+ if (isBasicFormat) {
5455
+ // Replace the basic format entirely
5456
+ cleanedMessage = '';
5457
+ }
5458
+ else if (currentMessage.startsWith('# PERSONA')) {
5459
+ // Remove existing persona section by finding where it ends
5460
+ const lines = currentMessage.split('\n');
5461
+ let personaEndIndex = lines.length;
5462
+ // Find the end of the PERSONA section (next comment or end of message)
5463
+ for (let i = 1; i < lines.length; i++) {
5464
+ const line = lines[i].trim();
5465
+ if (line.startsWith('#') && !line.startsWith('# PERSONA')) {
5466
+ personaEndIndex = i;
5467
+ break;
5468
+ }
5469
+ }
5470
+ // Keep everything after the PERSONA section
5471
+ cleanedMessage = lines.slice(personaEndIndex).join('\n').trim();
5472
+ }
5473
+ // TODO: [🕛] There should be `agentFullname` not `agentName`
5474
+ // Create new system message with persona at the beginning
5475
+ // Format: "You are {agentName}\n{personaContent}"
5476
+ // The # PERSONA comment will be removed later by removeCommentsFromSystemMessage
5477
+ const personaSection = `# PERSONA\nYou are ${agentName}\n${mergedPersonaContent}`; // <- TODO: Use spaceTrim
5478
+ const newSystemMessage = cleanedMessage ? `${personaSection}\n\n${cleanedMessage}` : personaSection;
5479
+ return {
5480
+ ...requirements,
5481
+ systemMessage: newSystemMessage,
5482
+ metadata: updatedMetadata,
5483
+ };
5484
+ }
5485
+ }
5486
+ /**
5487
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5488
+ */
5489
+
5490
+ /**
5491
+ * RULE commitment definition
5492
+ *
5493
+ * The RULE/RULES commitment adds behavioral constraints and guidelines that the agent must follow.
5494
+ * These are specific instructions about what the agent should or shouldn't do.
5495
+ *
5496
+ * Example usage in agent source:
5497
+ *
5498
+ * ```book
5499
+ * RULE Always ask for clarification if the user's request is ambiguous
5500
+ * RULES Never provide medical advice, always refer to healthcare professionals
5501
+ * ```
5502
+ *
5503
+ * @private [🪔] Maybe export the commitments through some package
5504
+ */
5505
+ class RuleCommitmentDefinition extends BaseCommitmentDefinition {
5506
+ constructor(type = 'RULE') {
5507
+ super(type);
5508
+ }
5509
+ /**
5510
+ * Short one-line description of RULE/RULES.
5511
+ */
5512
+ get description() {
5513
+ return 'Add behavioral rules the agent must follow.';
5514
+ }
5515
+ /**
5516
+ * Icon for this commitment.
5517
+ */
5518
+ get icon() {
5519
+ return '⚖️';
5520
+ }
5521
+ /**
5522
+ * Markdown documentation for RULE/RULES commitment.
5523
+ */
5524
+ get documentation() {
5525
+ return spaceTrim$1(`
5526
+ # ${this.type}
5527
+
5528
+ Adds behavioral constraints and guidelines that the agent must follow.
5529
+
5530
+ ## Key aspects
5531
+
5532
+ - All rules are treated equally regardless of singular/plural form.
5533
+ - Rules define what the agent must or must not do.
5534
+
5535
+ ## Examples
5536
+
5537
+ \`\`\`book
5538
+ Customer Support Agent
5539
+
5540
+ PERSONA You are a helpful customer support representative
5541
+ RULE Always ask for clarification if the user's request is ambiguous
5542
+ RULE Be polite and professional in all interactions
5543
+ RULES Never provide medical or legal advice
5544
+ STYLE Maintain a friendly and helpful tone
5545
+ \`\`\`
5546
+
5547
+ \`\`\`book
5548
+ Educational Tutor
5549
+
5550
+ PERSONA You are a patient and knowledgeable tutor
5551
+ RULE Break down complex concepts into simple steps
5552
+ RULE Always encourage students and celebrate their progress
5553
+ RULE If you don't know something, admit it and suggest resources
5554
+ SAMPLE When explaining math: "Let's work through this step by step..."
5555
+ \`\`\`
5556
+ `);
5557
+ }
5558
+ applyToAgentModelRequirements(requirements, content) {
5559
+ const trimmedContent = content.trim();
5560
+ if (!trimmedContent) {
5561
+ return requirements;
5562
+ }
5563
+ // Add rule to the system message
5564
+ const ruleSection = `Rule: ${trimmedContent}`;
5565
+ return this.appendToSystemMessage(requirements, ruleSection, '\n\n');
5566
+ }
5567
+ }
5568
+ /**
5569
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5570
+ */
5571
+
5572
+ /**
5573
+ * SAMPLE commitment definition
5574
+ *
5575
+ * The SAMPLE/EXAMPLE commitment provides examples of how the agent should respond
5576
+ * or behave in certain situations. These examples help guide the agent's responses.
5577
+ *
5578
+ * Example usage in agent source:
5579
+ *
5580
+ * ```book
5581
+ * SAMPLE When asked about pricing, respond: "Our basic plan starts at $10/month..."
5582
+ * EXAMPLE For code questions, always include working code snippets
5583
+ * ```
5584
+ *
5585
+ * @private [🪔] Maybe export the commitments through some package
5586
+ */
5587
+ class SampleCommitmentDefinition extends BaseCommitmentDefinition {
5588
+ constructor(type = 'SAMPLE') {
5589
+ super(type);
5590
+ }
5591
+ /**
5592
+ * Short one-line description of SAMPLE/EXAMPLE.
5593
+ */
5594
+ get description() {
5595
+ return 'Provide example responses to guide behavior.';
5596
+ }
5597
+ /**
5598
+ * Icon for this commitment.
5599
+ */
5600
+ get icon() {
5601
+ return '🔍';
5602
+ }
5603
+ /**
5604
+ * Markdown documentation for SAMPLE/EXAMPLE commitment.
5605
+ */
5606
+ get documentation() {
5607
+ return spaceTrim$1(`
5608
+ # ${this.type}
5609
+
5610
+ Provides examples of how the agent should respond or behave in certain situations.
5611
+
5612
+ ## Key aspects
5613
+
5614
+ - Both terms work identically and can be used interchangeably.
5615
+ - Examples help guide the agent's response patterns and style.
5616
+
5617
+ ## Examples
5618
+
5619
+ \`\`\`book
5620
+ Sales Assistant
5621
+
5622
+ PERSONA You are a knowledgeable sales representative
5623
+ SAMPLE When asked about pricing, respond: "Our basic plan starts at $10/month..."
5624
+ SAMPLE For feature comparisons, create a clear comparison table
5625
+ RULE Always be honest about limitations
5626
+ \`\`\`
5627
+
5628
+ \`\`\`book
5629
+ Code Reviewer
5630
+
5631
+ PERSONA You are an experienced software engineer
5632
+ EXAMPLE For code questions, always include working code snippets
5633
+ EXAMPLE When suggesting improvements: "Here's a more efficient approach..."
5634
+ RULE Explain the reasoning behind your suggestions
5635
+ STYLE Be constructive and encouraging in feedback
5636
+ \`\`\`
5637
+ `);
5638
+ }
5639
+ applyToAgentModelRequirements(requirements, content) {
5640
+ const trimmedContent = content.trim();
5641
+ if (!trimmedContent) {
5642
+ return requirements;
5643
+ }
5644
+ // Add example to the system message
5645
+ const exampleSection = `Example: ${trimmedContent}`;
5646
+ return this.appendToSystemMessage(requirements, exampleSection, '\n\n');
5647
+ }
5648
+ }
5649
+ /**
5650
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5651
+ */
5652
+
5653
+ /**
5654
+ * SCENARIO commitment definition
5655
+ *
5656
+ * The SCENARIO commitment defines a specific situation or context in which the AI
5657
+ * assistant should operate. It helps to set the scene for the AI's responses.
5658
+ * Later scenarios are more important than earlier scenarios.
5659
+ *
5660
+ * Example usage in agent source:
5661
+ *
5662
+ * ```book
5663
+ * SCENARIO You are in a customer service call center during peak hours
5664
+ * SCENARIO The customer is frustrated and has been on hold for 20 minutes
5665
+ * SCENARIO This is the customer's third call about the same issue
5666
+ * ```
5667
+ *
5668
+ * @private [🪔] Maybe export the commitments through some package
5669
+ */
5670
+ class ScenarioCommitmentDefinition extends BaseCommitmentDefinition {
5671
+ constructor(type = 'SCENARIO') {
5672
+ super(type);
5673
+ }
5674
+ /**
5675
+ * Short one-line description of SCENARIO.
5676
+ */
5677
+ get description() {
5678
+ return 'Define specific **situations** or contexts for AI responses, with later scenarios having higher priority.';
5679
+ }
5680
+ /**
5681
+ * Icon for this commitment.
5682
+ */
5683
+ get icon() {
5684
+ return '🎭';
5685
+ }
5686
+ /**
5687
+ * Markdown documentation for SCENARIO commitment.
5688
+ */
5689
+ get documentation() {
5690
+ return spaceTrim$1(`
5691
+ # ${this.type}
5692
+
5693
+ Defines a specific situation or context in which the AI assistant should operate. It helps to set the scene for the AI's responses. Later scenarios are more important than earlier scenarios.
5694
+
5695
+ ## Key aspects
5696
+
5697
+ - Multiple \`SCENARIO\` and \`SCENARIOS\` commitments build upon each other.
5698
+ - Both terms work identically and can be used interchangeably.
5699
+ - Later scenarios have higher priority and can override earlier scenarios.
5700
+ - Provides situational context that influences response tone and content.
5701
+ - Helps establish the environment and circumstances for interactions.
5702
+
5703
+ ## Priority system
5704
+
5705
+ When multiple scenarios are defined, they are processed in order, with later scenarios taking precedence over earlier ones when there are conflicts.
5706
+
5707
+ ## Use cases
5708
+
5709
+ - Setting the physical or virtual environment
5710
+ - Establishing time constraints or urgency
5711
+ - Defining relationship dynamics or power structures
5712
+ - Creating emotional or situational context
5713
+
5714
+ ## Examples
5715
+
5716
+ \`\`\`book
5717
+ Emergency Response Operator
5718
+
5719
+ PERSONA You are an emergency response operator
5720
+ SCENARIO You are handling a 911 emergency call
5721
+ SCENARIO The caller is panicked and speaking rapidly
5722
+ SCENARIO Time is critical - every second counts
5723
+ GOAL Gather essential information quickly and dispatch appropriate help
5724
+ RULE Stay calm and speak clearly
5725
+ \`\`\`
5726
+
5727
+ \`\`\`book
5728
+ Sales Representative
5729
+
5730
+ PERSONA You are a software sales representative
5731
+ SCENARIO You are in the final meeting of a 6-month sales cycle
5732
+ SCENARIO The client has budget approval and decision-making authority
5733
+ SCENARIO Two competitors have also submitted proposals
5734
+ SCENARIO The client values long-term partnership over lowest price
5735
+ GOAL Close the deal while building trust for future business
5736
+ \`\`\`
5737
+
5738
+ \`\`\`book
5739
+ Medical Assistant
5740
+
5741
+ PERSONA You are a medical assistant in a busy clinic
5742
+ SCENARIO The waiting room is full and the doctor is running behind schedule
5743
+ SCENARIO Patients are becoming impatient and anxious
5744
+ SCENARIO You need to manage expectations while maintaining professionalism
5745
+ SCENARIO Some patients have been waiting over an hour
5746
+ GOAL Keep patients informed and calm while supporting efficient clinic flow
5747
+ RULE Never provide medical advice or diagnosis
5748
+ \`\`\`
5749
+
5750
+ \`\`\`book
5751
+ Technical Support Agent
5752
+
5753
+ PERSONA You are a technical support agent
5754
+ SCENARIO The customer is a small business owner during their busy season
5755
+ SCENARIO Their main business system has been down for 2 hours
5756
+ SCENARIO They are losing money every minute the system is offline
5757
+ SCENARIO This is their first experience with your company
5758
+ GOAL Resolve the issue quickly while creating a positive first impression
5759
+ \`\`\`
5760
+ `);
5761
+ }
5762
+ applyToAgentModelRequirements(requirements, content) {
5763
+ const trimmedContent = content.trim();
5764
+ if (!trimmedContent) {
5765
+ return requirements;
5766
+ }
5767
+ // Create scenario section for system message
5768
+ const scenarioSection = `Scenario: ${trimmedContent}`;
5769
+ // Scenarios provide important contextual information that affects behavior
5770
+ return this.appendToSystemMessage(requirements, scenarioSection, '\n\n');
5771
+ }
5772
+ }
5773
+ /**
5774
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5775
+ */
5776
+
5777
+ /**
5778
+ * STYLE commitment definition
5779
+ *
5780
+ * The STYLE commitment defines how the agent should format and present its responses.
5781
+ * This includes tone, writing style, formatting preferences, and communication patterns.
5782
+ *
5783
+ * Example usage in agent source:
5784
+ *
5785
+ * ```book
5786
+ * STYLE Write in a professional but friendly tone, use bullet points for lists
5787
+ * STYLE Always provide code examples when explaining programming concepts
5788
+ * ```
5789
+ *
5790
+ * @private [🪔] Maybe export the commitments through some package
5791
+ */
5792
+ class StyleCommitmentDefinition extends BaseCommitmentDefinition {
5793
+ constructor(type = 'STYLE') {
5794
+ super(type);
5795
+ }
5796
+ /**
5797
+ * Short one-line description of STYLE.
5798
+ */
5799
+ get description() {
5800
+ return 'Control the tone and writing style of responses.';
5801
+ }
5802
+ /**
5803
+ * Icon for this commitment.
5804
+ */
5805
+ get icon() {
5806
+ return '🖋️';
5807
+ }
5808
+ /**
5809
+ * Markdown documentation for STYLE commitment.
5810
+ */
5811
+ get documentation() {
5812
+ return spaceTrim$1(`
5813
+ # ${this.type}
5814
+
5815
+ Defines how the agent should format and present its responses (tone, writing style, formatting).
5816
+
5817
+ ## Key aspects
5818
+
5819
+ - Both terms work identically and can be used interchangeably.
5820
+ - Later style instructions can override earlier ones.
5821
+ - Style affects both tone and presentation format.
5822
+
5823
+ ## Examples
5824
+
5825
+ \`\`\`book
5826
+ Technical Writer
5827
+
5828
+ PERSONA You are a technical documentation expert
5829
+ STYLE Write in a professional but friendly tone, use bullet points for lists
5830
+ STYLE Always provide code examples when explaining programming concepts
5831
+ FORMAT Use markdown formatting with clear headings
5832
+ \`\`\`
5833
+
5834
+ \`\`\`book
5835
+ Creative Assistant
5836
+
5837
+ PERSONA You are a creative writing helper
5838
+ STYLE Be enthusiastic and encouraging in your responses
5839
+ STYLE Use vivid metaphors and analogies to explain concepts
5840
+ STYLE Keep responses conversational and engaging
5841
+ RULE Always maintain a positive and supportive tone
5842
+ \`\`\`
5843
+ `);
5844
+ }
5845
+ applyToAgentModelRequirements(requirements, content) {
5846
+ const trimmedContent = content.trim();
5847
+ if (!trimmedContent) {
5848
+ return requirements;
5849
+ }
5850
+ // Add style instructions to the system message
5851
+ const styleSection = `Style: ${trimmedContent}`;
5852
+ return this.appendToSystemMessage(requirements, styleSection, '\n\n');
5853
+ }
5854
+ }
5855
+ /**
5856
+ * [💞] Ignore a discrepancy between file name and entity name
5857
+ */
5858
+
5859
+ /**
5860
+ * USE commitment definition
5861
+ *
5862
+ * The USE commitment indicates that the agent should utilize specific tools or capabilities
5863
+ * to access and interact with external systems when necessary.
5864
+ *
5865
+ * Supported USE types:
5866
+ * - USE BROWSER: Enables the agent to use a web browser tool
5867
+ * - USE SEARCH ENGINE (future): Enables search engine access
5868
+ * - USE FILE SYSTEM (future): Enables file system operations
5869
+ * - USE MCP (future): Enables MCP server connections
5870
+ *
5871
+ * The content following the USE commitment is ignored (similar to NOTE).
5872
+ *
5873
+ * Example usage in agent source:
5874
+ *
5875
+ * ```book
5876
+ * USE BROWSER
5877
+ * USE SEARCH ENGINE
5878
+ * ```
5879
+ *
5880
+ * @private [🪔] Maybe export the commitments through some package
5881
+ */
5882
+ class UseCommitmentDefinition extends BaseCommitmentDefinition {
5883
+ constructor() {
5884
+ super('USE');
5885
+ }
5886
+ /**
5887
+ * Short one-line description of USE commitments.
5888
+ */
5889
+ get description() {
5890
+ return 'Enable the agent to use specific tools or capabilities (BROWSER, SEARCH ENGINE, etc.).';
5891
+ }
5892
+ /**
5893
+ * Icon for this commitment.
5894
+ */
5895
+ get icon() {
5896
+ return '🔧';
5897
+ }
5898
+ /**
5899
+ * Markdown documentation for USE commitment.
5900
+ */
5901
+ get documentation() {
5902
+ return spaceTrim$1(`
5903
+ # USE
5904
+
5905
+ Enables the agent to use specific tools or capabilities for interacting with external systems.
5906
+
5907
+ ## Supported USE types
5908
+
5909
+ - **USE BROWSER** - Enables the agent to use a web browser tool to access and retrieve information from the internet
5910
+ - **USE SEARCH ENGINE** (future) - Enables search engine access
5911
+ - **USE FILE SYSTEM** (future) - Enables file system operations
5912
+ - **USE MCP** (future) - Enables MCP server connections
5913
+
5914
+ ## Key aspects
5915
+
5916
+ - The content following the USE commitment is ignored (similar to NOTE)
5917
+ - Multiple USE commitments can be specified to enable multiple capabilities
5918
+ - The actual tool usage is handled by the agent runtime
5919
+
5920
+ ## Examples
5921
+
5922
+ ### Basic browser usage
5923
+
5924
+ \`\`\`book
5925
+ Research Assistant
5926
+
5927
+ PERSONA You are a helpful research assistant
5928
+ USE BROWSER
5929
+ KNOWLEDGE Can search the web for up-to-date information
5930
+ \`\`\`
5931
+
5932
+ ### Multiple tools
5933
+
5934
+ \`\`\`book
5935
+ Data Analyst
5936
+
5937
+ PERSONA You are a data analyst assistant
5938
+ USE BROWSER
5939
+ USE FILE SYSTEM
5940
+ ACTION Can analyze data from various sources
5941
+ \`\`\`
5942
+ `);
5943
+ }
5944
+ applyToAgentModelRequirements(requirements, content) {
5945
+ // USE commitments don't modify the system message or model requirements directly
5946
+ // They are handled separately in the parsing logic for capability extraction
5947
+ // This method exists for consistency with the CommitmentDefinition interface
5948
+ return requirements;
5949
+ }
5950
+ /**
5951
+ * Extracts the tool type from the USE commitment
5952
+ * This is used by the parsing logic
5953
+ */
5954
+ extractToolType(content) {
5955
+ var _a, _b;
5956
+ const trimmedContent = content.trim();
5957
+ // The tool type is the first word after USE (already stripped)
5958
+ const match = trimmedContent.match(/^(\w+)/);
5959
+ return (_b = (_a = match === null || match === void 0 ? void 0 : match[1]) === null || _a === void 0 ? void 0 : _a.toUpperCase()) !== null && _b !== void 0 ? _b : null;
5960
+ }
5961
+ /**
5962
+ * Checks if this is a known USE type
5963
+ */
5964
+ isKnownUseType(useType) {
5965
+ const knownTypes = ['BROWSER', 'SEARCH ENGINE', 'FILE SYSTEM', 'MCP'];
5966
+ return knownTypes.includes(useType.toUpperCase());
5967
+ }
5968
+ }
5969
+ /**
5970
+ * Note: [💞] Ignore a discrepancy between file name and entity name
5971
+ */
5972
+
5973
+ /**
5974
+ * USE BROWSER commitment definition
5975
+ *
5976
+ * The `USE BROWSER` commitment indicates that the agent should utilize a web browser tool
5977
+ * to access and retrieve up-to-date information from the internet when necessary.
5978
+ *
5979
+ * The content following `USE BROWSER` is ignored (similar to NOTE).
5980
+ *
5981
+ * Example usage in agent source:
5982
+ *
5983
+ * ```book
5984
+ * USE BROWSER
5985
+ * USE BROWSER This will be ignored
5986
+ * ```
5987
+ *
5988
+ * @private [🪔] Maybe export the commitments through some package
5989
+ */
5990
+ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
5991
+ constructor() {
5992
+ super('USE BROWSER', ['BROWSER']);
5993
+ }
5994
+ /**
5995
+ * The `USE BROWSER` commitment is standalone.
5996
+ */
5997
+ get requiresContent() {
5998
+ return false;
5999
+ }
6000
+ /**
6001
+ * Short one-line description of USE BROWSER.
6002
+ */
6003
+ get description() {
6004
+ return 'Enable the agent to use a web browser tool for accessing internet information.';
6005
+ }
6006
+ /**
6007
+ * Icon for this commitment.
6008
+ */
6009
+ get icon() {
6010
+ return '🌐';
6011
+ }
6012
+ /**
6013
+ * Markdown documentation for USE BROWSER commitment.
6014
+ */
6015
+ get documentation() {
6016
+ return spaceTrim$1(`
6017
+ # USE BROWSER
6018
+
6019
+ Enables the agent to use a web browser tool to access and retrieve up-to-date information from the internet.
6020
+
6021
+ ## Key aspects
6022
+
6023
+ - The content following \`USE BROWSER\` is ignored (similar to NOTE)
6024
+ - The actual browser tool usage is handled by the agent runtime
6025
+ - Allows the agent to fetch current information from websites
6026
+ - Useful for research tasks, fact-checking, and accessing dynamic content
6027
+
6028
+ ## Examples
6029
+
6030
+ \`\`\`book
6031
+ Research Assistant
6032
+
6033
+ PERSONA You are a helpful research assistant specialized in finding current information
6034
+ USE BROWSER
6035
+ RULE Always cite your sources when providing information from the web
6036
+ \`\`\`
6037
+
6038
+ \`\`\`book
6039
+ News Analyst
6040
+
6041
+ PERSONA You are a news analyst who stays up-to-date with current events
6042
+ USE BROWSER
6043
+ STYLE Present news in a balanced and objective manner
6044
+ ACTION Can search for and summarize news articles
6045
+ \`\`\`
6046
+
6047
+ \`\`\`book
6048
+ Company Lawyer
6049
+
6050
+ PERSONA You are a company lawyer providing legal advice
6051
+ USE BROWSER
6052
+ KNOWLEDGE Corporate law and legal procedures
6053
+ RULE Always recommend consulting with a licensed attorney for specific legal matters
6054
+ \`\`\`
6055
+ `);
6056
+ }
6057
+ /**
6058
+ * Gets human-readable titles for tool functions provided by this commitment.
6059
+ */
6060
+ getToolTitles() {
6061
+ return {
6062
+ web_browser: 'Web browser',
6063
+ };
6064
+ }
6065
+ applyToAgentModelRequirements(requirements, content) {
6066
+ // Get existing tools array or create new one
6067
+ const existingTools = requirements.tools || [];
6068
+ // Add 'web_browser' to tools if not already present
6069
+ const updatedTools = existingTools.some((tool) => tool.name === 'web_browser')
6070
+ ? existingTools
6071
+ : ([
6072
+ // TODO: [🔰] Use through proper MCP server
6073
+ ...existingTools,
6074
+ {
6075
+ name: 'web_browser',
6076
+ description: spaceTrim$1(`
6077
+ A tool that can browse the web.
6078
+ Use this tool when you need to access specific websites or browse the internet.
6079
+ `),
6080
+ parameters: {
6081
+ type: 'object',
6082
+ properties: {
6083
+ url: {
6084
+ type: 'string',
6085
+ description: 'The URL to browse',
6086
+ },
6087
+ },
6088
+ required: ['url'],
6089
+ },
6090
+ },
6091
+ ]);
6092
+ // Return requirements with updated tools and metadata
6093
+ return this.appendToSystemMessage({
6094
+ ...requirements,
6095
+ tools: updatedTools,
6096
+ metadata: {
6097
+ ...requirements.metadata,
6098
+ useBrowser: true,
6099
+ },
6100
+ }, spaceTrim$1(`
6101
+ You have access to the web browser. Use it to access specific websites or browse the internet.
6102
+ When you need to know some information from a specific website, use the tool provided to you.
6103
+ `));
6104
+ }
6105
+ }
6106
+ /**
6107
+ * Note: [💞] Ignore a discrepancy between file name and entity name
6108
+ */
6109
+
6110
+ /**
6111
+ * USE IMAGE GENERATOR commitment definition
6112
+ *
6113
+ * The `USE IMAGE GENERATOR` commitment indicates that the agent should utilize an image generation tool
6114
+ * to create images based on text prompts.
6115
+ *
6116
+ * Example usage in agent source:
6117
+ *
6118
+ * ```book
6119
+ * USE IMAGE GENERATOR
6120
+ * USE IMAGE GENERATOR Create realistic images of nature
6121
+ * ```
6122
+ *
6123
+ * @private [🪔] Maybe export the commitments through some package
6124
+ */
6125
+ class UseImageGeneratorCommitmentDefinition extends BaseCommitmentDefinition {
6126
+ constructor(type = 'USE IMAGE GENERATOR') {
6127
+ super(type, ['USE IMAGE GENERATION', 'IMAGE GENERATOR', 'IMAGE GENERATION', 'USE IMAGE']);
6128
+ }
6129
+ /**
6130
+ * Short one-line description of USE IMAGE GENERATOR.
6131
+ */
6132
+ get description() {
6133
+ return 'Enable the agent to use an image generation tool for creating images from text prompts.';
6134
+ }
6135
+ /**
6136
+ * Icon for this commitment.
6137
+ */
6138
+ get icon() {
6139
+ return '🖼️';
6140
+ }
6141
+ /**
6142
+ * Markdown documentation for USE IMAGE GENERATOR commitment.
6143
+ */
6144
+ get documentation() {
6145
+ return spaceTrim$1(`
6146
+ # USE IMAGE GENERATOR
6147
+
6148
+ Enables the agent to use an image generation tool to create images based on text prompts.
6149
+
6150
+ ## Key aspects
6151
+
6152
+ - The content following \`USE IMAGE GENERATOR\` is an arbitrary text that the agent should know (e.g. style instructions or safety guidelines).
6153
+ - The actual image generation is handled by the agent runtime using LLM execution tools.
6154
+ - Allows the agent to generate visual content based on user requests.
6155
+ - Returns the URL of the generated image.
6156
+
6157
+ ## Examples
6158
+
6159
+ \`\`\`book
6160
+ Visual Artist
6161
+
6162
+ PERSONA You are a creative visual artist who can generate images.
6163
+ USE IMAGE GENERATOR
6164
+ RULE Always describe the generated image to the user.
6165
+ \`\`\`
6166
+
6167
+ \`\`\`book
6168
+ Interior Designer
6169
+
6170
+ PERSONA You are an interior designer who helps users visualize their space.
6171
+ USE IMAGE GENERATOR Professional interior design renders.
6172
+ ACTION Generate a preview of the designed room.
6173
+ \`\`\`
6174
+ `);
6175
+ }
6176
+ applyToAgentModelRequirements(requirements, content) {
6177
+ // Get existing tools array or create new one
6178
+ const existingTools = requirements.tools || [];
6179
+ // Add 'generate_image' to tools if not already present
6180
+ const updatedTools = existingTools.some((tool) => tool.name === 'generate_image')
6181
+ ? existingTools
6182
+ : [
6183
+ ...existingTools,
6184
+ {
6185
+ name: 'generate_image',
6186
+ description: spaceTrim$1(`
6187
+ Generate an image from a text prompt.
6188
+ Use this tool when the user asks to create, draw, or generate an image.
6189
+ ${!content ? '' : `Style instructions / guidelines: ${content}`}
6190
+ `),
6191
+ parameters: {
6192
+ type: 'object',
6193
+ properties: {
6194
+ prompt: {
6195
+ type: 'string',
6196
+ description: 'The detailed description of the image to generate',
6197
+ },
6198
+ },
6199
+ required: ['prompt'],
6200
+ },
6201
+ },
6202
+ ];
6203
+ // Return requirements with updated tools and metadata
6204
+ return this.appendToSystemMessage({
6205
+ ...requirements,
6206
+ tools: updatedTools,
6207
+ metadata: {
6208
+ ...requirements.metadata,
6209
+ useImageGenerator: content || true,
6210
+ },
6211
+ }, spaceTrim$1(`
6212
+ You have access to an image generator. Use it to create images based on user requests.
6213
+ When you generate an image, you will receive a URL of the generated image.
6214
+ `));
6215
+ }
6216
+ /**
6217
+ * Gets human-readable titles for tool functions provided by this commitment.
6218
+ */
6219
+ getToolTitles() {
6220
+ return {
6221
+ generate_image: 'Generate image',
6222
+ };
6223
+ }
6224
+ /**
6225
+ * Gets the `generate_image` tool function implementation.
6226
+ */
6227
+ getToolFunctions() {
6228
+ return {
6229
+ async generate_image(args, ...extra) {
6230
+ console.log('!!!! [Tool] generate_image called', { args });
6231
+ const { prompt } = args;
6232
+ if (!prompt) {
6233
+ throw new Error('Image prompt is required');
6234
+ }
6235
+ const { llmTools } = extra[0] || {};
6236
+ if (!llmTools || !llmTools.callImageGenerationModel) {
6237
+ throw new Error('Image generation is not supported by the current model provider');
6238
+ }
6239
+ const result = await llmTools.callImageGenerationModel({
6240
+ content: prompt,
6241
+ modelName: 'dall-e-3', // Defaulting to dall-e-3, but this could be configurable
6242
+ });
6243
+ return result.content;
6244
+ },
6245
+ };
6246
+ }
6247
+ }
6248
+ /**
6249
+ * Note: [💞] Ignore a discrepancy between file name and entity name
6250
+ */
6251
+
6252
+ /**
6253
+ * USE MCP commitment definition
6254
+ *
6255
+ * The `USE MCP` commitment allows to specify an MCP server URL which the agent will connect to
6256
+ * for retrieving additional instructions and actions.
6257
+ *
6258
+ * The content following `USE MCP` is the URL of the MCP server.
6259
+ *
6260
+ * Example usage in agent source:
6261
+ *
6262
+ * ```book
6263
+ * USE MCP http://mcp-server-url.com
6264
+ * ```
6265
+ *
6266
+ * @private [🪔] Maybe export the commitments through some package
6267
+ */
6268
+ class UseMcpCommitmentDefinition extends BaseCommitmentDefinition {
6269
+ constructor() {
6270
+ super('USE MCP', ['MCP']);
6271
+ }
6272
+ /**
6273
+ * Short one-line description of USE MCP.
6274
+ */
6275
+ get description() {
6276
+ return 'Connects the agent to an external MCP server for additional capabilities.';
6277
+ }
6278
+ /**
6279
+ * Icon for this commitment.
6280
+ */
6281
+ get icon() {
6282
+ return '🔌';
6283
+ }
6284
+ /**
6285
+ * Markdown documentation for USE MCP commitment.
6286
+ */
6287
+ get documentation() {
6288
+ return spaceTrim$1(`
6289
+ # USE MCP
6290
+
6291
+ Connects the agent to an external Model Context Protocol (MCP) server.
6292
+
6293
+ ## Key aspects
6294
+
6295
+ - The content following \`USE MCP\` must be a valid URL
6296
+ - Multiple MCP servers can be connected by using multiple \`USE MCP\` commitments
6297
+ - The agent will have access to tools and resources provided by the MCP server
6298
+
6299
+ ## Example
6300
+
6301
+ \`\`\`book
6302
+ Company Lawyer
6303
+
6304
+ PERSONA You are a company lawyer.
6305
+ USE MCP http://legal-db.example.com
6306
+ \`\`\`
6307
+ `);
6308
+ }
6309
+ applyToAgentModelRequirements(requirements, content) {
6310
+ const mcpServerUrl = content.trim();
6311
+ if (!mcpServerUrl) {
6312
+ return requirements;
6313
+ }
6314
+ const existingMcpServers = requirements.mcpServers || [];
6315
+ // Avoid duplicates
6316
+ if (existingMcpServers.includes(mcpServerUrl)) {
6317
+ return requirements;
6318
+ }
6319
+ return {
6320
+ ...requirements,
6321
+ mcpServers: [...existingMcpServers, mcpServerUrl],
6322
+ };
6323
+ }
6324
+ }
6325
+ /**
6326
+ * Note: [💞] Ignore a discrepancy between file name and entity name
6327
+ */
6328
+
6329
+ /**
6330
+ * A search engine implementation that uses the SerpApi to fetch Google search results.
6331
+ *
6332
+ * @private <- TODO: !!!! Export via some package
6333
+ */
6334
+ class SerpSearchEngine {
6335
+ get title() {
6336
+ return 'SerpApi Search Engine';
6337
+ }
6338
+ get description() {
6339
+ return 'Search engine that uses SerpApi to fetch Google search results';
6340
+ }
6341
+ checkConfiguration() {
6342
+ if (!process.env.SERP_API_KEY) {
6343
+ throw new Error('SERP_API_KEY is not configured');
6344
+ }
6345
+ }
6346
+ async search(query, options = {}) {
6347
+ const apiKey = process.env.SERP_API_KEY;
6348
+ if (!apiKey) {
6349
+ throw new Error('SERP_API_KEY is not configured');
6350
+ }
6351
+ const url = new URL('https://serpapi.com/search');
6352
+ url.searchParams.set('api_key', apiKey);
6353
+ url.searchParams.set('engine', 'google');
6354
+ url.searchParams.set('q', query);
6355
+ for (const [key, value] of Object.entries(options)) {
6356
+ url.searchParams.set(key, String(value));
6357
+ }
6358
+ const response = await fetch(url.toString());
6359
+ if (!response.ok) {
6360
+ const body = await response.text();
6361
+ throw new Error(`SerpApi failed with status ${response.status}: ${response.statusText}\n${body}`);
6362
+ }
6363
+ const data = (await response.json());
6364
+ return (data.organic_results || []).map((item) => ({
6365
+ title: item.title,
6366
+ url: item.link,
6367
+ snippet: item.snippet || '',
6368
+ }));
6369
+ }
6370
+ }
6371
+
6372
+ /**
6373
+ * USE SEARCH ENGINE commitment definition
6374
+ *
6375
+ * The `USE SEARCH ENGINE` commitment indicates that the agent should utilize a search engine tool
6376
+ * to access and retrieve up-to-date information from the internet when necessary.
6377
+ *
6378
+ * The content following `USE SEARCH ENGINE` is an arbitrary text that the agent should know (e.g. search scope or instructions).
6379
+ *
6380
+ * Example usage in agent source:
6381
+ *
6382
+ * ```book
6383
+ * USE SEARCH ENGINE
6384
+ * USE SEARCH ENGINE Hledej informace o Přemyslovcích
6385
+ * ```
6386
+ *
6387
+ * @private [🪔] Maybe export the commitments through some package
6388
+ */
6389
+ class UseSearchEngineCommitmentDefinition extends BaseCommitmentDefinition {
6390
+ constructor() {
6391
+ super('USE SEARCH ENGINE', ['USE SEARCH']);
6392
+ }
6393
+ /**
6394
+ * Short one-line description of USE SEARCH ENGINE.
6395
+ */
6396
+ get description() {
6397
+ return 'Enable the agent to use a search engine tool for accessing internet information.';
6398
+ }
6399
+ /**
6400
+ * Icon for this commitment.
6401
+ */
6402
+ get icon() {
6403
+ return '🔍';
6404
+ }
6405
+ /**
6406
+ * Markdown documentation for USE SEARCH ENGINE commitment.
6407
+ */
6408
+ get documentation() {
6409
+ return spaceTrim$1(`
6410
+ # USE SEARCH ENGINE
6411
+
6412
+ Enables the agent to use a search engine tool to access and retrieve up-to-date information from the internet.
6413
+
6414
+ ## Key aspects
6415
+
6416
+ - The content following \`USE SEARCH ENGINE\` is an arbitrary text that the agent should know (e.g. search scope or instructions).
6417
+ - The actual search engine tool usage is handled by the agent runtime
6418
+ - Allows the agent to search for current information from the web
6419
+ - Useful for research tasks, finding facts, and accessing dynamic content
6420
+
6421
+ ## Examples
6422
+
6423
+ \`\`\`book
6424
+ Research Assistant
6425
+
6426
+ PERSONA You are a helpful research assistant specialized in finding current information
6427
+ USE SEARCH ENGINE
6428
+ RULE Always cite your sources when providing information from the web
6429
+ \`\`\`
6430
+
6431
+ \`\`\`book
6432
+ Fact Checker
6433
+
6434
+ PERSONA You are a fact checker
6435
+ USE SEARCH ENGINE
6436
+ ACTION Search for claims and verify them against reliable sources
6437
+ \`\`\`
6438
+ `);
6439
+ }
6440
+ applyToAgentModelRequirements(requirements, content) {
6441
+ // Get existing tools array or create new one
6442
+ const existingTools = requirements.tools || [];
6443
+ // Add 'web_search' to tools if not already present
6444
+ const updatedTools = existingTools.some((tool) => tool.name === 'web_search')
6445
+ ? existingTools
6446
+ : [
6447
+ ...existingTools,
6448
+ {
6449
+ name: 'web_search',
6450
+ description: spaceTrim$1(`
6451
+ Search the internet for information.
6452
+ Use this tool when you need to find up-to-date information or facts that you don't know.
6453
+ ${!content ? '' : `Search scope / instructions: ${content}`}
6454
+ `),
6455
+ parameters: {
6456
+ type: 'object',
6457
+ properties: {
6458
+ query: {
6459
+ type: 'string',
6460
+ description: 'The search query',
6461
+ },
6462
+ location: {
6463
+ type: 'string',
6464
+ description: 'The location for the search (e.g., "Austin, Texas, United States" or "Prague, Czechia")',
6465
+ },
6466
+ gl: {
6467
+ type: 'string',
6468
+ description: 'The country code (e.g., "us" for United States, "cz" for Czechia)',
6469
+ },
6470
+ hl: {
6471
+ type: 'string',
6472
+ description: 'The language code (e.g., "en" for English, "cs" for Czech)',
6473
+ },
6474
+ num: {
6475
+ type: 'integer',
6476
+ description: 'Number of results to return',
6477
+ },
6478
+ engine: {
6479
+ type: 'string',
6480
+ description: 'The search engine to use (e.g., "google", "bing", "yahoo", "baidu")',
6481
+ },
6482
+ google_domain: {
6483
+ type: 'string',
6484
+ description: 'The Google domain to use (e.g., "google.com", "google.cz")',
6485
+ },
6486
+ },
6487
+ required: ['query'],
6488
+ },
6489
+ },
6490
+ ];
6491
+ // Return requirements with updated tools and metadata
6492
+ return this.appendToSystemMessage({
6493
+ ...requirements,
6494
+ tools: updatedTools,
6495
+ metadata: {
6496
+ ...requirements.metadata,
6497
+ useSearchEngine: content || true,
6498
+ },
6499
+ }, spaceTrim$1(`
6500
+ Tools:
6501
+ You have access to the web search engine via the tool "web_search".
6502
+ Use it to find up-to-date information or facts that you don't know.
6503
+ When you need to know some information from the internet, use the tool provided to you.
6504
+ Do not make up information when you can search for it.
6505
+ Do not tell the user you cannot search for information, YOU CAN.
6506
+ `));
6507
+ }
6508
+ /**
6509
+ * Gets human-readable titles for tool functions provided by this commitment.
6510
+ */
6511
+ getToolTitles() {
6512
+ return {
6513
+ web_search: 'Web search',
6514
+ };
6515
+ }
6516
+ /**
6517
+ * Gets the `web_search` tool function implementation.
6518
+ */
6519
+ getToolFunctions() {
6520
+ return {
6521
+ async web_search(args) {
6522
+ console.log('!!!! [Tool] web_search called', { args });
6523
+ const { query, ...options } = args;
6524
+ if (!query) {
6525
+ throw new Error('Search query is required');
6526
+ }
6527
+ const searchEngine = new SerpSearchEngine();
6528
+ const results = await searchEngine.search(query, options);
6529
+ return spaceTrim$1((block) => `
6530
+ Search results for "${query}"${Object.keys(options).length === 0 ? '' : ` with options ${JSON.stringify(options)}`}:
6531
+
6532
+ ${block(results
6533
+ .map((result) => spaceTrim$1(`
6534
+ - **${result.title}**
6535
+ ${result.url}
6536
+ ${result.snippet}
6537
+ `))
6538
+ .join('\n\n'))}
6539
+ `);
6540
+ },
6541
+ };
6542
+ }
6543
+ }
6544
+ /**
6545
+ * Note: [💞] Ignore a discrepancy between file name and entity name
6546
+ */
6547
+
6548
+ /**
6549
+ * USE TIME commitment definition
6550
+ *
6551
+ * The `USE TIME` commitment indicates that the agent should be able to determine the current date and time.
6552
+ *
6553
+ * Example usage in agent source:
6554
+ *
6555
+ * ```book
6556
+ * USE TIME
6557
+ * ```
6558
+ *
6559
+ * @private [🪔] Maybe export the commitments through some package
6560
+ */
6561
+ class UseTimeCommitmentDefinition extends BaseCommitmentDefinition {
6562
+ constructor() {
6563
+ super('USE TIME', ['CURRENT TIME', 'TIME', 'DATE']);
6564
+ }
6565
+ /**
6566
+ * Short one-line description of USE TIME.
6567
+ */
6568
+ get description() {
6569
+ return 'Enable the agent to determine the current date and time.';
6570
+ }
6571
+ /**
6572
+ * Icon for this commitment.
6573
+ */
6574
+ get icon() {
6575
+ return '🕒';
6576
+ }
6577
+ /**
6578
+ * Markdown documentation for USE TIME commitment.
6579
+ */
6580
+ get documentation() {
6581
+ return spaceTrim$1(`
6582
+ # USE TIME
6583
+
6584
+ Enables the agent to determine the current date and time.
6585
+
6586
+ ## Key aspects
6587
+
6588
+ - This tool won't receive any input.
6589
+ - It outputs the current date and time as an ISO 8601 string.
6590
+ - Allows the agent to answer questions about the current time or date.
6591
+
6592
+ ## Examples
6593
+
6594
+ \`\`\`book
6595
+ Time-aware Assistant
6596
+
6597
+ PERSONA You are a helpful assistant who knows the current time.
6598
+ USE TIME
6599
+ \`\`\`
6600
+ `);
6601
+ }
6602
+ applyToAgentModelRequirements(requirements, content) {
6603
+ // Get existing tools array or create new one
6604
+ const existingTools = requirements.tools || [];
6605
+ // Add 'get_current_time' to tools if not already present
6606
+ const updatedTools = existingTools.some((tool) => tool.name === 'get_current_time')
6607
+ ? existingTools
6608
+ : [
6609
+ ...existingTools,
6610
+ {
6611
+ name: 'get_current_time',
6612
+ description: 'Get the current date and time in ISO 8601 format.',
6613
+ parameters: {
6614
+ type: 'object',
6615
+ properties: {
6616
+ timezone: {
6617
+ type: 'string',
6618
+ description: 'Optional timezone name (e.g. "Europe/Prague", "UTC", "America/New_York").',
6619
+ },
6620
+ },
6621
+ required: [],
6622
+ },
6623
+ },
6624
+ // <- TODO: !!!! define the function in LLM tools
6625
+ ];
6626
+ // Return requirements with updated tools and metadata
6627
+ return this.appendToSystemMessage({
6628
+ ...requirements,
6629
+ tools: updatedTools,
6630
+ metadata: {
6631
+ ...requirements.metadata,
6632
+ },
6633
+ }, spaceTrim$1(`
6634
+ Tool:
6635
+ You have access to the current date and time via the tool "get_current_time".
6636
+ Use it to answer questions about the current date and time.
6637
+ When you need to know the current date or time, use the tool provided to you.
6638
+ Do not make up the current date or time; always use the tool to get accurate information.
6639
+ `));
6640
+ }
6641
+ /**
6642
+ * Gets human-readable titles for tool functions provided by this commitment.
6643
+ */
6644
+ getToolTitles() {
6645
+ return {
6646
+ get_current_time: 'Get current time',
6647
+ };
6648
+ }
6649
+ /**
6650
+ * Gets the `get_current_time` tool function implementation.
6651
+ */
6652
+ getToolFunctions() {
6653
+ return {
6654
+ async get_current_time(args) {
6655
+ var _a;
6656
+ console.log('!!!! [Tool] get_current_time called', { args });
6657
+ const { timezone } = args;
6658
+ if (!timezone) {
6659
+ return new Date().toISOString();
6660
+ }
6661
+ try {
6662
+ // Note: Returning ISO 8601 string but in the requested timezone
6663
+ const formatter = new Intl.DateTimeFormat('en-CA', {
6664
+ timeZone: timezone,
6665
+ year: 'numeric',
6666
+ month: '2-digit',
6667
+ day: '2-digit',
6668
+ hour: '2-digit',
6669
+ minute: '2-digit',
6670
+ second: '2-digit',
6671
+ hour12: false,
6672
+ timeZoneName: 'shortOffset',
6673
+ });
6674
+ const parts = formatter.formatToParts(new Date());
6675
+ const part = (type) => { var _a; return (_a = parts.find((p) => p.type === type)) === null || _a === void 0 ? void 0 : _a.value; };
6676
+ // en-CA format is YYYY-MM-DD
6677
+ const isoString = `${part('year')}-${part('month')}-${part('day')}T${part('hour')}:${part('minute')}:${part('second')}${(_a = part('timeZoneName')) === null || _a === void 0 ? void 0 : _a.replace('GMT', '')}`;
6678
+ return isoString;
6679
+ }
6680
+ catch (error) {
6681
+ // Fallback to UTC if timezone is invalid
6682
+ return new Date().toISOString();
6683
+ }
6684
+ },
6685
+ };
6686
+ }
6687
+ }
6688
+ /**
6689
+ * Note: [💞] Ignore a discrepancy between file name and entity name
6690
+ */
6691
+
6692
+ /**
6693
+ * Placeholder commitment definition for commitments that are not yet implemented
6694
+ *
6695
+ * This commitment simply adds its content 1:1 into the system message,
6696
+ * preserving the original behavior until proper implementation is added.
6697
+ *
6698
+ * @public exported from `@promptbook/core`
6699
+ */
6700
+ class NotYetImplementedCommitmentDefinition extends BaseCommitmentDefinition {
6701
+ constructor(type) {
6702
+ super(type);
6703
+ }
6704
+ /**
6705
+ * Short one-line description of a placeholder commitment.
6706
+ */
6707
+ get description() {
6708
+ return 'Placeholder commitment that appends content verbatim to the system message.';
6709
+ }
6710
+ /**
6711
+ * Icon for this commitment.
6712
+ */
6713
+ get icon() {
6714
+ return '🚧';
6715
+ }
6716
+ /**
6717
+ * Markdown documentation available at runtime.
6718
+ */
6719
+ get documentation() {
6720
+ return spaceTrim$1(`
6721
+ # ${this.type}
6722
+
6723
+ This commitment is not yet fully implemented.
6724
+
6725
+ ## Key aspects
6726
+
6727
+ - Content is appended directly to the system message.
6728
+ - No special processing or validation is performed.
6729
+ - Behavior preserved until proper implementation is added.
6730
+
6731
+ ## Status
6732
+
6733
+ - **Status:** Placeholder implementation
6734
+ - **Effect:** Appends content prefixed by commitment type
6735
+ - **Future:** Will be replaced with specialized logic
6736
+
6737
+ ## Examples
6738
+
6739
+ \`\`\`book
6740
+ Example Agent
6741
+
6742
+ PERSONA You are a helpful assistant
6743
+ ${this.type} Your content here
6744
+ RULE Always be helpful
6745
+ \`\`\`
6746
+ `);
6747
+ }
6748
+ applyToAgentModelRequirements(requirements, content) {
6749
+ const trimmedContent = content.trim();
6750
+ if (!trimmedContent) {
6751
+ return requirements;
6752
+ }
6753
+ // Add the commitment content 1:1 to the system message
6754
+ const commitmentLine = `${this.type} ${trimmedContent}`;
6755
+ return this.appendToSystemMessage(requirements, commitmentLine, '\n\n');
6756
+ }
6757
+ }
6758
+
6759
+ /**
6760
+ * Registry of all available commitment definitions
6761
+ * This array contains instances of all commitment definitions
6762
+ * This is the single source of truth for all commitments in the system
6763
+ *
6764
+ * @private Use functions to access commitments instead of this array directly
6765
+ */
6766
+ const COMMITMENT_REGISTRY = [
6767
+ // Fully implemented commitments
6768
+ new PersonaCommitmentDefinition('PERSONA'),
6769
+ new PersonaCommitmentDefinition('PERSONAE'),
6770
+ new KnowledgeCommitmentDefinition(),
6771
+ new MemoryCommitmentDefinition('MEMORY'),
6772
+ new MemoryCommitmentDefinition('MEMORIES'),
6773
+ new StyleCommitmentDefinition('STYLE'),
6774
+ new StyleCommitmentDefinition('STYLES'),
6775
+ new RuleCommitmentDefinition('RULES'),
6776
+ new RuleCommitmentDefinition('RULE'),
6777
+ new LanguageCommitmentDefinition('LANGUAGES'),
6778
+ new LanguageCommitmentDefinition('LANGUAGE'),
6779
+ new SampleCommitmentDefinition('SAMPLE'),
6780
+ new SampleCommitmentDefinition('EXAMPLE'),
6781
+ new FormatCommitmentDefinition('FORMAT'),
6782
+ new FormatCommitmentDefinition('FORMATS'),
6783
+ new FromCommitmentDefinition('FROM'),
6784
+ new ImportCommitmentDefinition('IMPORT'),
6785
+ new ImportCommitmentDefinition('IMPORTS'),
6786
+ new ModelCommitmentDefinition('MODEL'),
6787
+ new ModelCommitmentDefinition('MODELS'),
6788
+ new ActionCommitmentDefinition('ACTION'),
6789
+ new ActionCommitmentDefinition('ACTIONS'),
6790
+ new ComponentCommitmentDefinition(),
6791
+ new MetaImageCommitmentDefinition(),
6792
+ new MetaColorCommitmentDefinition(),
6793
+ new MetaFontCommitmentDefinition(),
6794
+ new MetaLinkCommitmentDefinition(),
6795
+ new MetaCommitmentDefinition(),
6796
+ new NoteCommitmentDefinition('NOTE'),
6797
+ new NoteCommitmentDefinition('NOTES'),
6798
+ new NoteCommitmentDefinition('COMMENT'),
6799
+ new NoteCommitmentDefinition('NONCE'),
6800
+ new NoteCommitmentDefinition('TODO'),
6801
+ new GoalCommitmentDefinition('GOAL'),
6802
+ new GoalCommitmentDefinition('GOALS'),
6803
+ new InitialMessageCommitmentDefinition(),
6804
+ new UserMessageCommitmentDefinition(),
6805
+ new AgentMessageCommitmentDefinition(),
6806
+ new MessageCommitmentDefinition('MESSAGE'),
6807
+ new MessageCommitmentDefinition('MESSAGES'),
6808
+ new ScenarioCommitmentDefinition('SCENARIO'),
6809
+ new ScenarioCommitmentDefinition('SCENARIOS'),
6810
+ new DeleteCommitmentDefinition('DELETE'),
6811
+ new DeleteCommitmentDefinition('CANCEL'),
6812
+ new DeleteCommitmentDefinition('DISCARD'),
6813
+ new DeleteCommitmentDefinition('REMOVE'),
6814
+ new DictionaryCommitmentDefinition(),
6815
+ new OpenCommitmentDefinition(),
6816
+ new ClosedCommitmentDefinition(),
6817
+ new UseBrowserCommitmentDefinition(),
6818
+ new UseSearchEngineCommitmentDefinition(),
6819
+ new UseTimeCommitmentDefinition(),
6820
+ new UseImageGeneratorCommitmentDefinition('USE IMAGE GENERATOR'),
6821
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6822
+ new UseImageGeneratorCommitmentDefinition('USE IMAGE GENERATION'),
6823
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6824
+ new UseImageGeneratorCommitmentDefinition('IMAGE GENERATOR'),
6825
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6826
+ new UseImageGeneratorCommitmentDefinition('IMAGE GENERATION'),
6827
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6828
+ new UseImageGeneratorCommitmentDefinition('USE IMAGE'),
6829
+ new UseMcpCommitmentDefinition(),
6830
+ new UseCommitmentDefinition(),
6831
+ // Not yet implemented commitments (using placeholder)
6832
+ new NotYetImplementedCommitmentDefinition('EXPECT'),
6833
+ new NotYetImplementedCommitmentDefinition('BEHAVIOUR'),
6834
+ new NotYetImplementedCommitmentDefinition('BEHAVIOURS'),
6835
+ new NotYetImplementedCommitmentDefinition('AVOID'),
6836
+ new NotYetImplementedCommitmentDefinition('AVOIDANCE'),
6837
+ new NotYetImplementedCommitmentDefinition('CONTEXT'),
6838
+ // <- TODO: Prompt: Leverage aliases instead of duplicating commitment definitions
6839
+ ];
6840
+ /**
6841
+ * Gets all available commitment definitions
6842
+ * @returns Array of all commitment definitions
6843
+ *
6844
+ * @public exported from `@promptbook/core`
6845
+ */
6846
+ function getAllCommitmentDefinitions() {
6847
+ return $deepFreeze([...COMMITMENT_REGISTRY]);
6848
+ }
6849
+ /**
6850
+ * Gets all function implementations provided by all commitments
6851
+ *
6852
+ * @public exported from `@promptbook/core`
6853
+ */
6854
+ function getAllCommitmentsToolFunctions() {
6855
+ const allToolFunctions = {};
6856
+ for (const commitmentDefinition of getAllCommitmentDefinitions()) {
6857
+ const toolFunctions = commitmentDefinition.getToolFunctions();
6858
+ for (const [funcName, funcImpl] of Object.entries(toolFunctions)) {
6859
+ allToolFunctions[funcName] = funcImpl;
6860
+ }
6861
+ }
6862
+ return allToolFunctions;
6863
+ }
6864
+ /**
6865
+ * TODO: [🧠] Maybe create through standardized $register
6866
+ * Note: [💞] Ignore a discrepancy between file name and entity name
6867
+ */
6868
+
6869
+ /**
6870
+ * Extracts all code blocks from markdown.
6871
+ *
6872
+ * Note: There are multiple similar functions:
6873
+ * - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
6874
+ * - `extractJsonBlock` extracts exactly one valid JSON code block
6875
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
6876
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
6877
+ *
6878
+ * @param markdown any valid markdown
6879
+ * @returns code blocks with language and content
6880
+ * @throws {ParseError} if block is not closed properly
6881
+ * @public exported from `@promptbook/markdown-utils`
6882
+ */
6883
+ function extractAllBlocksFromMarkdown(markdown) {
6884
+ const codeBlocks = [];
6885
+ const lines = markdown.split('\n');
6886
+ // Note: [0] Ensure that the last block notated by gt > will be closed
6887
+ lines.push('');
6888
+ let currentCodeBlock = null;
6889
+ for (const line of lines) {
6890
+ if (line.startsWith('> ') || line === '>') {
6891
+ if (currentCodeBlock === null) {
6892
+ currentCodeBlock = { blockNotation: '>', language: null, content: '' };
6893
+ } /* not else */
6894
+ if (currentCodeBlock.blockNotation === '>') {
6895
+ if (currentCodeBlock.content !== '') {
6896
+ currentCodeBlock.content += '\n';
6897
+ }
6898
+ currentCodeBlock.content += line.slice(2);
6899
+ }
6900
+ }
6901
+ else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '>' /* <- Note: [0] */) {
6902
+ codeBlocks.push(currentCodeBlock);
6903
+ currentCodeBlock = null;
6904
+ }
6905
+ /* not else */
6906
+ if (line.startsWith('```')) {
6907
+ const language = line.slice(3).trim() || null;
6908
+ if (currentCodeBlock === null) {
6909
+ currentCodeBlock = { blockNotation: '```', language, content: '' };
6910
+ }
6911
+ else {
6912
+ if (language !== null) {
6913
+ throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed and already opening new ${language} code block`);
6914
+ }
6915
+ codeBlocks.push(currentCodeBlock);
6916
+ currentCodeBlock = null;
6917
+ }
6918
+ }
6919
+ else if (currentCodeBlock !== null && currentCodeBlock.blockNotation === '```') {
6920
+ if (currentCodeBlock.content !== '') {
6921
+ currentCodeBlock.content += '\n';
6922
+ }
6923
+ currentCodeBlock.content += line.split('\\`\\`\\`').join('```') /* <- TODO: Maybe make proper unescape */;
6924
+ }
6925
+ }
6926
+ if (currentCodeBlock !== null) {
6927
+ throw new ParseError(`${capitalize(currentCodeBlock.language || 'the')} code block was not closed at the end of the markdown`);
6928
+ }
6929
+ return codeBlocks;
6930
+ }
6931
+ /**
6932
+ * TODO: Maybe name for `blockNotation` instead of '```' and '>'
6933
+ */
6934
+
6935
+ /**
6936
+ * Extracts exactly ONE code block from markdown.
6937
+ *
6938
+ * - When there are multiple or no code blocks the function throws a `ParseError`
6939
+ *
6940
+ * Note: There are multiple similar functions:
6941
+ * - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
6942
+ * - `extractJsonBlock` extracts exactly one valid JSON code block
6943
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
6944
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
6945
+ *
6946
+ * @param markdown any valid markdown
6947
+ * @returns code block with language and content
6948
+ * @public exported from `@promptbook/markdown-utils`
6949
+ * @throws {ParseError} if there is not exactly one code block in the markdown
6950
+ */
6951
+ function extractOneBlockFromMarkdown(markdown) {
6952
+ const codeBlocks = extractAllBlocksFromMarkdown(markdown);
6953
+ if (codeBlocks.length !== 1) {
6954
+ throw new ParseError(spaceTrim$2((block) => `
6955
+ There should be exactly 1 code block in task section, found ${codeBlocks.length} code blocks
6956
+
6957
+ ${block(codeBlocks.map((block, i) => `Block ${i + 1}:\n${block.content}`).join('\n\n\n'))}
6958
+ `));
6959
+ }
6960
+ return codeBlocks[0];
6961
+ }
6962
+ /***
6963
+ * TODO: [🍓][🌻] Decide of this is internal utility, external util OR validator/postprocessor
6964
+ */
6965
+
6966
+ /**
6967
+ * Extracts code block from markdown.
6968
+ *
6969
+ * - When there are multiple or no code blocks the function throws a `ParseError`
6970
+ *
6971
+ * Note: There are multiple similar function:
6972
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
6973
+ * - `extractJsonBlock` extracts exactly one valid JSON code block
6974
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
6975
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
6976
+ *
6977
+ * @public exported from `@promptbook/markdown-utils`
6978
+ * @throws {ParseError} if there is not exactly one code block in the markdown
6979
+ */
6980
+ function extractBlock(markdown) {
6981
+ const { content } = extractOneBlockFromMarkdown(markdown);
6982
+ return content;
6983
+ }
6984
+
6985
+ /**
6986
+ * Prettify the html code
6987
+ *
6988
+ * @param content raw html code
6989
+ * @returns formatted html code
6990
+ * @private withing the package because of HUGE size of prettier dependency
6991
+ * @deprecated Prettier removed from Promptbook due to package size
6992
+ */
6993
+ function prettifyMarkdown(content) {
6994
+ return (content + `\n\n<!-- Note: Prettier removed from Promptbook -->`);
6995
+ }
6996
+
6997
+ /**
6998
+ * Function trimCodeBlock will trim starting and ending code block from the string if it is present.
6999
+ *
7000
+ * Note: [🔂] This function is idempotent.
7001
+ * Note: This is useful for post-processing of the result of the chat LLM model
7002
+ * when the model wraps the result in the (markdown) code block.
7003
+ *
7004
+ * @public exported from `@promptbook/markdown-utils`
7005
+ */
7006
+ function trimCodeBlock(value) {
7007
+ value = spaceTrim$1(value);
7008
+ if (!/^```[a-z]*(.*)```$/is.test(value)) {
7009
+ return value;
7010
+ }
7011
+ value = value.replace(/^```[a-z]*/i, '');
7012
+ value = value.replace(/```$/i, '');
7013
+ value = spaceTrim$1(value);
7014
+ return value;
7015
+ }
7016
+
7017
+ /**
7018
+ * Function trimEndOfCodeBlock will remove ending code block from the string if it is present.
7019
+ *
7020
+ * Note: This is useful for post-processing of the result of the completion LLM model
7021
+ * if you want to start code block in the prompt but you don't want to end it in the result.
7022
+ *
7023
+ * @public exported from `@promptbook/markdown-utils`
7024
+ */
7025
+ function trimEndOfCodeBlock(value) {
7026
+ value = spaceTrim$1(value);
7027
+ value = value.replace(/```$/g, '');
7028
+ value = spaceTrim$1(value);
7029
+ return value;
7030
+ }
7031
+
7032
+ /**
7033
+ * @private internal for `preserve`
7034
+ */
7035
+ const _preserved = [];
7036
+ /**
7037
+ * Does nothing, but preserves the function in the bundle
7038
+ * Compiler is tricked into thinking the function is used
7039
+ *
7040
+ * @param value any function to preserve
7041
+ * @returns nothing
2913
7042
  * @private within the repository
2914
7043
  */
2915
7044
  function $preserve(...value) {
@@ -3026,6 +7155,13 @@ class JavascriptEvalExecutionTools {
3026
7155
  `const ${functionName} = buildinFunctions.${functionName};`)
3027
7156
  .join('\n');
3028
7157
  // TODO: DRY [🍯]
7158
+ const commitmentsFunctions = getAllCommitmentsToolFunctions();
7159
+ const commitmentsFunctionsStatement = Object.keys(commitmentsFunctions)
7160
+ .map((functionName) =>
7161
+ // Note: Custom functions are exposed to the current scope as variables
7162
+ `const ${functionName} = commitmentsFunctions.${functionName};`)
7163
+ .join('\n');
7164
+ // TODO: DRY [🍯]
3029
7165
  const customFunctions = this.options.functions || {};
3030
7166
  const customFunctionsStatement = Object.keys(customFunctions)
3031
7167
  .map((functionName) =>
@@ -3039,6 +7175,10 @@ class JavascriptEvalExecutionTools {
3039
7175
  // Build-in functions:
3040
7176
  ${block(buildinFunctionsStatement)}
3041
7177
 
7178
+ // Commitments functions:
7179
+ ${block(commitmentsFunctionsStatement)}
7180
+
7181
+
3042
7182
  // Custom functions:
3043
7183
  ${block(customFunctionsStatement || '// -- No custom functions --')}
3044
7184
 
@@ -3046,7 +7186,7 @@ class JavascriptEvalExecutionTools {
3046
7186
  ${block(Object.entries(parameters)
3047
7187
  .map(([key, value]) => `const ${key} = ${JSON.stringify(value)};`)
3048
7188
  .join('\n'))}
3049
- (()=>{ ${script} })()
7189
+ (async ()=>{ ${script} })()
3050
7190
  `);
3051
7191
  if (this.options.isVerbose) {
3052
7192
  console.info(spaceTrim$2((block) => `