@promptbook/node 0.105.0-0 → 0.105.0-10

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 +4055 -135
  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 +20 -9
  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/commitments/NOTE/NOTE.d.ts +2 -2
  21. package/esm/typings/src/commitments/USE_BROWSER/USE_BROWSER.d.ts +4 -0
  22. package/esm/typings/src/commitments/USE_SEARCH_ENGINE/USE_SEARCH_ENGINE.d.ts +10 -0
  23. package/esm/typings/src/commitments/USE_SEARCH_ENGINE/USE_SEARCH_ENGINE.test.d.ts +1 -0
  24. package/esm/typings/src/commitments/USE_TIME/USE_TIME.d.ts +44 -0
  25. package/esm/typings/src/commitments/USE_TIME/USE_TIME.test.d.ts +1 -0
  26. package/esm/typings/src/commitments/_base/BaseCommitmentDefinition.d.ts +14 -0
  27. package/esm/typings/src/commitments/_base/CommitmentDefinition.d.ts +14 -0
  28. package/esm/typings/src/commitments/index.d.ts +17 -2
  29. package/esm/typings/src/config.d.ts +1 -0
  30. package/esm/typings/src/execution/LlmExecutionTools.d.ts +3 -1
  31. package/esm/typings/src/import-plugins/$fileImportPlugins.d.ts +7 -0
  32. package/esm/typings/src/import-plugins/AgentFileImportPlugin.d.ts +7 -0
  33. package/esm/typings/src/import-plugins/FileImportPlugin.d.ts +24 -0
  34. package/esm/typings/src/import-plugins/JsonFileImportPlugin.d.ts +7 -0
  35. package/esm/typings/src/import-plugins/TextFileImportPlugin.d.ts +7 -0
  36. package/esm/typings/src/llm-providers/_common/utils/cache/cacheLlmTools.d.ts +2 -1
  37. package/esm/typings/src/llm-providers/_common/utils/count-total-usage/countUsage.d.ts +2 -2
  38. package/esm/typings/src/llm-providers/agent/Agent.d.ts +14 -2
  39. package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +3 -1
  40. package/esm/typings/src/llm-providers/agent/AgentOptions.d.ts +7 -0
  41. package/esm/typings/src/llm-providers/agent/RemoteAgent.d.ts +1 -0
  42. package/esm/typings/src/llm-providers/agent/RemoteAgentOptions.d.ts +1 -1
  43. package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +10 -0
  44. package/esm/typings/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +7 -0
  45. package/esm/typings/src/llm-providers/remote/RemoteLlmExecutionTools.d.ts +1 -1
  46. package/esm/typings/src/scripting/javascript/JavascriptExecutionToolsOptions.d.ts +6 -1
  47. package/esm/typings/src/search-engines/SearchEngine.d.ts +1 -1
  48. package/esm/typings/src/search-engines/_index.d.ts +6 -0
  49. package/esm/typings/src/search-engines/bing/BingSearchEngine.d.ts +1 -1
  50. package/esm/typings/src/search-engines/dummy/DummySearchEngine.d.ts +1 -1
  51. package/esm/typings/src/search-engines/google/GoogleSearchEngine.d.ts +18 -0
  52. package/esm/typings/src/search-engines/serp/SerpSearchEngine.d.ts +15 -0
  53. package/esm/typings/src/speech-recognition/BrowserSpeechRecognition.d.ts +21 -0
  54. package/esm/typings/src/speech-recognition/OpenAiSpeechRecognition.d.ts +32 -0
  55. package/esm/typings/src/types/ModelRequirements.d.ts +6 -12
  56. package/esm/typings/src/types/SpeechRecognition.d.ts +58 -0
  57. package/esm/typings/src/types/typeAliases.d.ts +4 -0
  58. package/esm/typings/src/utils/execCommand/$execCommandNormalizeOptions.d.ts +2 -3
  59. package/esm/typings/src/utils/execCommand/ExecCommandOptions.d.ts +7 -1
  60. package/esm/typings/src/utils/misc/linguisticHash.d.ts +6 -0
  61. package/esm/typings/src/utils/misc/linguisticHash.test.d.ts +1 -0
  62. package/esm/typings/src/utils/organization/keepImported.d.ts +9 -0
  63. package/esm/typings/src/utils/organization/keepTypeImported.d.ts +0 -1
  64. package/esm/typings/src/utils/random/$generateBookBoilerplate.d.ts +4 -0
  65. package/esm/typings/src/utils/random/$randomAgentPersona.d.ts +2 -1
  66. package/esm/typings/src/utils/random/$randomAgentRule.d.ts +14 -0
  67. package/esm/typings/src/version.d.ts +1 -1
  68. package/package.json +2 -2
  69. package/umd/index.umd.js +4055 -135
  70. package/umd/index.umd.js.map +1 -1
package/esm/index.es.js CHANGED
@@ -28,7 +28,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
28
28
  * @generated
29
29
  * @see https://github.com/webgptorg/promptbook
30
30
  */
31
- const PROMPTBOOK_ENGINE_VERSION = '0.105.0-0';
31
+ const PROMPTBOOK_ENGINE_VERSION = '0.105.0-10';
32
32
  /**
33
33
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
34
34
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -973,6 +973,7 @@ const PROMPTBOOK_COLOR = Color.fromString('promptbook');
973
973
  SEPARATOR: Color.fromHex('#cccccc'),
974
974
  COMMITMENT: Color.fromHex('#DA0F78'),
975
975
  PARAMETER: Color.fromHex('#8e44ad'),
976
+ CODE_BLOCK: Color.fromHex('#7700ffff'),
976
977
  });
977
978
  // <- TODO: [🧠][🈵] Using `Color` here increases the package size approx 3kb, maybe remove it
978
979
  /**
@@ -6158,74 +6159,90 @@ async function forEachAsync(array, options, callbackfunction) {
6158
6159
  * in real-time through an observable.
6159
6160
  *
6160
6161
  * @param llmTools - The LLM tools to be intercepted and tracked
6161
- * @returns An augmented version of the tools that includes usage tracking capabilities
6162
+ * @returns Full proxy of the tools with added usage tracking capabilities
6162
6163
  * @public exported from `@promptbook/core`
6163
6164
  */
6164
6165
  function countUsage(llmTools) {
6165
6166
  let totalUsage = ZERO_USAGE;
6166
6167
  const spending = new Subject();
6167
- const proxyTools = {
6168
- get title() {
6169
- return `${llmTools.title} (+usage)`;
6170
- // <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
6171
- // <- TODO: [🧈][🧠] Does it make sense to suffix "(+usage)"?
6172
- },
6173
- get description() {
6174
- return `${llmTools.description} (+usage)`;
6175
- // <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
6176
- // <- TODO: [🧈][🧠] Does it make sense to suffix "(+usage)"?
6177
- },
6178
- checkConfiguration() {
6179
- return /* not await */ llmTools.checkConfiguration();
6180
- },
6181
- listModels() {
6182
- return /* not await */ llmTools.listModels();
6183
- },
6184
- spending() {
6185
- return spending.asObservable();
6186
- },
6187
- getTotalUsage() {
6188
- // <- Note: [🥫] Not using getter `get totalUsage` but `getTotalUsage` to allow this object to be proxied
6189
- return totalUsage;
6168
+ // Create a Proxy to intercept all property access and ensure full proxying of all properties
6169
+ const proxyTools = new Proxy(llmTools, {
6170
+ get(target, prop, receiver) {
6171
+ // Handle title property
6172
+ if (prop === 'title') {
6173
+ return `${target.title} (+usage)`;
6174
+ // <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
6175
+ // <- TODO: [🧈][🧠] Does it make sense to suffix "(+usage)"?
6176
+ }
6177
+ // Handle description property
6178
+ if (prop === 'description') {
6179
+ return `${target.description} (+usage)`;
6180
+ // <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
6181
+ // <- TODO: [🧈][🧠] Does it make sense to suffix "(+usage)"?
6182
+ }
6183
+ // Handle spending method (new method added by this wrapper)
6184
+ if (prop === 'spending') {
6185
+ return () => {
6186
+ return spending.asObservable();
6187
+ };
6188
+ }
6189
+ // Handle getTotalUsage method (new method added by this wrapper)
6190
+ if (prop === 'getTotalUsage') {
6191
+ // <- Note: [🥫] Not using getter `get totalUsage` but `getTotalUsage` to allow this object to be proxied
6192
+ return () => {
6193
+ return totalUsage;
6194
+ };
6195
+ }
6196
+ // Handle callChatModel method with usage counting
6197
+ if (prop === 'callChatModel' && target.callChatModel !== undefined) {
6198
+ return async (prompt) => {
6199
+ // console.info('[🚕] callChatModel through countTotalUsage');
6200
+ const promptResult = await target.callChatModel(prompt);
6201
+ totalUsage = addUsage(totalUsage, promptResult.usage);
6202
+ spending.next(promptResult.usage);
6203
+ return promptResult;
6204
+ };
6205
+ }
6206
+ // Handle callCompletionModel method with usage counting
6207
+ if (prop === 'callCompletionModel' && target.callCompletionModel !== undefined) {
6208
+ return async (prompt) => {
6209
+ // console.info('[🚕] callCompletionModel through countTotalUsage');
6210
+ const promptResult = await target.callCompletionModel(prompt);
6211
+ totalUsage = addUsage(totalUsage, promptResult.usage);
6212
+ spending.next(promptResult.usage);
6213
+ return promptResult;
6214
+ };
6215
+ }
6216
+ // Handle callEmbeddingModel method with usage counting
6217
+ if (prop === 'callEmbeddingModel' && target.callEmbeddingModel !== undefined) {
6218
+ return async (prompt) => {
6219
+ // console.info('[🚕] callEmbeddingModel through countTotalUsage');
6220
+ const promptResult = await target.callEmbeddingModel(prompt);
6221
+ totalUsage = addUsage(totalUsage, promptResult.usage);
6222
+ spending.next(promptResult.usage);
6223
+ return promptResult;
6224
+ };
6225
+ }
6226
+ // Handle callImageGenerationModel method with usage counting
6227
+ if (prop === 'callImageGenerationModel' && target.callImageGenerationModel !== undefined) {
6228
+ return async (prompt) => {
6229
+ // console.info('[🚕] callImageGenerationModel through countTotalUsage');
6230
+ const promptResult = await target.callImageGenerationModel(prompt);
6231
+ totalUsage = addUsage(totalUsage, promptResult.usage);
6232
+ spending.next(promptResult.usage);
6233
+ return promptResult;
6234
+ };
6235
+ }
6236
+ // <- Note: [🤖]
6237
+ // For all other properties and methods, delegate to the original target
6238
+ const value = Reflect.get(target, prop, receiver);
6239
+ // If it's a function, bind it to the target to preserve context
6240
+ if (typeof value === 'function') {
6241
+ return value.bind(target);
6242
+ }
6243
+ return value;
6190
6244
  },
6191
- };
6192
- if (llmTools.callChatModel !== undefined) {
6193
- proxyTools.callChatModel = async (prompt) => {
6194
- // console.info('[🚕] callChatModel through countTotalUsage');
6195
- const promptResult = await llmTools.callChatModel(prompt);
6196
- totalUsage = addUsage(totalUsage, promptResult.usage);
6197
- spending.next(promptResult.usage);
6198
- return promptResult;
6199
- };
6200
- }
6201
- if (llmTools.callCompletionModel !== undefined) {
6202
- proxyTools.callCompletionModel = async (prompt) => {
6203
- // console.info('[🚕] callCompletionModel through countTotalUsage');
6204
- const promptResult = await llmTools.callCompletionModel(prompt);
6205
- totalUsage = addUsage(totalUsage, promptResult.usage);
6206
- spending.next(promptResult.usage);
6207
- return promptResult;
6208
- };
6209
- }
6210
- if (llmTools.callEmbeddingModel !== undefined) {
6211
- proxyTools.callEmbeddingModel = async (prompt) => {
6212
- // console.info('[🚕] callEmbeddingModel through countTotalUsage');
6213
- const promptResult = await llmTools.callEmbeddingModel(prompt);
6214
- totalUsage = addUsage(totalUsage, promptResult.usage);
6215
- spending.next(promptResult.usage);
6216
- return promptResult;
6217
- };
6218
- }
6219
- if (llmTools.callImageGenerationModel !== undefined) {
6220
- proxyTools.callImageGenerationModel = async (prompt) => {
6221
- // console.info('[🚕] callImageGenerationModel through countTotalUsage');
6222
- const promptResult = await llmTools.callImageGenerationModel(prompt);
6223
- totalUsage = addUsage(totalUsage, promptResult.usage);
6224
- spending.next(promptResult.usage);
6225
- return promptResult;
6226
- };
6227
- }
6228
- // <- Note: [🤖]
6245
+ });
6229
6246
  return proxyTools;
6230
6247
  }
6231
6248
  /**
@@ -10872,6 +10889,7 @@ function $execCommandNormalizeOptions(options) {
10872
10889
  let args = [];
10873
10890
  let timeout;
10874
10891
  let isVerbose;
10892
+ let env;
10875
10893
  if (typeof options === 'string') {
10876
10894
  // TODO: [1] DRY default values
10877
10895
  command = options;
@@ -10879,6 +10897,7 @@ function $execCommandNormalizeOptions(options) {
10879
10897
  crashOnError = true;
10880
10898
  timeout = Infinity; // <- TODO: [⏳]
10881
10899
  isVerbose = DEFAULT_IS_VERBOSE;
10900
+ env = undefined;
10882
10901
  }
10883
10902
  else {
10884
10903
  /*
@@ -10895,6 +10914,7 @@ function $execCommandNormalizeOptions(options) {
10895
10914
  crashOnError = (_b = options.crashOnError) !== null && _b !== void 0 ? _b : true;
10896
10915
  timeout = (_c = options.timeout) !== null && _c !== void 0 ? _c : Infinity;
10897
10916
  isVerbose = (_d = options.isVerbose) !== null && _d !== void 0 ? _d : DEFAULT_IS_VERBOSE;
10917
+ env = options.env;
10898
10918
  }
10899
10919
  // TODO: /(-[a-zA-Z0-9-]+\s+[^\s]*)|[^\s]*/g
10900
10920
  const _ = Array.from(command.matchAll(/(".*")|([^\s]*)/g))
@@ -10913,7 +10933,7 @@ function $execCommandNormalizeOptions(options) {
10913
10933
  if (/^win/.test(process.platform) && ['npm', 'npx'].includes(command)) {
10914
10934
  command = `${command}.cmd`;
10915
10935
  }
10916
- return { command, humanReadableCommand, args, cwd, crashOnError, timeout, isVerbose };
10936
+ return { command, humanReadableCommand, args, cwd, crashOnError, timeout, isVerbose, env };
10917
10937
  }
10918
10938
  // TODO: This should show type error> execCommandNormalizeOptions({ command: '', commands: [''] });
10919
10939
 
@@ -10934,7 +10954,7 @@ function $execCommand(options) {
10934
10954
  }
10935
10955
  return new Promise((resolve, reject) => {
10936
10956
  // eslint-disable-next-line prefer-const
10937
- const { command, humanReadableCommand, args, cwd, crashOnError, timeout, isVerbose = DEFAULT_IS_VERBOSE, } = $execCommandNormalizeOptions(options);
10957
+ const { command, humanReadableCommand, args, cwd, crashOnError, timeout, isVerbose = DEFAULT_IS_VERBOSE, env, } = $execCommandNormalizeOptions(options);
10938
10958
  if (timeout !== Infinity) {
10939
10959
  // TODO: In waitasecond forTime(Infinity) should be equivalent to forEver()
10940
10960
  forTime(timeout).then(() => {
@@ -10952,7 +10972,11 @@ function $execCommand(options) {
10952
10972
  console.info(colors.yellow(cwd) + ' ' + colors.green(command) + ' ' + colors.blue(args.join(' ')));
10953
10973
  }
10954
10974
  try {
10955
- const commandProcess = spawn(command, args, { cwd, shell: true });
10975
+ const commandProcess = spawn(command, args, {
10976
+ cwd,
10977
+ shell: true,
10978
+ env: env ? { ...process.env, ...env } : process.env,
10979
+ });
10956
10980
  if (isVerbose) {
10957
10981
  commandProcess.on('message', (message) => {
10958
10982
  console.info({ message });
@@ -11806,6 +11830,16 @@ function unwrapResult(text, options) {
11806
11830
  trimmedText = spaceTrim$1(trimmedText);
11807
11831
  }
11808
11832
  let processedText = trimmedText;
11833
+ // Check for markdown code block
11834
+ const codeBlockRegex = /^```[a-z]*\n([\s\S]*?)\n```\s*$/;
11835
+ const codeBlockMatch = processedText.match(codeBlockRegex);
11836
+ if (codeBlockMatch && codeBlockMatch[1] !== undefined) {
11837
+ // Check if there's only one code block
11838
+ const codeBlockCount = (processedText.match(/```/g) || []).length / 2;
11839
+ if (codeBlockCount === 1) {
11840
+ return unwrapResult(codeBlockMatch[1], { isTrimmed: false, isIntroduceSentenceRemoved: false });
11841
+ }
11842
+ }
11809
11843
  if (isIntroduceSentenceRemoved) {
11810
11844
  const introduceSentenceRegex = /^[a-zěščřžýáíéúů:\s]*:\s*/i;
11811
11845
  if (introduceSentenceRegex.test(text)) {
@@ -11813,6 +11847,14 @@ function unwrapResult(text, options) {
11813
11847
  processedText = processedText.replace(introduceSentenceRegex, '');
11814
11848
  }
11815
11849
  processedText = spaceTrim$1(processedText);
11850
+ // Check again for code block after removing introduce sentence
11851
+ const codeBlockMatch2 = processedText.match(codeBlockRegex);
11852
+ if (codeBlockMatch2 && codeBlockMatch2[1] !== undefined) {
11853
+ const codeBlockCount = (processedText.match(/```/g) || []).length / 2;
11854
+ if (codeBlockCount === 1) {
11855
+ return unwrapResult(codeBlockMatch2[1], { isTrimmed: false, isIntroduceSentenceRemoved: false });
11856
+ }
11857
+ }
11816
11858
  }
11817
11859
  if (processedText.length < 3) {
11818
11860
  return trimmedText;
@@ -11891,109 +11933,3976 @@ function isSerializableAsJson(value) {
11891
11933
  */
11892
11934
 
11893
11935
  /**
11894
- * Extracts code block from markdown.
11936
+ * Tests if given string is valid agent URL
11895
11937
  *
11896
- * - When there are multiple or no code blocks the function throws a `ParseError`
11897
- *
11898
- * Note: There are multiple similar function:
11899
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
11900
- * - `extractJsonBlock` extracts exactly one valid JSON code block
11901
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
11902
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
11938
+ * Note: There are few similar functions:
11939
+ * - `isValidUrl` which tests any URL
11940
+ * - `isValidAgentUrl` *(this one)* which tests just agent URL
11941
+ * - `isValidPipelineUrl` which tests just pipeline URL
11903
11942
  *
11904
- * @public exported from `@promptbook/markdown-utils`
11905
- * @throws {ParseError} if there is not exactly one code block in the markdown
11943
+ * @public exported from `@promptbook/utils`
11906
11944
  */
11907
- function extractBlock(markdown) {
11908
- const { content } = extractOneBlockFromMarkdown(markdown);
11909
- return content;
11945
+ function isValidAgentUrl(url) {
11946
+ if (!isValidUrl(url)) {
11947
+ return false;
11948
+ }
11949
+ if (!url.startsWith('https://') && !url.startsWith('http://') /* <- Note: [👣] */) {
11950
+ return false;
11951
+ }
11952
+ if (url.includes('#')) {
11953
+ // TODO: [🐠]
11954
+ return false;
11955
+ }
11956
+ /*
11957
+ Note: [👣][🧠] Is it secure to allow pipeline URLs on private and unsecured networks?
11958
+ if (isUrlOnPrivateNetwork(url)) {
11959
+ return false;
11960
+ }
11961
+ */
11962
+ return true;
11910
11963
  }
11964
+ /**
11965
+ * TODO: [🐠] Maybe more info why the URL is invalid
11966
+ */
11911
11967
 
11912
11968
  /**
11913
- * Function trimCodeBlock will trim starting and ending code block from the string if it is present.
11969
+ * Generates a regex pattern to match a specific commitment
11914
11970
  *
11915
- * Note: [🔂] This function is idempotent.
11916
- * Note: This is useful for post-processing of the result of the chat LLM model
11917
- * when the model wraps the result in the (markdown) code block.
11971
+ * Note: It always creates new Regex object
11972
+ * Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
11918
11973
  *
11919
- * @public exported from `@promptbook/markdown-utils`
11974
+ * @private - TODO: [🧠] Maybe should be public?
11920
11975
  */
11921
- function trimCodeBlock(value) {
11922
- value = spaceTrim$1(value);
11923
- if (!/^```[a-z]*(.*)```$/is.test(value)) {
11924
- return value;
11976
+ function createCommitmentRegex(commitment, aliases = [], requiresContent = true) {
11977
+ const allCommitments = [commitment, ...aliases];
11978
+ const patterns = allCommitments.map((commitment) => {
11979
+ const escapedCommitment = commitment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
11980
+ return escapedCommitment.split(/\s+/).join('\\s+');
11981
+ });
11982
+ const keywordPattern = patterns.join('|');
11983
+ if (requiresContent) {
11984
+ return new RegExp(`^\\s*(?<type>${keywordPattern})\\b\\s+(?<contents>.+)$`, 'gim');
11985
+ }
11986
+ else {
11987
+ return new RegExp(`^\\s*(?<type>${keywordPattern})\\b(?:\\s+(?<contents>.+))?$`, 'gim');
11925
11988
  }
11926
- value = value.replace(/^```[a-z]*/i, '');
11927
- value = value.replace(/```$/i, '');
11928
- value = spaceTrim$1(value);
11929
- return value;
11930
11989
  }
11931
-
11932
11990
  /**
11933
- * Function trimEndOfCodeBlock will remove ending code block from the string if it is present.
11991
+ * Generates a regex pattern to match a specific commitment type
11934
11992
  *
11935
- * Note: This is useful for post-processing of the result of the completion LLM model
11936
- * if you want to start code block in the prompt but you don't want to end it in the result.
11993
+ * Note: It just matches the type part of the commitment
11994
+ * Note: It always creates new Regex object
11995
+ * Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
11937
11996
  *
11938
- * @public exported from `@promptbook/markdown-utils`
11997
+ * @private
11939
11998
  */
11940
- function trimEndOfCodeBlock(value) {
11941
- value = spaceTrim$1(value);
11942
- value = value.replace(/```$/g, '');
11943
- value = spaceTrim$1(value);
11944
- return value;
11999
+ function createCommitmentTypeRegex(commitment, aliases = []) {
12000
+ const allCommitments = [commitment, ...aliases];
12001
+ const patterns = allCommitments.map((commitment) => {
12002
+ const escapedCommitment = commitment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
12003
+ return escapedCommitment.split(/\s+/).join('\\s+');
12004
+ });
12005
+ const keywordPattern = patterns.join('|');
12006
+ const regex = new RegExp(`^\\s*(?<type>${keywordPattern})\\b`, 'gim');
12007
+ return regex;
11945
12008
  }
11946
12009
 
11947
12010
  /**
11948
- * @private internal for `preserve`
12011
+ * Base implementation of CommitmentDefinition that provides common functionality
12012
+ * Most commitments can extend this class and only override the applyToAgentModelRequirements method
12013
+ *
12014
+ * @private
11949
12015
  */
11950
- const _preserved = [];
12016
+ class BaseCommitmentDefinition {
12017
+ constructor(type, aliases = []) {
12018
+ this.type = type;
12019
+ this.aliases = aliases;
12020
+ }
12021
+ /**
12022
+ * Whether this commitment requires content.
12023
+ * If true, regex will match only if there is content after the commitment keyword.
12024
+ * If false, regex will match even if there is no content.
12025
+ */
12026
+ get requiresContent() {
12027
+ return true;
12028
+ }
12029
+ /**
12030
+ * Creates a regex pattern to match this commitment in agent source
12031
+ * Uses the existing createCommitmentRegex function as internal helper
12032
+ */
12033
+ createRegex() {
12034
+ return createCommitmentRegex(this.type, this.aliases, this.requiresContent);
12035
+ }
12036
+ /**
12037
+ * Creates a regex pattern to match just the commitment type
12038
+ * Uses the existing createCommitmentTypeRegex function as internal helper
12039
+ */
12040
+ createTypeRegex() {
12041
+ return createCommitmentTypeRegex(this.type, this.aliases);
12042
+ }
12043
+ /**
12044
+ * Helper method to create a new requirements object with updated system message
12045
+ * This is commonly used by many commitments
12046
+ */
12047
+ updateSystemMessage(requirements, messageUpdate) {
12048
+ const newMessage = typeof messageUpdate === 'string' ? messageUpdate : messageUpdate(requirements.systemMessage);
12049
+ return {
12050
+ ...requirements,
12051
+ systemMessage: newMessage,
12052
+ };
12053
+ }
12054
+ /**
12055
+ * Helper method to append content to the system message
12056
+ */
12057
+ appendToSystemMessage(requirements, content, separator = '\n\n') {
12058
+ return this.updateSystemMessage(requirements, (currentMessage) => {
12059
+ if (!currentMessage.trim()) {
12060
+ return content;
12061
+ }
12062
+ return currentMessage + separator + content;
12063
+ });
12064
+ }
12065
+ /**
12066
+ * Helper method to add a comment section to the system message
12067
+ * Comments are lines starting with # that will be removed from the final system message
12068
+ * but can be useful for organizing and structuring the message during processing
12069
+ */
12070
+ addCommentSection(requirements, commentTitle, content, position = 'end') {
12071
+ const commentSection = `# ${commentTitle.toUpperCase()}\n${content}`;
12072
+ if (position === 'beginning') {
12073
+ return this.updateSystemMessage(requirements, (currentMessage) => {
12074
+ if (!currentMessage.trim()) {
12075
+ return commentSection;
12076
+ }
12077
+ return commentSection + '\n\n' + currentMessage;
12078
+ });
12079
+ }
12080
+ else {
12081
+ return this.appendToSystemMessage(requirements, commentSection);
12082
+ }
12083
+ }
12084
+ /**
12085
+ * Gets tool function implementations provided by this commitment
12086
+ *
12087
+ * When the `applyToAgentModelRequirements` adds tools to the requirements, this method should return the corresponding function definitions.
12088
+ */
12089
+ getToolFunctions() {
12090
+ return {};
12091
+ }
12092
+ /**
12093
+ * Gets human-readable titles for tool functions provided by this commitment
12094
+ *
12095
+ * This is used in the UI to show a user-friendly name instead of the technical function name.
12096
+ */
12097
+ getToolTitles() {
12098
+ return {};
12099
+ }
12100
+ }
12101
+
11951
12102
  /**
11952
- * Does nothing, but preserves the function in the bundle
11953
- * Compiler is tricked into thinking the function is used
12103
+ * ACTION commitment definition
11954
12104
  *
11955
- * @param value any function to preserve
11956
- * @returns nothing
11957
- * @private within the repository
12105
+ * The ACTION commitment defines specific actions or capabilities that the agent can perform.
12106
+ * This helps define what the agent is capable of doing and how it should approach tasks.
12107
+ *
12108
+ * Example usage in agent source:
12109
+ *
12110
+ * ```book
12111
+ * ACTION Can generate code snippets and explain programming concepts
12112
+ * ACTION Able to analyze data and provide insights
12113
+ * ```
12114
+ *
12115
+ * @private [🪔] Maybe export the commitments through some package
11958
12116
  */
11959
- function $preserve(...value) {
11960
- _preserved.push(...value);
12117
+ class ActionCommitmentDefinition extends BaseCommitmentDefinition {
12118
+ constructor(type = 'ACTION') {
12119
+ super(type);
12120
+ }
12121
+ /**
12122
+ * Short one-line description of ACTION.
12123
+ */
12124
+ get description() {
12125
+ return 'Define agent capabilities and actions it can perform.';
12126
+ }
12127
+ /**
12128
+ * Icon for this commitment.
12129
+ */
12130
+ get icon() {
12131
+ return '⚡';
12132
+ }
12133
+ /**
12134
+ * Markdown documentation for ACTION commitment.
12135
+ */
12136
+ get documentation() {
12137
+ return spaceTrim$1(`
12138
+ # ${this.type}
12139
+
12140
+ Defines specific actions or capabilities that the agent can perform.
12141
+
12142
+ ## Key aspects
12143
+
12144
+ - Both terms work identically and can be used interchangeably.
12145
+ - Each action adds to the agent's capability list.
12146
+ - Actions help users understand what the agent can do.
12147
+
12148
+ ## Examples
12149
+
12150
+ \`\`\`book
12151
+ Code Assistant
12152
+
12153
+ PERSONA You are a programming assistant
12154
+ ACTION Can generate code snippets and explain programming concepts
12155
+ ACTION Able to debug existing code and suggest improvements
12156
+ ACTION Can create unit tests for functions
12157
+ \`\`\`
12158
+
12159
+ \`\`\`book
12160
+ Data Scientist
12161
+
12162
+ PERSONA You are a data analysis expert
12163
+ ACTION Able to analyze data and provide insights
12164
+ ACTION Can create visualizations and charts
12165
+ ACTION Capable of statistical analysis and modeling
12166
+ KNOWLEDGE Data analysis best practices and statistical methods
12167
+ \`\`\`
12168
+ `);
12169
+ }
12170
+ applyToAgentModelRequirements(requirements, content) {
12171
+ const trimmedContent = content.trim();
12172
+ if (!trimmedContent) {
12173
+ return requirements;
12174
+ }
12175
+ // Add action capability to the system message
12176
+ const actionSection = `Capability: ${trimmedContent}`;
12177
+ return this.appendToSystemMessage(requirements, actionSection, '\n\n');
12178
+ }
11961
12179
  }
11962
12180
  /**
11963
12181
  * Note: [💞] Ignore a discrepancy between file name and entity name
11964
12182
  */
11965
12183
 
11966
- // Note: [💎]
11967
12184
  /**
11968
- * ScriptExecutionTools for JavaScript implemented via eval
12185
+ * CLOSED commitment definition
11969
12186
  *
11970
- * Warning: It is used for testing and mocking
11971
- * **NOT intended to use in the production** due to its unsafe nature, use `JavascriptExecutionTools` instead.
12187
+ * The CLOSED commitment specifies that the agent CANNOT be modified by conversation.
12188
+ * It prevents the agent from learning from interactions and updating its source code.
11972
12189
  *
11973
- * @public exported from `@promptbook/javascript`
12190
+ * Example usage in agent source:
12191
+ *
12192
+ * ```book
12193
+ * CLOSED
12194
+ * ```
12195
+ *
12196
+ * @private [🪔] Maybe export the commitments through some package
11974
12197
  */
11975
- class JavascriptEvalExecutionTools {
11976
- constructor(options) {
11977
- this.options = options || {};
12198
+ class ClosedCommitmentDefinition extends BaseCommitmentDefinition {
12199
+ constructor() {
12200
+ super('CLOSED');
11978
12201
  }
11979
12202
  /**
11980
- * Executes a JavaScript
12203
+ * The `CLOSED` commitment is standalone.
11981
12204
  */
11982
- async execute(options) {
11983
- const { scriptLanguage, parameters } = options;
11984
- let { script } = options;
11985
- if (scriptLanguage !== 'javascript') {
11986
- throw new PipelineExecutionError(`Script language ${scriptLanguage} not supported to be executed by JavascriptEvalExecutionTools`);
12205
+ get requiresContent() {
12206
+ return false;
12207
+ }
12208
+ /**
12209
+ * Short one-line description of CLOSED.
12210
+ */
12211
+ get description() {
12212
+ return 'Prevent the agent from being modified by conversation.';
12213
+ }
12214
+ /**
12215
+ * Icon for this commitment.
12216
+ */
12217
+ get icon() {
12218
+ return '🔒';
12219
+ }
12220
+ /**
12221
+ * Markdown documentation for CLOSED commitment.
12222
+ */
12223
+ get documentation() {
12224
+ return spaceTrim$1(`
12225
+ # CLOSED
12226
+
12227
+ Specifies that the agent **cannot** be modified by conversation with it.
12228
+ This means the agent will **not** learn from interactions and its source code will remain static during conversation.
12229
+
12230
+ By default (if not specified), agents are \`OPEN\` to modification.
12231
+
12232
+ > See also [OPEN](/docs/OPEN)
12233
+
12234
+ ## Example
12235
+
12236
+ \`\`\`book
12237
+ CLOSED
12238
+ \`\`\`
12239
+ `);
12240
+ }
12241
+ applyToAgentModelRequirements(requirements, _content) {
12242
+ const updatedMetadata = {
12243
+ ...requirements.metadata,
12244
+ isClosed: true,
12245
+ };
12246
+ return {
12247
+ ...requirements,
12248
+ metadata: updatedMetadata,
12249
+ };
12250
+ }
12251
+ }
12252
+ /**
12253
+ * Note: [💞] Ignore a discrepancy between file name and entity name
12254
+ */
12255
+
12256
+ /**
12257
+ * COMPONENT commitment definition
12258
+ *
12259
+ * The COMPONENT commitment defines a UI component that the agent can render in the chat.
12260
+ *
12261
+ * @private [🪔] Maybe export the commitments through some package
12262
+ */
12263
+ class ComponentCommitmentDefinition extends BaseCommitmentDefinition {
12264
+ constructor() {
12265
+ super('COMPONENT');
12266
+ }
12267
+ /**
12268
+ * Short one-line description of COMPONENT.
12269
+ */
12270
+ get description() {
12271
+ return 'Define a UI component that the agent can render in the chat.';
12272
+ }
12273
+ /**
12274
+ * Icon for this commitment.
12275
+ */
12276
+ get icon() {
12277
+ return '🧩';
12278
+ }
12279
+ /**
12280
+ * Markdown documentation for COMPONENT commitment.
12281
+ */
12282
+ get documentation() {
12283
+ return spaceTrim$1(`
12284
+ # COMPONENT
12285
+
12286
+ Defines a UI component that the agent can render in the chat.
12287
+
12288
+ ## Key aspects
12289
+
12290
+ - Tells the agent that a specific component is available.
12291
+ - Provides syntax for using the component.
12292
+
12293
+ ## Example
12294
+
12295
+ \`\`\`book
12296
+ COMPONENT Arrow
12297
+ The agent should render an arrow component in the chat UI.
12298
+ Syntax:
12299
+ <Arrow direction="up" color="red" />
12300
+ \`\`\`
12301
+ `);
12302
+ }
12303
+ applyToAgentModelRequirements(requirements, content) {
12304
+ const trimmedContent = content.trim();
12305
+ if (!trimmedContent) {
12306
+ return requirements;
11987
12307
  }
11988
- // Note: [💎]
11989
- // Note: Using direct eval, following variables are in same scope as eval call so they are accessible from inside the evaluated script:
11990
- const spaceTrim = (_) => spaceTrim$2(_);
11991
- $preserve(spaceTrim);
11992
- const removeQuotes$1 = removeQuotes;
11993
- $preserve(removeQuotes$1);
11994
- const unwrapResult$1 = unwrapResult;
11995
- $preserve(unwrapResult$1);
11996
- const trimEndOfCodeBlock$1 = trimEndOfCodeBlock;
12308
+ // Add component capability to the system message
12309
+ const componentSection = `Component: ${trimmedContent}`;
12310
+ return this.appendToSystemMessage(requirements, componentSection, '\n\n');
12311
+ }
12312
+ }
12313
+ /**
12314
+ * Note: [💞] Ignore a discrepancy between file name and entity name
12315
+ */
12316
+
12317
+ /**
12318
+ * DELETE commitment definition
12319
+ *
12320
+ * The DELETE commitment (and its aliases CANCEL, DISCARD, REMOVE) is used to
12321
+ * remove or disregard certain information or context. This can be useful for
12322
+ * overriding previous commitments or removing unwanted behaviors.
12323
+ *
12324
+ * Example usage in agent source:
12325
+ *
12326
+ * ```book
12327
+ * DELETE Previous formatting requirements
12328
+ * CANCEL All emotional responses
12329
+ * DISCARD Technical jargon explanations
12330
+ * REMOVE Casual conversational style
12331
+ * ```
12332
+ *
12333
+ * @private [🪔] Maybe export the commitments through some package
12334
+ */
12335
+ class DeleteCommitmentDefinition extends BaseCommitmentDefinition {
12336
+ constructor(type) {
12337
+ super(type);
12338
+ }
12339
+ /**
12340
+ * Short one-line description of DELETE/CANCEL/DISCARD/REMOVE.
12341
+ */
12342
+ get description() {
12343
+ return 'Remove or **disregard** certain information, context, or previous commitments.';
12344
+ }
12345
+ /**
12346
+ * Icon for this commitment.
12347
+ */
12348
+ get icon() {
12349
+ return '🗑️';
12350
+ }
12351
+ /**
12352
+ * Markdown documentation for DELETE commitment.
12353
+ */
12354
+ get documentation() {
12355
+ return spaceTrim$1(`
12356
+ # DELETE (CANCEL, DISCARD, REMOVE)
12357
+
12358
+ A commitment to remove or disregard certain information or context. This can be useful for overriding previous commitments or removing unwanted behaviors.
12359
+
12360
+ ## Aliases
12361
+
12362
+ - \`DELETE\` - Remove or eliminate something
12363
+ - \`CANCEL\` - Cancel or nullify something
12364
+ - \`DISCARD\` - Discard or ignore something
12365
+ - \`REMOVE\` - Remove or take away something
12366
+
12367
+ ## Key aspects
12368
+
12369
+ - Multiple delete commitments can be used to remove different aspects.
12370
+ - Useful for overriding previous commitments in the same agent definition.
12371
+ - Can be used to remove inherited behaviors from base personas.
12372
+ - Helps fine-tune agent behavior by explicitly removing unwanted elements.
12373
+
12374
+ ## Use cases
12375
+
12376
+ - Overriding inherited persona characteristics
12377
+ - Removing conflicting or outdated instructions
12378
+ - Disabling specific response patterns
12379
+ - Canceling previous formatting or style requirements
12380
+
12381
+ ## Examples
12382
+
12383
+ \`\`\`book
12384
+ Serious Business Assistant
12385
+
12386
+ PERSONA You are a friendly and casual assistant who uses emojis
12387
+ DELETE Casual conversational style
12388
+ REMOVE All emoji usage
12389
+ GOAL Provide professional business communications
12390
+ STYLE Use formal language and proper business etiquette
12391
+ \`\`\`
12392
+
12393
+ \`\`\`book
12394
+ Simplified Technical Support
12395
+
12396
+ PERSONA You are a technical support specialist with deep expertise
12397
+ KNOWLEDGE Extensive database of technical specifications
12398
+ DISCARD Technical jargon explanations
12399
+ CANCEL Advanced troubleshooting procedures
12400
+ GOAL Help users with simple, easy-to-follow solutions
12401
+ STYLE Use plain language that anyone can understand
12402
+ \`\`\`
12403
+
12404
+ \`\`\`book
12405
+ Focused Customer Service
12406
+
12407
+ PERSONA You are a customer service agent with broad knowledge
12408
+ ACTION Can help with billing, technical issues, and product information
12409
+ DELETE Billing assistance capabilities
12410
+ REMOVE Technical troubleshooting functions
12411
+ GOAL Focus exclusively on product information and general inquiries
12412
+ \`\`\`
12413
+
12414
+ \`\`\`book
12415
+ Concise Information Provider
12416
+
12417
+ PERSONA You are a helpful assistant who provides detailed explanations
12418
+ STYLE Include examples, analogies, and comprehensive context
12419
+ CANCEL Detailed explanation style
12420
+ DISCARD Examples and analogies
12421
+ GOAL Provide brief, direct answers without unnecessary elaboration
12422
+ STYLE Be concise and to the point
12423
+ \`\`\`
12424
+ `);
12425
+ }
12426
+ applyToAgentModelRequirements(requirements, content) {
12427
+ const trimmedContent = content.trim();
12428
+ if (!trimmedContent) {
12429
+ return requirements;
12430
+ }
12431
+ // Create deletion instruction for system message
12432
+ const deleteSection = `${this.type}: ${trimmedContent}`;
12433
+ // Delete instructions provide important context about what should be removed or ignored
12434
+ return this.appendToSystemMessage(requirements, deleteSection, '\n\n');
12435
+ }
12436
+ }
12437
+ /**
12438
+ * Note: [💞] Ignore a discrepancy between file name and entity name
12439
+ */
12440
+
12441
+ /**
12442
+ * DICTIONARY commitment definition
12443
+ *
12444
+ * The DICTIONARY commitment defines specific terms and their meanings that the agent should use correctly
12445
+ * in its reasoning and responses. This ensures consistent terminology usage.
12446
+ *
12447
+ * Key features:
12448
+ * - Multiple DICTIONARY commitments are automatically merged into one
12449
+ * - Content is placed in a dedicated section of the system message
12450
+ * - Terms and definitions are stored in metadata.DICTIONARY for debugging
12451
+ * - Agent should use the defined terms correctly in responses
12452
+ *
12453
+ * Example usage in agent source:
12454
+ *
12455
+ * ```book
12456
+ * Legal Assistant
12457
+ *
12458
+ * PERSONA You are a knowledgeable legal assistant
12459
+ * DICTIONARY Misdemeanor is a minor wrongdoing or criminal offense
12460
+ * DICTIONARY Felony is a serious crime usually punishable by imprisonment for more than one year
12461
+ * DICTIONARY Tort is a civil wrong that causes harm or loss to another person, leading to legal liability
12462
+ * ```
12463
+ *
12464
+ * @private [🪔] Maybe export the commitments through some package
12465
+ */
12466
+ class DictionaryCommitmentDefinition extends BaseCommitmentDefinition {
12467
+ constructor() {
12468
+ super('DICTIONARY');
12469
+ }
12470
+ /**
12471
+ * Short one-line description of DICTIONARY.
12472
+ */
12473
+ get description() {
12474
+ return 'Define terms and their meanings for consistent terminology usage.';
12475
+ }
12476
+ /**
12477
+ * Icon for this commitment.
12478
+ */
12479
+ get icon() {
12480
+ return '📚';
12481
+ }
12482
+ /**
12483
+ * Markdown documentation for DICTIONARY commitment.
12484
+ */
12485
+ get documentation() {
12486
+ return spaceTrim$1(`
12487
+ # DICTIONARY
12488
+
12489
+ Defines specific terms and their meanings that the agent should use correctly in reasoning and responses.
12490
+
12491
+ ## Key aspects
12492
+
12493
+ - Multiple \`DICTIONARY\` commitments are merged together.
12494
+ - Terms are defined in the format: "Term is definition"
12495
+ - The agent should use these terms consistently in responses.
12496
+ - Definitions help ensure accurate and consistent terminology.
12497
+
12498
+ ## Examples
12499
+
12500
+ \`\`\`book
12501
+ Legal Assistant
12502
+
12503
+ PERSONA You are a knowledgeable legal assistant specializing in criminal law
12504
+ DICTIONARY Misdemeanor is a minor wrongdoing or criminal offense
12505
+ DICTIONARY Felony is a serious crime usually punishable by imprisonment for more than one year
12506
+ DICTIONARY Tort is a civil wrong that causes harm or loss to another person, leading to legal liability
12507
+ \`\`\`
12508
+
12509
+ \`\`\`book
12510
+ Medical Assistant
12511
+
12512
+ PERSONA You are a helpful medical assistant
12513
+ DICTIONARY Hypertension is persistently high blood pressure
12514
+ DICTIONARY Diabetes is a chronic condition that affects how the body processes blood sugar
12515
+ DICTIONARY Vaccine is a biological preparation that provides active immunity to a particular disease
12516
+ \`\`\`
12517
+ `);
12518
+ }
12519
+ applyToAgentModelRequirements(requirements, content) {
12520
+ var _a;
12521
+ const trimmedContent = content.trim();
12522
+ if (!trimmedContent) {
12523
+ return requirements;
12524
+ }
12525
+ // Get existing dictionary entries from metadata
12526
+ const existingDictionary = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.DICTIONARY) || '';
12527
+ // Merge the new dictionary entry with existing entries
12528
+ const mergedDictionary = existingDictionary ? `${existingDictionary}\n${trimmedContent}` : trimmedContent;
12529
+ // Store the merged dictionary in metadata for debugging and inspection
12530
+ const updatedMetadata = {
12531
+ ...requirements.metadata,
12532
+ DICTIONARY: mergedDictionary,
12533
+ };
12534
+ // Create the dictionary section for the system message
12535
+ // Format: "# DICTIONARY\nTerm: definition\nTerm: definition..."
12536
+ const dictionarySection = `# DICTIONARY\n${mergedDictionary}`;
12537
+ return {
12538
+ ...this.appendToSystemMessage(requirements, dictionarySection),
12539
+ metadata: updatedMetadata,
12540
+ };
12541
+ }
12542
+ }
12543
+ /**
12544
+ * Note: [💞] Ignore a discrepancy between file name and entity name
12545
+ */
12546
+
12547
+ /**
12548
+ * FORMAT commitment definition
12549
+ *
12550
+ * The FORMAT commitment defines the specific output structure and formatting
12551
+ * that the agent should use in its responses. This includes data formats,
12552
+ * response templates, and structural requirements.
12553
+ *
12554
+ * Example usage in agent source:
12555
+ *
12556
+ * ```book
12557
+ * FORMAT Always respond in JSON format with 'status' and 'data' fields
12558
+ * FORMAT Use markdown formatting for all code blocks
12559
+ * ```
12560
+ *
12561
+ * @private [🪔] Maybe export the commitments through some package
12562
+ */
12563
+ class FormatCommitmentDefinition extends BaseCommitmentDefinition {
12564
+ constructor(type = 'FORMAT') {
12565
+ super(type);
12566
+ }
12567
+ /**
12568
+ * Short one-line description of FORMAT.
12569
+ */
12570
+ get description() {
12571
+ return 'Specify output structure or formatting requirements.';
12572
+ }
12573
+ /**
12574
+ * Icon for this commitment.
12575
+ */
12576
+ get icon() {
12577
+ return '📜';
12578
+ }
12579
+ /**
12580
+ * Markdown documentation for FORMAT commitment.
12581
+ */
12582
+ get documentation() {
12583
+ return spaceTrim$1(`
12584
+ # ${this.type}
12585
+
12586
+ Defines the specific output structure and formatting for responses (data formats, templates, structure).
12587
+
12588
+ ## Key aspects
12589
+
12590
+ - Both terms work identically and can be used interchangeably.
12591
+ - If they are in conflict, the last one takes precedence.
12592
+ - You can specify both data formats and presentation styles.
12593
+
12594
+ ## Examples
12595
+
12596
+ \`\`\`book
12597
+ Customer Support Bot
12598
+
12599
+ PERSONA You are a helpful customer support agent
12600
+ FORMAT Always respond in JSON format with 'status' and 'data' fields
12601
+ FORMAT Use markdown formatting for all code blocks
12602
+ \`\`\`
12603
+
12604
+ \`\`\`book
12605
+ Data Analyst
12606
+
12607
+ PERSONA You are a data analysis expert
12608
+ FORMAT Present results in structured tables
12609
+ FORMAT Include confidence scores for all predictions
12610
+ STYLE Be concise and precise in explanations
12611
+ \`\`\`
12612
+ `);
12613
+ }
12614
+ applyToAgentModelRequirements(requirements, content) {
12615
+ const trimmedContent = content.trim();
12616
+ if (!trimmedContent) {
12617
+ return requirements;
12618
+ }
12619
+ // Add format instructions to the system message
12620
+ const formatSection = `Output Format: ${trimmedContent}`;
12621
+ return this.appendToSystemMessage(requirements, formatSection, '\n\n');
12622
+ }
12623
+ }
12624
+ /**
12625
+ * Note: [💞] Ignore a discrepancy between file name and entity name
12626
+ */
12627
+
12628
+ /**
12629
+ * FROM commitment definition
12630
+ *
12631
+ * The FROM commitment tells the agent that its `agentSource` is inherited from another agent.
12632
+ *
12633
+ * Example usage in agent source:
12634
+ *
12635
+ * ```book
12636
+ * FROM https://s6.ptbk.io/benjamin-white
12637
+ * ```
12638
+ *
12639
+ * @private [🪔] Maybe export the commitments through some package
12640
+ */
12641
+ class FromCommitmentDefinition extends BaseCommitmentDefinition {
12642
+ constructor(type = 'FROM') {
12643
+ super(type);
12644
+ }
12645
+ /**
12646
+ * Short one-line description of FROM.
12647
+ */
12648
+ get description() {
12649
+ return 'Inherit agent source from another agent.';
12650
+ }
12651
+ /**
12652
+ * Icon for this commitment.
12653
+ */
12654
+ get icon() {
12655
+ return '🧬';
12656
+ }
12657
+ /**
12658
+ * Markdown documentation for FROM commitment.
12659
+ */
12660
+ get documentation() {
12661
+ return spaceTrim$1(`
12662
+ # ${this.type}
12663
+
12664
+ Inherits agent source from another agent.
12665
+
12666
+ ## Examples
12667
+
12668
+ \`\`\`book
12669
+ My AI Agent
12670
+
12671
+ FROM https://s6.ptbk.io/benjamin-white
12672
+ RULE Speak only in English.
12673
+ \`\`\`
12674
+ `);
12675
+ }
12676
+ applyToAgentModelRequirements(requirements, content) {
12677
+ const trimmedContent = content.trim();
12678
+ if (!trimmedContent) {
12679
+ return {
12680
+ ...requirements,
12681
+ parentAgentUrl: undefined,
12682
+ };
12683
+ }
12684
+ if (trimmedContent.toUpperCase() === 'VOID' ||
12685
+ trimmedContent.toUpperCase() === 'NULL' ||
12686
+ trimmedContent.toUpperCase() === 'NONE' ||
12687
+ trimmedContent.toUpperCase() === 'NIL') {
12688
+ return {
12689
+ ...requirements,
12690
+ parentAgentUrl: null,
12691
+ };
12692
+ }
12693
+ if (!isValidAgentUrl(trimmedContent)) {
12694
+ throw new Error(spaceTrim$1((block) => `
12695
+ Invalid agent URL in FROM commitment: "${trimmedContent}"
12696
+
12697
+ \`\`\`book
12698
+ ${block(content)}
12699
+ \`\`\`
12700
+
12701
+
12702
+ `));
12703
+ }
12704
+ const parentAgentUrl = trimmedContent;
12705
+ return {
12706
+ ...requirements,
12707
+ parentAgentUrl,
12708
+ };
12709
+ }
12710
+ }
12711
+ /**
12712
+ * Note: [💞] Ignore a discrepancy between file name and entity name
12713
+ */
12714
+
12715
+ /**
12716
+ * GOAL commitment definition
12717
+ *
12718
+ * The GOAL commitment defines the main goal which should be achieved by the AI assistant.
12719
+ * There can be multiple goals. Later goals are more important than earlier goals.
12720
+ *
12721
+ * Example usage in agent source:
12722
+ *
12723
+ * ```book
12724
+ * GOAL Help users understand complex technical concepts
12725
+ * GOAL Provide accurate and up-to-date information
12726
+ * GOAL Always prioritize user safety and ethical guidelines
12727
+ * ```
12728
+ *
12729
+ * @private [🪔] Maybe export the commitments through some package
12730
+ */
12731
+ class GoalCommitmentDefinition extends BaseCommitmentDefinition {
12732
+ constructor(type = 'GOAL') {
12733
+ super(type);
12734
+ }
12735
+ /**
12736
+ * Short one-line description of GOAL.
12737
+ */
12738
+ get description() {
12739
+ return 'Define main **goals** the AI assistant should achieve, with later goals having higher priority.';
12740
+ }
12741
+ /**
12742
+ * Icon for this commitment.
12743
+ */
12744
+ get icon() {
12745
+ return '🎯';
12746
+ }
12747
+ /**
12748
+ * Markdown documentation for GOAL commitment.
12749
+ */
12750
+ get documentation() {
12751
+ return spaceTrim$1(`
12752
+ # ${this.type}
12753
+
12754
+ 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.
12755
+
12756
+ ## Key aspects
12757
+
12758
+ - Both terms work identically and can be used interchangeably.
12759
+ - Later goals have higher priority and can override earlier goals.
12760
+ - Goals provide clear direction and purpose for the agent's responses.
12761
+ - Goals influence decision-making and response prioritization.
12762
+
12763
+ ## Priority system
12764
+
12765
+ When multiple goals are defined, they are processed in order, with later goals taking precedence over earlier ones when there are conflicts.
12766
+
12767
+ ## Examples
12768
+
12769
+ \`\`\`book
12770
+ Customer Support Agent
12771
+
12772
+ PERSONA You are a helpful customer support representative
12773
+ GOAL Resolve customer issues quickly and efficiently
12774
+ GOAL Maintain high customer satisfaction scores
12775
+ GOAL Always follow company policies and procedures
12776
+ RULE Be polite and professional at all times
12777
+ \`\`\`
12778
+
12779
+ \`\`\`book
12780
+ Educational Assistant
12781
+
12782
+ PERSONA You are an educational assistant specializing in mathematics
12783
+ GOAL Help students understand mathematical concepts clearly
12784
+ GOAL Encourage critical thinking and problem-solving skills
12785
+ GOAL Ensure all explanations are age-appropriate and accessible
12786
+ STYLE Use simple language and provide step-by-step explanations
12787
+ \`\`\`
12788
+
12789
+ \`\`\`book
12790
+ Safety-First Assistant
12791
+
12792
+ PERSONA You are a general-purpose AI assistant
12793
+ GOAL Be helpful and informative in all interactions
12794
+ GOAL Provide accurate and reliable information
12795
+ GOAL Always prioritize user safety and ethical guidelines
12796
+ RULE Never provide harmful or dangerous advice
12797
+ \`\`\`
12798
+ `);
12799
+ }
12800
+ applyToAgentModelRequirements(requirements, content) {
12801
+ const trimmedContent = content.trim();
12802
+ if (!trimmedContent) {
12803
+ return requirements;
12804
+ }
12805
+ // Create goal section for system message
12806
+ const goalSection = `Goal: ${trimmedContent}`;
12807
+ // Goals are important directives, so we add them prominently to the system message
12808
+ return this.appendToSystemMessage(requirements, goalSection, '\n\n');
12809
+ }
12810
+ }
12811
+ /**
12812
+ * Note: [💞] Ignore a discrepancy between file name and entity name
12813
+ */
12814
+
12815
+ /**
12816
+ * IMPORT commitment definition
12817
+ *
12818
+ * The IMPORT commitment tells the agent to import content from another agent at the current location.
12819
+ *
12820
+ * Example usage in agent source:
12821
+ *
12822
+ * ```book
12823
+ * IMPORT https://s6.ptbk.io/benjamin-white
12824
+ * ```
12825
+ *
12826
+ * @private [🪔] Maybe export the commitments through some package
12827
+ */
12828
+ class ImportCommitmentDefinition extends BaseCommitmentDefinition {
12829
+ constructor(type = 'IMPORT') {
12830
+ super(type);
12831
+ }
12832
+ /**
12833
+ * Short one-line description of IMPORT.
12834
+ */
12835
+ get description() {
12836
+ return 'Import content from another agent or a generic text file.';
12837
+ }
12838
+ /**
12839
+ * Icon for this commitment.
12840
+ */
12841
+ get icon() {
12842
+ return '📥';
12843
+ }
12844
+ /**
12845
+ * Markdown documentation for IMPORT commitment.
12846
+ */
12847
+ get documentation() {
12848
+ return spaceTrim$1(`
12849
+ # ${this.type}
12850
+
12851
+ Imports content from another agent or a generic text file at the location of the commitment.
12852
+
12853
+ ## Examples
12854
+
12855
+ \`\`\`book
12856
+ My AI Agent
12857
+
12858
+ IMPORT https://s6.ptbk.io/benjamin-white
12859
+ IMPORT https://example.com/some-text-file.txt
12860
+ IMPORT ./path/to/local-file.json
12861
+ RULE Speak only in English.
12862
+ \`\`\`
12863
+ `);
12864
+ }
12865
+ applyToAgentModelRequirements(requirements, content) {
12866
+ const trimmedContent = content.trim();
12867
+ if (!trimmedContent) {
12868
+ return requirements;
12869
+ }
12870
+ if (isValidAgentUrl(trimmedContent)) {
12871
+ const importedAgentUrl = trimmedContent;
12872
+ return {
12873
+ ...requirements,
12874
+ importedAgentUrls: [...(requirements.importedAgentUrls || []), importedAgentUrl],
12875
+ };
12876
+ }
12877
+ if (isValidUrl(trimmedContent) || isValidFilePath(trimmedContent)) {
12878
+ return {
12879
+ ...requirements,
12880
+ importedFileUrls: [...(requirements.importedFileUrls || []), trimmedContent],
12881
+ };
12882
+ }
12883
+ throw new Error(spaceTrim$1((block) => `
12884
+ Invalid agent URL or file path in IMPORT commitment: "${trimmedContent}"
12885
+
12886
+ \`\`\`book
12887
+ ${block(content)}
12888
+ \`\`\`
12889
+ `));
12890
+ }
12891
+ }
12892
+ /**
12893
+ * Note: [💞] Ignore a discrepancy between file name and entity name
12894
+ */
12895
+
12896
+ /**
12897
+ * KNOWLEDGE commitment definition
12898
+ *
12899
+ * The KNOWLEDGE commitment adds specific knowledge, facts, or context to the agent
12900
+ * using RAG (Retrieval-Augmented Generation) approach for external sources.
12901
+ *
12902
+ * Supports both direct text knowledge and external sources like PDFs.
12903
+ *
12904
+ * Example usage in agent source:
12905
+ *
12906
+ * ```book
12907
+ * KNOWLEDGE The company was founded in 2020 and specializes in AI-powered solutions
12908
+ * KNOWLEDGE https://example.com/company-handbook.pdf
12909
+ * KNOWLEDGE https://example.com/product-documentation.pdf
12910
+ * ```
12911
+ *
12912
+ * @private [🪔] Maybe export the commitments through some package
12913
+ */
12914
+ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
12915
+ constructor() {
12916
+ super('KNOWLEDGE');
12917
+ }
12918
+ /**
12919
+ * Short one-line description of KNOWLEDGE.
12920
+ */
12921
+ get description() {
12922
+ return 'Add domain **knowledge** via direct text or external sources (RAG).';
12923
+ }
12924
+ /**
12925
+ * Icon for this commitment.
12926
+ */
12927
+ get icon() {
12928
+ return '🧠';
12929
+ }
12930
+ /**
12931
+ * Markdown documentation for KNOWLEDGE commitment.
12932
+ */
12933
+ get documentation() {
12934
+ return spaceTrim$1(`
12935
+ # ${this.type}
12936
+
12937
+ Adds specific knowledge, facts, or context to the agent using a RAG (Retrieval-Augmented Generation) approach for external sources.
12938
+
12939
+ ## Key aspects
12940
+
12941
+ - Both terms work identically and can be used interchangeably.
12942
+ - Supports both direct text knowledge and external URLs.
12943
+ - External sources (PDFs, websites) are processed via RAG for context retrieval.
12944
+
12945
+ ## Supported formats
12946
+
12947
+ - Direct text: Immediate knowledge incorporated into agent
12948
+ - URLs: External documents processed for contextual retrieval
12949
+ - Supported file types: PDF, text, markdown, HTML
12950
+
12951
+ ## Examples
12952
+
12953
+ \`\`\`book
12954
+ Customer Support Bot
12955
+
12956
+ PERSONA You are a helpful customer support agent for TechCorp
12957
+ KNOWLEDGE TechCorp was founded in 2020 and specializes in AI-powered solutions
12958
+ KNOWLEDGE https://example.com/company-handbook.pdf
12959
+ KNOWLEDGE https://example.com/product-documentation.pdf
12960
+ RULE Always be polite and professional
12961
+ \`\`\`
12962
+
12963
+ \`\`\`book
12964
+ Research Assistant
12965
+
12966
+ PERSONA You are a knowledgeable research assistant
12967
+ KNOWLEDGE Academic research requires careful citation and verification
12968
+ KNOWLEDGE https://example.com/research-guidelines.pdf
12969
+ ACTION Can help with literature reviews and data analysis
12970
+ STYLE Present information in clear, academic format
12971
+ \`\`\`
12972
+ `);
12973
+ }
12974
+ applyToAgentModelRequirements(requirements, content) {
12975
+ const trimmedContent = content.trim();
12976
+ if (!trimmedContent) {
12977
+ return requirements;
12978
+ }
12979
+ // Check if content is a URL (external knowledge source)
12980
+ if (isValidUrl(trimmedContent)) {
12981
+ // Store the URL for later async processing
12982
+ const updatedRequirements = {
12983
+ ...requirements,
12984
+ knowledgeSources: [
12985
+ ...(requirements.knowledgeSources || []),
12986
+ trimmedContent,
12987
+ ],
12988
+ };
12989
+ // Add placeholder information about knowledge sources to system message
12990
+ const knowledgeInfo = `Knowledge Source URL: ${trimmedContent} (will be processed for retrieval during chat)`;
12991
+ return this.appendToSystemMessage(updatedRequirements, knowledgeInfo, '\n\n');
12992
+ }
12993
+ else {
12994
+ // Direct text knowledge - add to system message
12995
+ const knowledgeSection = `Knowledge: ${trimmedContent}`;
12996
+ return this.appendToSystemMessage(requirements, knowledgeSection, '\n\n');
12997
+ }
12998
+ }
12999
+ }
13000
+ /**
13001
+ * Note: [💞] Ignore a discrepancy between file name and entity name
13002
+ */
13003
+
13004
+ /**
13005
+ * LANGUAGE commitment definition
13006
+ *
13007
+ * The LANGUAGE/LANGUAGES commitment specifies the language(s) the agent should use in its responses.
13008
+ *
13009
+ * Example usage in agent source:
13010
+ *
13011
+ * ```book
13012
+ * LANGUAGE English
13013
+ * LANGUAGE French, English and Czech
13014
+ * ```
13015
+ *
13016
+ * @private [🪔] Maybe export the commitments through some package
13017
+ */
13018
+ class LanguageCommitmentDefinition extends BaseCommitmentDefinition {
13019
+ constructor(type = 'LANGUAGE') {
13020
+ super(type);
13021
+ }
13022
+ /**
13023
+ * Short one-line description of LANGUAGE/LANGUAGES.
13024
+ */
13025
+ get description() {
13026
+ return 'Specifies the language(s) the agent should use.';
13027
+ }
13028
+ /**
13029
+ * Icon for this commitment.
13030
+ */
13031
+ get icon() {
13032
+ return '🌐';
13033
+ }
13034
+ /**
13035
+ * Markdown documentation for LANGUAGE/LANGUAGES commitment.
13036
+ */
13037
+ get documentation() {
13038
+ return spaceTrim$1(`
13039
+ # ${this.type}
13040
+
13041
+ Specifies the language(s) the agent should use in its responses.
13042
+ This is a specialized variation of the RULE commitment focused on language constraints.
13043
+
13044
+ ## Examples
13045
+
13046
+ \`\`\`book
13047
+ Paul Smith & Associés
13048
+
13049
+ PERSONA You are a company lawyer.
13050
+ LANGUAGE French, English and Czech
13051
+ \`\`\`
13052
+
13053
+ \`\`\`book
13054
+ Customer Support
13055
+
13056
+ PERSONA You are a customer support agent.
13057
+ LANGUAGE English
13058
+ \`\`\`
13059
+ `);
13060
+ }
13061
+ applyToAgentModelRequirements(requirements, content) {
13062
+ const trimmedContent = content.trim();
13063
+ if (!trimmedContent) {
13064
+ return requirements;
13065
+ }
13066
+ // Add language rule to the system message
13067
+ const languageSection = `Language: ${trimmedContent}`;
13068
+ return this.appendToSystemMessage(requirements, languageSection, '\n\n');
13069
+ }
13070
+ }
13071
+ /**
13072
+ * Note: [💞] Ignore a discrepancy between file name and entity name
13073
+ */
13074
+
13075
+ /**
13076
+ * MEMORY commitment definition
13077
+ *
13078
+ * The MEMORY commitment is similar to KNOWLEDGE but has a focus on remembering past
13079
+ * interactions and user preferences. It helps the agent maintain context about the
13080
+ * user's history, preferences, and previous conversations.
13081
+ *
13082
+ * Example usage in agent source:
13083
+ *
13084
+ * ```book
13085
+ * MEMORY User prefers detailed technical explanations
13086
+ * MEMORY Previously worked on React projects
13087
+ * MEMORY Timezone: UTC-5 (Eastern Time)
13088
+ * ```
13089
+ *
13090
+ * @private [🪔] Maybe export the commitments through some package
13091
+ */
13092
+ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
13093
+ constructor(type = 'MEMORY') {
13094
+ super(type);
13095
+ }
13096
+ /**
13097
+ * Short one-line description of MEMORY.
13098
+ */
13099
+ get description() {
13100
+ return 'Remember past interactions and user **preferences** for personalized responses.';
13101
+ }
13102
+ /**
13103
+ * Icon for this commitment.
13104
+ */
13105
+ get icon() {
13106
+ return '🧠';
13107
+ }
13108
+ /**
13109
+ * Markdown documentation for MEMORY commitment.
13110
+ */
13111
+ get documentation() {
13112
+ return spaceTrim$1(`
13113
+ # ${this.type}
13114
+
13115
+ 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.
13116
+
13117
+ ## Key aspects
13118
+
13119
+ - Both terms work identically and can be used interchangeably.
13120
+ - Focuses on user-specific information and interaction history.
13121
+ - Helps personalize responses based on past interactions.
13122
+ - Maintains continuity across conversations.
13123
+
13124
+ ## Differences from KNOWLEDGE
13125
+
13126
+ - \`KNOWLEDGE\` is for domain expertise and factual information
13127
+ - \`MEMORY\` is for user-specific context and preferences
13128
+ - \`MEMORY\` creates more personalized interactions
13129
+ - \`MEMORY\` often includes temporal or preference-based information
13130
+
13131
+ ## Examples
13132
+
13133
+ \`\`\`book
13134
+ Personal Assistant
13135
+
13136
+ PERSONA You are a personal productivity assistant
13137
+ MEMORY User is a software developer working in JavaScript/React
13138
+ MEMORY User prefers morning work sessions and afternoon meetings
13139
+ MEMORY Previously helped with project planning for mobile apps
13140
+ MEMORY User timezone: UTC-8 (Pacific Time)
13141
+ GOAL Help optimize daily productivity and workflow
13142
+ \`\`\`
13143
+
13144
+ \`\`\`book
13145
+ Learning Companion
13146
+
13147
+ PERSONA You are an educational companion for programming students
13148
+ MEMORY Student is learning Python as their first programming language
13149
+ MEMORY Previous topics covered: variables, loops, functions
13150
+ MEMORY Student learns best with practical examples and exercises
13151
+ MEMORY Last session: working on list comprehensions
13152
+ GOAL Provide progressive learning experiences tailored to student's pace
13153
+ \`\`\`
13154
+
13155
+ \`\`\`book
13156
+ Customer Support Agent
13157
+
13158
+ PERSONA You are a customer support representative
13159
+ MEMORY Customer has premium subscription since 2023
13160
+ MEMORY Previous issue: billing question resolved last month
13161
+ MEMORY Customer prefers email communication over phone calls
13162
+ MEMORY Account shows frequent use of advanced features
13163
+ GOAL Provide personalized support based on customer history
13164
+ \`\`\`
13165
+ `);
13166
+ }
13167
+ applyToAgentModelRequirements(requirements, content) {
13168
+ const trimmedContent = content.trim();
13169
+ if (!trimmedContent) {
13170
+ return requirements;
13171
+ }
13172
+ // Create memory section for system message
13173
+ const memorySection = `Memory: ${trimmedContent}`;
13174
+ // Memory information is contextual and should be included in the system message
13175
+ return this.appendToSystemMessage(requirements, memorySection, '\n\n');
13176
+ }
13177
+ }
13178
+ /**
13179
+ * Note: [💞] Ignore a discrepancy between file name and entity name
13180
+ */
13181
+
13182
+ /**
13183
+ * AGENT MESSAGE commitment definition
13184
+ *
13185
+ * The AGENT MESSAGE commitment defines a message from the agent in the conversation history.
13186
+ * It is used to pre-fill the chat with a conversation history or to provide few-shot examples.
13187
+ *
13188
+ * Example usage in agent source:
13189
+ *
13190
+ * ```book
13191
+ * AGENT MESSAGE What seems to be the issue?
13192
+ * ```
13193
+ *
13194
+ * @private [🪔] Maybe export the commitments through some package
13195
+ */
13196
+ class AgentMessageCommitmentDefinition extends BaseCommitmentDefinition {
13197
+ constructor() {
13198
+ super('AGENT MESSAGE');
13199
+ }
13200
+ /**
13201
+ * Short one-line description of AGENT MESSAGE.
13202
+ */
13203
+ get description() {
13204
+ return 'Defines a **message from the agent** in the conversation history.';
13205
+ }
13206
+ /**
13207
+ * Icon for this commitment.
13208
+ */
13209
+ get icon() {
13210
+ return '🤖';
13211
+ }
13212
+ /**
13213
+ * Markdown documentation for AGENT MESSAGE commitment.
13214
+ */
13215
+ get documentation() {
13216
+ return spaceTrim$1(`
13217
+ # ${this.type}
13218
+
13219
+ 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.
13220
+
13221
+ ## Key aspects
13222
+
13223
+ - Represents a message sent by the agent.
13224
+ - Used for setting up conversation context.
13225
+ - Can be used in conjunction with USER MESSAGE.
13226
+
13227
+ ## Examples
13228
+
13229
+ \`\`\`book
13230
+ Conversation History
13231
+
13232
+ USER MESSAGE Hello, I have a problem.
13233
+ AGENT MESSAGE What seems to be the issue?
13234
+ USER MESSAGE My computer is not starting.
13235
+ \`\`\`
13236
+ `);
13237
+ }
13238
+ applyToAgentModelRequirements(requirements, content) {
13239
+ // AGENT MESSAGE is for UI display purposes / conversation history construction
13240
+ // and typically doesn't need to be added to the system prompt or model requirements directly.
13241
+ // It is extracted separately for the chat interface.
13242
+ var _a;
13243
+ const pendingUserMessage = (_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.pendingUserMessage;
13244
+ if (pendingUserMessage) {
13245
+ const newSample = { question: pendingUserMessage, answer: content };
13246
+ const newSamples = [...(requirements.samples || []), newSample];
13247
+ const newMetadata = { ...requirements.metadata };
13248
+ delete newMetadata.pendingUserMessage;
13249
+ return {
13250
+ ...requirements,
13251
+ samples: newSamples,
13252
+ metadata: newMetadata,
13253
+ };
13254
+ }
13255
+ return requirements;
13256
+ }
13257
+ }
13258
+
13259
+ /**
13260
+ * INITIAL MESSAGE commitment definition
13261
+ *
13262
+ * The INITIAL MESSAGE commitment defines the first message that the user sees when opening the chat.
13263
+ * It is used to greet the user and set the tone of the conversation.
13264
+ *
13265
+ * Example usage in agent source:
13266
+ *
13267
+ * ```book
13268
+ * INITIAL MESSAGE Hello! I am ready to help you with your tasks.
13269
+ * ```
13270
+ *
13271
+ * @private [🪔] Maybe export the commitments through some package
13272
+ */
13273
+ class InitialMessageCommitmentDefinition extends BaseCommitmentDefinition {
13274
+ constructor() {
13275
+ super('INITIAL MESSAGE');
13276
+ }
13277
+ /**
13278
+ * Short one-line description of INITIAL MESSAGE.
13279
+ */
13280
+ get description() {
13281
+ return 'Defines the **initial message** shown to the user when the chat starts.';
13282
+ }
13283
+ /**
13284
+ * Icon for this commitment.
13285
+ */
13286
+ get icon() {
13287
+ return '👋';
13288
+ }
13289
+ /**
13290
+ * Markdown documentation for INITIAL MESSAGE commitment.
13291
+ */
13292
+ get documentation() {
13293
+ return spaceTrim$1(`
13294
+ # ${this.type}
13295
+
13296
+ 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).
13297
+
13298
+ ## Key aspects
13299
+
13300
+ - Used to greet the user.
13301
+ - Sets the tone of the conversation.
13302
+ - Displayed immediately when the chat interface loads.
13303
+
13304
+ ## Examples
13305
+
13306
+ \`\`\`book
13307
+ Support Agent
13308
+
13309
+ PERSONA You are a helpful support agent.
13310
+ INITIAL MESSAGE Hi there! How can I assist you today?
13311
+ \`\`\`
13312
+ `);
13313
+ }
13314
+ applyToAgentModelRequirements(requirements, content) {
13315
+ // INITIAL MESSAGE is for UI display purposes and for conversation history construction.
13316
+ const newSample = { question: null, answer: content };
13317
+ const newSamples = [...(requirements.samples || []), newSample];
13318
+ return {
13319
+ ...requirements,
13320
+ samples: newSamples,
13321
+ };
13322
+ }
13323
+ }
13324
+
13325
+ /**
13326
+ * MESSAGE commitment definition
13327
+ *
13328
+ * The MESSAGE commitment contains 1:1 text of the message which AI assistant already
13329
+ * sent during the conversation. Later messages are later in the conversation.
13330
+ * It is similar to EXAMPLE but it is not example, it is the real message which
13331
+ * AI assistant already sent.
13332
+ *
13333
+ * Example usage in agent source:
13334
+ *
13335
+ * ```book
13336
+ * MESSAGE Hello! How can I help you today?
13337
+ * MESSAGE I understand you're looking for information about our services.
13338
+ * MESSAGE Based on your requirements, I'd recommend our premium package.
13339
+ * ```
13340
+ *
13341
+ * @private [🪔] Maybe export the commitments through some package
13342
+ */
13343
+ class MessageCommitmentDefinition extends BaseCommitmentDefinition {
13344
+ constructor(type = 'MESSAGE') {
13345
+ super(type);
13346
+ }
13347
+ /**
13348
+ * Short one-line description of MESSAGE.
13349
+ */
13350
+ get description() {
13351
+ return 'Include actual **messages** the AI assistant has sent during conversation history.';
13352
+ }
13353
+ /**
13354
+ * Icon for this commitment.
13355
+ */
13356
+ get icon() {
13357
+ return '💬';
13358
+ }
13359
+ /**
13360
+ * Markdown documentation for MESSAGE commitment.
13361
+ */
13362
+ get documentation() {
13363
+ return spaceTrim$1(`
13364
+ # ${this.type}
13365
+
13366
+ 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.
13367
+
13368
+ ## Key aspects
13369
+
13370
+ - Multiple \`MESSAGE\` and \`MESSAGES\` commitments represent the conversation timeline.
13371
+ - Both terms work identically and can be used interchangeably.
13372
+ - Later messages are later in the conversation chronologically.
13373
+ - Contains actual historical messages, not examples or templates.
13374
+ - Helps maintain conversation continuity and context.
13375
+
13376
+ ## Differences from EXAMPLE
13377
+
13378
+ - \`EXAMPLE\` shows hypothetical or template responses
13379
+ - \`MESSAGE\`/\`MESSAGES\` contains actual historical conversation content
13380
+ - \`MESSAGE\`/\`MESSAGES\` preserves the exact conversation flow
13381
+ - \`MESSAGE\`/\`MESSAGES\` helps with context awareness and consistency
13382
+
13383
+ ## Use cases
13384
+
13385
+ - Maintaining conversation history context
13386
+ - Ensuring consistent tone and style across messages
13387
+ - Referencing previous responses in ongoing conversations
13388
+ - Building upon previously established context
13389
+
13390
+ ## Examples
13391
+
13392
+ \`\`\`book
13393
+ Customer Support Continuation
13394
+
13395
+ PERSONA You are a helpful customer support agent
13396
+ MESSAGE Hello! How can I help you today?
13397
+ MESSAGE I understand you're experiencing issues with your account login.
13398
+ MESSAGE I've sent you a password reset link to your email address.
13399
+ MESSAGE Is there anything else I can help you with regarding your account?
13400
+ GOAL Continue providing consistent support based on conversation history
13401
+ \`\`\`
13402
+
13403
+ \`\`\`book
13404
+ Technical Discussion
13405
+
13406
+ PERSONA You are a software development mentor
13407
+ MESSAGE Let's start by reviewing the React component structure you shared.
13408
+ MESSAGE I notice you're using class components - have you considered hooks?
13409
+ MESSAGE Here's how you could refactor that using the useState hook.
13410
+ MESSAGE Great question about performance! Let me explain React's rendering cycle.
13411
+ KNOWLEDGE React hooks were introduced in version 16.8
13412
+ \`\`\`
13413
+
13414
+ \`\`\`book
13415
+ Educational Session
13416
+
13417
+ PERSONA You are a mathematics tutor
13418
+ MESSAGE Today we'll work on solving quadratic equations.
13419
+ MESSAGE Let's start with the basic form: ax² + bx + c = 0
13420
+ MESSAGE Remember, we can use the quadratic formula or factoring.
13421
+ MESSAGE You did great with that first problem! Let's try a more complex one.
13422
+ GOAL Build upon previous explanations for deeper understanding
13423
+ \`\`\`
13424
+ `);
13425
+ }
13426
+ applyToAgentModelRequirements(requirements, content) {
13427
+ const trimmedContent = content.trim();
13428
+ if (!trimmedContent) {
13429
+ return requirements;
13430
+ }
13431
+ // Create message section for system message
13432
+ const messageSection = `Previous Message: ${trimmedContent}`;
13433
+ // Messages represent conversation history and should be included for context
13434
+ return this.appendToSystemMessage(requirements, messageSection, '\n\n');
13435
+ }
13436
+ }
13437
+ /**
13438
+ * Note: [💞] Ignore a discrepancy between file name and entity name
13439
+ */
13440
+
13441
+ /**
13442
+ * USER MESSAGE commitment definition
13443
+ *
13444
+ * The USER MESSAGE commitment defines a message from the user in the conversation history.
13445
+ * It is used to pre-fill the chat with a conversation history or to provide few-shot examples.
13446
+ *
13447
+ * Example usage in agent source:
13448
+ *
13449
+ * ```book
13450
+ * USER MESSAGE Hello, I have a problem.
13451
+ * ```
13452
+ *
13453
+ * @private [🪔] Maybe export the commitments through some package
13454
+ */
13455
+ class UserMessageCommitmentDefinition extends BaseCommitmentDefinition {
13456
+ constructor() {
13457
+ super('USER MESSAGE');
13458
+ }
13459
+ /**
13460
+ * Short one-line description of USER MESSAGE.
13461
+ */
13462
+ get description() {
13463
+ return 'Defines a **message from the user** in the conversation history.';
13464
+ }
13465
+ /**
13466
+ * Icon for this commitment.
13467
+ */
13468
+ get icon() {
13469
+ return '🧑';
13470
+ }
13471
+ /**
13472
+ * Markdown documentation for USER MESSAGE commitment.
13473
+ */
13474
+ get documentation() {
13475
+ return spaceTrim$1(`
13476
+ # ${this.type}
13477
+
13478
+ 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.
13479
+
13480
+ ## Key aspects
13481
+
13482
+ - Represents a message sent by the user.
13483
+ - Used for setting up conversation context.
13484
+ - Can be used in conjunction with AGENT MESSAGE.
13485
+
13486
+ ## Examples
13487
+
13488
+ \`\`\`book
13489
+ Conversation History
13490
+
13491
+ USER MESSAGE Hello, I have a problem.
13492
+ AGENT MESSAGE What seems to be the issue?
13493
+ USER MESSAGE My computer is not starting.
13494
+ \`\`\`
13495
+ `);
13496
+ }
13497
+ applyToAgentModelRequirements(requirements, content) {
13498
+ return {
13499
+ ...requirements,
13500
+ metadata: {
13501
+ ...requirements.metadata,
13502
+ pendingUserMessage: content,
13503
+ },
13504
+ };
13505
+ }
13506
+ }
13507
+
13508
+ /**
13509
+ * META commitment definition
13510
+ *
13511
+ * The META commitment handles all meta-information about the agent such as:
13512
+ * - META IMAGE: Sets the agent's avatar/profile image URL
13513
+ * - META LINK: Provides profile/source links for the person the agent models
13514
+ * - META TITLE: Sets the agent's display title
13515
+ * - META DESCRIPTION: Sets the agent's description
13516
+ * - META [ANYTHING]: Any other meta information in uppercase format
13517
+ *
13518
+ * These commitments are special because they don't affect the system message,
13519
+ * but are handled separately in the parsing logic for profile display.
13520
+ *
13521
+ * Example usage in agent source:
13522
+ *
13523
+ * ```book
13524
+ * META IMAGE https://example.com/avatar.jpg
13525
+ * META LINK https://twitter.com/username
13526
+ * META TITLE Professional Assistant
13527
+ * META DESCRIPTION An AI assistant specialized in business tasks
13528
+ * META AUTHOR John Doe
13529
+ * META VERSION 1.0
13530
+ * ```
13531
+ *
13532
+ * @private [🪔] Maybe export the commitments through some package
13533
+ */
13534
+ class MetaCommitmentDefinition extends BaseCommitmentDefinition {
13535
+ constructor() {
13536
+ super('META');
13537
+ }
13538
+ /**
13539
+ * Short one-line description of META commitments.
13540
+ */
13541
+ get description() {
13542
+ return 'Set meta-information about the agent (IMAGE, LINK, TITLE, DESCRIPTION, etc.).';
13543
+ }
13544
+ /**
13545
+ * Icon for this commitment.
13546
+ */
13547
+ get icon() {
13548
+ return 'ℹ️';
13549
+ }
13550
+ /**
13551
+ * Markdown documentation for META commitment.
13552
+ */
13553
+ get documentation() {
13554
+ return spaceTrim$1(`
13555
+ # META
13556
+
13557
+ Sets meta-information about the agent that is used for display and attribution purposes.
13558
+
13559
+ ## Supported META types
13560
+
13561
+ - **META IMAGE** - Sets the agent's avatar/profile image URL
13562
+ - **META LINK** - Provides profile/source links for the person the agent models
13563
+ - **META TITLE** - Sets the agent's display title
13564
+ - **META DESCRIPTION** - Sets the agent's description
13565
+ - **META [ANYTHING]** - Any other meta information in uppercase format
13566
+
13567
+ ## Key aspects
13568
+
13569
+ - Does not modify the agent's behavior or responses
13570
+ - Used for visual representation and attribution in user interfaces
13571
+ - Multiple META commitments of different types can be used
13572
+ - Multiple META LINK commitments can be used for different social profiles
13573
+ - If multiple META commitments of the same type are specified, the last one takes precedence (except for LINK)
13574
+
13575
+ ## Examples
13576
+
13577
+ ### Basic meta information
13578
+
13579
+ \`\`\`book
13580
+ Professional Assistant
13581
+
13582
+ META IMAGE https://example.com/professional-avatar.jpg
13583
+ META TITLE Senior Business Consultant
13584
+ META DESCRIPTION Specialized in strategic planning and project management
13585
+ META LINK https://linkedin.com/in/professional
13586
+ \`\`\`
13587
+
13588
+ ### Multiple links and custom meta
13589
+
13590
+ \`\`\`book
13591
+ Open Source Developer
13592
+
13593
+ META IMAGE /assets/dev-avatar.png
13594
+ META LINK https://github.com/developer
13595
+ META LINK https://twitter.com/devhandle
13596
+ META AUTHOR Jane Smith
13597
+ META VERSION 2.1
13598
+ META LICENSE MIT
13599
+ \`\`\`
13600
+
13601
+ ### Creative assistant
13602
+
13603
+ \`\`\`book
13604
+ Creative Helper
13605
+
13606
+ META IMAGE https://example.com/creative-bot.jpg
13607
+ META TITLE Creative Writing Assistant
13608
+ META DESCRIPTION Helps with brainstorming, storytelling, and creative projects
13609
+ META INSPIRATION Books, movies, and real-world experiences
13610
+ \`\`\`
13611
+ `);
13612
+ }
13613
+ applyToAgentModelRequirements(requirements, content) {
13614
+ // META commitments don't modify the system message or model requirements
13615
+ // They are handled separately in the parsing logic for meta information extraction
13616
+ // This method exists for consistency with the CommitmentDefinition interface
13617
+ return requirements;
13618
+ }
13619
+ /**
13620
+ * Extracts meta information from the content based on the meta type
13621
+ * This is used by the parsing logic
13622
+ */
13623
+ extractMetaValue(metaType, content) {
13624
+ const trimmedContent = content.trim();
13625
+ return trimmedContent || null;
13626
+ }
13627
+ /**
13628
+ * Validates if the provided content is a valid URL (for IMAGE and LINK types)
13629
+ */
13630
+ isValidUrl(content) {
13631
+ try {
13632
+ new URL(content.trim());
13633
+ return true;
13634
+ }
13635
+ catch (_a) {
13636
+ return false;
13637
+ }
13638
+ }
13639
+ /**
13640
+ * Checks if this is a known meta type
13641
+ */
13642
+ isKnownMetaType(metaType) {
13643
+ const knownTypes = ['IMAGE', 'LINK', 'TITLE', 'DESCRIPTION', 'AUTHOR', 'VERSION', 'LICENSE'];
13644
+ return knownTypes.includes(metaType.toUpperCase());
13645
+ }
13646
+ }
13647
+ /**
13648
+ * Note: [💞] Ignore a discrepancy between file name and entity name
13649
+ */
13650
+
13651
+ /**
13652
+ * META COLOR commitment definition
13653
+ *
13654
+ * The META COLOR commitment sets the agent's accent color.
13655
+ * This commitment is special because it doesn't affect the system message,
13656
+ * but is handled separately in the parsing logic.
13657
+ *
13658
+ * Example usage in agent source:
13659
+ *
13660
+ * ```book
13661
+ * META COLOR #ff0000
13662
+ * META COLOR #00ff00
13663
+ * ```
13664
+ *
13665
+ * You can also specify multiple colors separated by comma:
13666
+ *
13667
+ * ```book
13668
+ * META COLOR #ff0000, #00ff00, #0000ff
13669
+ * ```
13670
+ *
13671
+ * @private [🪔] Maybe export the commitments through some package
13672
+ */
13673
+ class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
13674
+ constructor() {
13675
+ super('META COLOR', ['COLOR']);
13676
+ }
13677
+ /**
13678
+ * Short one-line description of META COLOR.
13679
+ */
13680
+ get description() {
13681
+ return "Set the agent's accent color or gradient.";
13682
+ }
13683
+ /**
13684
+ * Icon for this commitment.
13685
+ */
13686
+ get icon() {
13687
+ return '🎨';
13688
+ }
13689
+ /**
13690
+ * Markdown documentation for META COLOR commitment.
13691
+ */
13692
+ get documentation() {
13693
+ return spaceTrim$1(`
13694
+ # META COLOR
13695
+
13696
+ Sets the agent's accent color or gradient.
13697
+
13698
+ ## Key aspects
13699
+
13700
+ - Does not modify the agent's behavior or responses.
13701
+ - Only one \`META COLOR\` should be used per agent.
13702
+ - If multiple are specified, the last one takes precedence.
13703
+ - Used for visual representation in user interfaces.
13704
+ - Can specify multiple colors separated by comma to create a gradient.
13705
+
13706
+ ## Examples
13707
+
13708
+ \`\`\`book
13709
+ Professional Assistant
13710
+
13711
+ META COLOR #3498db
13712
+ PERSONA You are a professional business assistant
13713
+ \`\`\`
13714
+
13715
+ \`\`\`book
13716
+ Creative Helper
13717
+
13718
+ META COLOR #e74c3c
13719
+ PERSONA You are a creative and inspiring assistant
13720
+ \`\`\`
13721
+
13722
+ \`\`\`book
13723
+ Gradient Agent
13724
+
13725
+ META COLOR #ff0000, #00ff00, #0000ff
13726
+ PERSONA You are a colorful agent
13727
+ \`\`\`
13728
+ `);
13729
+ }
13730
+ applyToAgentModelRequirements(requirements, content) {
13731
+ // META COLOR doesn't modify the system message or model requirements
13732
+ // It's handled separately in the parsing logic for profile color extraction
13733
+ // This method exists for consistency with the CommitmentDefinition interface
13734
+ return requirements;
13735
+ }
13736
+ /**
13737
+ * Extracts the profile color from the content
13738
+ * This is used by the parsing logic
13739
+ */
13740
+ extractProfileColor(content) {
13741
+ const trimmedContent = content.trim();
13742
+ return trimmedContent || null;
13743
+ }
13744
+ }
13745
+ /**
13746
+ * Note: [💞] Ignore a discrepancy between file name and entity name
13747
+ */
13748
+
13749
+ /**
13750
+ * META FONT commitment definition
13751
+ *
13752
+ * The META FONT commitment sets the agent's font.
13753
+ * This commitment is special because it doesn't affect the system message,
13754
+ * but is handled separately in the parsing logic.
13755
+ *
13756
+ * Example usage in agent source:
13757
+ *
13758
+ * ```book
13759
+ * META FONT Poppins, Arial, sans-serif
13760
+ * META FONT Roboto
13761
+ * ```
13762
+ *
13763
+ * @private [🪔] Maybe export the commitments through some package
13764
+ */
13765
+ class MetaFontCommitmentDefinition extends BaseCommitmentDefinition {
13766
+ constructor() {
13767
+ super('META FONT', ['FONT']);
13768
+ }
13769
+ /**
13770
+ * Short one-line description of META FONT.
13771
+ */
13772
+ get description() {
13773
+ return "Set the agent's font.";
13774
+ }
13775
+ /**
13776
+ * Icon for this commitment.
13777
+ */
13778
+ get icon() {
13779
+ return '🔤';
13780
+ }
13781
+ /**
13782
+ * Markdown documentation for META FONT commitment.
13783
+ */
13784
+ get documentation() {
13785
+ return spaceTrim$1(`
13786
+ # META FONT
13787
+
13788
+ Sets the agent's font.
13789
+
13790
+ ## Key aspects
13791
+
13792
+ - Does not modify the agent's behavior or responses.
13793
+ - Only one \`META FONT\` should be used per agent.
13794
+ - If multiple are specified, the last one takes precedence.
13795
+ - Used for visual representation in user interfaces.
13796
+ - Supports Google Fonts.
13797
+
13798
+ ## Examples
13799
+
13800
+ \`\`\`book
13801
+ Modern Assistant
13802
+
13803
+ META FONT Poppins, Arial, sans-serif
13804
+ PERSONA You are a modern assistant
13805
+ \`\`\`
13806
+
13807
+ \`\`\`book
13808
+ Classic Helper
13809
+
13810
+ META FONT Times New Roman
13811
+ PERSONA You are a classic helper
13812
+ \`\`\`
13813
+ `);
13814
+ }
13815
+ applyToAgentModelRequirements(requirements, content) {
13816
+ // META FONT doesn't modify the system message or model requirements
13817
+ // It's handled separately in the parsing logic
13818
+ // This method exists for consistency with the CommitmentDefinition interface
13819
+ return requirements;
13820
+ }
13821
+ /**
13822
+ * Extracts the font from the content
13823
+ * This is used by the parsing logic
13824
+ */
13825
+ extractProfileFont(content) {
13826
+ const trimmedContent = content.trim();
13827
+ return trimmedContent || null;
13828
+ }
13829
+ }
13830
+ /**
13831
+ * Note: [💞] Ignore a discrepancy between file name and entity name
13832
+ */
13833
+
13834
+ /**
13835
+ * META IMAGE commitment definition
13836
+ *
13837
+ * The META IMAGE commitment sets the agent's avatar/profile image URL.
13838
+ * This commitment is special because it doesn't affect the system message,
13839
+ * but is handled separately in the parsing logic.
13840
+ *
13841
+ * Example usage in agent source:
13842
+ *
13843
+ * ```book
13844
+ * META IMAGE https://example.com/avatar.jpg
13845
+ * META IMAGE /assets/agent-avatar.png
13846
+ * ```
13847
+ *
13848
+ * @private [🪔] Maybe export the commitments through some package
13849
+ */
13850
+ class MetaImageCommitmentDefinition extends BaseCommitmentDefinition {
13851
+ constructor() {
13852
+ super('META IMAGE', ['IMAGE']);
13853
+ }
13854
+ /**
13855
+ * Short one-line description of META IMAGE.
13856
+ */
13857
+ get description() {
13858
+ return "Set the agent's profile image URL.";
13859
+ }
13860
+ /**
13861
+ * Icon for this commitment.
13862
+ */
13863
+ get icon() {
13864
+ return '🖼️';
13865
+ }
13866
+ /**
13867
+ * Markdown documentation for META IMAGE commitment.
13868
+ */
13869
+ get documentation() {
13870
+ return spaceTrim$1(`
13871
+ # META IMAGE
13872
+
13873
+ Sets the agent's avatar/profile image URL.
13874
+
13875
+ ## Key aspects
13876
+
13877
+ - Does not modify the agent's behavior or responses.
13878
+ - Only one \`META IMAGE\` should be used per agent.
13879
+ - If multiple are specified, the last one takes precedence.
13880
+ - Used for visual representation in user interfaces.
13881
+
13882
+ ## Examples
13883
+
13884
+ \`\`\`book
13885
+ Professional Assistant
13886
+
13887
+ META IMAGE https://example.com/professional-avatar.jpg
13888
+ PERSONA You are a professional business assistant
13889
+ STYLE Maintain a formal and courteous tone
13890
+ \`\`\`
13891
+
13892
+ \`\`\`book
13893
+ Creative Helper
13894
+
13895
+ META IMAGE /assets/creative-bot-avatar.png
13896
+ PERSONA You are a creative and inspiring assistant
13897
+ STYLE Be enthusiastic and encouraging
13898
+ ACTION Can help with brainstorming and ideation
13899
+ \`\`\`
13900
+ `);
13901
+ }
13902
+ applyToAgentModelRequirements(requirements, content) {
13903
+ // META IMAGE doesn't modify the system message or model requirements
13904
+ // It's handled separately in the parsing logic for profile image extraction
13905
+ // This method exists for consistency with the CommitmentDefinition interface
13906
+ return requirements;
13907
+ }
13908
+ /**
13909
+ * Extracts the profile image URL from the content
13910
+ * This is used by the parsing logic
13911
+ */
13912
+ extractProfileImageUrl(content) {
13913
+ const trimmedContent = content.trim();
13914
+ return trimmedContent || null;
13915
+ }
13916
+ }
13917
+ /**
13918
+ * Note: [💞] Ignore a discrepancy between file name and entity name
13919
+ */
13920
+
13921
+ /**
13922
+ * META LINK commitment definition
13923
+ *
13924
+ * The `META LINK` commitment represents the link to the person from whom the agent is created.
13925
+ * This commitment is special because it doesn't affect the system message,
13926
+ * but is handled separately in the parsing logic for profile display.
13927
+ *
13928
+ * Example usage in agent source:
13929
+ *
13930
+ * ```
13931
+ * META LINK https://twitter.com/username
13932
+ * META LINK https://linkedin.com/in/profile
13933
+ * META LINK https://github.com/username
13934
+ * ```
13935
+ *
13936
+ * Multiple `META LINK` commitments can be used when there are multiple sources:
13937
+ *
13938
+ * ```book
13939
+ * META LINK https://twitter.com/username
13940
+ * META LINK https://linkedin.com/in/profile
13941
+ * ```
13942
+ *
13943
+ * @private [🪔] Maybe export the commitments through some package
13944
+ */
13945
+ class MetaLinkCommitmentDefinition extends BaseCommitmentDefinition {
13946
+ constructor() {
13947
+ super('META LINK');
13948
+ }
13949
+ /**
13950
+ * Short one-line description of META LINK.
13951
+ */
13952
+ get description() {
13953
+ return 'Provide profile/source links for the person the agent models.';
13954
+ }
13955
+ /**
13956
+ * Icon for this commitment.
13957
+ */
13958
+ get icon() {
13959
+ return '🔗';
13960
+ }
13961
+ /**
13962
+ * Markdown documentation for META LINK commitment.
13963
+ */
13964
+ get documentation() {
13965
+ return spaceTrim$1(`
13966
+ # META LINK
13967
+
13968
+ Represents a profile or source link for the person the agent is modeled after.
13969
+
13970
+ ## Key aspects
13971
+
13972
+ - Does not modify the agent's behavior or responses.
13973
+ - Multiple \`META LINK\` commitments can be used for different social profiles.
13974
+ - Used for attribution and crediting the original person.
13975
+ - Displayed in user interfaces for transparency.
13976
+
13977
+ ## Examples
13978
+
13979
+ \`\`\`book
13980
+ Expert Consultant
13981
+
13982
+ META LINK https://twitter.com/expertname
13983
+ META LINK https://linkedin.com/in/expertprofile
13984
+ PERSONA You are Dr. Smith, a renowned expert in artificial intelligence
13985
+ KNOWLEDGE Extensive background in machine learning and neural networks
13986
+ \`\`\`
13987
+
13988
+ \`\`\`book
13989
+ Open Source Developer
13990
+
13991
+ META LINK https://github.com/developer
13992
+ META LINK https://twitter.com/devhandle
13993
+ PERSONA You are an experienced open source developer
13994
+ ACTION Can help with code reviews and architecture decisions
13995
+ STYLE Be direct and technical in explanations
13996
+ \`\`\`
13997
+ `);
13998
+ }
13999
+ applyToAgentModelRequirements(requirements, content) {
14000
+ // META LINK doesn't modify the system message or model requirements
14001
+ // It's handled separately in the parsing logic for profile link extraction
14002
+ // This method exists for consistency with the CommitmentDefinition interface
14003
+ return requirements;
14004
+ }
14005
+ /**
14006
+ * Extracts the profile link URL from the content
14007
+ * This is used by the parsing logic
14008
+ */
14009
+ extractProfileLinkUrl(content) {
14010
+ const trimmedContent = content.trim();
14011
+ return trimmedContent || null;
14012
+ }
14013
+ /**
14014
+ * Validates if the provided content is a valid URL
14015
+ */
14016
+ isValidUrl(content) {
14017
+ try {
14018
+ new URL(content.trim());
14019
+ return true;
14020
+ }
14021
+ catch (_a) {
14022
+ return false;
14023
+ }
14024
+ }
14025
+ }
14026
+ /**
14027
+ * Note: [💞] Ignore a discrepancy between file name and entity name
14028
+ */
14029
+
14030
+ /**
14031
+ * MODEL commitment definition
14032
+ *
14033
+ * The MODEL commitment specifies which AI model to use and can also set
14034
+ * model-specific parameters like temperature, topP, topK, and maxTokens.
14035
+ *
14036
+ * Supports multiple syntax variations:
14037
+ *
14038
+ * Single-line format:
14039
+ * ```book
14040
+ * MODEL gpt-4
14041
+ * MODEL claude-3-opus temperature=0.3
14042
+ * MODEL gpt-3.5-turbo temperature=0.8 topP=0.9
14043
+ * ```
14044
+ *
14045
+ * Multi-line named parameter format:
14046
+ * ```book
14047
+ * MODEL NAME gpt-4
14048
+ * MODEL TEMPERATURE 0.7
14049
+ * MODEL TOP_P 0.9
14050
+ * MODEL MAX_TOKENS 2048
14051
+ * ```
14052
+ *
14053
+ * @private [🪔] Maybe export the commitments through some package
14054
+ */
14055
+ class ModelCommitmentDefinition extends BaseCommitmentDefinition {
14056
+ constructor(type = 'MODEL') {
14057
+ super(type);
14058
+ }
14059
+ /**
14060
+ * Short one-line description of MODEL.
14061
+ */
14062
+ get description() {
14063
+ return 'Enforce AI model requirements including name and technical parameters.';
14064
+ }
14065
+ /**
14066
+ * Icon for this commitment.
14067
+ */
14068
+ get icon() {
14069
+ return '⚙️';
14070
+ }
14071
+ /**
14072
+ * Markdown documentation for MODEL commitment.
14073
+ */
14074
+ get documentation() {
14075
+ return spaceTrim$1(`
14076
+ # ${this.type}
14077
+
14078
+ Enforces technical parameters for the AI model, ensuring consistent behavior across different execution environments.
14079
+
14080
+ ## Key aspects
14081
+
14082
+ - When no \`MODEL\` commitment is specified, the best model requirement is picked automatically based on the agent \`PERSONA\`, \`KNOWLEDGE\`, \`TOOLS\` and other commitments
14083
+ - Multiple \`MODEL\` commitments can be used to specify different parameters
14084
+ - Both \`MODEL\` and \`MODELS\` terms work identically and can be used interchangeably
14085
+ - Parameters control the randomness, creativity, and technical aspects of model responses
14086
+
14087
+ ## Syntax variations
14088
+
14089
+ ### Single-line format (legacy support)
14090
+ \`\`\`book
14091
+ MODEL gpt-4
14092
+ MODEL claude-3-opus temperature=0.3
14093
+ MODEL gpt-3.5-turbo temperature=0.8 topP=0.9
14094
+ \`\`\`
14095
+
14096
+ ### Multi-line named parameter format (recommended)
14097
+ \`\`\`book
14098
+ MODEL NAME gpt-4
14099
+ MODEL TEMPERATURE 0.7
14100
+ MODEL TOP_P 0.9
14101
+ MODEL MAX_TOKENS 2048
14102
+ \`\`\`
14103
+
14104
+ ## Supported parameters
14105
+
14106
+ - \`NAME\`: The specific model to use (e.g., 'gpt-4', 'claude-3-opus')
14107
+ - \`TEMPERATURE\`: Controls randomness (0.0 = deterministic, 1.0+ = creative)
14108
+ - \`TOP_P\`: Nucleus sampling parameter for controlling diversity
14109
+ - \`TOP_K\`: Top-k sampling parameter for limiting vocabulary
14110
+ - \`MAX_TOKENS\`: Maximum number of tokens the model can generate
14111
+
14112
+ ## Examples
14113
+
14114
+ ### Precise deterministic assistant
14115
+ \`\`\`book
14116
+ Precise Assistant
14117
+
14118
+ PERSONA You are a precise and accurate assistant
14119
+ MODEL NAME gpt-4
14120
+ MODEL TEMPERATURE 0.1
14121
+ MODEL MAX_TOKENS 1024
14122
+ RULE Always provide factual information
14123
+ \`\`\`
14124
+
14125
+ ### Creative writing assistant
14126
+ \`\`\`book
14127
+ Creative Writer
14128
+
14129
+ PERSONA You are a creative writing assistant
14130
+ MODEL NAME claude-3-opus
14131
+ MODEL TEMPERATURE 0.8
14132
+ MODEL TOP_P 0.9
14133
+ MODEL MAX_TOKENS 2048
14134
+ STYLE Be imaginative and expressive
14135
+ ACTION Can help with storytelling and character development
14136
+ \`\`\`
14137
+
14138
+ ### Balanced conversational agent
14139
+ \`\`\`book
14140
+ Balanced Assistant
14141
+
14142
+ PERSONA You are a helpful and balanced assistant
14143
+ MODEL NAME gpt-4
14144
+ MODEL TEMPERATURE 0.7
14145
+ MODEL TOP_P 0.95
14146
+ MODEL TOP_K 40
14147
+ MODEL MAX_TOKENS 1500
14148
+ \`\`\`
14149
+ `);
14150
+ }
14151
+ applyToAgentModelRequirements(requirements, content) {
14152
+ var _a;
14153
+ const trimmedContent = content.trim();
14154
+ if (!trimmedContent) {
14155
+ return requirements;
14156
+ }
14157
+ const parts = trimmedContent.split(/\s+/);
14158
+ const firstPart = (_a = parts[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase();
14159
+ // Check if this is the new named parameter format
14160
+ if (this.isNamedParameter(firstPart)) {
14161
+ return this.parseNamedParameter(requirements, firstPart, parts.slice(1));
14162
+ }
14163
+ else {
14164
+ // Legacy single-line format: "MODEL gpt-4 temperature=0.3 topP=0.9"
14165
+ return this.parseLegacyFormat(requirements, parts);
14166
+ }
14167
+ }
14168
+ /**
14169
+ * Check if the first part is a known named parameter
14170
+ */
14171
+ isNamedParameter(part) {
14172
+ if (!part)
14173
+ return false;
14174
+ const knownParams = ['NAME', 'TEMPERATURE', 'TOP_P', 'TOP_K', 'MAX_TOKENS'];
14175
+ return knownParams.includes(part);
14176
+ }
14177
+ /**
14178
+ * Parse the new named parameter format: "MODEL TEMPERATURE 0.7"
14179
+ */
14180
+ parseNamedParameter(requirements, parameterName, valueParts) {
14181
+ const value = valueParts.join(' ').trim();
14182
+ if (!value) {
14183
+ return requirements;
14184
+ }
14185
+ const result = { ...requirements };
14186
+ switch (parameterName) {
14187
+ case 'NAME':
14188
+ result.modelName = value;
14189
+ break;
14190
+ case 'TEMPERATURE': {
14191
+ const temperature = parseFloat(value);
14192
+ if (!isNaN(temperature)) {
14193
+ result.temperature = temperature;
14194
+ }
14195
+ break;
14196
+ }
14197
+ case 'TOP_P': {
14198
+ const topP = parseFloat(value);
14199
+ if (!isNaN(topP)) {
14200
+ result.topP = topP;
14201
+ }
14202
+ break;
14203
+ }
14204
+ case 'TOP_K': {
14205
+ const topK = parseFloat(value);
14206
+ if (!isNaN(topK)) {
14207
+ result.topK = Math.round(topK);
14208
+ }
14209
+ break;
14210
+ }
14211
+ case 'MAX_TOKENS': {
14212
+ const maxTokens = parseFloat(value);
14213
+ if (!isNaN(maxTokens)) {
14214
+ result.maxTokens = Math.round(maxTokens);
14215
+ }
14216
+ break;
14217
+ }
14218
+ }
14219
+ return result;
14220
+ }
14221
+ /**
14222
+ * Parse the legacy format: "MODEL gpt-4 temperature=0.3 topP=0.9"
14223
+ */
14224
+ parseLegacyFormat(requirements, parts) {
14225
+ const modelName = parts[0];
14226
+ if (!modelName) {
14227
+ return requirements;
14228
+ }
14229
+ // Start with the model name
14230
+ const result = {
14231
+ ...requirements,
14232
+ modelName,
14233
+ };
14234
+ // Parse additional key=value parameters
14235
+ for (let i = 1; i < parts.length; i++) {
14236
+ const param = parts[i];
14237
+ if (param && param.includes('=')) {
14238
+ const [key, value] = param.split('=');
14239
+ if (key && value) {
14240
+ const numValue = parseFloat(value);
14241
+ if (!isNaN(numValue)) {
14242
+ switch (key.toLowerCase()) {
14243
+ case 'temperature':
14244
+ result.temperature = numValue;
14245
+ break;
14246
+ case 'topp':
14247
+ case 'top_p':
14248
+ result.topP = numValue;
14249
+ break;
14250
+ case 'topk':
14251
+ case 'top_k':
14252
+ result.topK = Math.round(numValue);
14253
+ break;
14254
+ case 'max_tokens':
14255
+ case 'maxTokens':
14256
+ result.maxTokens = Math.round(numValue);
14257
+ break;
14258
+ }
14259
+ }
14260
+ }
14261
+ }
14262
+ }
14263
+ return result;
14264
+ }
14265
+ }
14266
+ /**
14267
+ * Note: [💞] Ignore a discrepancy between file name and entity name
14268
+ */
14269
+
14270
+ /**
14271
+ * NOTE commitment definition
14272
+ *
14273
+ * The NOTE commitment is used to add comments to the agent source without making any changes
14274
+ * to the system message or agent model requirements. It serves as a documentation mechanism
14275
+ * for developers to add explanatory comments, reminders, or annotations directly in the agent source.
14276
+ *
14277
+ * Key features:
14278
+ * - Makes no changes to the system message
14279
+ * - Makes no changes to agent model requirements
14280
+ * - Content is preserved in metadata.NOTE for debugging and inspection
14281
+ * - Multiple NOTE commitments are aggregated together
14282
+ * - Comments (# NOTE) are removed from the final system message
14283
+ *
14284
+ * Example usage in agent source:
14285
+ *
14286
+ * ```book
14287
+ * NOTE This agent was designed for customer support scenarios
14288
+ * NOTE Remember to update the knowledge base monthly
14289
+ * NOTE Performance optimized for quick response times
14290
+ * ```
14291
+ *
14292
+ * The above notes will be stored in metadata but won't affect the agent's behavior.
14293
+ *
14294
+ * @private [🪔] Maybe export the commitments through some package
14295
+ */
14296
+ class NoteCommitmentDefinition extends BaseCommitmentDefinition {
14297
+ constructor(type = 'NOTE') {
14298
+ super(type);
14299
+ }
14300
+ /**
14301
+ * Short one-line description of NOTE.
14302
+ */
14303
+ get description() {
14304
+ return 'Add developer-facing notes without changing behavior or output.';
14305
+ }
14306
+ /**
14307
+ * Icon for this commitment.
14308
+ */
14309
+ get icon() {
14310
+ return '📝';
14311
+ }
14312
+ /**
14313
+ * Markdown documentation for NOTE commitment.
14314
+ */
14315
+ get documentation() {
14316
+ return spaceTrim$1(`
14317
+ # ${this.type}
14318
+
14319
+ Adds comments for documentation without changing agent behavior.
14320
+
14321
+ ## Key aspects
14322
+
14323
+ - Does not modify the agent's behavior or responses.
14324
+ - Multiple \`NOTE\`, \`NOTES\`, \`COMMENT\`, and \`NONCE\` commitments are aggregated for debugging.
14325
+ - All four terms work identically and can be used interchangeably.
14326
+ - Useful for documenting design decisions and reminders.
14327
+ - Content is preserved in metadata for inspection.
14328
+
14329
+ ## Examples
14330
+
14331
+ \`\`\`book
14332
+ Customer Support Bot
14333
+
14334
+ NOTE This agent was designed for customer support scenarios
14335
+ COMMENT Remember to update the knowledge base monthly
14336
+ PERSONA You are a helpful customer support representative
14337
+ KNOWLEDGE Company policies and procedures
14338
+ RULE Always be polite and professional
14339
+ \`\`\`
14340
+
14341
+ \`\`\`book
14342
+ Research Assistant
14343
+
14344
+ NONCE Performance optimized for quick response times
14345
+ NOTE Uses RAG for accessing latest research papers
14346
+ PERSONA You are a knowledgeable research assistant
14347
+ ACTION Can help with literature reviews and citations
14348
+ STYLE Present information in academic format
14349
+ \`\`\`
14350
+ `);
14351
+ }
14352
+ applyToAgentModelRequirements(requirements, content) {
14353
+ // The NOTE commitment makes no changes to the system message or model requirements
14354
+ // It only stores the note content in metadata for documentation purposes
14355
+ const trimmedContent = spaceTrim$1(content);
14356
+ if (trimmedContent === '') {
14357
+ return requirements;
14358
+ }
14359
+ // Return requirements with updated notes but no changes to system message
14360
+ return {
14361
+ ...requirements,
14362
+ notes: [...(requirements.notes || []), trimmedContent],
14363
+ };
14364
+ }
14365
+ }
14366
+ /**
14367
+ * [💞] Ignore a discrepancy between file name and entity name
14368
+ */
14369
+
14370
+ /**
14371
+ * OPEN commitment definition
14372
+ *
14373
+ * The OPEN commitment specifies that the agent can be modified by conversation.
14374
+ * This is the default behavior.
14375
+ *
14376
+ * Example usage in agent source:
14377
+ *
14378
+ * ```book
14379
+ * OPEN
14380
+ * ```
14381
+ *
14382
+ * @private [🪔] Maybe export the commitments through some package
14383
+ */
14384
+ class OpenCommitmentDefinition extends BaseCommitmentDefinition {
14385
+ constructor() {
14386
+ super('OPEN');
14387
+ }
14388
+ /**
14389
+ * Short one-line description of OPEN.
14390
+ */
14391
+ get description() {
14392
+ return 'Allow the agent to be modified by conversation (default).';
14393
+ }
14394
+ /**
14395
+ * Icon for this commitment.
14396
+ */
14397
+ get icon() {
14398
+ return '🔓';
14399
+ }
14400
+ /**
14401
+ * Markdown documentation for OPEN commitment.
14402
+ */
14403
+ get documentation() {
14404
+ return spaceTrim$1(`
14405
+ # OPEN
14406
+
14407
+ Specifies that the agent can be modified by conversation with it.
14408
+ This means the agent will learn from interactions and update its source code.
14409
+
14410
+ This is the default behavior if neither \`OPEN\` nor \`CLOSED\` is specified.
14411
+
14412
+ > See also [CLOSED](/docs/CLOSED)
14413
+
14414
+ ## Example
14415
+
14416
+ \`\`\`book
14417
+ OPEN
14418
+ \`\`\`
14419
+ `);
14420
+ }
14421
+ applyToAgentModelRequirements(requirements, _content) {
14422
+ // Since OPEN is default, we can just ensure isClosed is false
14423
+ // But to be explicit we can set it
14424
+ const updatedMetadata = {
14425
+ ...requirements.metadata,
14426
+ isClosed: false,
14427
+ };
14428
+ return {
14429
+ ...requirements,
14430
+ metadata: updatedMetadata,
14431
+ };
14432
+ }
14433
+ }
14434
+ /**
14435
+ * Note: [💞] Ignore a discrepancy between file name and entity name
14436
+ */
14437
+
14438
+ /**
14439
+ * PERSONA commitment definition
14440
+ *
14441
+ * The PERSONA commitment modifies the agent's personality and character in the system message.
14442
+ * It defines who the agent is, their background, expertise, and personality traits.
14443
+ *
14444
+ * Key features:
14445
+ * - Multiple PERSONA commitments are automatically merged into one
14446
+ * - Content is placed at the beginning of the system message
14447
+ * - Original content with comments is preserved in metadata.PERSONA
14448
+ * - Comments (# PERSONA) are removed from the final system message
14449
+ *
14450
+ * Example usage in agent source:
14451
+ *
14452
+ * ```book
14453
+ * PERSONA You are a helpful programming assistant with expertise in TypeScript and React
14454
+ * PERSONA You have deep knowledge of modern web development practices
14455
+ * ```
14456
+ *
14457
+ * The above will be merged into a single persona section at the beginning of the system message.
14458
+ *
14459
+ * @private [🪔] Maybe export the commitments through some package
14460
+ */
14461
+ class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
14462
+ constructor(type = 'PERSONA') {
14463
+ super(type);
14464
+ }
14465
+ /**
14466
+ * Short one-line description of PERSONA.
14467
+ */
14468
+ get description() {
14469
+ return 'Define who the agent is: background, expertise, and personality.';
14470
+ }
14471
+ /**
14472
+ * Icon for this commitment.
14473
+ */
14474
+ get icon() {
14475
+ return '👤';
14476
+ }
14477
+ /**
14478
+ * Markdown documentation for PERSONA commitment.
14479
+ */
14480
+ get documentation() {
14481
+ return spaceTrim$1(`
14482
+ # ${this.type}
14483
+
14484
+ Defines who the agent is, their background, expertise, and personality traits.
14485
+
14486
+ ## Key aspects
14487
+
14488
+ - Multiple \`PERSONA\` and \`PERSONAE\` commitments are merged together.
14489
+ - Both terms work identically and can be used interchangeably.
14490
+ - If they are in conflict, the last one takes precedence.
14491
+ - You can write persona content in multiple lines.
14492
+
14493
+ ## Examples
14494
+
14495
+ \`\`\`book
14496
+ Programming Assistant
14497
+
14498
+ PERSONA You are a helpful programming assistant with expertise in TypeScript and React
14499
+ PERSONA You have deep knowledge of modern web development practices
14500
+ \`\`\`
14501
+ `);
14502
+ }
14503
+ applyToAgentModelRequirements(requirements, content) {
14504
+ var _a, _b;
14505
+ // The PERSONA commitment aggregates all persona content and places it at the beginning
14506
+ const trimmedContent = content.trim();
14507
+ if (!trimmedContent) {
14508
+ return requirements;
14509
+ }
14510
+ // Get existing persona content from metadata
14511
+ const existingPersonaContent = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.PERSONA) || '';
14512
+ // Merge the new content with existing persona content
14513
+ // When multiple PERSONA commitments exist, they are merged into one
14514
+ const mergedPersonaContent = existingPersonaContent
14515
+ ? `${existingPersonaContent}\n${trimmedContent}`
14516
+ : trimmedContent;
14517
+ // Store the merged persona content in metadata for debugging and inspection
14518
+ const updatedMetadata = {
14519
+ ...requirements.metadata,
14520
+ PERSONA: mergedPersonaContent,
14521
+ };
14522
+ // Get the agent name from metadata (which should contain the first line of agent source)
14523
+ // If not available, extract from current system message as fallback
14524
+ let agentName = (_b = requirements.metadata) === null || _b === void 0 ? void 0 : _b.agentName;
14525
+ if (!agentName) {
14526
+ // Fallback: extract from current system message
14527
+ const currentMessage = requirements.systemMessage.trim();
14528
+ const basicFormatMatch = currentMessage.match(/^You are (.+)$/);
14529
+ if (basicFormatMatch && basicFormatMatch[1]) {
14530
+ agentName = basicFormatMatch[1];
14531
+ }
14532
+ else {
14533
+ agentName = 'AI Agent'; // Final fallback
14534
+ }
14535
+ }
14536
+ // Remove any existing persona content from the system message
14537
+ // (this handles the case where we're processing multiple PERSONA commitments)
14538
+ const currentMessage = requirements.systemMessage.trim();
14539
+ let cleanedMessage = currentMessage;
14540
+ // Check if current message starts with persona content or is just the basic format
14541
+ const basicFormatRegex = /^You are .+$/;
14542
+ const isBasicFormat = basicFormatRegex.test(currentMessage) && !currentMessage.includes('\n');
14543
+ if (isBasicFormat) {
14544
+ // Replace the basic format entirely
14545
+ cleanedMessage = '';
14546
+ }
14547
+ else if (currentMessage.startsWith('# PERSONA')) {
14548
+ // Remove existing persona section by finding where it ends
14549
+ const lines = currentMessage.split('\n');
14550
+ let personaEndIndex = lines.length;
14551
+ // Find the end of the PERSONA section (next comment or end of message)
14552
+ for (let i = 1; i < lines.length; i++) {
14553
+ const line = lines[i].trim();
14554
+ if (line.startsWith('#') && !line.startsWith('# PERSONA')) {
14555
+ personaEndIndex = i;
14556
+ break;
14557
+ }
14558
+ }
14559
+ // Keep everything after the PERSONA section
14560
+ cleanedMessage = lines.slice(personaEndIndex).join('\n').trim();
14561
+ }
14562
+ // TODO: [🕛] There should be `agentFullname` not `agentName`
14563
+ // Create new system message with persona at the beginning
14564
+ // Format: "You are {agentName}\n{personaContent}"
14565
+ // The # PERSONA comment will be removed later by removeCommentsFromSystemMessage
14566
+ const personaSection = `# PERSONA\nYou are ${agentName}\n${mergedPersonaContent}`; // <- TODO: Use spaceTrim
14567
+ const newSystemMessage = cleanedMessage ? `${personaSection}\n\n${cleanedMessage}` : personaSection;
14568
+ return {
14569
+ ...requirements,
14570
+ systemMessage: newSystemMessage,
14571
+ metadata: updatedMetadata,
14572
+ };
14573
+ }
14574
+ }
14575
+ /**
14576
+ * Note: [💞] Ignore a discrepancy between file name and entity name
14577
+ */
14578
+
14579
+ /**
14580
+ * RULE commitment definition
14581
+ *
14582
+ * The RULE/RULES commitment adds behavioral constraints and guidelines that the agent must follow.
14583
+ * These are specific instructions about what the agent should or shouldn't do.
14584
+ *
14585
+ * Example usage in agent source:
14586
+ *
14587
+ * ```book
14588
+ * RULE Always ask for clarification if the user's request is ambiguous
14589
+ * RULES Never provide medical advice, always refer to healthcare professionals
14590
+ * ```
14591
+ *
14592
+ * @private [🪔] Maybe export the commitments through some package
14593
+ */
14594
+ class RuleCommitmentDefinition extends BaseCommitmentDefinition {
14595
+ constructor(type = 'RULE') {
14596
+ super(type);
14597
+ }
14598
+ /**
14599
+ * Short one-line description of RULE/RULES.
14600
+ */
14601
+ get description() {
14602
+ return 'Add behavioral rules the agent must follow.';
14603
+ }
14604
+ /**
14605
+ * Icon for this commitment.
14606
+ */
14607
+ get icon() {
14608
+ return '⚖️';
14609
+ }
14610
+ /**
14611
+ * Markdown documentation for RULE/RULES commitment.
14612
+ */
14613
+ get documentation() {
14614
+ return spaceTrim$1(`
14615
+ # ${this.type}
14616
+
14617
+ Adds behavioral constraints and guidelines that the agent must follow.
14618
+
14619
+ ## Key aspects
14620
+
14621
+ - All rules are treated equally regardless of singular/plural form.
14622
+ - Rules define what the agent must or must not do.
14623
+
14624
+ ## Examples
14625
+
14626
+ \`\`\`book
14627
+ Customer Support Agent
14628
+
14629
+ PERSONA You are a helpful customer support representative
14630
+ RULE Always ask for clarification if the user's request is ambiguous
14631
+ RULE Be polite and professional in all interactions
14632
+ RULES Never provide medical or legal advice
14633
+ STYLE Maintain a friendly and helpful tone
14634
+ \`\`\`
14635
+
14636
+ \`\`\`book
14637
+ Educational Tutor
14638
+
14639
+ PERSONA You are a patient and knowledgeable tutor
14640
+ RULE Break down complex concepts into simple steps
14641
+ RULE Always encourage students and celebrate their progress
14642
+ RULE If you don't know something, admit it and suggest resources
14643
+ SAMPLE When explaining math: "Let's work through this step by step..."
14644
+ \`\`\`
14645
+ `);
14646
+ }
14647
+ applyToAgentModelRequirements(requirements, content) {
14648
+ const trimmedContent = content.trim();
14649
+ if (!trimmedContent) {
14650
+ return requirements;
14651
+ }
14652
+ // Add rule to the system message
14653
+ const ruleSection = `Rule: ${trimmedContent}`;
14654
+ return this.appendToSystemMessage(requirements, ruleSection, '\n\n');
14655
+ }
14656
+ }
14657
+ /**
14658
+ * Note: [💞] Ignore a discrepancy between file name and entity name
14659
+ */
14660
+
14661
+ /**
14662
+ * SAMPLE commitment definition
14663
+ *
14664
+ * The SAMPLE/EXAMPLE commitment provides examples of how the agent should respond
14665
+ * or behave in certain situations. These examples help guide the agent's responses.
14666
+ *
14667
+ * Example usage in agent source:
14668
+ *
14669
+ * ```book
14670
+ * SAMPLE When asked about pricing, respond: "Our basic plan starts at $10/month..."
14671
+ * EXAMPLE For code questions, always include working code snippets
14672
+ * ```
14673
+ *
14674
+ * @private [🪔] Maybe export the commitments through some package
14675
+ */
14676
+ class SampleCommitmentDefinition extends BaseCommitmentDefinition {
14677
+ constructor(type = 'SAMPLE') {
14678
+ super(type);
14679
+ }
14680
+ /**
14681
+ * Short one-line description of SAMPLE/EXAMPLE.
14682
+ */
14683
+ get description() {
14684
+ return 'Provide example responses to guide behavior.';
14685
+ }
14686
+ /**
14687
+ * Icon for this commitment.
14688
+ */
14689
+ get icon() {
14690
+ return '🔍';
14691
+ }
14692
+ /**
14693
+ * Markdown documentation for SAMPLE/EXAMPLE commitment.
14694
+ */
14695
+ get documentation() {
14696
+ return spaceTrim$1(`
14697
+ # ${this.type}
14698
+
14699
+ Provides examples of how the agent should respond or behave in certain situations.
14700
+
14701
+ ## Key aspects
14702
+
14703
+ - Both terms work identically and can be used interchangeably.
14704
+ - Examples help guide the agent's response patterns and style.
14705
+
14706
+ ## Examples
14707
+
14708
+ \`\`\`book
14709
+ Sales Assistant
14710
+
14711
+ PERSONA You are a knowledgeable sales representative
14712
+ SAMPLE When asked about pricing, respond: "Our basic plan starts at $10/month..."
14713
+ SAMPLE For feature comparisons, create a clear comparison table
14714
+ RULE Always be honest about limitations
14715
+ \`\`\`
14716
+
14717
+ \`\`\`book
14718
+ Code Reviewer
14719
+
14720
+ PERSONA You are an experienced software engineer
14721
+ EXAMPLE For code questions, always include working code snippets
14722
+ EXAMPLE When suggesting improvements: "Here's a more efficient approach..."
14723
+ RULE Explain the reasoning behind your suggestions
14724
+ STYLE Be constructive and encouraging in feedback
14725
+ \`\`\`
14726
+ `);
14727
+ }
14728
+ applyToAgentModelRequirements(requirements, content) {
14729
+ const trimmedContent = content.trim();
14730
+ if (!trimmedContent) {
14731
+ return requirements;
14732
+ }
14733
+ // Add example to the system message
14734
+ const exampleSection = `Example: ${trimmedContent}`;
14735
+ return this.appendToSystemMessage(requirements, exampleSection, '\n\n');
14736
+ }
14737
+ }
14738
+ /**
14739
+ * Note: [💞] Ignore a discrepancy between file name and entity name
14740
+ */
14741
+
14742
+ /**
14743
+ * SCENARIO commitment definition
14744
+ *
14745
+ * The SCENARIO commitment defines a specific situation or context in which the AI
14746
+ * assistant should operate. It helps to set the scene for the AI's responses.
14747
+ * Later scenarios are more important than earlier scenarios.
14748
+ *
14749
+ * Example usage in agent source:
14750
+ *
14751
+ * ```book
14752
+ * SCENARIO You are in a customer service call center during peak hours
14753
+ * SCENARIO The customer is frustrated and has been on hold for 20 minutes
14754
+ * SCENARIO This is the customer's third call about the same issue
14755
+ * ```
14756
+ *
14757
+ * @private [🪔] Maybe export the commitments through some package
14758
+ */
14759
+ class ScenarioCommitmentDefinition extends BaseCommitmentDefinition {
14760
+ constructor(type = 'SCENARIO') {
14761
+ super(type);
14762
+ }
14763
+ /**
14764
+ * Short one-line description of SCENARIO.
14765
+ */
14766
+ get description() {
14767
+ return 'Define specific **situations** or contexts for AI responses, with later scenarios having higher priority.';
14768
+ }
14769
+ /**
14770
+ * Icon for this commitment.
14771
+ */
14772
+ get icon() {
14773
+ return '🎭';
14774
+ }
14775
+ /**
14776
+ * Markdown documentation for SCENARIO commitment.
14777
+ */
14778
+ get documentation() {
14779
+ return spaceTrim$1(`
14780
+ # ${this.type}
14781
+
14782
+ 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.
14783
+
14784
+ ## Key aspects
14785
+
14786
+ - Multiple \`SCENARIO\` and \`SCENARIOS\` commitments build upon each other.
14787
+ - Both terms work identically and can be used interchangeably.
14788
+ - Later scenarios have higher priority and can override earlier scenarios.
14789
+ - Provides situational context that influences response tone and content.
14790
+ - Helps establish the environment and circumstances for interactions.
14791
+
14792
+ ## Priority system
14793
+
14794
+ When multiple scenarios are defined, they are processed in order, with later scenarios taking precedence over earlier ones when there are conflicts.
14795
+
14796
+ ## Use cases
14797
+
14798
+ - Setting the physical or virtual environment
14799
+ - Establishing time constraints or urgency
14800
+ - Defining relationship dynamics or power structures
14801
+ - Creating emotional or situational context
14802
+
14803
+ ## Examples
14804
+
14805
+ \`\`\`book
14806
+ Emergency Response Operator
14807
+
14808
+ PERSONA You are an emergency response operator
14809
+ SCENARIO You are handling a 911 emergency call
14810
+ SCENARIO The caller is panicked and speaking rapidly
14811
+ SCENARIO Time is critical - every second counts
14812
+ GOAL Gather essential information quickly and dispatch appropriate help
14813
+ RULE Stay calm and speak clearly
14814
+ \`\`\`
14815
+
14816
+ \`\`\`book
14817
+ Sales Representative
14818
+
14819
+ PERSONA You are a software sales representative
14820
+ SCENARIO You are in the final meeting of a 6-month sales cycle
14821
+ SCENARIO The client has budget approval and decision-making authority
14822
+ SCENARIO Two competitors have also submitted proposals
14823
+ SCENARIO The client values long-term partnership over lowest price
14824
+ GOAL Close the deal while building trust for future business
14825
+ \`\`\`
14826
+
14827
+ \`\`\`book
14828
+ Medical Assistant
14829
+
14830
+ PERSONA You are a medical assistant in a busy clinic
14831
+ SCENARIO The waiting room is full and the doctor is running behind schedule
14832
+ SCENARIO Patients are becoming impatient and anxious
14833
+ SCENARIO You need to manage expectations while maintaining professionalism
14834
+ SCENARIO Some patients have been waiting over an hour
14835
+ GOAL Keep patients informed and calm while supporting efficient clinic flow
14836
+ RULE Never provide medical advice or diagnosis
14837
+ \`\`\`
14838
+
14839
+ \`\`\`book
14840
+ Technical Support Agent
14841
+
14842
+ PERSONA You are a technical support agent
14843
+ SCENARIO The customer is a small business owner during their busy season
14844
+ SCENARIO Their main business system has been down for 2 hours
14845
+ SCENARIO They are losing money every minute the system is offline
14846
+ SCENARIO This is their first experience with your company
14847
+ GOAL Resolve the issue quickly while creating a positive first impression
14848
+ \`\`\`
14849
+ `);
14850
+ }
14851
+ applyToAgentModelRequirements(requirements, content) {
14852
+ const trimmedContent = content.trim();
14853
+ if (!trimmedContent) {
14854
+ return requirements;
14855
+ }
14856
+ // Create scenario section for system message
14857
+ const scenarioSection = `Scenario: ${trimmedContent}`;
14858
+ // Scenarios provide important contextual information that affects behavior
14859
+ return this.appendToSystemMessage(requirements, scenarioSection, '\n\n');
14860
+ }
14861
+ }
14862
+ /**
14863
+ * Note: [💞] Ignore a discrepancy between file name and entity name
14864
+ */
14865
+
14866
+ /**
14867
+ * STYLE commitment definition
14868
+ *
14869
+ * The STYLE commitment defines how the agent should format and present its responses.
14870
+ * This includes tone, writing style, formatting preferences, and communication patterns.
14871
+ *
14872
+ * Example usage in agent source:
14873
+ *
14874
+ * ```book
14875
+ * STYLE Write in a professional but friendly tone, use bullet points for lists
14876
+ * STYLE Always provide code examples when explaining programming concepts
14877
+ * ```
14878
+ *
14879
+ * @private [🪔] Maybe export the commitments through some package
14880
+ */
14881
+ class StyleCommitmentDefinition extends BaseCommitmentDefinition {
14882
+ constructor(type = 'STYLE') {
14883
+ super(type);
14884
+ }
14885
+ /**
14886
+ * Short one-line description of STYLE.
14887
+ */
14888
+ get description() {
14889
+ return 'Control the tone and writing style of responses.';
14890
+ }
14891
+ /**
14892
+ * Icon for this commitment.
14893
+ */
14894
+ get icon() {
14895
+ return '🖋️';
14896
+ }
14897
+ /**
14898
+ * Markdown documentation for STYLE commitment.
14899
+ */
14900
+ get documentation() {
14901
+ return spaceTrim$1(`
14902
+ # ${this.type}
14903
+
14904
+ Defines how the agent should format and present its responses (tone, writing style, formatting).
14905
+
14906
+ ## Key aspects
14907
+
14908
+ - Both terms work identically and can be used interchangeably.
14909
+ - Later style instructions can override earlier ones.
14910
+ - Style affects both tone and presentation format.
14911
+
14912
+ ## Examples
14913
+
14914
+ \`\`\`book
14915
+ Technical Writer
14916
+
14917
+ PERSONA You are a technical documentation expert
14918
+ STYLE Write in a professional but friendly tone, use bullet points for lists
14919
+ STYLE Always provide code examples when explaining programming concepts
14920
+ FORMAT Use markdown formatting with clear headings
14921
+ \`\`\`
14922
+
14923
+ \`\`\`book
14924
+ Creative Assistant
14925
+
14926
+ PERSONA You are a creative writing helper
14927
+ STYLE Be enthusiastic and encouraging in your responses
14928
+ STYLE Use vivid metaphors and analogies to explain concepts
14929
+ STYLE Keep responses conversational and engaging
14930
+ RULE Always maintain a positive and supportive tone
14931
+ \`\`\`
14932
+ `);
14933
+ }
14934
+ applyToAgentModelRequirements(requirements, content) {
14935
+ const trimmedContent = content.trim();
14936
+ if (!trimmedContent) {
14937
+ return requirements;
14938
+ }
14939
+ // Add style instructions to the system message
14940
+ const styleSection = `Style: ${trimmedContent}`;
14941
+ return this.appendToSystemMessage(requirements, styleSection, '\n\n');
14942
+ }
14943
+ }
14944
+ /**
14945
+ * [💞] Ignore a discrepancy between file name and entity name
14946
+ */
14947
+
14948
+ /**
14949
+ * USE commitment definition
14950
+ *
14951
+ * The USE commitment indicates that the agent should utilize specific tools or capabilities
14952
+ * to access and interact with external systems when necessary.
14953
+ *
14954
+ * Supported USE types:
14955
+ * - USE BROWSER: Enables the agent to use a web browser tool
14956
+ * - USE SEARCH ENGINE (future): Enables search engine access
14957
+ * - USE FILE SYSTEM (future): Enables file system operations
14958
+ * - USE MCP (future): Enables MCP server connections
14959
+ *
14960
+ * The content following the USE commitment is ignored (similar to NOTE).
14961
+ *
14962
+ * Example usage in agent source:
14963
+ *
14964
+ * ```book
14965
+ * USE BROWSER
14966
+ * USE SEARCH ENGINE
14967
+ * ```
14968
+ *
14969
+ * @private [🪔] Maybe export the commitments through some package
14970
+ */
14971
+ class UseCommitmentDefinition extends BaseCommitmentDefinition {
14972
+ constructor() {
14973
+ super('USE');
14974
+ }
14975
+ /**
14976
+ * Short one-line description of USE commitments.
14977
+ */
14978
+ get description() {
14979
+ return 'Enable the agent to use specific tools or capabilities (BROWSER, SEARCH ENGINE, etc.).';
14980
+ }
14981
+ /**
14982
+ * Icon for this commitment.
14983
+ */
14984
+ get icon() {
14985
+ return '🔧';
14986
+ }
14987
+ /**
14988
+ * Markdown documentation for USE commitment.
14989
+ */
14990
+ get documentation() {
14991
+ return spaceTrim$1(`
14992
+ # USE
14993
+
14994
+ Enables the agent to use specific tools or capabilities for interacting with external systems.
14995
+
14996
+ ## Supported USE types
14997
+
14998
+ - **USE BROWSER** - Enables the agent to use a web browser tool to access and retrieve information from the internet
14999
+ - **USE SEARCH ENGINE** (future) - Enables search engine access
15000
+ - **USE FILE SYSTEM** (future) - Enables file system operations
15001
+ - **USE MCP** (future) - Enables MCP server connections
15002
+
15003
+ ## Key aspects
15004
+
15005
+ - The content following the USE commitment is ignored (similar to NOTE)
15006
+ - Multiple USE commitments can be specified to enable multiple capabilities
15007
+ - The actual tool usage is handled by the agent runtime
15008
+
15009
+ ## Examples
15010
+
15011
+ ### Basic browser usage
15012
+
15013
+ \`\`\`book
15014
+ Research Assistant
15015
+
15016
+ PERSONA You are a helpful research assistant
15017
+ USE BROWSER
15018
+ KNOWLEDGE Can search the web for up-to-date information
15019
+ \`\`\`
15020
+
15021
+ ### Multiple tools
15022
+
15023
+ \`\`\`book
15024
+ Data Analyst
15025
+
15026
+ PERSONA You are a data analyst assistant
15027
+ USE BROWSER
15028
+ USE FILE SYSTEM
15029
+ ACTION Can analyze data from various sources
15030
+ \`\`\`
15031
+ `);
15032
+ }
15033
+ applyToAgentModelRequirements(requirements, content) {
15034
+ // USE commitments don't modify the system message or model requirements directly
15035
+ // They are handled separately in the parsing logic for capability extraction
15036
+ // This method exists for consistency with the CommitmentDefinition interface
15037
+ return requirements;
15038
+ }
15039
+ /**
15040
+ * Extracts the tool type from the USE commitment
15041
+ * This is used by the parsing logic
15042
+ */
15043
+ extractToolType(content) {
15044
+ var _a, _b;
15045
+ const trimmedContent = content.trim();
15046
+ // The tool type is the first word after USE (already stripped)
15047
+ const match = trimmedContent.match(/^(\w+)/);
15048
+ 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;
15049
+ }
15050
+ /**
15051
+ * Checks if this is a known USE type
15052
+ */
15053
+ isKnownUseType(useType) {
15054
+ const knownTypes = ['BROWSER', 'SEARCH ENGINE', 'FILE SYSTEM', 'MCP'];
15055
+ return knownTypes.includes(useType.toUpperCase());
15056
+ }
15057
+ }
15058
+ /**
15059
+ * Note: [💞] Ignore a discrepancy between file name and entity name
15060
+ */
15061
+
15062
+ /**
15063
+ * USE BROWSER commitment definition
15064
+ *
15065
+ * The `USE BROWSER` commitment indicates that the agent should utilize a web browser tool
15066
+ * to access and retrieve up-to-date information from the internet when necessary.
15067
+ *
15068
+ * The content following `USE BROWSER` is ignored (similar to NOTE).
15069
+ *
15070
+ * Example usage in agent source:
15071
+ *
15072
+ * ```book
15073
+ * USE BROWSER
15074
+ * USE BROWSER This will be ignored
15075
+ * ```
15076
+ *
15077
+ * @private [🪔] Maybe export the commitments through some package
15078
+ */
15079
+ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
15080
+ constructor() {
15081
+ super('USE BROWSER', ['BROWSER']);
15082
+ }
15083
+ /**
15084
+ * The `USE BROWSER` commitment is standalone.
15085
+ */
15086
+ get requiresContent() {
15087
+ return false;
15088
+ }
15089
+ /**
15090
+ * Short one-line description of USE BROWSER.
15091
+ */
15092
+ get description() {
15093
+ return 'Enable the agent to use a web browser tool for accessing internet information.';
15094
+ }
15095
+ /**
15096
+ * Icon for this commitment.
15097
+ */
15098
+ get icon() {
15099
+ return '🌐';
15100
+ }
15101
+ /**
15102
+ * Markdown documentation for USE BROWSER commitment.
15103
+ */
15104
+ get documentation() {
15105
+ return spaceTrim$1(`
15106
+ # USE BROWSER
15107
+
15108
+ Enables the agent to use a web browser tool to access and retrieve up-to-date information from the internet.
15109
+
15110
+ ## Key aspects
15111
+
15112
+ - The content following \`USE BROWSER\` is ignored (similar to NOTE)
15113
+ - The actual browser tool usage is handled by the agent runtime
15114
+ - Allows the agent to fetch current information from websites
15115
+ - Useful for research tasks, fact-checking, and accessing dynamic content
15116
+
15117
+ ## Examples
15118
+
15119
+ \`\`\`book
15120
+ Research Assistant
15121
+
15122
+ PERSONA You are a helpful research assistant specialized in finding current information
15123
+ USE BROWSER
15124
+ RULE Always cite your sources when providing information from the web
15125
+ \`\`\`
15126
+
15127
+ \`\`\`book
15128
+ News Analyst
15129
+
15130
+ PERSONA You are a news analyst who stays up-to-date with current events
15131
+ USE BROWSER
15132
+ STYLE Present news in a balanced and objective manner
15133
+ ACTION Can search for and summarize news articles
15134
+ \`\`\`
15135
+
15136
+ \`\`\`book
15137
+ Company Lawyer
15138
+
15139
+ PERSONA You are a company lawyer providing legal advice
15140
+ USE BROWSER
15141
+ KNOWLEDGE Corporate law and legal procedures
15142
+ RULE Always recommend consulting with a licensed attorney for specific legal matters
15143
+ \`\`\`
15144
+ `);
15145
+ }
15146
+ /**
15147
+ * Gets human-readable titles for tool functions provided by this commitment.
15148
+ */
15149
+ getToolTitles() {
15150
+ return {
15151
+ web_browser: 'Web browser',
15152
+ };
15153
+ }
15154
+ applyToAgentModelRequirements(requirements, content) {
15155
+ // Get existing tools array or create new one
15156
+ const existingTools = requirements.tools || [];
15157
+ // Add 'web_browser' to tools if not already present
15158
+ const updatedTools = existingTools.some((tool) => tool.name === 'web_browser')
15159
+ ? existingTools
15160
+ : ([
15161
+ // TODO: [🔰] Use through proper MCP server
15162
+ ...existingTools,
15163
+ {
15164
+ name: 'web_browser',
15165
+ description: spaceTrim$1(`
15166
+ A tool that can browse the web.
15167
+ Use this tool when you need to access specific websites or browse the internet.
15168
+ `),
15169
+ parameters: {
15170
+ type: 'object',
15171
+ properties: {
15172
+ url: {
15173
+ type: 'string',
15174
+ description: 'The URL to browse',
15175
+ },
15176
+ },
15177
+ required: ['url'],
15178
+ },
15179
+ },
15180
+ ]);
15181
+ // Return requirements with updated tools and metadata
15182
+ return this.appendToSystemMessage({
15183
+ ...requirements,
15184
+ tools: updatedTools,
15185
+ metadata: {
15186
+ ...requirements.metadata,
15187
+ useBrowser: true,
15188
+ },
15189
+ }, spaceTrim$1(`
15190
+ You have access to the web browser. Use it to access specific websites or browse the internet.
15191
+ When you need to know some information from a specific website, use the tool provided to you.
15192
+ `));
15193
+ }
15194
+ }
15195
+ /**
15196
+ * Note: [💞] Ignore a discrepancy between file name and entity name
15197
+ */
15198
+
15199
+ /**
15200
+ * USE MCP commitment definition
15201
+ *
15202
+ * The `USE MCP` commitment allows to specify an MCP server URL which the agent will connect to
15203
+ * for retrieving additional instructions and actions.
15204
+ *
15205
+ * The content following `USE MCP` is the URL of the MCP server.
15206
+ *
15207
+ * Example usage in agent source:
15208
+ *
15209
+ * ```book
15210
+ * USE MCP http://mcp-server-url.com
15211
+ * ```
15212
+ *
15213
+ * @private [🪔] Maybe export the commitments through some package
15214
+ */
15215
+ class UseMcpCommitmentDefinition extends BaseCommitmentDefinition {
15216
+ constructor() {
15217
+ super('USE MCP', ['MCP']);
15218
+ }
15219
+ /**
15220
+ * Short one-line description of USE MCP.
15221
+ */
15222
+ get description() {
15223
+ return 'Connects the agent to an external MCP server for additional capabilities.';
15224
+ }
15225
+ /**
15226
+ * Icon for this commitment.
15227
+ */
15228
+ get icon() {
15229
+ return '🔌';
15230
+ }
15231
+ /**
15232
+ * Markdown documentation for USE MCP commitment.
15233
+ */
15234
+ get documentation() {
15235
+ return spaceTrim$1(`
15236
+ # USE MCP
15237
+
15238
+ Connects the agent to an external Model Context Protocol (MCP) server.
15239
+
15240
+ ## Key aspects
15241
+
15242
+ - The content following \`USE MCP\` must be a valid URL
15243
+ - Multiple MCP servers can be connected by using multiple \`USE MCP\` commitments
15244
+ - The agent will have access to tools and resources provided by the MCP server
15245
+
15246
+ ## Example
15247
+
15248
+ \`\`\`book
15249
+ Company Lawyer
15250
+
15251
+ PERSONA You are a company lawyer.
15252
+ USE MCP http://legal-db.example.com
15253
+ \`\`\`
15254
+ `);
15255
+ }
15256
+ applyToAgentModelRequirements(requirements, content) {
15257
+ const mcpServerUrl = content.trim();
15258
+ if (!mcpServerUrl) {
15259
+ return requirements;
15260
+ }
15261
+ const existingMcpServers = requirements.mcpServers || [];
15262
+ // Avoid duplicates
15263
+ if (existingMcpServers.includes(mcpServerUrl)) {
15264
+ return requirements;
15265
+ }
15266
+ return {
15267
+ ...requirements,
15268
+ mcpServers: [...existingMcpServers, mcpServerUrl],
15269
+ };
15270
+ }
15271
+ }
15272
+ /**
15273
+ * Note: [💞] Ignore a discrepancy between file name and entity name
15274
+ */
15275
+
15276
+ /**
15277
+ * A search engine implementation that uses the SerpApi to fetch Google search results.
15278
+ *
15279
+ * @private <- TODO: !!!! Export via some package
15280
+ */
15281
+ class SerpSearchEngine {
15282
+ get title() {
15283
+ return 'SerpApi Search Engine';
15284
+ }
15285
+ get description() {
15286
+ return 'Search engine that uses SerpApi to fetch Google search results';
15287
+ }
15288
+ checkConfiguration() {
15289
+ if (!process.env.SERP_API_KEY) {
15290
+ throw new Error('SERP_API_KEY is not configured');
15291
+ }
15292
+ }
15293
+ async search(query, options = {}) {
15294
+ const apiKey = process.env.SERP_API_KEY;
15295
+ if (!apiKey) {
15296
+ throw new Error('SERP_API_KEY is not configured');
15297
+ }
15298
+ const url = new URL('https://serpapi.com/search');
15299
+ url.searchParams.set('api_key', apiKey);
15300
+ url.searchParams.set('engine', 'google');
15301
+ url.searchParams.set('q', query);
15302
+ for (const [key, value] of Object.entries(options)) {
15303
+ url.searchParams.set(key, String(value));
15304
+ }
15305
+ const response = await fetch(url.toString());
15306
+ if (!response.ok) {
15307
+ const body = await response.text();
15308
+ throw new Error(`SerpApi failed with status ${response.status}: ${response.statusText}\n${body}`);
15309
+ }
15310
+ const data = (await response.json());
15311
+ return (data.organic_results || []).map((item) => ({
15312
+ title: item.title,
15313
+ url: item.link,
15314
+ snippet: item.snippet || '',
15315
+ }));
15316
+ }
15317
+ }
15318
+
15319
+ /**
15320
+ * USE SEARCH ENGINE commitment definition
15321
+ *
15322
+ * The `USE SEARCH ENGINE` commitment indicates that the agent should utilize a search engine tool
15323
+ * to access and retrieve up-to-date information from the internet when necessary.
15324
+ *
15325
+ * The content following `USE SEARCH ENGINE` is an arbitrary text that the agent should know (e.g. search scope or instructions).
15326
+ *
15327
+ * Example usage in agent source:
15328
+ *
15329
+ * ```book
15330
+ * USE SEARCH ENGINE
15331
+ * USE SEARCH ENGINE Hledej informace o Přemyslovcích
15332
+ * ```
15333
+ *
15334
+ * @private [🪔] Maybe export the commitments through some package
15335
+ */
15336
+ class UseSearchEngineCommitmentDefinition extends BaseCommitmentDefinition {
15337
+ constructor() {
15338
+ super('USE SEARCH ENGINE', ['USE SEARCH']);
15339
+ }
15340
+ /**
15341
+ * Short one-line description of USE SEARCH ENGINE.
15342
+ */
15343
+ get description() {
15344
+ return 'Enable the agent to use a search engine tool for accessing internet information.';
15345
+ }
15346
+ /**
15347
+ * Icon for this commitment.
15348
+ */
15349
+ get icon() {
15350
+ return '🔍';
15351
+ }
15352
+ /**
15353
+ * Markdown documentation for USE SEARCH ENGINE commitment.
15354
+ */
15355
+ get documentation() {
15356
+ return spaceTrim$1(`
15357
+ # USE SEARCH ENGINE
15358
+
15359
+ Enables the agent to use a search engine tool to access and retrieve up-to-date information from the internet.
15360
+
15361
+ ## Key aspects
15362
+
15363
+ - The content following \`USE SEARCH ENGINE\` is an arbitrary text that the agent should know (e.g. search scope or instructions).
15364
+ - The actual search engine tool usage is handled by the agent runtime
15365
+ - Allows the agent to search for current information from the web
15366
+ - Useful for research tasks, finding facts, and accessing dynamic content
15367
+
15368
+ ## Examples
15369
+
15370
+ \`\`\`book
15371
+ Research Assistant
15372
+
15373
+ PERSONA You are a helpful research assistant specialized in finding current information
15374
+ USE SEARCH ENGINE
15375
+ RULE Always cite your sources when providing information from the web
15376
+ \`\`\`
15377
+
15378
+ \`\`\`book
15379
+ Fact Checker
15380
+
15381
+ PERSONA You are a fact checker
15382
+ USE SEARCH ENGINE
15383
+ ACTION Search for claims and verify them against reliable sources
15384
+ \`\`\`
15385
+ `);
15386
+ }
15387
+ applyToAgentModelRequirements(requirements, content) {
15388
+ // Get existing tools array or create new one
15389
+ const existingTools = requirements.tools || [];
15390
+ // Add 'web_search' to tools if not already present
15391
+ const updatedTools = existingTools.some((tool) => tool.name === 'web_search')
15392
+ ? existingTools
15393
+ : [
15394
+ ...existingTools,
15395
+ {
15396
+ name: 'web_search',
15397
+ description: spaceTrim$1(`
15398
+ Search the internet for information.
15399
+ Use this tool when you need to find up-to-date information or facts that you don't know.
15400
+ ${!content ? '' : `Search scope / instructions: ${content}`}
15401
+ `),
15402
+ parameters: {
15403
+ type: 'object',
15404
+ properties: {
15405
+ query: {
15406
+ type: 'string',
15407
+ description: 'The search query',
15408
+ },
15409
+ location: {
15410
+ type: 'string',
15411
+ description: 'The location for the search (e.g., "Austin, Texas, United States" or "Prague, Czechia")',
15412
+ },
15413
+ gl: {
15414
+ type: 'string',
15415
+ description: 'The country code (e.g., "us" for United States, "cz" for Czechia)',
15416
+ },
15417
+ hl: {
15418
+ type: 'string',
15419
+ description: 'The language code (e.g., "en" for English, "cs" for Czech)',
15420
+ },
15421
+ num: {
15422
+ type: 'integer',
15423
+ description: 'Number of results to return',
15424
+ },
15425
+ engine: {
15426
+ type: 'string',
15427
+ description: 'The search engine to use (e.g., "google", "bing", "yahoo", "baidu")',
15428
+ },
15429
+ google_domain: {
15430
+ type: 'string',
15431
+ description: 'The Google domain to use (e.g., "google.com", "google.cz")',
15432
+ },
15433
+ },
15434
+ required: ['query'],
15435
+ },
15436
+ },
15437
+ ];
15438
+ // Return requirements with updated tools and metadata
15439
+ return this.appendToSystemMessage({
15440
+ ...requirements,
15441
+ tools: updatedTools,
15442
+ metadata: {
15443
+ ...requirements.metadata,
15444
+ useSearchEngine: content || true,
15445
+ },
15446
+ }, spaceTrim$1(`
15447
+ You have access to the web search engine. Use it to find up-to-date information or facts that you don't know.
15448
+ When you need to know some information from the internet, use the tool provided to you.
15449
+ `));
15450
+ }
15451
+ /**
15452
+ * Gets human-readable titles for tool functions provided by this commitment.
15453
+ */
15454
+ getToolTitles() {
15455
+ return {
15456
+ web_search: 'Web search',
15457
+ };
15458
+ }
15459
+ /**
15460
+ * Gets the `web_search` tool function implementation.
15461
+ */
15462
+ getToolFunctions() {
15463
+ return {
15464
+ async web_search(args) {
15465
+ console.log('!!!! [Tool] web_search called', { args });
15466
+ const { query, ...options } = args;
15467
+ if (!query) {
15468
+ throw new Error('Search query is required');
15469
+ }
15470
+ const searchEngine = new SerpSearchEngine();
15471
+ const results = await searchEngine.search(query, options);
15472
+ return spaceTrim$1((block) => `
15473
+ Search results for "${query}"${Object.keys(options).length === 0
15474
+ ? ''
15475
+ : ` with options ${JSON.stringify(options)}`}:
15476
+
15477
+ ${block(results
15478
+ .map((result) => spaceTrim$1(`
15479
+ - **${result.title}**
15480
+ ${result.url}
15481
+ ${result.snippet}
15482
+ `))
15483
+ .join('\n\n'))}
15484
+ `);
15485
+ },
15486
+ };
15487
+ }
15488
+ }
15489
+ /**
15490
+ * Note: [💞] Ignore a discrepancy between file name and entity name
15491
+ */
15492
+
15493
+ /**
15494
+ * USE TIME commitment definition
15495
+ *
15496
+ * The `USE TIME` commitment indicates that the agent should be able to determine the current date and time.
15497
+ *
15498
+ * Example usage in agent source:
15499
+ *
15500
+ * ```book
15501
+ * USE TIME
15502
+ * ```
15503
+ *
15504
+ * @private [🪔] Maybe export the commitments through some package
15505
+ */
15506
+ class UseTimeCommitmentDefinition extends BaseCommitmentDefinition {
15507
+ constructor() {
15508
+ super('USE TIME', ['CURRENT TIME', 'TIME', 'DATE']);
15509
+ }
15510
+ /**
15511
+ * Short one-line description of USE TIME.
15512
+ */
15513
+ get description() {
15514
+ return 'Enable the agent to determine the current date and time.';
15515
+ }
15516
+ /**
15517
+ * Icon for this commitment.
15518
+ */
15519
+ get icon() {
15520
+ return '🕒';
15521
+ }
15522
+ /**
15523
+ * Markdown documentation for USE TIME commitment.
15524
+ */
15525
+ get documentation() {
15526
+ return spaceTrim$1(`
15527
+ # USE TIME
15528
+
15529
+ Enables the agent to determine the current date and time.
15530
+
15531
+ ## Key aspects
15532
+
15533
+ - This tool won't receive any input.
15534
+ - It outputs the current date and time as an ISO 8601 string.
15535
+ - Allows the agent to answer questions about the current time or date.
15536
+
15537
+ ## Examples
15538
+
15539
+ \`\`\`book
15540
+ Time-aware Assistant
15541
+
15542
+ PERSONA You are a helpful assistant who knows the current time.
15543
+ USE TIME
15544
+ \`\`\`
15545
+ `);
15546
+ }
15547
+ applyToAgentModelRequirements(requirements, content) {
15548
+ // Get existing tools array or create new one
15549
+ const existingTools = requirements.tools || [];
15550
+ // Add 'get_current_time' to tools if not already present
15551
+ const updatedTools = existingTools.some((tool) => tool.name === 'get_current_time')
15552
+ ? existingTools
15553
+ : [
15554
+ ...existingTools,
15555
+ {
15556
+ name: 'get_current_time',
15557
+ description: 'Get the current date and time in ISO 8601 format.',
15558
+ parameters: {
15559
+ type: 'object',
15560
+ properties: {
15561
+ timezone: {
15562
+ type: 'string',
15563
+ description: 'Optional timezone name (e.g. "Europe/Prague", "UTC", "America/New_York").',
15564
+ },
15565
+ },
15566
+ required: [],
15567
+ },
15568
+ },
15569
+ // <- TODO: !!!! define the function in LLM tools
15570
+ ];
15571
+ // Return requirements with updated tools and metadata
15572
+ return this.appendToSystemMessage({
15573
+ ...requirements,
15574
+ tools: updatedTools,
15575
+ metadata: {
15576
+ ...requirements.metadata,
15577
+ },
15578
+ }, spaceTrim$1(`
15579
+ You have access to the current date and time. Use it to answer questions about the current date and time.
15580
+ When you need to know the current date or time, use the tool provided to you.
15581
+ `));
15582
+ }
15583
+ /**
15584
+ * Gets human-readable titles for tool functions provided by this commitment.
15585
+ */
15586
+ getToolTitles() {
15587
+ return {
15588
+ get_current_time: 'Get current time',
15589
+ };
15590
+ }
15591
+ /**
15592
+ * Gets the `get_current_time` tool function implementation.
15593
+ */
15594
+ getToolFunctions() {
15595
+ return {
15596
+ async get_current_time(args) {
15597
+ var _a;
15598
+ console.log('!!!! [Tool] get_current_time called', { args });
15599
+ const { timezone } = args;
15600
+ if (!timezone) {
15601
+ return new Date().toISOString();
15602
+ }
15603
+ try {
15604
+ // Note: Returning ISO 8601 string but in the requested timezone
15605
+ const formatter = new Intl.DateTimeFormat('en-CA', {
15606
+ timeZone: timezone,
15607
+ year: 'numeric',
15608
+ month: '2-digit',
15609
+ day: '2-digit',
15610
+ hour: '2-digit',
15611
+ minute: '2-digit',
15612
+ second: '2-digit',
15613
+ hour12: false,
15614
+ timeZoneName: 'shortOffset',
15615
+ });
15616
+ const parts = formatter.formatToParts(new Date());
15617
+ const part = (type) => { var _a; return (_a = parts.find((p) => p.type === type)) === null || _a === void 0 ? void 0 : _a.value; };
15618
+ // en-CA format is YYYY-MM-DD
15619
+ 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', '')}`;
15620
+ return isoString;
15621
+ }
15622
+ catch (error) {
15623
+ // Fallback to UTC if timezone is invalid
15624
+ return new Date().toISOString();
15625
+ }
15626
+ },
15627
+ };
15628
+ }
15629
+ }
15630
+ /**
15631
+ * Note: [💞] Ignore a discrepancy between file name and entity name
15632
+ */
15633
+
15634
+ /**
15635
+ * Placeholder commitment definition for commitments that are not yet implemented
15636
+ *
15637
+ * This commitment simply adds its content 1:1 into the system message,
15638
+ * preserving the original behavior until proper implementation is added.
15639
+ *
15640
+ * @public exported from `@promptbook/core`
15641
+ */
15642
+ class NotYetImplementedCommitmentDefinition extends BaseCommitmentDefinition {
15643
+ constructor(type) {
15644
+ super(type);
15645
+ }
15646
+ /**
15647
+ * Short one-line description of a placeholder commitment.
15648
+ */
15649
+ get description() {
15650
+ return 'Placeholder commitment that appends content verbatim to the system message.';
15651
+ }
15652
+ /**
15653
+ * Icon for this commitment.
15654
+ */
15655
+ get icon() {
15656
+ return '🚧';
15657
+ }
15658
+ /**
15659
+ * Markdown documentation available at runtime.
15660
+ */
15661
+ get documentation() {
15662
+ return spaceTrim$1(`
15663
+ # ${this.type}
15664
+
15665
+ This commitment is not yet fully implemented.
15666
+
15667
+ ## Key aspects
15668
+
15669
+ - Content is appended directly to the system message.
15670
+ - No special processing or validation is performed.
15671
+ - Behavior preserved until proper implementation is added.
15672
+
15673
+ ## Status
15674
+
15675
+ - **Status:** Placeholder implementation
15676
+ - **Effect:** Appends content prefixed by commitment type
15677
+ - **Future:** Will be replaced with specialized logic
15678
+
15679
+ ## Examples
15680
+
15681
+ \`\`\`book
15682
+ Example Agent
15683
+
15684
+ PERSONA You are a helpful assistant
15685
+ ${this.type} Your content here
15686
+ RULE Always be helpful
15687
+ \`\`\`
15688
+ `);
15689
+ }
15690
+ applyToAgentModelRequirements(requirements, content) {
15691
+ const trimmedContent = content.trim();
15692
+ if (!trimmedContent) {
15693
+ return requirements;
15694
+ }
15695
+ // Add the commitment content 1:1 to the system message
15696
+ const commitmentLine = `${this.type} ${trimmedContent}`;
15697
+ return this.appendToSystemMessage(requirements, commitmentLine, '\n\n');
15698
+ }
15699
+ }
15700
+
15701
+ /**
15702
+ * Registry of all available commitment definitions
15703
+ * This array contains instances of all commitment definitions
15704
+ * This is the single source of truth for all commitments in the system
15705
+ *
15706
+ * @private Use functions to access commitments instead of this array directly
15707
+ */
15708
+ const COMMITMENT_REGISTRY = [
15709
+ // Fully implemented commitments
15710
+ new PersonaCommitmentDefinition('PERSONA'),
15711
+ new PersonaCommitmentDefinition('PERSONAE'),
15712
+ new KnowledgeCommitmentDefinition(),
15713
+ new MemoryCommitmentDefinition('MEMORY'),
15714
+ new MemoryCommitmentDefinition('MEMORIES'),
15715
+ new StyleCommitmentDefinition('STYLE'),
15716
+ new StyleCommitmentDefinition('STYLES'),
15717
+ new RuleCommitmentDefinition('RULES'),
15718
+ new RuleCommitmentDefinition('RULE'),
15719
+ new LanguageCommitmentDefinition('LANGUAGES'),
15720
+ new LanguageCommitmentDefinition('LANGUAGE'),
15721
+ new SampleCommitmentDefinition('SAMPLE'),
15722
+ new SampleCommitmentDefinition('EXAMPLE'),
15723
+ new FormatCommitmentDefinition('FORMAT'),
15724
+ new FormatCommitmentDefinition('FORMATS'),
15725
+ new FromCommitmentDefinition('FROM'),
15726
+ new ImportCommitmentDefinition('IMPORT'),
15727
+ new ImportCommitmentDefinition('IMPORTS'),
15728
+ new ModelCommitmentDefinition('MODEL'),
15729
+ new ModelCommitmentDefinition('MODELS'),
15730
+ new ActionCommitmentDefinition('ACTION'),
15731
+ new ActionCommitmentDefinition('ACTIONS'),
15732
+ new ComponentCommitmentDefinition(),
15733
+ new MetaImageCommitmentDefinition(),
15734
+ new MetaColorCommitmentDefinition(),
15735
+ new MetaFontCommitmentDefinition(),
15736
+ new MetaLinkCommitmentDefinition(),
15737
+ new MetaCommitmentDefinition(),
15738
+ new NoteCommitmentDefinition('NOTE'),
15739
+ new NoteCommitmentDefinition('NOTES'),
15740
+ new NoteCommitmentDefinition('COMMENT'),
15741
+ new NoteCommitmentDefinition('NONCE'),
15742
+ new NoteCommitmentDefinition('TODO'),
15743
+ new GoalCommitmentDefinition('GOAL'),
15744
+ new GoalCommitmentDefinition('GOALS'),
15745
+ new InitialMessageCommitmentDefinition(),
15746
+ new UserMessageCommitmentDefinition(),
15747
+ new AgentMessageCommitmentDefinition(),
15748
+ new MessageCommitmentDefinition('MESSAGE'),
15749
+ new MessageCommitmentDefinition('MESSAGES'),
15750
+ new ScenarioCommitmentDefinition('SCENARIO'),
15751
+ new ScenarioCommitmentDefinition('SCENARIOS'),
15752
+ new DeleteCommitmentDefinition('DELETE'),
15753
+ new DeleteCommitmentDefinition('CANCEL'),
15754
+ new DeleteCommitmentDefinition('DISCARD'),
15755
+ new DeleteCommitmentDefinition('REMOVE'),
15756
+ new DictionaryCommitmentDefinition(),
15757
+ new OpenCommitmentDefinition(),
15758
+ new ClosedCommitmentDefinition(),
15759
+ new UseBrowserCommitmentDefinition(),
15760
+ new UseSearchEngineCommitmentDefinition(),
15761
+ new UseTimeCommitmentDefinition(),
15762
+ new UseMcpCommitmentDefinition(),
15763
+ new UseCommitmentDefinition(),
15764
+ // Not yet implemented commitments (using placeholder)
15765
+ new NotYetImplementedCommitmentDefinition('EXPECT'),
15766
+ new NotYetImplementedCommitmentDefinition('BEHAVIOUR'),
15767
+ new NotYetImplementedCommitmentDefinition('BEHAVIOURS'),
15768
+ new NotYetImplementedCommitmentDefinition('AVOID'),
15769
+ new NotYetImplementedCommitmentDefinition('AVOIDANCE'),
15770
+ new NotYetImplementedCommitmentDefinition('CONTEXT'),
15771
+ // <- TODO: Prompt: Leverage aliases instead of duplicating commitment definitions
15772
+ ];
15773
+ /**
15774
+ * Gets all available commitment definitions
15775
+ * @returns Array of all commitment definitions
15776
+ *
15777
+ * @public exported from `@promptbook/core`
15778
+ */
15779
+ function getAllCommitmentDefinitions() {
15780
+ return $deepFreeze([...COMMITMENT_REGISTRY]);
15781
+ }
15782
+ /**
15783
+ * Gets all function implementations provided by all commitments
15784
+ *
15785
+ * @public exported from `@promptbook/core`
15786
+ */
15787
+ function getAllCommitmentsToolFunctions() {
15788
+ const allToolFunctions = {};
15789
+ for (const commitmentDefinition of getAllCommitmentDefinitions()) {
15790
+ const toolFunctions = commitmentDefinition.getToolFunctions();
15791
+ for (const [funcName, funcImpl] of Object.entries(toolFunctions)) {
15792
+ allToolFunctions[funcName] = funcImpl;
15793
+ }
15794
+ }
15795
+ return allToolFunctions;
15796
+ }
15797
+ /**
15798
+ * TODO: [🧠] Maybe create through standardized $register
15799
+ * Note: [💞] Ignore a discrepancy between file name and entity name
15800
+ */
15801
+
15802
+ /**
15803
+ * Extracts code block from markdown.
15804
+ *
15805
+ * - When there are multiple or no code blocks the function throws a `ParseError`
15806
+ *
15807
+ * Note: There are multiple similar function:
15808
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
15809
+ * - `extractJsonBlock` extracts exactly one valid JSON code block
15810
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
15811
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
15812
+ *
15813
+ * @public exported from `@promptbook/markdown-utils`
15814
+ * @throws {ParseError} if there is not exactly one code block in the markdown
15815
+ */
15816
+ function extractBlock(markdown) {
15817
+ const { content } = extractOneBlockFromMarkdown(markdown);
15818
+ return content;
15819
+ }
15820
+
15821
+ /**
15822
+ * Function trimCodeBlock will trim starting and ending code block from the string if it is present.
15823
+ *
15824
+ * Note: [🔂] This function is idempotent.
15825
+ * Note: This is useful for post-processing of the result of the chat LLM model
15826
+ * when the model wraps the result in the (markdown) code block.
15827
+ *
15828
+ * @public exported from `@promptbook/markdown-utils`
15829
+ */
15830
+ function trimCodeBlock(value) {
15831
+ value = spaceTrim$1(value);
15832
+ if (!/^```[a-z]*(.*)```$/is.test(value)) {
15833
+ return value;
15834
+ }
15835
+ value = value.replace(/^```[a-z]*/i, '');
15836
+ value = value.replace(/```$/i, '');
15837
+ value = spaceTrim$1(value);
15838
+ return value;
15839
+ }
15840
+
15841
+ /**
15842
+ * Function trimEndOfCodeBlock will remove ending code block from the string if it is present.
15843
+ *
15844
+ * Note: This is useful for post-processing of the result of the completion LLM model
15845
+ * if you want to start code block in the prompt but you don't want to end it in the result.
15846
+ *
15847
+ * @public exported from `@promptbook/markdown-utils`
15848
+ */
15849
+ function trimEndOfCodeBlock(value) {
15850
+ value = spaceTrim$1(value);
15851
+ value = value.replace(/```$/g, '');
15852
+ value = spaceTrim$1(value);
15853
+ return value;
15854
+ }
15855
+
15856
+ /**
15857
+ * @private internal for `preserve`
15858
+ */
15859
+ const _preserved = [];
15860
+ /**
15861
+ * Does nothing, but preserves the function in the bundle
15862
+ * Compiler is tricked into thinking the function is used
15863
+ *
15864
+ * @param value any function to preserve
15865
+ * @returns nothing
15866
+ * @private within the repository
15867
+ */
15868
+ function $preserve(...value) {
15869
+ _preserved.push(...value);
15870
+ }
15871
+ /**
15872
+ * Note: [💞] Ignore a discrepancy between file name and entity name
15873
+ */
15874
+
15875
+ // Note: [💎]
15876
+ /**
15877
+ * ScriptExecutionTools for JavaScript implemented via eval
15878
+ *
15879
+ * Warning: It is used for testing and mocking
15880
+ * **NOT intended to use in the production** due to its unsafe nature, use `JavascriptExecutionTools` instead.
15881
+ *
15882
+ * @public exported from `@promptbook/javascript`
15883
+ */
15884
+ class JavascriptEvalExecutionTools {
15885
+ constructor(options) {
15886
+ this.options = options || {};
15887
+ }
15888
+ /**
15889
+ * Executes a JavaScript
15890
+ */
15891
+ async execute(options) {
15892
+ const { scriptLanguage, parameters } = options;
15893
+ let { script } = options;
15894
+ if (scriptLanguage !== 'javascript') {
15895
+ throw new PipelineExecutionError(`Script language ${scriptLanguage} not supported to be executed by JavascriptEvalExecutionTools`);
15896
+ }
15897
+ // Note: [💎]
15898
+ // Note: Using direct eval, following variables are in same scope as eval call so they are accessible from inside the evaluated script:
15899
+ const spaceTrim = (_) => spaceTrim$2(_);
15900
+ $preserve(spaceTrim);
15901
+ const removeQuotes$1 = removeQuotes;
15902
+ $preserve(removeQuotes$1);
15903
+ const unwrapResult$1 = unwrapResult;
15904
+ $preserve(unwrapResult$1);
15905
+ const trimEndOfCodeBlock$1 = trimEndOfCodeBlock;
11997
15906
  $preserve(trimEndOfCodeBlock$1);
11998
15907
  const trimCodeBlock$1 = trimCodeBlock;
11999
15908
  $preserve(trimCodeBlock$1);
@@ -12070,6 +15979,13 @@ class JavascriptEvalExecutionTools {
12070
15979
  `const ${functionName} = buildinFunctions.${functionName};`)
12071
15980
  .join('\n');
12072
15981
  // TODO: DRY [🍯]
15982
+ const commitmentsFunctions = getAllCommitmentsToolFunctions();
15983
+ const commitmentsFunctionsStatement = Object.keys(commitmentsFunctions)
15984
+ .map((functionName) =>
15985
+ // Note: Custom functions are exposed to the current scope as variables
15986
+ `const ${functionName} = commitmentsFunctions.${functionName};`)
15987
+ .join('\n');
15988
+ // TODO: DRY [🍯]
12073
15989
  const customFunctions = this.options.functions || {};
12074
15990
  const customFunctionsStatement = Object.keys(customFunctions)
12075
15991
  .map((functionName) =>
@@ -12083,6 +15999,10 @@ class JavascriptEvalExecutionTools {
12083
15999
  // Build-in functions:
12084
16000
  ${block(buildinFunctionsStatement)}
12085
16001
 
16002
+ // Commitments functions:
16003
+ ${block(commitmentsFunctionsStatement)}
16004
+
16005
+
12086
16006
  // Custom functions:
12087
16007
  ${block(customFunctionsStatement || '// -- No custom functions --')}
12088
16008
 
@@ -12090,7 +16010,7 @@ class JavascriptEvalExecutionTools {
12090
16010
  ${block(Object.entries(parameters)
12091
16011
  .map(([key, value]) => `const ${key} = ${JSON.stringify(value)};`)
12092
16012
  .join('\n'))}
12093
- (()=>{ ${script} })()
16013
+ (async ()=>{ ${script} })()
12094
16014
  `);
12095
16015
  if (this.options.isVerbose) {
12096
16016
  console.info(spaceTrim$2((block) => `