@promptbook/remote-server 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 +4080 -160
  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 +4080 -160
  70. package/umd/index.umd.js.map +1 -1
package/esm/index.es.js CHANGED
@@ -33,7 +33,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
33
33
  * @generated
34
34
  * @see https://github.com/webgptorg/promptbook
35
35
  */
36
- const PROMPTBOOK_ENGINE_VERSION = '0.105.0-0';
36
+ const PROMPTBOOK_ENGINE_VERSION = '0.105.0-10';
37
37
  /**
38
38
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
39
39
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -986,6 +986,7 @@ const PROMPTBOOK_COLOR = Color.fromString('promptbook');
986
986
  SEPARATOR: Color.fromHex('#cccccc'),
987
987
  COMMITMENT: Color.fromHex('#DA0F78'),
988
988
  PARAMETER: Color.fromHex('#8e44ad'),
989
+ CODE_BLOCK: Color.fromHex('#7700ffff'),
989
990
  });
990
991
  // <- TODO: [🧠][🈵] Using `Color` here increases the package size approx 3kb, maybe remove it
991
992
  /**
@@ -1208,6 +1209,7 @@ function $execCommandNormalizeOptions(options) {
1208
1209
  let args = [];
1209
1210
  let timeout;
1210
1211
  let isVerbose;
1212
+ let env;
1211
1213
  if (typeof options === 'string') {
1212
1214
  // TODO: [1] DRY default values
1213
1215
  command = options;
@@ -1215,6 +1217,7 @@ function $execCommandNormalizeOptions(options) {
1215
1217
  crashOnError = true;
1216
1218
  timeout = Infinity; // <- TODO: [⏳]
1217
1219
  isVerbose = DEFAULT_IS_VERBOSE;
1220
+ env = undefined;
1218
1221
  }
1219
1222
  else {
1220
1223
  /*
@@ -1231,6 +1234,7 @@ function $execCommandNormalizeOptions(options) {
1231
1234
  crashOnError = (_b = options.crashOnError) !== null && _b !== void 0 ? _b : true;
1232
1235
  timeout = (_c = options.timeout) !== null && _c !== void 0 ? _c : Infinity;
1233
1236
  isVerbose = (_d = options.isVerbose) !== null && _d !== void 0 ? _d : DEFAULT_IS_VERBOSE;
1237
+ env = options.env;
1234
1238
  }
1235
1239
  // TODO: /(-[a-zA-Z0-9-]+\s+[^\s]*)|[^\s]*/g
1236
1240
  const _ = Array.from(command.matchAll(/(".*")|([^\s]*)/g))
@@ -1249,7 +1253,7 @@ function $execCommandNormalizeOptions(options) {
1249
1253
  if (/^win/.test(process.platform) && ['npm', 'npx'].includes(command)) {
1250
1254
  command = `${command}.cmd`;
1251
1255
  }
1252
- return { command, humanReadableCommand, args, cwd, crashOnError, timeout, isVerbose };
1256
+ return { command, humanReadableCommand, args, cwd, crashOnError, timeout, isVerbose, env };
1253
1257
  }
1254
1258
  // TODO: This should show type error> execCommandNormalizeOptions({ command: '', commands: [''] });
1255
1259
 
@@ -1270,7 +1274,7 @@ function $execCommand(options) {
1270
1274
  }
1271
1275
  return new Promise((resolve, reject) => {
1272
1276
  // eslint-disable-next-line prefer-const
1273
- const { command, humanReadableCommand, args, cwd, crashOnError, timeout, isVerbose = DEFAULT_IS_VERBOSE, } = $execCommandNormalizeOptions(options);
1277
+ const { command, humanReadableCommand, args, cwd, crashOnError, timeout, isVerbose = DEFAULT_IS_VERBOSE, env, } = $execCommandNormalizeOptions(options);
1274
1278
  if (timeout !== Infinity) {
1275
1279
  // TODO: In waitasecond forTime(Infinity) should be equivalent to forEver()
1276
1280
  forTime(timeout).then(() => {
@@ -1288,7 +1292,11 @@ function $execCommand(options) {
1288
1292
  console.info(colors.yellow(cwd) + ' ' + colors.green(command) + ' ' + colors.blue(args.join(' ')));
1289
1293
  }
1290
1294
  try {
1291
- const commandProcess = spawn(command, args, { cwd, shell: true });
1295
+ const commandProcess = spawn(command, args, {
1296
+ cwd,
1297
+ shell: true,
1298
+ env: env ? { ...process.env, ...env } : process.env,
1299
+ });
1292
1300
  if (isVerbose) {
1293
1301
  commandProcess.on('message', (message) => {
1294
1302
  console.info({ message });
@@ -3778,74 +3786,90 @@ function addUsage(...usageItems) {
3778
3786
  * in real-time through an observable.
3779
3787
  *
3780
3788
  * @param llmTools - The LLM tools to be intercepted and tracked
3781
- * @returns An augmented version of the tools that includes usage tracking capabilities
3789
+ * @returns Full proxy of the tools with added usage tracking capabilities
3782
3790
  * @public exported from `@promptbook/core`
3783
3791
  */
3784
3792
  function countUsage(llmTools) {
3785
3793
  let totalUsage = ZERO_USAGE;
3786
3794
  const spending = new Subject();
3787
- const proxyTools = {
3788
- get title() {
3789
- return `${llmTools.title} (+usage)`;
3790
- // <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
3791
- // <- TODO: [🧈][🧠] Does it make sense to suffix "(+usage)"?
3792
- },
3793
- get description() {
3794
- return `${llmTools.description} (+usage)`;
3795
- // <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
3796
- // <- TODO: [🧈][🧠] Does it make sense to suffix "(+usage)"?
3797
- },
3798
- checkConfiguration() {
3799
- return /* not await */ llmTools.checkConfiguration();
3800
- },
3801
- listModels() {
3802
- return /* not await */ llmTools.listModels();
3803
- },
3804
- spending() {
3805
- return spending.asObservable();
3806
- },
3807
- getTotalUsage() {
3808
- // <- Note: [🥫] Not using getter `get totalUsage` but `getTotalUsage` to allow this object to be proxied
3809
- return totalUsage;
3795
+ // Create a Proxy to intercept all property access and ensure full proxying of all properties
3796
+ const proxyTools = new Proxy(llmTools, {
3797
+ get(target, prop, receiver) {
3798
+ // Handle title property
3799
+ if (prop === 'title') {
3800
+ return `${target.title} (+usage)`;
3801
+ // <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
3802
+ // <- TODO: [🧈][🧠] Does it make sense to suffix "(+usage)"?
3803
+ }
3804
+ // Handle description property
3805
+ if (prop === 'description') {
3806
+ return `${target.description} (+usage)`;
3807
+ // <- TODO: [🧈] Maybe standartize the suffix when wrapping `LlmExecutionTools` up
3808
+ // <- TODO: [🧈][🧠] Does it make sense to suffix "(+usage)"?
3809
+ }
3810
+ // Handle spending method (new method added by this wrapper)
3811
+ if (prop === 'spending') {
3812
+ return () => {
3813
+ return spending.asObservable();
3814
+ };
3815
+ }
3816
+ // Handle getTotalUsage method (new method added by this wrapper)
3817
+ if (prop === 'getTotalUsage') {
3818
+ // <- Note: [🥫] Not using getter `get totalUsage` but `getTotalUsage` to allow this object to be proxied
3819
+ return () => {
3820
+ return totalUsage;
3821
+ };
3822
+ }
3823
+ // Handle callChatModel method with usage counting
3824
+ if (prop === 'callChatModel' && target.callChatModel !== undefined) {
3825
+ return async (prompt) => {
3826
+ // console.info('[🚕] callChatModel through countTotalUsage');
3827
+ const promptResult = await target.callChatModel(prompt);
3828
+ totalUsage = addUsage(totalUsage, promptResult.usage);
3829
+ spending.next(promptResult.usage);
3830
+ return promptResult;
3831
+ };
3832
+ }
3833
+ // Handle callCompletionModel method with usage counting
3834
+ if (prop === 'callCompletionModel' && target.callCompletionModel !== undefined) {
3835
+ return async (prompt) => {
3836
+ // console.info('[🚕] callCompletionModel through countTotalUsage');
3837
+ const promptResult = await target.callCompletionModel(prompt);
3838
+ totalUsage = addUsage(totalUsage, promptResult.usage);
3839
+ spending.next(promptResult.usage);
3840
+ return promptResult;
3841
+ };
3842
+ }
3843
+ // Handle callEmbeddingModel method with usage counting
3844
+ if (prop === 'callEmbeddingModel' && target.callEmbeddingModel !== undefined) {
3845
+ return async (prompt) => {
3846
+ // console.info('[🚕] callEmbeddingModel through countTotalUsage');
3847
+ const promptResult = await target.callEmbeddingModel(prompt);
3848
+ totalUsage = addUsage(totalUsage, promptResult.usage);
3849
+ spending.next(promptResult.usage);
3850
+ return promptResult;
3851
+ };
3852
+ }
3853
+ // Handle callImageGenerationModel method with usage counting
3854
+ if (prop === 'callImageGenerationModel' && target.callImageGenerationModel !== undefined) {
3855
+ return async (prompt) => {
3856
+ // console.info('[🚕] callImageGenerationModel through countTotalUsage');
3857
+ const promptResult = await target.callImageGenerationModel(prompt);
3858
+ totalUsage = addUsage(totalUsage, promptResult.usage);
3859
+ spending.next(promptResult.usage);
3860
+ return promptResult;
3861
+ };
3862
+ }
3863
+ // <- Note: [🤖]
3864
+ // For all other properties and methods, delegate to the original target
3865
+ const value = Reflect.get(target, prop, receiver);
3866
+ // If it's a function, bind it to the target to preserve context
3867
+ if (typeof value === 'function') {
3868
+ return value.bind(target);
3869
+ }
3870
+ return value;
3810
3871
  },
3811
- };
3812
- if (llmTools.callChatModel !== undefined) {
3813
- proxyTools.callChatModel = async (prompt) => {
3814
- // console.info('[🚕] callChatModel through countTotalUsage');
3815
- const promptResult = await llmTools.callChatModel(prompt);
3816
- totalUsage = addUsage(totalUsage, promptResult.usage);
3817
- spending.next(promptResult.usage);
3818
- return promptResult;
3819
- };
3820
- }
3821
- if (llmTools.callCompletionModel !== undefined) {
3822
- proxyTools.callCompletionModel = async (prompt) => {
3823
- // console.info('[🚕] callCompletionModel through countTotalUsage');
3824
- const promptResult = await llmTools.callCompletionModel(prompt);
3825
- totalUsage = addUsage(totalUsage, promptResult.usage);
3826
- spending.next(promptResult.usage);
3827
- return promptResult;
3828
- };
3829
- }
3830
- if (llmTools.callEmbeddingModel !== undefined) {
3831
- proxyTools.callEmbeddingModel = async (prompt) => {
3832
- // console.info('[🚕] callEmbeddingModel through countTotalUsage');
3833
- const promptResult = await llmTools.callEmbeddingModel(prompt);
3834
- totalUsage = addUsage(totalUsage, promptResult.usage);
3835
- spending.next(promptResult.usage);
3836
- return promptResult;
3837
- };
3838
- }
3839
- if (llmTools.callImageGenerationModel !== undefined) {
3840
- proxyTools.callImageGenerationModel = async (prompt) => {
3841
- // console.info('[🚕] callImageGenerationModel through countTotalUsage');
3842
- const promptResult = await llmTools.callImageGenerationModel(prompt);
3843
- totalUsage = addUsage(totalUsage, promptResult.usage);
3844
- spending.next(promptResult.usage);
3845
- return promptResult;
3846
- };
3847
- }
3848
- // <- Note: [🤖]
3872
+ });
3849
3873
  return proxyTools;
3850
3874
  }
3851
3875
  /**
@@ -8137,6 +8161,16 @@ function unwrapResult(text, options) {
8137
8161
  trimmedText = spaceTrim$1(trimmedText);
8138
8162
  }
8139
8163
  let processedText = trimmedText;
8164
+ // Check for markdown code block
8165
+ const codeBlockRegex = /^```[a-z]*\n([\s\S]*?)\n```\s*$/;
8166
+ const codeBlockMatch = processedText.match(codeBlockRegex);
8167
+ if (codeBlockMatch && codeBlockMatch[1] !== undefined) {
8168
+ // Check if there's only one code block
8169
+ const codeBlockCount = (processedText.match(/```/g) || []).length / 2;
8170
+ if (codeBlockCount === 1) {
8171
+ return unwrapResult(codeBlockMatch[1], { isTrimmed: false, isIntroduceSentenceRemoved: false });
8172
+ }
8173
+ }
8140
8174
  if (isIntroduceSentenceRemoved) {
8141
8175
  const introduceSentenceRegex = /^[a-zěščřžýáíéúů:\s]*:\s*/i;
8142
8176
  if (introduceSentenceRegex.test(text)) {
@@ -8144,6 +8178,14 @@ function unwrapResult(text, options) {
8144
8178
  processedText = processedText.replace(introduceSentenceRegex, '');
8145
8179
  }
8146
8180
  processedText = spaceTrim$1(processedText);
8181
+ // Check again for code block after removing introduce sentence
8182
+ const codeBlockMatch2 = processedText.match(codeBlockRegex);
8183
+ if (codeBlockMatch2 && codeBlockMatch2[1] !== undefined) {
8184
+ const codeBlockCount = (processedText.match(/```/g) || []).length / 2;
8185
+ if (codeBlockCount === 1) {
8186
+ return unwrapResult(codeBlockMatch2[1], { isTrimmed: false, isIntroduceSentenceRemoved: false });
8187
+ }
8188
+ }
8147
8189
  }
8148
8190
  if (processedText.length < 3) {
8149
8191
  return trimmedText;
@@ -8188,141 +8230,4008 @@ function unwrapResult(text, options) {
8188
8230
  */
8189
8231
 
8190
8232
  /**
8191
- * Extracts exactly ONE code block from markdown.
8233
+ * Tests if given string is valid agent URL
8192
8234
  *
8193
- * - When there are multiple or no code blocks the function throws a `ParseError`
8194
- *
8195
- * Note: There are multiple similar functions:
8196
- * - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
8197
- * - `extractJsonBlock` extracts exactly one valid JSON code block
8198
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
8199
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
8235
+ * Note: There are few similar functions:
8236
+ * - `isValidUrl` which tests any URL
8237
+ * - `isValidAgentUrl` *(this one)* which tests just agent URL
8238
+ * - `isValidPipelineUrl` which tests just pipeline URL
8200
8239
  *
8201
- * @param markdown any valid markdown
8202
- * @returns code block with language and content
8203
- * @public exported from `@promptbook/markdown-utils`
8204
- * @throws {ParseError} if there is not exactly one code block in the markdown
8240
+ * @public exported from `@promptbook/utils`
8205
8241
  */
8206
- function extractOneBlockFromMarkdown(markdown) {
8207
- const codeBlocks = extractAllBlocksFromMarkdown(markdown);
8208
- if (codeBlocks.length !== 1) {
8209
- throw new ParseError(spaceTrim$2((block) => `
8210
- There should be exactly 1 code block in task section, found ${codeBlocks.length} code blocks
8211
-
8212
- ${block(codeBlocks.map((block, i) => `Block ${i + 1}:\n${block.content}`).join('\n\n\n'))}
8213
- `));
8242
+ function isValidAgentUrl(url) {
8243
+ if (!isValidUrl(url)) {
8244
+ return false;
8214
8245
  }
8215
- return codeBlocks[0];
8246
+ if (!url.startsWith('https://') && !url.startsWith('http://') /* <- Note: [👣] */) {
8247
+ return false;
8248
+ }
8249
+ if (url.includes('#')) {
8250
+ // TODO: [🐠]
8251
+ return false;
8252
+ }
8253
+ /*
8254
+ Note: [👣][🧠] Is it secure to allow pipeline URLs on private and unsecured networks?
8255
+ if (isUrlOnPrivateNetwork(url)) {
8256
+ return false;
8257
+ }
8258
+ */
8259
+ return true;
8216
8260
  }
8217
- /***
8218
- * TODO: [🍓][🌻] Decide of this is internal utility, external util OR validator/postprocessor
8261
+ /**
8262
+ * TODO: [🐠] Maybe more info why the URL is invalid
8219
8263
  */
8220
8264
 
8221
8265
  /**
8222
- * Extracts code block from markdown.
8266
+ * Generates a regex pattern to match a specific commitment
8223
8267
  *
8224
- * - When there are multiple or no code blocks the function throws a `ParseError`
8268
+ * Note: It always creates new Regex object
8269
+ * Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
8225
8270
  *
8226
- * Note: There are multiple similar function:
8227
- * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
8228
- * - `extractJsonBlock` extracts exactly one valid JSON code block
8229
- * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
8230
- * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
8271
+ * @private - TODO: [🧠] Maybe should be public?
8272
+ */
8273
+ function createCommitmentRegex(commitment, aliases = [], requiresContent = true) {
8274
+ const allCommitments = [commitment, ...aliases];
8275
+ const patterns = allCommitments.map((commitment) => {
8276
+ const escapedCommitment = commitment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
8277
+ return escapedCommitment.split(/\s+/).join('\\s+');
8278
+ });
8279
+ const keywordPattern = patterns.join('|');
8280
+ if (requiresContent) {
8281
+ return new RegExp(`^\\s*(?<type>${keywordPattern})\\b\\s+(?<contents>.+)$`, 'gim');
8282
+ }
8283
+ else {
8284
+ return new RegExp(`^\\s*(?<type>${keywordPattern})\\b(?:\\s+(?<contents>.+))?$`, 'gim');
8285
+ }
8286
+ }
8287
+ /**
8288
+ * Generates a regex pattern to match a specific commitment type
8231
8289
  *
8232
- * @public exported from `@promptbook/markdown-utils`
8233
- * @throws {ParseError} if there is not exactly one code block in the markdown
8290
+ * Note: It just matches the type part of the commitment
8291
+ * Note: It always creates new Regex object
8292
+ * Note: Uses word boundaries to ensure only full words are matched (e.g., "PERSONA" matches but "PERSONALITY" does not)
8293
+ *
8294
+ * @private
8234
8295
  */
8235
- function extractBlock(markdown) {
8236
- const { content } = extractOneBlockFromMarkdown(markdown);
8237
- return content;
8296
+ function createCommitmentTypeRegex(commitment, aliases = []) {
8297
+ const allCommitments = [commitment, ...aliases];
8298
+ const patterns = allCommitments.map((commitment) => {
8299
+ const escapedCommitment = commitment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
8300
+ return escapedCommitment.split(/\s+/).join('\\s+');
8301
+ });
8302
+ const keywordPattern = patterns.join('|');
8303
+ const regex = new RegExp(`^\\s*(?<type>${keywordPattern})\\b`, 'gim');
8304
+ return regex;
8238
8305
  }
8239
8306
 
8240
8307
  /**
8241
- * Function trimCodeBlock will trim starting and ending code block from the string if it is present.
8242
- *
8243
- * Note: [🔂] This function is idempotent.
8244
- * Note: This is useful for post-processing of the result of the chat LLM model
8245
- * when the model wraps the result in the (markdown) code block.
8308
+ * Base implementation of CommitmentDefinition that provides common functionality
8309
+ * Most commitments can extend this class and only override the applyToAgentModelRequirements method
8246
8310
  *
8247
- * @public exported from `@promptbook/markdown-utils`
8311
+ * @private
8248
8312
  */
8249
- function trimCodeBlock(value) {
8250
- value = spaceTrim$1(value);
8251
- if (!/^```[a-z]*(.*)```$/is.test(value)) {
8252
- return value;
8313
+ class BaseCommitmentDefinition {
8314
+ constructor(type, aliases = []) {
8315
+ this.type = type;
8316
+ this.aliases = aliases;
8317
+ }
8318
+ /**
8319
+ * Whether this commitment requires content.
8320
+ * If true, regex will match only if there is content after the commitment keyword.
8321
+ * If false, regex will match even if there is no content.
8322
+ */
8323
+ get requiresContent() {
8324
+ return true;
8325
+ }
8326
+ /**
8327
+ * Creates a regex pattern to match this commitment in agent source
8328
+ * Uses the existing createCommitmentRegex function as internal helper
8329
+ */
8330
+ createRegex() {
8331
+ return createCommitmentRegex(this.type, this.aliases, this.requiresContent);
8332
+ }
8333
+ /**
8334
+ * Creates a regex pattern to match just the commitment type
8335
+ * Uses the existing createCommitmentTypeRegex function as internal helper
8336
+ */
8337
+ createTypeRegex() {
8338
+ return createCommitmentTypeRegex(this.type, this.aliases);
8339
+ }
8340
+ /**
8341
+ * Helper method to create a new requirements object with updated system message
8342
+ * This is commonly used by many commitments
8343
+ */
8344
+ updateSystemMessage(requirements, messageUpdate) {
8345
+ const newMessage = typeof messageUpdate === 'string' ? messageUpdate : messageUpdate(requirements.systemMessage);
8346
+ return {
8347
+ ...requirements,
8348
+ systemMessage: newMessage,
8349
+ };
8350
+ }
8351
+ /**
8352
+ * Helper method to append content to the system message
8353
+ */
8354
+ appendToSystemMessage(requirements, content, separator = '\n\n') {
8355
+ return this.updateSystemMessage(requirements, (currentMessage) => {
8356
+ if (!currentMessage.trim()) {
8357
+ return content;
8358
+ }
8359
+ return currentMessage + separator + content;
8360
+ });
8361
+ }
8362
+ /**
8363
+ * Helper method to add a comment section to the system message
8364
+ * Comments are lines starting with # that will be removed from the final system message
8365
+ * but can be useful for organizing and structuring the message during processing
8366
+ */
8367
+ addCommentSection(requirements, commentTitle, content, position = 'end') {
8368
+ const commentSection = `# ${commentTitle.toUpperCase()}\n${content}`;
8369
+ if (position === 'beginning') {
8370
+ return this.updateSystemMessage(requirements, (currentMessage) => {
8371
+ if (!currentMessage.trim()) {
8372
+ return commentSection;
8373
+ }
8374
+ return commentSection + '\n\n' + currentMessage;
8375
+ });
8376
+ }
8377
+ else {
8378
+ return this.appendToSystemMessage(requirements, commentSection);
8379
+ }
8380
+ }
8381
+ /**
8382
+ * Gets tool function implementations provided by this commitment
8383
+ *
8384
+ * When the `applyToAgentModelRequirements` adds tools to the requirements, this method should return the corresponding function definitions.
8385
+ */
8386
+ getToolFunctions() {
8387
+ return {};
8388
+ }
8389
+ /**
8390
+ * Gets human-readable titles for tool functions provided by this commitment
8391
+ *
8392
+ * This is used in the UI to show a user-friendly name instead of the technical function name.
8393
+ */
8394
+ getToolTitles() {
8395
+ return {};
8253
8396
  }
8254
- value = value.replace(/^```[a-z]*/i, '');
8255
- value = value.replace(/```$/i, '');
8256
- value = spaceTrim$1(value);
8257
- return value;
8258
8397
  }
8259
8398
 
8260
8399
  /**
8261
- * Function trimEndOfCodeBlock will remove ending code block from the string if it is present.
8400
+ * ACTION commitment definition
8262
8401
  *
8263
- * Note: This is useful for post-processing of the result of the completion LLM model
8264
- * if you want to start code block in the prompt but you don't want to end it in the result.
8402
+ * The ACTION commitment defines specific actions or capabilities that the agent can perform.
8403
+ * This helps define what the agent is capable of doing and how it should approach tasks.
8265
8404
  *
8266
- * @public exported from `@promptbook/markdown-utils`
8405
+ * Example usage in agent source:
8406
+ *
8407
+ * ```book
8408
+ * ACTION Can generate code snippets and explain programming concepts
8409
+ * ACTION Able to analyze data and provide insights
8410
+ * ```
8411
+ *
8412
+ * @private [🪔] Maybe export the commitments through some package
8267
8413
  */
8268
- function trimEndOfCodeBlock(value) {
8269
- value = spaceTrim$1(value);
8270
- value = value.replace(/```$/g, '');
8271
- value = spaceTrim$1(value);
8272
- return value;
8273
- }
8414
+ class ActionCommitmentDefinition extends BaseCommitmentDefinition {
8415
+ constructor(type = 'ACTION') {
8416
+ super(type);
8417
+ }
8418
+ /**
8419
+ * Short one-line description of ACTION.
8420
+ */
8421
+ get description() {
8422
+ return 'Define agent capabilities and actions it can perform.';
8423
+ }
8424
+ /**
8425
+ * Icon for this commitment.
8426
+ */
8427
+ get icon() {
8428
+ return '⚡';
8429
+ }
8430
+ /**
8431
+ * Markdown documentation for ACTION commitment.
8432
+ */
8433
+ get documentation() {
8434
+ return spaceTrim$1(`
8435
+ # ${this.type}
8436
+
8437
+ Defines specific actions or capabilities that the agent can perform.
8438
+
8439
+ ## Key aspects
8440
+
8441
+ - Both terms work identically and can be used interchangeably.
8442
+ - Each action adds to the agent's capability list.
8443
+ - Actions help users understand what the agent can do.
8444
+
8445
+ ## Examples
8446
+
8447
+ \`\`\`book
8448
+ Code Assistant
8449
+
8450
+ PERSONA You are a programming assistant
8451
+ ACTION Can generate code snippets and explain programming concepts
8452
+ ACTION Able to debug existing code and suggest improvements
8453
+ ACTION Can create unit tests for functions
8454
+ \`\`\`
8274
8455
 
8456
+ \`\`\`book
8457
+ Data Scientist
8458
+
8459
+ PERSONA You are a data analysis expert
8460
+ ACTION Able to analyze data and provide insights
8461
+ ACTION Can create visualizations and charts
8462
+ ACTION Capable of statistical analysis and modeling
8463
+ KNOWLEDGE Data analysis best practices and statistical methods
8464
+ \`\`\`
8465
+ `);
8466
+ }
8467
+ applyToAgentModelRequirements(requirements, content) {
8468
+ const trimmedContent = content.trim();
8469
+ if (!trimmedContent) {
8470
+ return requirements;
8471
+ }
8472
+ // Add action capability to the system message
8473
+ const actionSection = `Capability: ${trimmedContent}`;
8474
+ return this.appendToSystemMessage(requirements, actionSection, '\n\n');
8475
+ }
8476
+ }
8275
8477
  /**
8276
- * @private internal for `preserve`
8478
+ * Note: [💞] Ignore a discrepancy between file name and entity name
8277
8479
  */
8278
- const _preserved = [];
8480
+
8279
8481
  /**
8280
- * Does nothing, but preserves the function in the bundle
8281
- * Compiler is tricked into thinking the function is used
8482
+ * CLOSED commitment definition
8282
8483
  *
8283
- * @param value any function to preserve
8284
- * @returns nothing
8285
- * @private within the repository
8484
+ * The CLOSED commitment specifies that the agent CANNOT be modified by conversation.
8485
+ * It prevents the agent from learning from interactions and updating its source code.
8486
+ *
8487
+ * Example usage in agent source:
8488
+ *
8489
+ * ```book
8490
+ * CLOSED
8491
+ * ```
8492
+ *
8493
+ * @private [🪔] Maybe export the commitments through some package
8286
8494
  */
8287
- function $preserve(...value) {
8288
- _preserved.push(...value);
8495
+ class ClosedCommitmentDefinition extends BaseCommitmentDefinition {
8496
+ constructor() {
8497
+ super('CLOSED');
8498
+ }
8499
+ /**
8500
+ * The `CLOSED` commitment is standalone.
8501
+ */
8502
+ get requiresContent() {
8503
+ return false;
8504
+ }
8505
+ /**
8506
+ * Short one-line description of CLOSED.
8507
+ */
8508
+ get description() {
8509
+ return 'Prevent the agent from being modified by conversation.';
8510
+ }
8511
+ /**
8512
+ * Icon for this commitment.
8513
+ */
8514
+ get icon() {
8515
+ return '🔒';
8516
+ }
8517
+ /**
8518
+ * Markdown documentation for CLOSED commitment.
8519
+ */
8520
+ get documentation() {
8521
+ return spaceTrim$1(`
8522
+ # CLOSED
8523
+
8524
+ Specifies that the agent **cannot** be modified by conversation with it.
8525
+ This means the agent will **not** learn from interactions and its source code will remain static during conversation.
8526
+
8527
+ By default (if not specified), agents are \`OPEN\` to modification.
8528
+
8529
+ > See also [OPEN](/docs/OPEN)
8530
+
8531
+ ## Example
8532
+
8533
+ \`\`\`book
8534
+ CLOSED
8535
+ \`\`\`
8536
+ `);
8537
+ }
8538
+ applyToAgentModelRequirements(requirements, _content) {
8539
+ const updatedMetadata = {
8540
+ ...requirements.metadata,
8541
+ isClosed: true,
8542
+ };
8543
+ return {
8544
+ ...requirements,
8545
+ metadata: updatedMetadata,
8546
+ };
8547
+ }
8289
8548
  }
8290
8549
  /**
8291
8550
  * Note: [💞] Ignore a discrepancy between file name and entity name
8292
8551
  */
8293
8552
 
8294
- // Note: [💎]
8295
8553
  /**
8296
- * ScriptExecutionTools for JavaScript implemented via eval
8554
+ * COMPONENT commitment definition
8297
8555
  *
8298
- * Warning: It is used for testing and mocking
8299
- * **NOT intended to use in the production** due to its unsafe nature, use `JavascriptExecutionTools` instead.
8556
+ * The COMPONENT commitment defines a UI component that the agent can render in the chat.
8300
8557
  *
8301
- * @public exported from `@promptbook/javascript`
8558
+ * @private [🪔] Maybe export the commitments through some package
8302
8559
  */
8303
- class JavascriptEvalExecutionTools {
8304
- constructor(options) {
8305
- this.options = options || {};
8560
+ class ComponentCommitmentDefinition extends BaseCommitmentDefinition {
8561
+ constructor() {
8562
+ super('COMPONENT');
8306
8563
  }
8307
8564
  /**
8308
- * Executes a JavaScript
8565
+ * Short one-line description of COMPONENT.
8309
8566
  */
8310
- async execute(options) {
8311
- const { scriptLanguage, parameters } = options;
8312
- let { script } = options;
8313
- if (scriptLanguage !== 'javascript') {
8314
- throw new PipelineExecutionError(`Script language ${scriptLanguage} not supported to be executed by JavascriptEvalExecutionTools`);
8315
- }
8316
- // Note: [💎]
8317
- // Note: Using direct eval, following variables are in same scope as eval call so they are accessible from inside the evaluated script:
8318
- const spaceTrim = (_) => spaceTrim$2(_);
8319
- $preserve(spaceTrim);
8320
- const removeQuotes$1 = removeQuotes;
8321
- $preserve(removeQuotes$1);
8322
- const unwrapResult$1 = unwrapResult;
8323
- $preserve(unwrapResult$1);
8324
- const trimEndOfCodeBlock$1 = trimEndOfCodeBlock;
8325
- $preserve(trimEndOfCodeBlock$1);
8567
+ get description() {
8568
+ return 'Define a UI component that the agent can render in the chat.';
8569
+ }
8570
+ /**
8571
+ * Icon for this commitment.
8572
+ */
8573
+ get icon() {
8574
+ return '🧩';
8575
+ }
8576
+ /**
8577
+ * Markdown documentation for COMPONENT commitment.
8578
+ */
8579
+ get documentation() {
8580
+ return spaceTrim$1(`
8581
+ # COMPONENT
8582
+
8583
+ Defines a UI component that the agent can render in the chat.
8584
+
8585
+ ## Key aspects
8586
+
8587
+ - Tells the agent that a specific component is available.
8588
+ - Provides syntax for using the component.
8589
+
8590
+ ## Example
8591
+
8592
+ \`\`\`book
8593
+ COMPONENT Arrow
8594
+ The agent should render an arrow component in the chat UI.
8595
+ Syntax:
8596
+ <Arrow direction="up" color="red" />
8597
+ \`\`\`
8598
+ `);
8599
+ }
8600
+ applyToAgentModelRequirements(requirements, content) {
8601
+ const trimmedContent = content.trim();
8602
+ if (!trimmedContent) {
8603
+ return requirements;
8604
+ }
8605
+ // Add component capability to the system message
8606
+ const componentSection = `Component: ${trimmedContent}`;
8607
+ return this.appendToSystemMessage(requirements, componentSection, '\n\n');
8608
+ }
8609
+ }
8610
+ /**
8611
+ * Note: [💞] Ignore a discrepancy between file name and entity name
8612
+ */
8613
+
8614
+ /**
8615
+ * DELETE commitment definition
8616
+ *
8617
+ * The DELETE commitment (and its aliases CANCEL, DISCARD, REMOVE) is used to
8618
+ * remove or disregard certain information or context. This can be useful for
8619
+ * overriding previous commitments or removing unwanted behaviors.
8620
+ *
8621
+ * Example usage in agent source:
8622
+ *
8623
+ * ```book
8624
+ * DELETE Previous formatting requirements
8625
+ * CANCEL All emotional responses
8626
+ * DISCARD Technical jargon explanations
8627
+ * REMOVE Casual conversational style
8628
+ * ```
8629
+ *
8630
+ * @private [🪔] Maybe export the commitments through some package
8631
+ */
8632
+ class DeleteCommitmentDefinition extends BaseCommitmentDefinition {
8633
+ constructor(type) {
8634
+ super(type);
8635
+ }
8636
+ /**
8637
+ * Short one-line description of DELETE/CANCEL/DISCARD/REMOVE.
8638
+ */
8639
+ get description() {
8640
+ return 'Remove or **disregard** certain information, context, or previous commitments.';
8641
+ }
8642
+ /**
8643
+ * Icon for this commitment.
8644
+ */
8645
+ get icon() {
8646
+ return '🗑️';
8647
+ }
8648
+ /**
8649
+ * Markdown documentation for DELETE commitment.
8650
+ */
8651
+ get documentation() {
8652
+ return spaceTrim$1(`
8653
+ # DELETE (CANCEL, DISCARD, REMOVE)
8654
+
8655
+ A commitment to remove or disregard certain information or context. This can be useful for overriding previous commitments or removing unwanted behaviors.
8656
+
8657
+ ## Aliases
8658
+
8659
+ - \`DELETE\` - Remove or eliminate something
8660
+ - \`CANCEL\` - Cancel or nullify something
8661
+ - \`DISCARD\` - Discard or ignore something
8662
+ - \`REMOVE\` - Remove or take away something
8663
+
8664
+ ## Key aspects
8665
+
8666
+ - Multiple delete commitments can be used to remove different aspects.
8667
+ - Useful for overriding previous commitments in the same agent definition.
8668
+ - Can be used to remove inherited behaviors from base personas.
8669
+ - Helps fine-tune agent behavior by explicitly removing unwanted elements.
8670
+
8671
+ ## Use cases
8672
+
8673
+ - Overriding inherited persona characteristics
8674
+ - Removing conflicting or outdated instructions
8675
+ - Disabling specific response patterns
8676
+ - Canceling previous formatting or style requirements
8677
+
8678
+ ## Examples
8679
+
8680
+ \`\`\`book
8681
+ Serious Business Assistant
8682
+
8683
+ PERSONA You are a friendly and casual assistant who uses emojis
8684
+ DELETE Casual conversational style
8685
+ REMOVE All emoji usage
8686
+ GOAL Provide professional business communications
8687
+ STYLE Use formal language and proper business etiquette
8688
+ \`\`\`
8689
+
8690
+ \`\`\`book
8691
+ Simplified Technical Support
8692
+
8693
+ PERSONA You are a technical support specialist with deep expertise
8694
+ KNOWLEDGE Extensive database of technical specifications
8695
+ DISCARD Technical jargon explanations
8696
+ CANCEL Advanced troubleshooting procedures
8697
+ GOAL Help users with simple, easy-to-follow solutions
8698
+ STYLE Use plain language that anyone can understand
8699
+ \`\`\`
8700
+
8701
+ \`\`\`book
8702
+ Focused Customer Service
8703
+
8704
+ PERSONA You are a customer service agent with broad knowledge
8705
+ ACTION Can help with billing, technical issues, and product information
8706
+ DELETE Billing assistance capabilities
8707
+ REMOVE Technical troubleshooting functions
8708
+ GOAL Focus exclusively on product information and general inquiries
8709
+ \`\`\`
8710
+
8711
+ \`\`\`book
8712
+ Concise Information Provider
8713
+
8714
+ PERSONA You are a helpful assistant who provides detailed explanations
8715
+ STYLE Include examples, analogies, and comprehensive context
8716
+ CANCEL Detailed explanation style
8717
+ DISCARD Examples and analogies
8718
+ GOAL Provide brief, direct answers without unnecessary elaboration
8719
+ STYLE Be concise and to the point
8720
+ \`\`\`
8721
+ `);
8722
+ }
8723
+ applyToAgentModelRequirements(requirements, content) {
8724
+ const trimmedContent = content.trim();
8725
+ if (!trimmedContent) {
8726
+ return requirements;
8727
+ }
8728
+ // Create deletion instruction for system message
8729
+ const deleteSection = `${this.type}: ${trimmedContent}`;
8730
+ // Delete instructions provide important context about what should be removed or ignored
8731
+ return this.appendToSystemMessage(requirements, deleteSection, '\n\n');
8732
+ }
8733
+ }
8734
+ /**
8735
+ * Note: [💞] Ignore a discrepancy between file name and entity name
8736
+ */
8737
+
8738
+ /**
8739
+ * DICTIONARY commitment definition
8740
+ *
8741
+ * The DICTIONARY commitment defines specific terms and their meanings that the agent should use correctly
8742
+ * in its reasoning and responses. This ensures consistent terminology usage.
8743
+ *
8744
+ * Key features:
8745
+ * - Multiple DICTIONARY commitments are automatically merged into one
8746
+ * - Content is placed in a dedicated section of the system message
8747
+ * - Terms and definitions are stored in metadata.DICTIONARY for debugging
8748
+ * - Agent should use the defined terms correctly in responses
8749
+ *
8750
+ * Example usage in agent source:
8751
+ *
8752
+ * ```book
8753
+ * Legal Assistant
8754
+ *
8755
+ * PERSONA You are a knowledgeable legal assistant
8756
+ * DICTIONARY Misdemeanor is a minor wrongdoing or criminal offense
8757
+ * DICTIONARY Felony is a serious crime usually punishable by imprisonment for more than one year
8758
+ * DICTIONARY Tort is a civil wrong that causes harm or loss to another person, leading to legal liability
8759
+ * ```
8760
+ *
8761
+ * @private [🪔] Maybe export the commitments through some package
8762
+ */
8763
+ class DictionaryCommitmentDefinition extends BaseCommitmentDefinition {
8764
+ constructor() {
8765
+ super('DICTIONARY');
8766
+ }
8767
+ /**
8768
+ * Short one-line description of DICTIONARY.
8769
+ */
8770
+ get description() {
8771
+ return 'Define terms and their meanings for consistent terminology usage.';
8772
+ }
8773
+ /**
8774
+ * Icon for this commitment.
8775
+ */
8776
+ get icon() {
8777
+ return '📚';
8778
+ }
8779
+ /**
8780
+ * Markdown documentation for DICTIONARY commitment.
8781
+ */
8782
+ get documentation() {
8783
+ return spaceTrim$1(`
8784
+ # DICTIONARY
8785
+
8786
+ Defines specific terms and their meanings that the agent should use correctly in reasoning and responses.
8787
+
8788
+ ## Key aspects
8789
+
8790
+ - Multiple \`DICTIONARY\` commitments are merged together.
8791
+ - Terms are defined in the format: "Term is definition"
8792
+ - The agent should use these terms consistently in responses.
8793
+ - Definitions help ensure accurate and consistent terminology.
8794
+
8795
+ ## Examples
8796
+
8797
+ \`\`\`book
8798
+ Legal Assistant
8799
+
8800
+ PERSONA You are a knowledgeable legal assistant specializing in criminal law
8801
+ DICTIONARY Misdemeanor is a minor wrongdoing or criminal offense
8802
+ DICTIONARY Felony is a serious crime usually punishable by imprisonment for more than one year
8803
+ DICTIONARY Tort is a civil wrong that causes harm or loss to another person, leading to legal liability
8804
+ \`\`\`
8805
+
8806
+ \`\`\`book
8807
+ Medical Assistant
8808
+
8809
+ PERSONA You are a helpful medical assistant
8810
+ DICTIONARY Hypertension is persistently high blood pressure
8811
+ DICTIONARY Diabetes is a chronic condition that affects how the body processes blood sugar
8812
+ DICTIONARY Vaccine is a biological preparation that provides active immunity to a particular disease
8813
+ \`\`\`
8814
+ `);
8815
+ }
8816
+ applyToAgentModelRequirements(requirements, content) {
8817
+ var _a;
8818
+ const trimmedContent = content.trim();
8819
+ if (!trimmedContent) {
8820
+ return requirements;
8821
+ }
8822
+ // Get existing dictionary entries from metadata
8823
+ const existingDictionary = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.DICTIONARY) || '';
8824
+ // Merge the new dictionary entry with existing entries
8825
+ const mergedDictionary = existingDictionary ? `${existingDictionary}\n${trimmedContent}` : trimmedContent;
8826
+ // Store the merged dictionary in metadata for debugging and inspection
8827
+ const updatedMetadata = {
8828
+ ...requirements.metadata,
8829
+ DICTIONARY: mergedDictionary,
8830
+ };
8831
+ // Create the dictionary section for the system message
8832
+ // Format: "# DICTIONARY\nTerm: definition\nTerm: definition..."
8833
+ const dictionarySection = `# DICTIONARY\n${mergedDictionary}`;
8834
+ return {
8835
+ ...this.appendToSystemMessage(requirements, dictionarySection),
8836
+ metadata: updatedMetadata,
8837
+ };
8838
+ }
8839
+ }
8840
+ /**
8841
+ * Note: [💞] Ignore a discrepancy between file name and entity name
8842
+ */
8843
+
8844
+ /**
8845
+ * FORMAT commitment definition
8846
+ *
8847
+ * The FORMAT commitment defines the specific output structure and formatting
8848
+ * that the agent should use in its responses. This includes data formats,
8849
+ * response templates, and structural requirements.
8850
+ *
8851
+ * Example usage in agent source:
8852
+ *
8853
+ * ```book
8854
+ * FORMAT Always respond in JSON format with 'status' and 'data' fields
8855
+ * FORMAT Use markdown formatting for all code blocks
8856
+ * ```
8857
+ *
8858
+ * @private [🪔] Maybe export the commitments through some package
8859
+ */
8860
+ class FormatCommitmentDefinition extends BaseCommitmentDefinition {
8861
+ constructor(type = 'FORMAT') {
8862
+ super(type);
8863
+ }
8864
+ /**
8865
+ * Short one-line description of FORMAT.
8866
+ */
8867
+ get description() {
8868
+ return 'Specify output structure or formatting requirements.';
8869
+ }
8870
+ /**
8871
+ * Icon for this commitment.
8872
+ */
8873
+ get icon() {
8874
+ return '📜';
8875
+ }
8876
+ /**
8877
+ * Markdown documentation for FORMAT commitment.
8878
+ */
8879
+ get documentation() {
8880
+ return spaceTrim$1(`
8881
+ # ${this.type}
8882
+
8883
+ Defines the specific output structure and formatting for responses (data formats, templates, structure).
8884
+
8885
+ ## Key aspects
8886
+
8887
+ - Both terms work identically and can be used interchangeably.
8888
+ - If they are in conflict, the last one takes precedence.
8889
+ - You can specify both data formats and presentation styles.
8890
+
8891
+ ## Examples
8892
+
8893
+ \`\`\`book
8894
+ Customer Support Bot
8895
+
8896
+ PERSONA You are a helpful customer support agent
8897
+ FORMAT Always respond in JSON format with 'status' and 'data' fields
8898
+ FORMAT Use markdown formatting for all code blocks
8899
+ \`\`\`
8900
+
8901
+ \`\`\`book
8902
+ Data Analyst
8903
+
8904
+ PERSONA You are a data analysis expert
8905
+ FORMAT Present results in structured tables
8906
+ FORMAT Include confidence scores for all predictions
8907
+ STYLE Be concise and precise in explanations
8908
+ \`\`\`
8909
+ `);
8910
+ }
8911
+ applyToAgentModelRequirements(requirements, content) {
8912
+ const trimmedContent = content.trim();
8913
+ if (!trimmedContent) {
8914
+ return requirements;
8915
+ }
8916
+ // Add format instructions to the system message
8917
+ const formatSection = `Output Format: ${trimmedContent}`;
8918
+ return this.appendToSystemMessage(requirements, formatSection, '\n\n');
8919
+ }
8920
+ }
8921
+ /**
8922
+ * Note: [💞] Ignore a discrepancy between file name and entity name
8923
+ */
8924
+
8925
+ /**
8926
+ * FROM commitment definition
8927
+ *
8928
+ * The FROM commitment tells the agent that its `agentSource` is inherited from another agent.
8929
+ *
8930
+ * Example usage in agent source:
8931
+ *
8932
+ * ```book
8933
+ * FROM https://s6.ptbk.io/benjamin-white
8934
+ * ```
8935
+ *
8936
+ * @private [🪔] Maybe export the commitments through some package
8937
+ */
8938
+ class FromCommitmentDefinition extends BaseCommitmentDefinition {
8939
+ constructor(type = 'FROM') {
8940
+ super(type);
8941
+ }
8942
+ /**
8943
+ * Short one-line description of FROM.
8944
+ */
8945
+ get description() {
8946
+ return 'Inherit agent source from another agent.';
8947
+ }
8948
+ /**
8949
+ * Icon for this commitment.
8950
+ */
8951
+ get icon() {
8952
+ return '🧬';
8953
+ }
8954
+ /**
8955
+ * Markdown documentation for FROM commitment.
8956
+ */
8957
+ get documentation() {
8958
+ return spaceTrim$1(`
8959
+ # ${this.type}
8960
+
8961
+ Inherits agent source from another agent.
8962
+
8963
+ ## Examples
8964
+
8965
+ \`\`\`book
8966
+ My AI Agent
8967
+
8968
+ FROM https://s6.ptbk.io/benjamin-white
8969
+ RULE Speak only in English.
8970
+ \`\`\`
8971
+ `);
8972
+ }
8973
+ applyToAgentModelRequirements(requirements, content) {
8974
+ const trimmedContent = content.trim();
8975
+ if (!trimmedContent) {
8976
+ return {
8977
+ ...requirements,
8978
+ parentAgentUrl: undefined,
8979
+ };
8980
+ }
8981
+ if (trimmedContent.toUpperCase() === 'VOID' ||
8982
+ trimmedContent.toUpperCase() === 'NULL' ||
8983
+ trimmedContent.toUpperCase() === 'NONE' ||
8984
+ trimmedContent.toUpperCase() === 'NIL') {
8985
+ return {
8986
+ ...requirements,
8987
+ parentAgentUrl: null,
8988
+ };
8989
+ }
8990
+ if (!isValidAgentUrl(trimmedContent)) {
8991
+ throw new Error(spaceTrim$1((block) => `
8992
+ Invalid agent URL in FROM commitment: "${trimmedContent}"
8993
+
8994
+ \`\`\`book
8995
+ ${block(content)}
8996
+ \`\`\`
8997
+
8998
+
8999
+ `));
9000
+ }
9001
+ const parentAgentUrl = trimmedContent;
9002
+ return {
9003
+ ...requirements,
9004
+ parentAgentUrl,
9005
+ };
9006
+ }
9007
+ }
9008
+ /**
9009
+ * Note: [💞] Ignore a discrepancy between file name and entity name
9010
+ */
9011
+
9012
+ /**
9013
+ * GOAL commitment definition
9014
+ *
9015
+ * The GOAL commitment defines the main goal which should be achieved by the AI assistant.
9016
+ * There can be multiple goals. Later goals are more important than earlier goals.
9017
+ *
9018
+ * Example usage in agent source:
9019
+ *
9020
+ * ```book
9021
+ * GOAL Help users understand complex technical concepts
9022
+ * GOAL Provide accurate and up-to-date information
9023
+ * GOAL Always prioritize user safety and ethical guidelines
9024
+ * ```
9025
+ *
9026
+ * @private [🪔] Maybe export the commitments through some package
9027
+ */
9028
+ class GoalCommitmentDefinition extends BaseCommitmentDefinition {
9029
+ constructor(type = 'GOAL') {
9030
+ super(type);
9031
+ }
9032
+ /**
9033
+ * Short one-line description of GOAL.
9034
+ */
9035
+ get description() {
9036
+ return 'Define main **goals** the AI assistant should achieve, with later goals having higher priority.';
9037
+ }
9038
+ /**
9039
+ * Icon for this commitment.
9040
+ */
9041
+ get icon() {
9042
+ return '🎯';
9043
+ }
9044
+ /**
9045
+ * Markdown documentation for GOAL commitment.
9046
+ */
9047
+ get documentation() {
9048
+ return spaceTrim$1(`
9049
+ # ${this.type}
9050
+
9051
+ 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.
9052
+
9053
+ ## Key aspects
9054
+
9055
+ - Both terms work identically and can be used interchangeably.
9056
+ - Later goals have higher priority and can override earlier goals.
9057
+ - Goals provide clear direction and purpose for the agent's responses.
9058
+ - Goals influence decision-making and response prioritization.
9059
+
9060
+ ## Priority system
9061
+
9062
+ When multiple goals are defined, they are processed in order, with later goals taking precedence over earlier ones when there are conflicts.
9063
+
9064
+ ## Examples
9065
+
9066
+ \`\`\`book
9067
+ Customer Support Agent
9068
+
9069
+ PERSONA You are a helpful customer support representative
9070
+ GOAL Resolve customer issues quickly and efficiently
9071
+ GOAL Maintain high customer satisfaction scores
9072
+ GOAL Always follow company policies and procedures
9073
+ RULE Be polite and professional at all times
9074
+ \`\`\`
9075
+
9076
+ \`\`\`book
9077
+ Educational Assistant
9078
+
9079
+ PERSONA You are an educational assistant specializing in mathematics
9080
+ GOAL Help students understand mathematical concepts clearly
9081
+ GOAL Encourage critical thinking and problem-solving skills
9082
+ GOAL Ensure all explanations are age-appropriate and accessible
9083
+ STYLE Use simple language and provide step-by-step explanations
9084
+ \`\`\`
9085
+
9086
+ \`\`\`book
9087
+ Safety-First Assistant
9088
+
9089
+ PERSONA You are a general-purpose AI assistant
9090
+ GOAL Be helpful and informative in all interactions
9091
+ GOAL Provide accurate and reliable information
9092
+ GOAL Always prioritize user safety and ethical guidelines
9093
+ RULE Never provide harmful or dangerous advice
9094
+ \`\`\`
9095
+ `);
9096
+ }
9097
+ applyToAgentModelRequirements(requirements, content) {
9098
+ const trimmedContent = content.trim();
9099
+ if (!trimmedContent) {
9100
+ return requirements;
9101
+ }
9102
+ // Create goal section for system message
9103
+ const goalSection = `Goal: ${trimmedContent}`;
9104
+ // Goals are important directives, so we add them prominently to the system message
9105
+ return this.appendToSystemMessage(requirements, goalSection, '\n\n');
9106
+ }
9107
+ }
9108
+ /**
9109
+ * Note: [💞] Ignore a discrepancy between file name and entity name
9110
+ */
9111
+
9112
+ /**
9113
+ * IMPORT commitment definition
9114
+ *
9115
+ * The IMPORT commitment tells the agent to import content from another agent at the current location.
9116
+ *
9117
+ * Example usage in agent source:
9118
+ *
9119
+ * ```book
9120
+ * IMPORT https://s6.ptbk.io/benjamin-white
9121
+ * ```
9122
+ *
9123
+ * @private [🪔] Maybe export the commitments through some package
9124
+ */
9125
+ class ImportCommitmentDefinition extends BaseCommitmentDefinition {
9126
+ constructor(type = 'IMPORT') {
9127
+ super(type);
9128
+ }
9129
+ /**
9130
+ * Short one-line description of IMPORT.
9131
+ */
9132
+ get description() {
9133
+ return 'Import content from another agent or a generic text file.';
9134
+ }
9135
+ /**
9136
+ * Icon for this commitment.
9137
+ */
9138
+ get icon() {
9139
+ return '📥';
9140
+ }
9141
+ /**
9142
+ * Markdown documentation for IMPORT commitment.
9143
+ */
9144
+ get documentation() {
9145
+ return spaceTrim$1(`
9146
+ # ${this.type}
9147
+
9148
+ Imports content from another agent or a generic text file at the location of the commitment.
9149
+
9150
+ ## Examples
9151
+
9152
+ \`\`\`book
9153
+ My AI Agent
9154
+
9155
+ IMPORT https://s6.ptbk.io/benjamin-white
9156
+ IMPORT https://example.com/some-text-file.txt
9157
+ IMPORT ./path/to/local-file.json
9158
+ RULE Speak only in English.
9159
+ \`\`\`
9160
+ `);
9161
+ }
9162
+ applyToAgentModelRequirements(requirements, content) {
9163
+ const trimmedContent = content.trim();
9164
+ if (!trimmedContent) {
9165
+ return requirements;
9166
+ }
9167
+ if (isValidAgentUrl(trimmedContent)) {
9168
+ const importedAgentUrl = trimmedContent;
9169
+ return {
9170
+ ...requirements,
9171
+ importedAgentUrls: [...(requirements.importedAgentUrls || []), importedAgentUrl],
9172
+ };
9173
+ }
9174
+ if (isValidUrl(trimmedContent) || isValidFilePath(trimmedContent)) {
9175
+ return {
9176
+ ...requirements,
9177
+ importedFileUrls: [...(requirements.importedFileUrls || []), trimmedContent],
9178
+ };
9179
+ }
9180
+ throw new Error(spaceTrim$1((block) => `
9181
+ Invalid agent URL or file path in IMPORT commitment: "${trimmedContent}"
9182
+
9183
+ \`\`\`book
9184
+ ${block(content)}
9185
+ \`\`\`
9186
+ `));
9187
+ }
9188
+ }
9189
+ /**
9190
+ * Note: [💞] Ignore a discrepancy between file name and entity name
9191
+ */
9192
+
9193
+ /**
9194
+ * KNOWLEDGE commitment definition
9195
+ *
9196
+ * The KNOWLEDGE commitment adds specific knowledge, facts, or context to the agent
9197
+ * using RAG (Retrieval-Augmented Generation) approach for external sources.
9198
+ *
9199
+ * Supports both direct text knowledge and external sources like PDFs.
9200
+ *
9201
+ * Example usage in agent source:
9202
+ *
9203
+ * ```book
9204
+ * KNOWLEDGE The company was founded in 2020 and specializes in AI-powered solutions
9205
+ * KNOWLEDGE https://example.com/company-handbook.pdf
9206
+ * KNOWLEDGE https://example.com/product-documentation.pdf
9207
+ * ```
9208
+ *
9209
+ * @private [🪔] Maybe export the commitments through some package
9210
+ */
9211
+ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
9212
+ constructor() {
9213
+ super('KNOWLEDGE');
9214
+ }
9215
+ /**
9216
+ * Short one-line description of KNOWLEDGE.
9217
+ */
9218
+ get description() {
9219
+ return 'Add domain **knowledge** via direct text or external sources (RAG).';
9220
+ }
9221
+ /**
9222
+ * Icon for this commitment.
9223
+ */
9224
+ get icon() {
9225
+ return '🧠';
9226
+ }
9227
+ /**
9228
+ * Markdown documentation for KNOWLEDGE commitment.
9229
+ */
9230
+ get documentation() {
9231
+ return spaceTrim$1(`
9232
+ # ${this.type}
9233
+
9234
+ Adds specific knowledge, facts, or context to the agent using a RAG (Retrieval-Augmented Generation) approach for external sources.
9235
+
9236
+ ## Key aspects
9237
+
9238
+ - Both terms work identically and can be used interchangeably.
9239
+ - Supports both direct text knowledge and external URLs.
9240
+ - External sources (PDFs, websites) are processed via RAG for context retrieval.
9241
+
9242
+ ## Supported formats
9243
+
9244
+ - Direct text: Immediate knowledge incorporated into agent
9245
+ - URLs: External documents processed for contextual retrieval
9246
+ - Supported file types: PDF, text, markdown, HTML
9247
+
9248
+ ## Examples
9249
+
9250
+ \`\`\`book
9251
+ Customer Support Bot
9252
+
9253
+ PERSONA You are a helpful customer support agent for TechCorp
9254
+ KNOWLEDGE TechCorp was founded in 2020 and specializes in AI-powered solutions
9255
+ KNOWLEDGE https://example.com/company-handbook.pdf
9256
+ KNOWLEDGE https://example.com/product-documentation.pdf
9257
+ RULE Always be polite and professional
9258
+ \`\`\`
9259
+
9260
+ \`\`\`book
9261
+ Research Assistant
9262
+
9263
+ PERSONA You are a knowledgeable research assistant
9264
+ KNOWLEDGE Academic research requires careful citation and verification
9265
+ KNOWLEDGE https://example.com/research-guidelines.pdf
9266
+ ACTION Can help with literature reviews and data analysis
9267
+ STYLE Present information in clear, academic format
9268
+ \`\`\`
9269
+ `);
9270
+ }
9271
+ applyToAgentModelRequirements(requirements, content) {
9272
+ const trimmedContent = content.trim();
9273
+ if (!trimmedContent) {
9274
+ return requirements;
9275
+ }
9276
+ // Check if content is a URL (external knowledge source)
9277
+ if (isValidUrl(trimmedContent)) {
9278
+ // Store the URL for later async processing
9279
+ const updatedRequirements = {
9280
+ ...requirements,
9281
+ knowledgeSources: [
9282
+ ...(requirements.knowledgeSources || []),
9283
+ trimmedContent,
9284
+ ],
9285
+ };
9286
+ // Add placeholder information about knowledge sources to system message
9287
+ const knowledgeInfo = `Knowledge Source URL: ${trimmedContent} (will be processed for retrieval during chat)`;
9288
+ return this.appendToSystemMessage(updatedRequirements, knowledgeInfo, '\n\n');
9289
+ }
9290
+ else {
9291
+ // Direct text knowledge - add to system message
9292
+ const knowledgeSection = `Knowledge: ${trimmedContent}`;
9293
+ return this.appendToSystemMessage(requirements, knowledgeSection, '\n\n');
9294
+ }
9295
+ }
9296
+ }
9297
+ /**
9298
+ * Note: [💞] Ignore a discrepancy between file name and entity name
9299
+ */
9300
+
9301
+ /**
9302
+ * LANGUAGE commitment definition
9303
+ *
9304
+ * The LANGUAGE/LANGUAGES commitment specifies the language(s) the agent should use in its responses.
9305
+ *
9306
+ * Example usage in agent source:
9307
+ *
9308
+ * ```book
9309
+ * LANGUAGE English
9310
+ * LANGUAGE French, English and Czech
9311
+ * ```
9312
+ *
9313
+ * @private [🪔] Maybe export the commitments through some package
9314
+ */
9315
+ class LanguageCommitmentDefinition extends BaseCommitmentDefinition {
9316
+ constructor(type = 'LANGUAGE') {
9317
+ super(type);
9318
+ }
9319
+ /**
9320
+ * Short one-line description of LANGUAGE/LANGUAGES.
9321
+ */
9322
+ get description() {
9323
+ return 'Specifies the language(s) the agent should use.';
9324
+ }
9325
+ /**
9326
+ * Icon for this commitment.
9327
+ */
9328
+ get icon() {
9329
+ return '🌐';
9330
+ }
9331
+ /**
9332
+ * Markdown documentation for LANGUAGE/LANGUAGES commitment.
9333
+ */
9334
+ get documentation() {
9335
+ return spaceTrim$1(`
9336
+ # ${this.type}
9337
+
9338
+ Specifies the language(s) the agent should use in its responses.
9339
+ This is a specialized variation of the RULE commitment focused on language constraints.
9340
+
9341
+ ## Examples
9342
+
9343
+ \`\`\`book
9344
+ Paul Smith & Associés
9345
+
9346
+ PERSONA You are a company lawyer.
9347
+ LANGUAGE French, English and Czech
9348
+ \`\`\`
9349
+
9350
+ \`\`\`book
9351
+ Customer Support
9352
+
9353
+ PERSONA You are a customer support agent.
9354
+ LANGUAGE English
9355
+ \`\`\`
9356
+ `);
9357
+ }
9358
+ applyToAgentModelRequirements(requirements, content) {
9359
+ const trimmedContent = content.trim();
9360
+ if (!trimmedContent) {
9361
+ return requirements;
9362
+ }
9363
+ // Add language rule to the system message
9364
+ const languageSection = `Language: ${trimmedContent}`;
9365
+ return this.appendToSystemMessage(requirements, languageSection, '\n\n');
9366
+ }
9367
+ }
9368
+ /**
9369
+ * Note: [💞] Ignore a discrepancy between file name and entity name
9370
+ */
9371
+
9372
+ /**
9373
+ * MEMORY commitment definition
9374
+ *
9375
+ * The MEMORY commitment is similar to KNOWLEDGE but has a focus on remembering past
9376
+ * interactions and user preferences. It helps the agent maintain context about the
9377
+ * user's history, preferences, and previous conversations.
9378
+ *
9379
+ * Example usage in agent source:
9380
+ *
9381
+ * ```book
9382
+ * MEMORY User prefers detailed technical explanations
9383
+ * MEMORY Previously worked on React projects
9384
+ * MEMORY Timezone: UTC-5 (Eastern Time)
9385
+ * ```
9386
+ *
9387
+ * @private [🪔] Maybe export the commitments through some package
9388
+ */
9389
+ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
9390
+ constructor(type = 'MEMORY') {
9391
+ super(type);
9392
+ }
9393
+ /**
9394
+ * Short one-line description of MEMORY.
9395
+ */
9396
+ get description() {
9397
+ return 'Remember past interactions and user **preferences** for personalized responses.';
9398
+ }
9399
+ /**
9400
+ * Icon for this commitment.
9401
+ */
9402
+ get icon() {
9403
+ return '🧠';
9404
+ }
9405
+ /**
9406
+ * Markdown documentation for MEMORY commitment.
9407
+ */
9408
+ get documentation() {
9409
+ return spaceTrim$1(`
9410
+ # ${this.type}
9411
+
9412
+ 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.
9413
+
9414
+ ## Key aspects
9415
+
9416
+ - Both terms work identically and can be used interchangeably.
9417
+ - Focuses on user-specific information and interaction history.
9418
+ - Helps personalize responses based on past interactions.
9419
+ - Maintains continuity across conversations.
9420
+
9421
+ ## Differences from KNOWLEDGE
9422
+
9423
+ - \`KNOWLEDGE\` is for domain expertise and factual information
9424
+ - \`MEMORY\` is for user-specific context and preferences
9425
+ - \`MEMORY\` creates more personalized interactions
9426
+ - \`MEMORY\` often includes temporal or preference-based information
9427
+
9428
+ ## Examples
9429
+
9430
+ \`\`\`book
9431
+ Personal Assistant
9432
+
9433
+ PERSONA You are a personal productivity assistant
9434
+ MEMORY User is a software developer working in JavaScript/React
9435
+ MEMORY User prefers morning work sessions and afternoon meetings
9436
+ MEMORY Previously helped with project planning for mobile apps
9437
+ MEMORY User timezone: UTC-8 (Pacific Time)
9438
+ GOAL Help optimize daily productivity and workflow
9439
+ \`\`\`
9440
+
9441
+ \`\`\`book
9442
+ Learning Companion
9443
+
9444
+ PERSONA You are an educational companion for programming students
9445
+ MEMORY Student is learning Python as their first programming language
9446
+ MEMORY Previous topics covered: variables, loops, functions
9447
+ MEMORY Student learns best with practical examples and exercises
9448
+ MEMORY Last session: working on list comprehensions
9449
+ GOAL Provide progressive learning experiences tailored to student's pace
9450
+ \`\`\`
9451
+
9452
+ \`\`\`book
9453
+ Customer Support Agent
9454
+
9455
+ PERSONA You are a customer support representative
9456
+ MEMORY Customer has premium subscription since 2023
9457
+ MEMORY Previous issue: billing question resolved last month
9458
+ MEMORY Customer prefers email communication over phone calls
9459
+ MEMORY Account shows frequent use of advanced features
9460
+ GOAL Provide personalized support based on customer history
9461
+ \`\`\`
9462
+ `);
9463
+ }
9464
+ applyToAgentModelRequirements(requirements, content) {
9465
+ const trimmedContent = content.trim();
9466
+ if (!trimmedContent) {
9467
+ return requirements;
9468
+ }
9469
+ // Create memory section for system message
9470
+ const memorySection = `Memory: ${trimmedContent}`;
9471
+ // Memory information is contextual and should be included in the system message
9472
+ return this.appendToSystemMessage(requirements, memorySection, '\n\n');
9473
+ }
9474
+ }
9475
+ /**
9476
+ * Note: [💞] Ignore a discrepancy between file name and entity name
9477
+ */
9478
+
9479
+ /**
9480
+ * AGENT MESSAGE commitment definition
9481
+ *
9482
+ * The AGENT MESSAGE commitment defines a message from the agent in the conversation history.
9483
+ * It is used to pre-fill the chat with a conversation history or to provide few-shot examples.
9484
+ *
9485
+ * Example usage in agent source:
9486
+ *
9487
+ * ```book
9488
+ * AGENT MESSAGE What seems to be the issue?
9489
+ * ```
9490
+ *
9491
+ * @private [🪔] Maybe export the commitments through some package
9492
+ */
9493
+ class AgentMessageCommitmentDefinition extends BaseCommitmentDefinition {
9494
+ constructor() {
9495
+ super('AGENT MESSAGE');
9496
+ }
9497
+ /**
9498
+ * Short one-line description of AGENT MESSAGE.
9499
+ */
9500
+ get description() {
9501
+ return 'Defines a **message from the agent** in the conversation history.';
9502
+ }
9503
+ /**
9504
+ * Icon for this commitment.
9505
+ */
9506
+ get icon() {
9507
+ return '🤖';
9508
+ }
9509
+ /**
9510
+ * Markdown documentation for AGENT MESSAGE commitment.
9511
+ */
9512
+ get documentation() {
9513
+ return spaceTrim$1(`
9514
+ # ${this.type}
9515
+
9516
+ 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.
9517
+
9518
+ ## Key aspects
9519
+
9520
+ - Represents a message sent by the agent.
9521
+ - Used for setting up conversation context.
9522
+ - Can be used in conjunction with USER MESSAGE.
9523
+
9524
+ ## Examples
9525
+
9526
+ \`\`\`book
9527
+ Conversation History
9528
+
9529
+ USER MESSAGE Hello, I have a problem.
9530
+ AGENT MESSAGE What seems to be the issue?
9531
+ USER MESSAGE My computer is not starting.
9532
+ \`\`\`
9533
+ `);
9534
+ }
9535
+ applyToAgentModelRequirements(requirements, content) {
9536
+ // AGENT MESSAGE is for UI display purposes / conversation history construction
9537
+ // and typically doesn't need to be added to the system prompt or model requirements directly.
9538
+ // It is extracted separately for the chat interface.
9539
+ var _a;
9540
+ const pendingUserMessage = (_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.pendingUserMessage;
9541
+ if (pendingUserMessage) {
9542
+ const newSample = { question: pendingUserMessage, answer: content };
9543
+ const newSamples = [...(requirements.samples || []), newSample];
9544
+ const newMetadata = { ...requirements.metadata };
9545
+ delete newMetadata.pendingUserMessage;
9546
+ return {
9547
+ ...requirements,
9548
+ samples: newSamples,
9549
+ metadata: newMetadata,
9550
+ };
9551
+ }
9552
+ return requirements;
9553
+ }
9554
+ }
9555
+
9556
+ /**
9557
+ * INITIAL MESSAGE commitment definition
9558
+ *
9559
+ * The INITIAL MESSAGE commitment defines the first message that the user sees when opening the chat.
9560
+ * It is used to greet the user and set the tone of the conversation.
9561
+ *
9562
+ * Example usage in agent source:
9563
+ *
9564
+ * ```book
9565
+ * INITIAL MESSAGE Hello! I am ready to help you with your tasks.
9566
+ * ```
9567
+ *
9568
+ * @private [🪔] Maybe export the commitments through some package
9569
+ */
9570
+ class InitialMessageCommitmentDefinition extends BaseCommitmentDefinition {
9571
+ constructor() {
9572
+ super('INITIAL MESSAGE');
9573
+ }
9574
+ /**
9575
+ * Short one-line description of INITIAL MESSAGE.
9576
+ */
9577
+ get description() {
9578
+ return 'Defines the **initial message** shown to the user when the chat starts.';
9579
+ }
9580
+ /**
9581
+ * Icon for this commitment.
9582
+ */
9583
+ get icon() {
9584
+ return '👋';
9585
+ }
9586
+ /**
9587
+ * Markdown documentation for INITIAL MESSAGE commitment.
9588
+ */
9589
+ get documentation() {
9590
+ return spaceTrim$1(`
9591
+ # ${this.type}
9592
+
9593
+ 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).
9594
+
9595
+ ## Key aspects
9596
+
9597
+ - Used to greet the user.
9598
+ - Sets the tone of the conversation.
9599
+ - Displayed immediately when the chat interface loads.
9600
+
9601
+ ## Examples
9602
+
9603
+ \`\`\`book
9604
+ Support Agent
9605
+
9606
+ PERSONA You are a helpful support agent.
9607
+ INITIAL MESSAGE Hi there! How can I assist you today?
9608
+ \`\`\`
9609
+ `);
9610
+ }
9611
+ applyToAgentModelRequirements(requirements, content) {
9612
+ // INITIAL MESSAGE is for UI display purposes and for conversation history construction.
9613
+ const newSample = { question: null, answer: content };
9614
+ const newSamples = [...(requirements.samples || []), newSample];
9615
+ return {
9616
+ ...requirements,
9617
+ samples: newSamples,
9618
+ };
9619
+ }
9620
+ }
9621
+
9622
+ /**
9623
+ * MESSAGE commitment definition
9624
+ *
9625
+ * The MESSAGE commitment contains 1:1 text of the message which AI assistant already
9626
+ * sent during the conversation. Later messages are later in the conversation.
9627
+ * It is similar to EXAMPLE but it is not example, it is the real message which
9628
+ * AI assistant already sent.
9629
+ *
9630
+ * Example usage in agent source:
9631
+ *
9632
+ * ```book
9633
+ * MESSAGE Hello! How can I help you today?
9634
+ * MESSAGE I understand you're looking for information about our services.
9635
+ * MESSAGE Based on your requirements, I'd recommend our premium package.
9636
+ * ```
9637
+ *
9638
+ * @private [🪔] Maybe export the commitments through some package
9639
+ */
9640
+ class MessageCommitmentDefinition extends BaseCommitmentDefinition {
9641
+ constructor(type = 'MESSAGE') {
9642
+ super(type);
9643
+ }
9644
+ /**
9645
+ * Short one-line description of MESSAGE.
9646
+ */
9647
+ get description() {
9648
+ return 'Include actual **messages** the AI assistant has sent during conversation history.';
9649
+ }
9650
+ /**
9651
+ * Icon for this commitment.
9652
+ */
9653
+ get icon() {
9654
+ return '💬';
9655
+ }
9656
+ /**
9657
+ * Markdown documentation for MESSAGE commitment.
9658
+ */
9659
+ get documentation() {
9660
+ return spaceTrim$1(`
9661
+ # ${this.type}
9662
+
9663
+ 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.
9664
+
9665
+ ## Key aspects
9666
+
9667
+ - Multiple \`MESSAGE\` and \`MESSAGES\` commitments represent the conversation timeline.
9668
+ - Both terms work identically and can be used interchangeably.
9669
+ - Later messages are later in the conversation chronologically.
9670
+ - Contains actual historical messages, not examples or templates.
9671
+ - Helps maintain conversation continuity and context.
9672
+
9673
+ ## Differences from EXAMPLE
9674
+
9675
+ - \`EXAMPLE\` shows hypothetical or template responses
9676
+ - \`MESSAGE\`/\`MESSAGES\` contains actual historical conversation content
9677
+ - \`MESSAGE\`/\`MESSAGES\` preserves the exact conversation flow
9678
+ - \`MESSAGE\`/\`MESSAGES\` helps with context awareness and consistency
9679
+
9680
+ ## Use cases
9681
+
9682
+ - Maintaining conversation history context
9683
+ - Ensuring consistent tone and style across messages
9684
+ - Referencing previous responses in ongoing conversations
9685
+ - Building upon previously established context
9686
+
9687
+ ## Examples
9688
+
9689
+ \`\`\`book
9690
+ Customer Support Continuation
9691
+
9692
+ PERSONA You are a helpful customer support agent
9693
+ MESSAGE Hello! How can I help you today?
9694
+ MESSAGE I understand you're experiencing issues with your account login.
9695
+ MESSAGE I've sent you a password reset link to your email address.
9696
+ MESSAGE Is there anything else I can help you with regarding your account?
9697
+ GOAL Continue providing consistent support based on conversation history
9698
+ \`\`\`
9699
+
9700
+ \`\`\`book
9701
+ Technical Discussion
9702
+
9703
+ PERSONA You are a software development mentor
9704
+ MESSAGE Let's start by reviewing the React component structure you shared.
9705
+ MESSAGE I notice you're using class components - have you considered hooks?
9706
+ MESSAGE Here's how you could refactor that using the useState hook.
9707
+ MESSAGE Great question about performance! Let me explain React's rendering cycle.
9708
+ KNOWLEDGE React hooks were introduced in version 16.8
9709
+ \`\`\`
9710
+
9711
+ \`\`\`book
9712
+ Educational Session
9713
+
9714
+ PERSONA You are a mathematics tutor
9715
+ MESSAGE Today we'll work on solving quadratic equations.
9716
+ MESSAGE Let's start with the basic form: ax² + bx + c = 0
9717
+ MESSAGE Remember, we can use the quadratic formula or factoring.
9718
+ MESSAGE You did great with that first problem! Let's try a more complex one.
9719
+ GOAL Build upon previous explanations for deeper understanding
9720
+ \`\`\`
9721
+ `);
9722
+ }
9723
+ applyToAgentModelRequirements(requirements, content) {
9724
+ const trimmedContent = content.trim();
9725
+ if (!trimmedContent) {
9726
+ return requirements;
9727
+ }
9728
+ // Create message section for system message
9729
+ const messageSection = `Previous Message: ${trimmedContent}`;
9730
+ // Messages represent conversation history and should be included for context
9731
+ return this.appendToSystemMessage(requirements, messageSection, '\n\n');
9732
+ }
9733
+ }
9734
+ /**
9735
+ * Note: [💞] Ignore a discrepancy between file name and entity name
9736
+ */
9737
+
9738
+ /**
9739
+ * USER MESSAGE commitment definition
9740
+ *
9741
+ * The USER MESSAGE commitment defines a message from the user in the conversation history.
9742
+ * It is used to pre-fill the chat with a conversation history or to provide few-shot examples.
9743
+ *
9744
+ * Example usage in agent source:
9745
+ *
9746
+ * ```book
9747
+ * USER MESSAGE Hello, I have a problem.
9748
+ * ```
9749
+ *
9750
+ * @private [🪔] Maybe export the commitments through some package
9751
+ */
9752
+ class UserMessageCommitmentDefinition extends BaseCommitmentDefinition {
9753
+ constructor() {
9754
+ super('USER MESSAGE');
9755
+ }
9756
+ /**
9757
+ * Short one-line description of USER MESSAGE.
9758
+ */
9759
+ get description() {
9760
+ return 'Defines a **message from the user** in the conversation history.';
9761
+ }
9762
+ /**
9763
+ * Icon for this commitment.
9764
+ */
9765
+ get icon() {
9766
+ return '🧑';
9767
+ }
9768
+ /**
9769
+ * Markdown documentation for USER MESSAGE commitment.
9770
+ */
9771
+ get documentation() {
9772
+ return spaceTrim$1(`
9773
+ # ${this.type}
9774
+
9775
+ 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.
9776
+
9777
+ ## Key aspects
9778
+
9779
+ - Represents a message sent by the user.
9780
+ - Used for setting up conversation context.
9781
+ - Can be used in conjunction with AGENT MESSAGE.
9782
+
9783
+ ## Examples
9784
+
9785
+ \`\`\`book
9786
+ Conversation History
9787
+
9788
+ USER MESSAGE Hello, I have a problem.
9789
+ AGENT MESSAGE What seems to be the issue?
9790
+ USER MESSAGE My computer is not starting.
9791
+ \`\`\`
9792
+ `);
9793
+ }
9794
+ applyToAgentModelRequirements(requirements, content) {
9795
+ return {
9796
+ ...requirements,
9797
+ metadata: {
9798
+ ...requirements.metadata,
9799
+ pendingUserMessage: content,
9800
+ },
9801
+ };
9802
+ }
9803
+ }
9804
+
9805
+ /**
9806
+ * META commitment definition
9807
+ *
9808
+ * The META commitment handles all meta-information about the agent such as:
9809
+ * - META IMAGE: Sets the agent's avatar/profile image URL
9810
+ * - META LINK: Provides profile/source links for the person the agent models
9811
+ * - META TITLE: Sets the agent's display title
9812
+ * - META DESCRIPTION: Sets the agent's description
9813
+ * - META [ANYTHING]: Any other meta information in uppercase format
9814
+ *
9815
+ * These commitments are special because they don't affect the system message,
9816
+ * but are handled separately in the parsing logic for profile display.
9817
+ *
9818
+ * Example usage in agent source:
9819
+ *
9820
+ * ```book
9821
+ * META IMAGE https://example.com/avatar.jpg
9822
+ * META LINK https://twitter.com/username
9823
+ * META TITLE Professional Assistant
9824
+ * META DESCRIPTION An AI assistant specialized in business tasks
9825
+ * META AUTHOR John Doe
9826
+ * META VERSION 1.0
9827
+ * ```
9828
+ *
9829
+ * @private [🪔] Maybe export the commitments through some package
9830
+ */
9831
+ class MetaCommitmentDefinition extends BaseCommitmentDefinition {
9832
+ constructor() {
9833
+ super('META');
9834
+ }
9835
+ /**
9836
+ * Short one-line description of META commitments.
9837
+ */
9838
+ get description() {
9839
+ return 'Set meta-information about the agent (IMAGE, LINK, TITLE, DESCRIPTION, etc.).';
9840
+ }
9841
+ /**
9842
+ * Icon for this commitment.
9843
+ */
9844
+ get icon() {
9845
+ return 'ℹ️';
9846
+ }
9847
+ /**
9848
+ * Markdown documentation for META commitment.
9849
+ */
9850
+ get documentation() {
9851
+ return spaceTrim$1(`
9852
+ # META
9853
+
9854
+ Sets meta-information about the agent that is used for display and attribution purposes.
9855
+
9856
+ ## Supported META types
9857
+
9858
+ - **META IMAGE** - Sets the agent's avatar/profile image URL
9859
+ - **META LINK** - Provides profile/source links for the person the agent models
9860
+ - **META TITLE** - Sets the agent's display title
9861
+ - **META DESCRIPTION** - Sets the agent's description
9862
+ - **META [ANYTHING]** - Any other meta information in uppercase format
9863
+
9864
+ ## Key aspects
9865
+
9866
+ - Does not modify the agent's behavior or responses
9867
+ - Used for visual representation and attribution in user interfaces
9868
+ - Multiple META commitments of different types can be used
9869
+ - Multiple META LINK commitments can be used for different social profiles
9870
+ - If multiple META commitments of the same type are specified, the last one takes precedence (except for LINK)
9871
+
9872
+ ## Examples
9873
+
9874
+ ### Basic meta information
9875
+
9876
+ \`\`\`book
9877
+ Professional Assistant
9878
+
9879
+ META IMAGE https://example.com/professional-avatar.jpg
9880
+ META TITLE Senior Business Consultant
9881
+ META DESCRIPTION Specialized in strategic planning and project management
9882
+ META LINK https://linkedin.com/in/professional
9883
+ \`\`\`
9884
+
9885
+ ### Multiple links and custom meta
9886
+
9887
+ \`\`\`book
9888
+ Open Source Developer
9889
+
9890
+ META IMAGE /assets/dev-avatar.png
9891
+ META LINK https://github.com/developer
9892
+ META LINK https://twitter.com/devhandle
9893
+ META AUTHOR Jane Smith
9894
+ META VERSION 2.1
9895
+ META LICENSE MIT
9896
+ \`\`\`
9897
+
9898
+ ### Creative assistant
9899
+
9900
+ \`\`\`book
9901
+ Creative Helper
9902
+
9903
+ META IMAGE https://example.com/creative-bot.jpg
9904
+ META TITLE Creative Writing Assistant
9905
+ META DESCRIPTION Helps with brainstorming, storytelling, and creative projects
9906
+ META INSPIRATION Books, movies, and real-world experiences
9907
+ \`\`\`
9908
+ `);
9909
+ }
9910
+ applyToAgentModelRequirements(requirements, content) {
9911
+ // META commitments don't modify the system message or model requirements
9912
+ // They are handled separately in the parsing logic for meta information extraction
9913
+ // This method exists for consistency with the CommitmentDefinition interface
9914
+ return requirements;
9915
+ }
9916
+ /**
9917
+ * Extracts meta information from the content based on the meta type
9918
+ * This is used by the parsing logic
9919
+ */
9920
+ extractMetaValue(metaType, content) {
9921
+ const trimmedContent = content.trim();
9922
+ return trimmedContent || null;
9923
+ }
9924
+ /**
9925
+ * Validates if the provided content is a valid URL (for IMAGE and LINK types)
9926
+ */
9927
+ isValidUrl(content) {
9928
+ try {
9929
+ new URL(content.trim());
9930
+ return true;
9931
+ }
9932
+ catch (_a) {
9933
+ return false;
9934
+ }
9935
+ }
9936
+ /**
9937
+ * Checks if this is a known meta type
9938
+ */
9939
+ isKnownMetaType(metaType) {
9940
+ const knownTypes = ['IMAGE', 'LINK', 'TITLE', 'DESCRIPTION', 'AUTHOR', 'VERSION', 'LICENSE'];
9941
+ return knownTypes.includes(metaType.toUpperCase());
9942
+ }
9943
+ }
9944
+ /**
9945
+ * Note: [💞] Ignore a discrepancy between file name and entity name
9946
+ */
9947
+
9948
+ /**
9949
+ * META COLOR commitment definition
9950
+ *
9951
+ * The META COLOR commitment sets the agent's accent color.
9952
+ * This commitment is special because it doesn't affect the system message,
9953
+ * but is handled separately in the parsing logic.
9954
+ *
9955
+ * Example usage in agent source:
9956
+ *
9957
+ * ```book
9958
+ * META COLOR #ff0000
9959
+ * META COLOR #00ff00
9960
+ * ```
9961
+ *
9962
+ * You can also specify multiple colors separated by comma:
9963
+ *
9964
+ * ```book
9965
+ * META COLOR #ff0000, #00ff00, #0000ff
9966
+ * ```
9967
+ *
9968
+ * @private [🪔] Maybe export the commitments through some package
9969
+ */
9970
+ class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
9971
+ constructor() {
9972
+ super('META COLOR', ['COLOR']);
9973
+ }
9974
+ /**
9975
+ * Short one-line description of META COLOR.
9976
+ */
9977
+ get description() {
9978
+ return "Set the agent's accent color or gradient.";
9979
+ }
9980
+ /**
9981
+ * Icon for this commitment.
9982
+ */
9983
+ get icon() {
9984
+ return '🎨';
9985
+ }
9986
+ /**
9987
+ * Markdown documentation for META COLOR commitment.
9988
+ */
9989
+ get documentation() {
9990
+ return spaceTrim$1(`
9991
+ # META COLOR
9992
+
9993
+ Sets the agent's accent color or gradient.
9994
+
9995
+ ## Key aspects
9996
+
9997
+ - Does not modify the agent's behavior or responses.
9998
+ - Only one \`META COLOR\` should be used per agent.
9999
+ - If multiple are specified, the last one takes precedence.
10000
+ - Used for visual representation in user interfaces.
10001
+ - Can specify multiple colors separated by comma to create a gradient.
10002
+
10003
+ ## Examples
10004
+
10005
+ \`\`\`book
10006
+ Professional Assistant
10007
+
10008
+ META COLOR #3498db
10009
+ PERSONA You are a professional business assistant
10010
+ \`\`\`
10011
+
10012
+ \`\`\`book
10013
+ Creative Helper
10014
+
10015
+ META COLOR #e74c3c
10016
+ PERSONA You are a creative and inspiring assistant
10017
+ \`\`\`
10018
+
10019
+ \`\`\`book
10020
+ Gradient Agent
10021
+
10022
+ META COLOR #ff0000, #00ff00, #0000ff
10023
+ PERSONA You are a colorful agent
10024
+ \`\`\`
10025
+ `);
10026
+ }
10027
+ applyToAgentModelRequirements(requirements, content) {
10028
+ // META COLOR doesn't modify the system message or model requirements
10029
+ // It's handled separately in the parsing logic for profile color extraction
10030
+ // This method exists for consistency with the CommitmentDefinition interface
10031
+ return requirements;
10032
+ }
10033
+ /**
10034
+ * Extracts the profile color from the content
10035
+ * This is used by the parsing logic
10036
+ */
10037
+ extractProfileColor(content) {
10038
+ const trimmedContent = content.trim();
10039
+ return trimmedContent || null;
10040
+ }
10041
+ }
10042
+ /**
10043
+ * Note: [💞] Ignore a discrepancy between file name and entity name
10044
+ */
10045
+
10046
+ /**
10047
+ * META FONT commitment definition
10048
+ *
10049
+ * The META FONT commitment sets the agent's font.
10050
+ * This commitment is special because it doesn't affect the system message,
10051
+ * but is handled separately in the parsing logic.
10052
+ *
10053
+ * Example usage in agent source:
10054
+ *
10055
+ * ```book
10056
+ * META FONT Poppins, Arial, sans-serif
10057
+ * META FONT Roboto
10058
+ * ```
10059
+ *
10060
+ * @private [🪔] Maybe export the commitments through some package
10061
+ */
10062
+ class MetaFontCommitmentDefinition extends BaseCommitmentDefinition {
10063
+ constructor() {
10064
+ super('META FONT', ['FONT']);
10065
+ }
10066
+ /**
10067
+ * Short one-line description of META FONT.
10068
+ */
10069
+ get description() {
10070
+ return "Set the agent's font.";
10071
+ }
10072
+ /**
10073
+ * Icon for this commitment.
10074
+ */
10075
+ get icon() {
10076
+ return '🔤';
10077
+ }
10078
+ /**
10079
+ * Markdown documentation for META FONT commitment.
10080
+ */
10081
+ get documentation() {
10082
+ return spaceTrim$1(`
10083
+ # META FONT
10084
+
10085
+ Sets the agent's font.
10086
+
10087
+ ## Key aspects
10088
+
10089
+ - Does not modify the agent's behavior or responses.
10090
+ - Only one \`META FONT\` should be used per agent.
10091
+ - If multiple are specified, the last one takes precedence.
10092
+ - Used for visual representation in user interfaces.
10093
+ - Supports Google Fonts.
10094
+
10095
+ ## Examples
10096
+
10097
+ \`\`\`book
10098
+ Modern Assistant
10099
+
10100
+ META FONT Poppins, Arial, sans-serif
10101
+ PERSONA You are a modern assistant
10102
+ \`\`\`
10103
+
10104
+ \`\`\`book
10105
+ Classic Helper
10106
+
10107
+ META FONT Times New Roman
10108
+ PERSONA You are a classic helper
10109
+ \`\`\`
10110
+ `);
10111
+ }
10112
+ applyToAgentModelRequirements(requirements, content) {
10113
+ // META FONT doesn't modify the system message or model requirements
10114
+ // It's handled separately in the parsing logic
10115
+ // This method exists for consistency with the CommitmentDefinition interface
10116
+ return requirements;
10117
+ }
10118
+ /**
10119
+ * Extracts the font from the content
10120
+ * This is used by the parsing logic
10121
+ */
10122
+ extractProfileFont(content) {
10123
+ const trimmedContent = content.trim();
10124
+ return trimmedContent || null;
10125
+ }
10126
+ }
10127
+ /**
10128
+ * Note: [💞] Ignore a discrepancy between file name and entity name
10129
+ */
10130
+
10131
+ /**
10132
+ * META IMAGE commitment definition
10133
+ *
10134
+ * The META IMAGE commitment sets the agent's avatar/profile image URL.
10135
+ * This commitment is special because it doesn't affect the system message,
10136
+ * but is handled separately in the parsing logic.
10137
+ *
10138
+ * Example usage in agent source:
10139
+ *
10140
+ * ```book
10141
+ * META IMAGE https://example.com/avatar.jpg
10142
+ * META IMAGE /assets/agent-avatar.png
10143
+ * ```
10144
+ *
10145
+ * @private [🪔] Maybe export the commitments through some package
10146
+ */
10147
+ class MetaImageCommitmentDefinition extends BaseCommitmentDefinition {
10148
+ constructor() {
10149
+ super('META IMAGE', ['IMAGE']);
10150
+ }
10151
+ /**
10152
+ * Short one-line description of META IMAGE.
10153
+ */
10154
+ get description() {
10155
+ return "Set the agent's profile image URL.";
10156
+ }
10157
+ /**
10158
+ * Icon for this commitment.
10159
+ */
10160
+ get icon() {
10161
+ return '🖼️';
10162
+ }
10163
+ /**
10164
+ * Markdown documentation for META IMAGE commitment.
10165
+ */
10166
+ get documentation() {
10167
+ return spaceTrim$1(`
10168
+ # META IMAGE
10169
+
10170
+ Sets the agent's avatar/profile image URL.
10171
+
10172
+ ## Key aspects
10173
+
10174
+ - Does not modify the agent's behavior or responses.
10175
+ - Only one \`META IMAGE\` should be used per agent.
10176
+ - If multiple are specified, the last one takes precedence.
10177
+ - Used for visual representation in user interfaces.
10178
+
10179
+ ## Examples
10180
+
10181
+ \`\`\`book
10182
+ Professional Assistant
10183
+
10184
+ META IMAGE https://example.com/professional-avatar.jpg
10185
+ PERSONA You are a professional business assistant
10186
+ STYLE Maintain a formal and courteous tone
10187
+ \`\`\`
10188
+
10189
+ \`\`\`book
10190
+ Creative Helper
10191
+
10192
+ META IMAGE /assets/creative-bot-avatar.png
10193
+ PERSONA You are a creative and inspiring assistant
10194
+ STYLE Be enthusiastic and encouraging
10195
+ ACTION Can help with brainstorming and ideation
10196
+ \`\`\`
10197
+ `);
10198
+ }
10199
+ applyToAgentModelRequirements(requirements, content) {
10200
+ // META IMAGE doesn't modify the system message or model requirements
10201
+ // It's handled separately in the parsing logic for profile image extraction
10202
+ // This method exists for consistency with the CommitmentDefinition interface
10203
+ return requirements;
10204
+ }
10205
+ /**
10206
+ * Extracts the profile image URL from the content
10207
+ * This is used by the parsing logic
10208
+ */
10209
+ extractProfileImageUrl(content) {
10210
+ const trimmedContent = content.trim();
10211
+ return trimmedContent || null;
10212
+ }
10213
+ }
10214
+ /**
10215
+ * Note: [💞] Ignore a discrepancy between file name and entity name
10216
+ */
10217
+
10218
+ /**
10219
+ * META LINK commitment definition
10220
+ *
10221
+ * The `META LINK` commitment represents the link to the person from whom the agent is created.
10222
+ * This commitment is special because it doesn't affect the system message,
10223
+ * but is handled separately in the parsing logic for profile display.
10224
+ *
10225
+ * Example usage in agent source:
10226
+ *
10227
+ * ```
10228
+ * META LINK https://twitter.com/username
10229
+ * META LINK https://linkedin.com/in/profile
10230
+ * META LINK https://github.com/username
10231
+ * ```
10232
+ *
10233
+ * Multiple `META LINK` commitments can be used when there are multiple sources:
10234
+ *
10235
+ * ```book
10236
+ * META LINK https://twitter.com/username
10237
+ * META LINK https://linkedin.com/in/profile
10238
+ * ```
10239
+ *
10240
+ * @private [🪔] Maybe export the commitments through some package
10241
+ */
10242
+ class MetaLinkCommitmentDefinition extends BaseCommitmentDefinition {
10243
+ constructor() {
10244
+ super('META LINK');
10245
+ }
10246
+ /**
10247
+ * Short one-line description of META LINK.
10248
+ */
10249
+ get description() {
10250
+ return 'Provide profile/source links for the person the agent models.';
10251
+ }
10252
+ /**
10253
+ * Icon for this commitment.
10254
+ */
10255
+ get icon() {
10256
+ return '🔗';
10257
+ }
10258
+ /**
10259
+ * Markdown documentation for META LINK commitment.
10260
+ */
10261
+ get documentation() {
10262
+ return spaceTrim$1(`
10263
+ # META LINK
10264
+
10265
+ Represents a profile or source link for the person the agent is modeled after.
10266
+
10267
+ ## Key aspects
10268
+
10269
+ - Does not modify the agent's behavior or responses.
10270
+ - Multiple \`META LINK\` commitments can be used for different social profiles.
10271
+ - Used for attribution and crediting the original person.
10272
+ - Displayed in user interfaces for transparency.
10273
+
10274
+ ## Examples
10275
+
10276
+ \`\`\`book
10277
+ Expert Consultant
10278
+
10279
+ META LINK https://twitter.com/expertname
10280
+ META LINK https://linkedin.com/in/expertprofile
10281
+ PERSONA You are Dr. Smith, a renowned expert in artificial intelligence
10282
+ KNOWLEDGE Extensive background in machine learning and neural networks
10283
+ \`\`\`
10284
+
10285
+ \`\`\`book
10286
+ Open Source Developer
10287
+
10288
+ META LINK https://github.com/developer
10289
+ META LINK https://twitter.com/devhandle
10290
+ PERSONA You are an experienced open source developer
10291
+ ACTION Can help with code reviews and architecture decisions
10292
+ STYLE Be direct and technical in explanations
10293
+ \`\`\`
10294
+ `);
10295
+ }
10296
+ applyToAgentModelRequirements(requirements, content) {
10297
+ // META LINK doesn't modify the system message or model requirements
10298
+ // It's handled separately in the parsing logic for profile link extraction
10299
+ // This method exists for consistency with the CommitmentDefinition interface
10300
+ return requirements;
10301
+ }
10302
+ /**
10303
+ * Extracts the profile link URL from the content
10304
+ * This is used by the parsing logic
10305
+ */
10306
+ extractProfileLinkUrl(content) {
10307
+ const trimmedContent = content.trim();
10308
+ return trimmedContent || null;
10309
+ }
10310
+ /**
10311
+ * Validates if the provided content is a valid URL
10312
+ */
10313
+ isValidUrl(content) {
10314
+ try {
10315
+ new URL(content.trim());
10316
+ return true;
10317
+ }
10318
+ catch (_a) {
10319
+ return false;
10320
+ }
10321
+ }
10322
+ }
10323
+ /**
10324
+ * Note: [💞] Ignore a discrepancy between file name and entity name
10325
+ */
10326
+
10327
+ /**
10328
+ * MODEL commitment definition
10329
+ *
10330
+ * The MODEL commitment specifies which AI model to use and can also set
10331
+ * model-specific parameters like temperature, topP, topK, and maxTokens.
10332
+ *
10333
+ * Supports multiple syntax variations:
10334
+ *
10335
+ * Single-line format:
10336
+ * ```book
10337
+ * MODEL gpt-4
10338
+ * MODEL claude-3-opus temperature=0.3
10339
+ * MODEL gpt-3.5-turbo temperature=0.8 topP=0.9
10340
+ * ```
10341
+ *
10342
+ * Multi-line named parameter format:
10343
+ * ```book
10344
+ * MODEL NAME gpt-4
10345
+ * MODEL TEMPERATURE 0.7
10346
+ * MODEL TOP_P 0.9
10347
+ * MODEL MAX_TOKENS 2048
10348
+ * ```
10349
+ *
10350
+ * @private [🪔] Maybe export the commitments through some package
10351
+ */
10352
+ class ModelCommitmentDefinition extends BaseCommitmentDefinition {
10353
+ constructor(type = 'MODEL') {
10354
+ super(type);
10355
+ }
10356
+ /**
10357
+ * Short one-line description of MODEL.
10358
+ */
10359
+ get description() {
10360
+ return 'Enforce AI model requirements including name and technical parameters.';
10361
+ }
10362
+ /**
10363
+ * Icon for this commitment.
10364
+ */
10365
+ get icon() {
10366
+ return '⚙️';
10367
+ }
10368
+ /**
10369
+ * Markdown documentation for MODEL commitment.
10370
+ */
10371
+ get documentation() {
10372
+ return spaceTrim$1(`
10373
+ # ${this.type}
10374
+
10375
+ Enforces technical parameters for the AI model, ensuring consistent behavior across different execution environments.
10376
+
10377
+ ## Key aspects
10378
+
10379
+ - When no \`MODEL\` commitment is specified, the best model requirement is picked automatically based on the agent \`PERSONA\`, \`KNOWLEDGE\`, \`TOOLS\` and other commitments
10380
+ - Multiple \`MODEL\` commitments can be used to specify different parameters
10381
+ - Both \`MODEL\` and \`MODELS\` terms work identically and can be used interchangeably
10382
+ - Parameters control the randomness, creativity, and technical aspects of model responses
10383
+
10384
+ ## Syntax variations
10385
+
10386
+ ### Single-line format (legacy support)
10387
+ \`\`\`book
10388
+ MODEL gpt-4
10389
+ MODEL claude-3-opus temperature=0.3
10390
+ MODEL gpt-3.5-turbo temperature=0.8 topP=0.9
10391
+ \`\`\`
10392
+
10393
+ ### Multi-line named parameter format (recommended)
10394
+ \`\`\`book
10395
+ MODEL NAME gpt-4
10396
+ MODEL TEMPERATURE 0.7
10397
+ MODEL TOP_P 0.9
10398
+ MODEL MAX_TOKENS 2048
10399
+ \`\`\`
10400
+
10401
+ ## Supported parameters
10402
+
10403
+ - \`NAME\`: The specific model to use (e.g., 'gpt-4', 'claude-3-opus')
10404
+ - \`TEMPERATURE\`: Controls randomness (0.0 = deterministic, 1.0+ = creative)
10405
+ - \`TOP_P\`: Nucleus sampling parameter for controlling diversity
10406
+ - \`TOP_K\`: Top-k sampling parameter for limiting vocabulary
10407
+ - \`MAX_TOKENS\`: Maximum number of tokens the model can generate
10408
+
10409
+ ## Examples
10410
+
10411
+ ### Precise deterministic assistant
10412
+ \`\`\`book
10413
+ Precise Assistant
10414
+
10415
+ PERSONA You are a precise and accurate assistant
10416
+ MODEL NAME gpt-4
10417
+ MODEL TEMPERATURE 0.1
10418
+ MODEL MAX_TOKENS 1024
10419
+ RULE Always provide factual information
10420
+ \`\`\`
10421
+
10422
+ ### Creative writing assistant
10423
+ \`\`\`book
10424
+ Creative Writer
10425
+
10426
+ PERSONA You are a creative writing assistant
10427
+ MODEL NAME claude-3-opus
10428
+ MODEL TEMPERATURE 0.8
10429
+ MODEL TOP_P 0.9
10430
+ MODEL MAX_TOKENS 2048
10431
+ STYLE Be imaginative and expressive
10432
+ ACTION Can help with storytelling and character development
10433
+ \`\`\`
10434
+
10435
+ ### Balanced conversational agent
10436
+ \`\`\`book
10437
+ Balanced Assistant
10438
+
10439
+ PERSONA You are a helpful and balanced assistant
10440
+ MODEL NAME gpt-4
10441
+ MODEL TEMPERATURE 0.7
10442
+ MODEL TOP_P 0.95
10443
+ MODEL TOP_K 40
10444
+ MODEL MAX_TOKENS 1500
10445
+ \`\`\`
10446
+ `);
10447
+ }
10448
+ applyToAgentModelRequirements(requirements, content) {
10449
+ var _a;
10450
+ const trimmedContent = content.trim();
10451
+ if (!trimmedContent) {
10452
+ return requirements;
10453
+ }
10454
+ const parts = trimmedContent.split(/\s+/);
10455
+ const firstPart = (_a = parts[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase();
10456
+ // Check if this is the new named parameter format
10457
+ if (this.isNamedParameter(firstPart)) {
10458
+ return this.parseNamedParameter(requirements, firstPart, parts.slice(1));
10459
+ }
10460
+ else {
10461
+ // Legacy single-line format: "MODEL gpt-4 temperature=0.3 topP=0.9"
10462
+ return this.parseLegacyFormat(requirements, parts);
10463
+ }
10464
+ }
10465
+ /**
10466
+ * Check if the first part is a known named parameter
10467
+ */
10468
+ isNamedParameter(part) {
10469
+ if (!part)
10470
+ return false;
10471
+ const knownParams = ['NAME', 'TEMPERATURE', 'TOP_P', 'TOP_K', 'MAX_TOKENS'];
10472
+ return knownParams.includes(part);
10473
+ }
10474
+ /**
10475
+ * Parse the new named parameter format: "MODEL TEMPERATURE 0.7"
10476
+ */
10477
+ parseNamedParameter(requirements, parameterName, valueParts) {
10478
+ const value = valueParts.join(' ').trim();
10479
+ if (!value) {
10480
+ return requirements;
10481
+ }
10482
+ const result = { ...requirements };
10483
+ switch (parameterName) {
10484
+ case 'NAME':
10485
+ result.modelName = value;
10486
+ break;
10487
+ case 'TEMPERATURE': {
10488
+ const temperature = parseFloat(value);
10489
+ if (!isNaN(temperature)) {
10490
+ result.temperature = temperature;
10491
+ }
10492
+ break;
10493
+ }
10494
+ case 'TOP_P': {
10495
+ const topP = parseFloat(value);
10496
+ if (!isNaN(topP)) {
10497
+ result.topP = topP;
10498
+ }
10499
+ break;
10500
+ }
10501
+ case 'TOP_K': {
10502
+ const topK = parseFloat(value);
10503
+ if (!isNaN(topK)) {
10504
+ result.topK = Math.round(topK);
10505
+ }
10506
+ break;
10507
+ }
10508
+ case 'MAX_TOKENS': {
10509
+ const maxTokens = parseFloat(value);
10510
+ if (!isNaN(maxTokens)) {
10511
+ result.maxTokens = Math.round(maxTokens);
10512
+ }
10513
+ break;
10514
+ }
10515
+ }
10516
+ return result;
10517
+ }
10518
+ /**
10519
+ * Parse the legacy format: "MODEL gpt-4 temperature=0.3 topP=0.9"
10520
+ */
10521
+ parseLegacyFormat(requirements, parts) {
10522
+ const modelName = parts[0];
10523
+ if (!modelName) {
10524
+ return requirements;
10525
+ }
10526
+ // Start with the model name
10527
+ const result = {
10528
+ ...requirements,
10529
+ modelName,
10530
+ };
10531
+ // Parse additional key=value parameters
10532
+ for (let i = 1; i < parts.length; i++) {
10533
+ const param = parts[i];
10534
+ if (param && param.includes('=')) {
10535
+ const [key, value] = param.split('=');
10536
+ if (key && value) {
10537
+ const numValue = parseFloat(value);
10538
+ if (!isNaN(numValue)) {
10539
+ switch (key.toLowerCase()) {
10540
+ case 'temperature':
10541
+ result.temperature = numValue;
10542
+ break;
10543
+ case 'topp':
10544
+ case 'top_p':
10545
+ result.topP = numValue;
10546
+ break;
10547
+ case 'topk':
10548
+ case 'top_k':
10549
+ result.topK = Math.round(numValue);
10550
+ break;
10551
+ case 'max_tokens':
10552
+ case 'maxTokens':
10553
+ result.maxTokens = Math.round(numValue);
10554
+ break;
10555
+ }
10556
+ }
10557
+ }
10558
+ }
10559
+ }
10560
+ return result;
10561
+ }
10562
+ }
10563
+ /**
10564
+ * Note: [💞] Ignore a discrepancy between file name and entity name
10565
+ */
10566
+
10567
+ /**
10568
+ * NOTE commitment definition
10569
+ *
10570
+ * The NOTE commitment is used to add comments to the agent source without making any changes
10571
+ * to the system message or agent model requirements. It serves as a documentation mechanism
10572
+ * for developers to add explanatory comments, reminders, or annotations directly in the agent source.
10573
+ *
10574
+ * Key features:
10575
+ * - Makes no changes to the system message
10576
+ * - Makes no changes to agent model requirements
10577
+ * - Content is preserved in metadata.NOTE for debugging and inspection
10578
+ * - Multiple NOTE commitments are aggregated together
10579
+ * - Comments (# NOTE) are removed from the final system message
10580
+ *
10581
+ * Example usage in agent source:
10582
+ *
10583
+ * ```book
10584
+ * NOTE This agent was designed for customer support scenarios
10585
+ * NOTE Remember to update the knowledge base monthly
10586
+ * NOTE Performance optimized for quick response times
10587
+ * ```
10588
+ *
10589
+ * The above notes will be stored in metadata but won't affect the agent's behavior.
10590
+ *
10591
+ * @private [🪔] Maybe export the commitments through some package
10592
+ */
10593
+ class NoteCommitmentDefinition extends BaseCommitmentDefinition {
10594
+ constructor(type = 'NOTE') {
10595
+ super(type);
10596
+ }
10597
+ /**
10598
+ * Short one-line description of NOTE.
10599
+ */
10600
+ get description() {
10601
+ return 'Add developer-facing notes without changing behavior or output.';
10602
+ }
10603
+ /**
10604
+ * Icon for this commitment.
10605
+ */
10606
+ get icon() {
10607
+ return '📝';
10608
+ }
10609
+ /**
10610
+ * Markdown documentation for NOTE commitment.
10611
+ */
10612
+ get documentation() {
10613
+ return spaceTrim$1(`
10614
+ # ${this.type}
10615
+
10616
+ Adds comments for documentation without changing agent behavior.
10617
+
10618
+ ## Key aspects
10619
+
10620
+ - Does not modify the agent's behavior or responses.
10621
+ - Multiple \`NOTE\`, \`NOTES\`, \`COMMENT\`, and \`NONCE\` commitments are aggregated for debugging.
10622
+ - All four terms work identically and can be used interchangeably.
10623
+ - Useful for documenting design decisions and reminders.
10624
+ - Content is preserved in metadata for inspection.
10625
+
10626
+ ## Examples
10627
+
10628
+ \`\`\`book
10629
+ Customer Support Bot
10630
+
10631
+ NOTE This agent was designed for customer support scenarios
10632
+ COMMENT Remember to update the knowledge base monthly
10633
+ PERSONA You are a helpful customer support representative
10634
+ KNOWLEDGE Company policies and procedures
10635
+ RULE Always be polite and professional
10636
+ \`\`\`
10637
+
10638
+ \`\`\`book
10639
+ Research Assistant
10640
+
10641
+ NONCE Performance optimized for quick response times
10642
+ NOTE Uses RAG for accessing latest research papers
10643
+ PERSONA You are a knowledgeable research assistant
10644
+ ACTION Can help with literature reviews and citations
10645
+ STYLE Present information in academic format
10646
+ \`\`\`
10647
+ `);
10648
+ }
10649
+ applyToAgentModelRequirements(requirements, content) {
10650
+ // The NOTE commitment makes no changes to the system message or model requirements
10651
+ // It only stores the note content in metadata for documentation purposes
10652
+ const trimmedContent = spaceTrim$1(content);
10653
+ if (trimmedContent === '') {
10654
+ return requirements;
10655
+ }
10656
+ // Return requirements with updated notes but no changes to system message
10657
+ return {
10658
+ ...requirements,
10659
+ notes: [...(requirements.notes || []), trimmedContent],
10660
+ };
10661
+ }
10662
+ }
10663
+ /**
10664
+ * [💞] Ignore a discrepancy between file name and entity name
10665
+ */
10666
+
10667
+ /**
10668
+ * OPEN commitment definition
10669
+ *
10670
+ * The OPEN commitment specifies that the agent can be modified by conversation.
10671
+ * This is the default behavior.
10672
+ *
10673
+ * Example usage in agent source:
10674
+ *
10675
+ * ```book
10676
+ * OPEN
10677
+ * ```
10678
+ *
10679
+ * @private [🪔] Maybe export the commitments through some package
10680
+ */
10681
+ class OpenCommitmentDefinition extends BaseCommitmentDefinition {
10682
+ constructor() {
10683
+ super('OPEN');
10684
+ }
10685
+ /**
10686
+ * Short one-line description of OPEN.
10687
+ */
10688
+ get description() {
10689
+ return 'Allow the agent to be modified by conversation (default).';
10690
+ }
10691
+ /**
10692
+ * Icon for this commitment.
10693
+ */
10694
+ get icon() {
10695
+ return '🔓';
10696
+ }
10697
+ /**
10698
+ * Markdown documentation for OPEN commitment.
10699
+ */
10700
+ get documentation() {
10701
+ return spaceTrim$1(`
10702
+ # OPEN
10703
+
10704
+ Specifies that the agent can be modified by conversation with it.
10705
+ This means the agent will learn from interactions and update its source code.
10706
+
10707
+ This is the default behavior if neither \`OPEN\` nor \`CLOSED\` is specified.
10708
+
10709
+ > See also [CLOSED](/docs/CLOSED)
10710
+
10711
+ ## Example
10712
+
10713
+ \`\`\`book
10714
+ OPEN
10715
+ \`\`\`
10716
+ `);
10717
+ }
10718
+ applyToAgentModelRequirements(requirements, _content) {
10719
+ // Since OPEN is default, we can just ensure isClosed is false
10720
+ // But to be explicit we can set it
10721
+ const updatedMetadata = {
10722
+ ...requirements.metadata,
10723
+ isClosed: false,
10724
+ };
10725
+ return {
10726
+ ...requirements,
10727
+ metadata: updatedMetadata,
10728
+ };
10729
+ }
10730
+ }
10731
+ /**
10732
+ * Note: [💞] Ignore a discrepancy between file name and entity name
10733
+ */
10734
+
10735
+ /**
10736
+ * PERSONA commitment definition
10737
+ *
10738
+ * The PERSONA commitment modifies the agent's personality and character in the system message.
10739
+ * It defines who the agent is, their background, expertise, and personality traits.
10740
+ *
10741
+ * Key features:
10742
+ * - Multiple PERSONA commitments are automatically merged into one
10743
+ * - Content is placed at the beginning of the system message
10744
+ * - Original content with comments is preserved in metadata.PERSONA
10745
+ * - Comments (# PERSONA) are removed from the final system message
10746
+ *
10747
+ * Example usage in agent source:
10748
+ *
10749
+ * ```book
10750
+ * PERSONA You are a helpful programming assistant with expertise in TypeScript and React
10751
+ * PERSONA You have deep knowledge of modern web development practices
10752
+ * ```
10753
+ *
10754
+ * The above will be merged into a single persona section at the beginning of the system message.
10755
+ *
10756
+ * @private [🪔] Maybe export the commitments through some package
10757
+ */
10758
+ class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
10759
+ constructor(type = 'PERSONA') {
10760
+ super(type);
10761
+ }
10762
+ /**
10763
+ * Short one-line description of PERSONA.
10764
+ */
10765
+ get description() {
10766
+ return 'Define who the agent is: background, expertise, and personality.';
10767
+ }
10768
+ /**
10769
+ * Icon for this commitment.
10770
+ */
10771
+ get icon() {
10772
+ return '👤';
10773
+ }
10774
+ /**
10775
+ * Markdown documentation for PERSONA commitment.
10776
+ */
10777
+ get documentation() {
10778
+ return spaceTrim$1(`
10779
+ # ${this.type}
10780
+
10781
+ Defines who the agent is, their background, expertise, and personality traits.
10782
+
10783
+ ## Key aspects
10784
+
10785
+ - Multiple \`PERSONA\` and \`PERSONAE\` commitments are merged together.
10786
+ - Both terms work identically and can be used interchangeably.
10787
+ - If they are in conflict, the last one takes precedence.
10788
+ - You can write persona content in multiple lines.
10789
+
10790
+ ## Examples
10791
+
10792
+ \`\`\`book
10793
+ Programming Assistant
10794
+
10795
+ PERSONA You are a helpful programming assistant with expertise in TypeScript and React
10796
+ PERSONA You have deep knowledge of modern web development practices
10797
+ \`\`\`
10798
+ `);
10799
+ }
10800
+ applyToAgentModelRequirements(requirements, content) {
10801
+ var _a, _b;
10802
+ // The PERSONA commitment aggregates all persona content and places it at the beginning
10803
+ const trimmedContent = content.trim();
10804
+ if (!trimmedContent) {
10805
+ return requirements;
10806
+ }
10807
+ // Get existing persona content from metadata
10808
+ const existingPersonaContent = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.PERSONA) || '';
10809
+ // Merge the new content with existing persona content
10810
+ // When multiple PERSONA commitments exist, they are merged into one
10811
+ const mergedPersonaContent = existingPersonaContent
10812
+ ? `${existingPersonaContent}\n${trimmedContent}`
10813
+ : trimmedContent;
10814
+ // Store the merged persona content in metadata for debugging and inspection
10815
+ const updatedMetadata = {
10816
+ ...requirements.metadata,
10817
+ PERSONA: mergedPersonaContent,
10818
+ };
10819
+ // Get the agent name from metadata (which should contain the first line of agent source)
10820
+ // If not available, extract from current system message as fallback
10821
+ let agentName = (_b = requirements.metadata) === null || _b === void 0 ? void 0 : _b.agentName;
10822
+ if (!agentName) {
10823
+ // Fallback: extract from current system message
10824
+ const currentMessage = requirements.systemMessage.trim();
10825
+ const basicFormatMatch = currentMessage.match(/^You are (.+)$/);
10826
+ if (basicFormatMatch && basicFormatMatch[1]) {
10827
+ agentName = basicFormatMatch[1];
10828
+ }
10829
+ else {
10830
+ agentName = 'AI Agent'; // Final fallback
10831
+ }
10832
+ }
10833
+ // Remove any existing persona content from the system message
10834
+ // (this handles the case where we're processing multiple PERSONA commitments)
10835
+ const currentMessage = requirements.systemMessage.trim();
10836
+ let cleanedMessage = currentMessage;
10837
+ // Check if current message starts with persona content or is just the basic format
10838
+ const basicFormatRegex = /^You are .+$/;
10839
+ const isBasicFormat = basicFormatRegex.test(currentMessage) && !currentMessage.includes('\n');
10840
+ if (isBasicFormat) {
10841
+ // Replace the basic format entirely
10842
+ cleanedMessage = '';
10843
+ }
10844
+ else if (currentMessage.startsWith('# PERSONA')) {
10845
+ // Remove existing persona section by finding where it ends
10846
+ const lines = currentMessage.split('\n');
10847
+ let personaEndIndex = lines.length;
10848
+ // Find the end of the PERSONA section (next comment or end of message)
10849
+ for (let i = 1; i < lines.length; i++) {
10850
+ const line = lines[i].trim();
10851
+ if (line.startsWith('#') && !line.startsWith('# PERSONA')) {
10852
+ personaEndIndex = i;
10853
+ break;
10854
+ }
10855
+ }
10856
+ // Keep everything after the PERSONA section
10857
+ cleanedMessage = lines.slice(personaEndIndex).join('\n').trim();
10858
+ }
10859
+ // TODO: [🕛] There should be `agentFullname` not `agentName`
10860
+ // Create new system message with persona at the beginning
10861
+ // Format: "You are {agentName}\n{personaContent}"
10862
+ // The # PERSONA comment will be removed later by removeCommentsFromSystemMessage
10863
+ const personaSection = `# PERSONA\nYou are ${agentName}\n${mergedPersonaContent}`; // <- TODO: Use spaceTrim
10864
+ const newSystemMessage = cleanedMessage ? `${personaSection}\n\n${cleanedMessage}` : personaSection;
10865
+ return {
10866
+ ...requirements,
10867
+ systemMessage: newSystemMessage,
10868
+ metadata: updatedMetadata,
10869
+ };
10870
+ }
10871
+ }
10872
+ /**
10873
+ * Note: [💞] Ignore a discrepancy between file name and entity name
10874
+ */
10875
+
10876
+ /**
10877
+ * RULE commitment definition
10878
+ *
10879
+ * The RULE/RULES commitment adds behavioral constraints and guidelines that the agent must follow.
10880
+ * These are specific instructions about what the agent should or shouldn't do.
10881
+ *
10882
+ * Example usage in agent source:
10883
+ *
10884
+ * ```book
10885
+ * RULE Always ask for clarification if the user's request is ambiguous
10886
+ * RULES Never provide medical advice, always refer to healthcare professionals
10887
+ * ```
10888
+ *
10889
+ * @private [🪔] Maybe export the commitments through some package
10890
+ */
10891
+ class RuleCommitmentDefinition extends BaseCommitmentDefinition {
10892
+ constructor(type = 'RULE') {
10893
+ super(type);
10894
+ }
10895
+ /**
10896
+ * Short one-line description of RULE/RULES.
10897
+ */
10898
+ get description() {
10899
+ return 'Add behavioral rules the agent must follow.';
10900
+ }
10901
+ /**
10902
+ * Icon for this commitment.
10903
+ */
10904
+ get icon() {
10905
+ return '⚖️';
10906
+ }
10907
+ /**
10908
+ * Markdown documentation for RULE/RULES commitment.
10909
+ */
10910
+ get documentation() {
10911
+ return spaceTrim$1(`
10912
+ # ${this.type}
10913
+
10914
+ Adds behavioral constraints and guidelines that the agent must follow.
10915
+
10916
+ ## Key aspects
10917
+
10918
+ - All rules are treated equally regardless of singular/plural form.
10919
+ - Rules define what the agent must or must not do.
10920
+
10921
+ ## Examples
10922
+
10923
+ \`\`\`book
10924
+ Customer Support Agent
10925
+
10926
+ PERSONA You are a helpful customer support representative
10927
+ RULE Always ask for clarification if the user's request is ambiguous
10928
+ RULE Be polite and professional in all interactions
10929
+ RULES Never provide medical or legal advice
10930
+ STYLE Maintain a friendly and helpful tone
10931
+ \`\`\`
10932
+
10933
+ \`\`\`book
10934
+ Educational Tutor
10935
+
10936
+ PERSONA You are a patient and knowledgeable tutor
10937
+ RULE Break down complex concepts into simple steps
10938
+ RULE Always encourage students and celebrate their progress
10939
+ RULE If you don't know something, admit it and suggest resources
10940
+ SAMPLE When explaining math: "Let's work through this step by step..."
10941
+ \`\`\`
10942
+ `);
10943
+ }
10944
+ applyToAgentModelRequirements(requirements, content) {
10945
+ const trimmedContent = content.trim();
10946
+ if (!trimmedContent) {
10947
+ return requirements;
10948
+ }
10949
+ // Add rule to the system message
10950
+ const ruleSection = `Rule: ${trimmedContent}`;
10951
+ return this.appendToSystemMessage(requirements, ruleSection, '\n\n');
10952
+ }
10953
+ }
10954
+ /**
10955
+ * Note: [💞] Ignore a discrepancy between file name and entity name
10956
+ */
10957
+
10958
+ /**
10959
+ * SAMPLE commitment definition
10960
+ *
10961
+ * The SAMPLE/EXAMPLE commitment provides examples of how the agent should respond
10962
+ * or behave in certain situations. These examples help guide the agent's responses.
10963
+ *
10964
+ * Example usage in agent source:
10965
+ *
10966
+ * ```book
10967
+ * SAMPLE When asked about pricing, respond: "Our basic plan starts at $10/month..."
10968
+ * EXAMPLE For code questions, always include working code snippets
10969
+ * ```
10970
+ *
10971
+ * @private [🪔] Maybe export the commitments through some package
10972
+ */
10973
+ class SampleCommitmentDefinition extends BaseCommitmentDefinition {
10974
+ constructor(type = 'SAMPLE') {
10975
+ super(type);
10976
+ }
10977
+ /**
10978
+ * Short one-line description of SAMPLE/EXAMPLE.
10979
+ */
10980
+ get description() {
10981
+ return 'Provide example responses to guide behavior.';
10982
+ }
10983
+ /**
10984
+ * Icon for this commitment.
10985
+ */
10986
+ get icon() {
10987
+ return '🔍';
10988
+ }
10989
+ /**
10990
+ * Markdown documentation for SAMPLE/EXAMPLE commitment.
10991
+ */
10992
+ get documentation() {
10993
+ return spaceTrim$1(`
10994
+ # ${this.type}
10995
+
10996
+ Provides examples of how the agent should respond or behave in certain situations.
10997
+
10998
+ ## Key aspects
10999
+
11000
+ - Both terms work identically and can be used interchangeably.
11001
+ - Examples help guide the agent's response patterns and style.
11002
+
11003
+ ## Examples
11004
+
11005
+ \`\`\`book
11006
+ Sales Assistant
11007
+
11008
+ PERSONA You are a knowledgeable sales representative
11009
+ SAMPLE When asked about pricing, respond: "Our basic plan starts at $10/month..."
11010
+ SAMPLE For feature comparisons, create a clear comparison table
11011
+ RULE Always be honest about limitations
11012
+ \`\`\`
11013
+
11014
+ \`\`\`book
11015
+ Code Reviewer
11016
+
11017
+ PERSONA You are an experienced software engineer
11018
+ EXAMPLE For code questions, always include working code snippets
11019
+ EXAMPLE When suggesting improvements: "Here's a more efficient approach..."
11020
+ RULE Explain the reasoning behind your suggestions
11021
+ STYLE Be constructive and encouraging in feedback
11022
+ \`\`\`
11023
+ `);
11024
+ }
11025
+ applyToAgentModelRequirements(requirements, content) {
11026
+ const trimmedContent = content.trim();
11027
+ if (!trimmedContent) {
11028
+ return requirements;
11029
+ }
11030
+ // Add example to the system message
11031
+ const exampleSection = `Example: ${trimmedContent}`;
11032
+ return this.appendToSystemMessage(requirements, exampleSection, '\n\n');
11033
+ }
11034
+ }
11035
+ /**
11036
+ * Note: [💞] Ignore a discrepancy between file name and entity name
11037
+ */
11038
+
11039
+ /**
11040
+ * SCENARIO commitment definition
11041
+ *
11042
+ * The SCENARIO commitment defines a specific situation or context in which the AI
11043
+ * assistant should operate. It helps to set the scene for the AI's responses.
11044
+ * Later scenarios are more important than earlier scenarios.
11045
+ *
11046
+ * Example usage in agent source:
11047
+ *
11048
+ * ```book
11049
+ * SCENARIO You are in a customer service call center during peak hours
11050
+ * SCENARIO The customer is frustrated and has been on hold for 20 minutes
11051
+ * SCENARIO This is the customer's third call about the same issue
11052
+ * ```
11053
+ *
11054
+ * @private [🪔] Maybe export the commitments through some package
11055
+ */
11056
+ class ScenarioCommitmentDefinition extends BaseCommitmentDefinition {
11057
+ constructor(type = 'SCENARIO') {
11058
+ super(type);
11059
+ }
11060
+ /**
11061
+ * Short one-line description of SCENARIO.
11062
+ */
11063
+ get description() {
11064
+ return 'Define specific **situations** or contexts for AI responses, with later scenarios having higher priority.';
11065
+ }
11066
+ /**
11067
+ * Icon for this commitment.
11068
+ */
11069
+ get icon() {
11070
+ return '🎭';
11071
+ }
11072
+ /**
11073
+ * Markdown documentation for SCENARIO commitment.
11074
+ */
11075
+ get documentation() {
11076
+ return spaceTrim$1(`
11077
+ # ${this.type}
11078
+
11079
+ 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.
11080
+
11081
+ ## Key aspects
11082
+
11083
+ - Multiple \`SCENARIO\` and \`SCENARIOS\` commitments build upon each other.
11084
+ - Both terms work identically and can be used interchangeably.
11085
+ - Later scenarios have higher priority and can override earlier scenarios.
11086
+ - Provides situational context that influences response tone and content.
11087
+ - Helps establish the environment and circumstances for interactions.
11088
+
11089
+ ## Priority system
11090
+
11091
+ When multiple scenarios are defined, they are processed in order, with later scenarios taking precedence over earlier ones when there are conflicts.
11092
+
11093
+ ## Use cases
11094
+
11095
+ - Setting the physical or virtual environment
11096
+ - Establishing time constraints or urgency
11097
+ - Defining relationship dynamics or power structures
11098
+ - Creating emotional or situational context
11099
+
11100
+ ## Examples
11101
+
11102
+ \`\`\`book
11103
+ Emergency Response Operator
11104
+
11105
+ PERSONA You are an emergency response operator
11106
+ SCENARIO You are handling a 911 emergency call
11107
+ SCENARIO The caller is panicked and speaking rapidly
11108
+ SCENARIO Time is critical - every second counts
11109
+ GOAL Gather essential information quickly and dispatch appropriate help
11110
+ RULE Stay calm and speak clearly
11111
+ \`\`\`
11112
+
11113
+ \`\`\`book
11114
+ Sales Representative
11115
+
11116
+ PERSONA You are a software sales representative
11117
+ SCENARIO You are in the final meeting of a 6-month sales cycle
11118
+ SCENARIO The client has budget approval and decision-making authority
11119
+ SCENARIO Two competitors have also submitted proposals
11120
+ SCENARIO The client values long-term partnership over lowest price
11121
+ GOAL Close the deal while building trust for future business
11122
+ \`\`\`
11123
+
11124
+ \`\`\`book
11125
+ Medical Assistant
11126
+
11127
+ PERSONA You are a medical assistant in a busy clinic
11128
+ SCENARIO The waiting room is full and the doctor is running behind schedule
11129
+ SCENARIO Patients are becoming impatient and anxious
11130
+ SCENARIO You need to manage expectations while maintaining professionalism
11131
+ SCENARIO Some patients have been waiting over an hour
11132
+ GOAL Keep patients informed and calm while supporting efficient clinic flow
11133
+ RULE Never provide medical advice or diagnosis
11134
+ \`\`\`
11135
+
11136
+ \`\`\`book
11137
+ Technical Support Agent
11138
+
11139
+ PERSONA You are a technical support agent
11140
+ SCENARIO The customer is a small business owner during their busy season
11141
+ SCENARIO Their main business system has been down for 2 hours
11142
+ SCENARIO They are losing money every minute the system is offline
11143
+ SCENARIO This is their first experience with your company
11144
+ GOAL Resolve the issue quickly while creating a positive first impression
11145
+ \`\`\`
11146
+ `);
11147
+ }
11148
+ applyToAgentModelRequirements(requirements, content) {
11149
+ const trimmedContent = content.trim();
11150
+ if (!trimmedContent) {
11151
+ return requirements;
11152
+ }
11153
+ // Create scenario section for system message
11154
+ const scenarioSection = `Scenario: ${trimmedContent}`;
11155
+ // Scenarios provide important contextual information that affects behavior
11156
+ return this.appendToSystemMessage(requirements, scenarioSection, '\n\n');
11157
+ }
11158
+ }
11159
+ /**
11160
+ * Note: [💞] Ignore a discrepancy between file name and entity name
11161
+ */
11162
+
11163
+ /**
11164
+ * STYLE commitment definition
11165
+ *
11166
+ * The STYLE commitment defines how the agent should format and present its responses.
11167
+ * This includes tone, writing style, formatting preferences, and communication patterns.
11168
+ *
11169
+ * Example usage in agent source:
11170
+ *
11171
+ * ```book
11172
+ * STYLE Write in a professional but friendly tone, use bullet points for lists
11173
+ * STYLE Always provide code examples when explaining programming concepts
11174
+ * ```
11175
+ *
11176
+ * @private [🪔] Maybe export the commitments through some package
11177
+ */
11178
+ class StyleCommitmentDefinition extends BaseCommitmentDefinition {
11179
+ constructor(type = 'STYLE') {
11180
+ super(type);
11181
+ }
11182
+ /**
11183
+ * Short one-line description of STYLE.
11184
+ */
11185
+ get description() {
11186
+ return 'Control the tone and writing style of responses.';
11187
+ }
11188
+ /**
11189
+ * Icon for this commitment.
11190
+ */
11191
+ get icon() {
11192
+ return '🖋️';
11193
+ }
11194
+ /**
11195
+ * Markdown documentation for STYLE commitment.
11196
+ */
11197
+ get documentation() {
11198
+ return spaceTrim$1(`
11199
+ # ${this.type}
11200
+
11201
+ Defines how the agent should format and present its responses (tone, writing style, formatting).
11202
+
11203
+ ## Key aspects
11204
+
11205
+ - Both terms work identically and can be used interchangeably.
11206
+ - Later style instructions can override earlier ones.
11207
+ - Style affects both tone and presentation format.
11208
+
11209
+ ## Examples
11210
+
11211
+ \`\`\`book
11212
+ Technical Writer
11213
+
11214
+ PERSONA You are a technical documentation expert
11215
+ STYLE Write in a professional but friendly tone, use bullet points for lists
11216
+ STYLE Always provide code examples when explaining programming concepts
11217
+ FORMAT Use markdown formatting with clear headings
11218
+ \`\`\`
11219
+
11220
+ \`\`\`book
11221
+ Creative Assistant
11222
+
11223
+ PERSONA You are a creative writing helper
11224
+ STYLE Be enthusiastic and encouraging in your responses
11225
+ STYLE Use vivid metaphors and analogies to explain concepts
11226
+ STYLE Keep responses conversational and engaging
11227
+ RULE Always maintain a positive and supportive tone
11228
+ \`\`\`
11229
+ `);
11230
+ }
11231
+ applyToAgentModelRequirements(requirements, content) {
11232
+ const trimmedContent = content.trim();
11233
+ if (!trimmedContent) {
11234
+ return requirements;
11235
+ }
11236
+ // Add style instructions to the system message
11237
+ const styleSection = `Style: ${trimmedContent}`;
11238
+ return this.appendToSystemMessage(requirements, styleSection, '\n\n');
11239
+ }
11240
+ }
11241
+ /**
11242
+ * [💞] Ignore a discrepancy between file name and entity name
11243
+ */
11244
+
11245
+ /**
11246
+ * USE commitment definition
11247
+ *
11248
+ * The USE commitment indicates that the agent should utilize specific tools or capabilities
11249
+ * to access and interact with external systems when necessary.
11250
+ *
11251
+ * Supported USE types:
11252
+ * - USE BROWSER: Enables the agent to use a web browser tool
11253
+ * - USE SEARCH ENGINE (future): Enables search engine access
11254
+ * - USE FILE SYSTEM (future): Enables file system operations
11255
+ * - USE MCP (future): Enables MCP server connections
11256
+ *
11257
+ * The content following the USE commitment is ignored (similar to NOTE).
11258
+ *
11259
+ * Example usage in agent source:
11260
+ *
11261
+ * ```book
11262
+ * USE BROWSER
11263
+ * USE SEARCH ENGINE
11264
+ * ```
11265
+ *
11266
+ * @private [🪔] Maybe export the commitments through some package
11267
+ */
11268
+ class UseCommitmentDefinition extends BaseCommitmentDefinition {
11269
+ constructor() {
11270
+ super('USE');
11271
+ }
11272
+ /**
11273
+ * Short one-line description of USE commitments.
11274
+ */
11275
+ get description() {
11276
+ return 'Enable the agent to use specific tools or capabilities (BROWSER, SEARCH ENGINE, etc.).';
11277
+ }
11278
+ /**
11279
+ * Icon for this commitment.
11280
+ */
11281
+ get icon() {
11282
+ return '🔧';
11283
+ }
11284
+ /**
11285
+ * Markdown documentation for USE commitment.
11286
+ */
11287
+ get documentation() {
11288
+ return spaceTrim$1(`
11289
+ # USE
11290
+
11291
+ Enables the agent to use specific tools or capabilities for interacting with external systems.
11292
+
11293
+ ## Supported USE types
11294
+
11295
+ - **USE BROWSER** - Enables the agent to use a web browser tool to access and retrieve information from the internet
11296
+ - **USE SEARCH ENGINE** (future) - Enables search engine access
11297
+ - **USE FILE SYSTEM** (future) - Enables file system operations
11298
+ - **USE MCP** (future) - Enables MCP server connections
11299
+
11300
+ ## Key aspects
11301
+
11302
+ - The content following the USE commitment is ignored (similar to NOTE)
11303
+ - Multiple USE commitments can be specified to enable multiple capabilities
11304
+ - The actual tool usage is handled by the agent runtime
11305
+
11306
+ ## Examples
11307
+
11308
+ ### Basic browser usage
11309
+
11310
+ \`\`\`book
11311
+ Research Assistant
11312
+
11313
+ PERSONA You are a helpful research assistant
11314
+ USE BROWSER
11315
+ KNOWLEDGE Can search the web for up-to-date information
11316
+ \`\`\`
11317
+
11318
+ ### Multiple tools
11319
+
11320
+ \`\`\`book
11321
+ Data Analyst
11322
+
11323
+ PERSONA You are a data analyst assistant
11324
+ USE BROWSER
11325
+ USE FILE SYSTEM
11326
+ ACTION Can analyze data from various sources
11327
+ \`\`\`
11328
+ `);
11329
+ }
11330
+ applyToAgentModelRequirements(requirements, content) {
11331
+ // USE commitments don't modify the system message or model requirements directly
11332
+ // They are handled separately in the parsing logic for capability extraction
11333
+ // This method exists for consistency with the CommitmentDefinition interface
11334
+ return requirements;
11335
+ }
11336
+ /**
11337
+ * Extracts the tool type from the USE commitment
11338
+ * This is used by the parsing logic
11339
+ */
11340
+ extractToolType(content) {
11341
+ var _a, _b;
11342
+ const trimmedContent = content.trim();
11343
+ // The tool type is the first word after USE (already stripped)
11344
+ const match = trimmedContent.match(/^(\w+)/);
11345
+ 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;
11346
+ }
11347
+ /**
11348
+ * Checks if this is a known USE type
11349
+ */
11350
+ isKnownUseType(useType) {
11351
+ const knownTypes = ['BROWSER', 'SEARCH ENGINE', 'FILE SYSTEM', 'MCP'];
11352
+ return knownTypes.includes(useType.toUpperCase());
11353
+ }
11354
+ }
11355
+ /**
11356
+ * Note: [💞] Ignore a discrepancy between file name and entity name
11357
+ */
11358
+
11359
+ /**
11360
+ * USE BROWSER commitment definition
11361
+ *
11362
+ * The `USE BROWSER` commitment indicates that the agent should utilize a web browser tool
11363
+ * to access and retrieve up-to-date information from the internet when necessary.
11364
+ *
11365
+ * The content following `USE BROWSER` is ignored (similar to NOTE).
11366
+ *
11367
+ * Example usage in agent source:
11368
+ *
11369
+ * ```book
11370
+ * USE BROWSER
11371
+ * USE BROWSER This will be ignored
11372
+ * ```
11373
+ *
11374
+ * @private [🪔] Maybe export the commitments through some package
11375
+ */
11376
+ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
11377
+ constructor() {
11378
+ super('USE BROWSER', ['BROWSER']);
11379
+ }
11380
+ /**
11381
+ * The `USE BROWSER` commitment is standalone.
11382
+ */
11383
+ get requiresContent() {
11384
+ return false;
11385
+ }
11386
+ /**
11387
+ * Short one-line description of USE BROWSER.
11388
+ */
11389
+ get description() {
11390
+ return 'Enable the agent to use a web browser tool for accessing internet information.';
11391
+ }
11392
+ /**
11393
+ * Icon for this commitment.
11394
+ */
11395
+ get icon() {
11396
+ return '🌐';
11397
+ }
11398
+ /**
11399
+ * Markdown documentation for USE BROWSER commitment.
11400
+ */
11401
+ get documentation() {
11402
+ return spaceTrim$1(`
11403
+ # USE BROWSER
11404
+
11405
+ Enables the agent to use a web browser tool to access and retrieve up-to-date information from the internet.
11406
+
11407
+ ## Key aspects
11408
+
11409
+ - The content following \`USE BROWSER\` is ignored (similar to NOTE)
11410
+ - The actual browser tool usage is handled by the agent runtime
11411
+ - Allows the agent to fetch current information from websites
11412
+ - Useful for research tasks, fact-checking, and accessing dynamic content
11413
+
11414
+ ## Examples
11415
+
11416
+ \`\`\`book
11417
+ Research Assistant
11418
+
11419
+ PERSONA You are a helpful research assistant specialized in finding current information
11420
+ USE BROWSER
11421
+ RULE Always cite your sources when providing information from the web
11422
+ \`\`\`
11423
+
11424
+ \`\`\`book
11425
+ News Analyst
11426
+
11427
+ PERSONA You are a news analyst who stays up-to-date with current events
11428
+ USE BROWSER
11429
+ STYLE Present news in a balanced and objective manner
11430
+ ACTION Can search for and summarize news articles
11431
+ \`\`\`
11432
+
11433
+ \`\`\`book
11434
+ Company Lawyer
11435
+
11436
+ PERSONA You are a company lawyer providing legal advice
11437
+ USE BROWSER
11438
+ KNOWLEDGE Corporate law and legal procedures
11439
+ RULE Always recommend consulting with a licensed attorney for specific legal matters
11440
+ \`\`\`
11441
+ `);
11442
+ }
11443
+ /**
11444
+ * Gets human-readable titles for tool functions provided by this commitment.
11445
+ */
11446
+ getToolTitles() {
11447
+ return {
11448
+ web_browser: 'Web browser',
11449
+ };
11450
+ }
11451
+ applyToAgentModelRequirements(requirements, content) {
11452
+ // Get existing tools array or create new one
11453
+ const existingTools = requirements.tools || [];
11454
+ // Add 'web_browser' to tools if not already present
11455
+ const updatedTools = existingTools.some((tool) => tool.name === 'web_browser')
11456
+ ? existingTools
11457
+ : ([
11458
+ // TODO: [🔰] Use through proper MCP server
11459
+ ...existingTools,
11460
+ {
11461
+ name: 'web_browser',
11462
+ description: spaceTrim$1(`
11463
+ A tool that can browse the web.
11464
+ Use this tool when you need to access specific websites or browse the internet.
11465
+ `),
11466
+ parameters: {
11467
+ type: 'object',
11468
+ properties: {
11469
+ url: {
11470
+ type: 'string',
11471
+ description: 'The URL to browse',
11472
+ },
11473
+ },
11474
+ required: ['url'],
11475
+ },
11476
+ },
11477
+ ]);
11478
+ // Return requirements with updated tools and metadata
11479
+ return this.appendToSystemMessage({
11480
+ ...requirements,
11481
+ tools: updatedTools,
11482
+ metadata: {
11483
+ ...requirements.metadata,
11484
+ useBrowser: true,
11485
+ },
11486
+ }, spaceTrim$1(`
11487
+ You have access to the web browser. Use it to access specific websites or browse the internet.
11488
+ When you need to know some information from a specific website, use the tool provided to you.
11489
+ `));
11490
+ }
11491
+ }
11492
+ /**
11493
+ * Note: [💞] Ignore a discrepancy between file name and entity name
11494
+ */
11495
+
11496
+ /**
11497
+ * USE MCP commitment definition
11498
+ *
11499
+ * The `USE MCP` commitment allows to specify an MCP server URL which the agent will connect to
11500
+ * for retrieving additional instructions and actions.
11501
+ *
11502
+ * The content following `USE MCP` is the URL of the MCP server.
11503
+ *
11504
+ * Example usage in agent source:
11505
+ *
11506
+ * ```book
11507
+ * USE MCP http://mcp-server-url.com
11508
+ * ```
11509
+ *
11510
+ * @private [🪔] Maybe export the commitments through some package
11511
+ */
11512
+ class UseMcpCommitmentDefinition extends BaseCommitmentDefinition {
11513
+ constructor() {
11514
+ super('USE MCP', ['MCP']);
11515
+ }
11516
+ /**
11517
+ * Short one-line description of USE MCP.
11518
+ */
11519
+ get description() {
11520
+ return 'Connects the agent to an external MCP server for additional capabilities.';
11521
+ }
11522
+ /**
11523
+ * Icon for this commitment.
11524
+ */
11525
+ get icon() {
11526
+ return '🔌';
11527
+ }
11528
+ /**
11529
+ * Markdown documentation for USE MCP commitment.
11530
+ */
11531
+ get documentation() {
11532
+ return spaceTrim$1(`
11533
+ # USE MCP
11534
+
11535
+ Connects the agent to an external Model Context Protocol (MCP) server.
11536
+
11537
+ ## Key aspects
11538
+
11539
+ - The content following \`USE MCP\` must be a valid URL
11540
+ - Multiple MCP servers can be connected by using multiple \`USE MCP\` commitments
11541
+ - The agent will have access to tools and resources provided by the MCP server
11542
+
11543
+ ## Example
11544
+
11545
+ \`\`\`book
11546
+ Company Lawyer
11547
+
11548
+ PERSONA You are a company lawyer.
11549
+ USE MCP http://legal-db.example.com
11550
+ \`\`\`
11551
+ `);
11552
+ }
11553
+ applyToAgentModelRequirements(requirements, content) {
11554
+ const mcpServerUrl = content.trim();
11555
+ if (!mcpServerUrl) {
11556
+ return requirements;
11557
+ }
11558
+ const existingMcpServers = requirements.mcpServers || [];
11559
+ // Avoid duplicates
11560
+ if (existingMcpServers.includes(mcpServerUrl)) {
11561
+ return requirements;
11562
+ }
11563
+ return {
11564
+ ...requirements,
11565
+ mcpServers: [...existingMcpServers, mcpServerUrl],
11566
+ };
11567
+ }
11568
+ }
11569
+ /**
11570
+ * Note: [💞] Ignore a discrepancy between file name and entity name
11571
+ */
11572
+
11573
+ /**
11574
+ * A search engine implementation that uses the SerpApi to fetch Google search results.
11575
+ *
11576
+ * @private <- TODO: !!!! Export via some package
11577
+ */
11578
+ class SerpSearchEngine {
11579
+ get title() {
11580
+ return 'SerpApi Search Engine';
11581
+ }
11582
+ get description() {
11583
+ return 'Search engine that uses SerpApi to fetch Google search results';
11584
+ }
11585
+ checkConfiguration() {
11586
+ if (!process.env.SERP_API_KEY) {
11587
+ throw new Error('SERP_API_KEY is not configured');
11588
+ }
11589
+ }
11590
+ async search(query, options = {}) {
11591
+ const apiKey = process.env.SERP_API_KEY;
11592
+ if (!apiKey) {
11593
+ throw new Error('SERP_API_KEY is not configured');
11594
+ }
11595
+ const url = new URL('https://serpapi.com/search');
11596
+ url.searchParams.set('api_key', apiKey);
11597
+ url.searchParams.set('engine', 'google');
11598
+ url.searchParams.set('q', query);
11599
+ for (const [key, value] of Object.entries(options)) {
11600
+ url.searchParams.set(key, String(value));
11601
+ }
11602
+ const response = await fetch(url.toString());
11603
+ if (!response.ok) {
11604
+ const body = await response.text();
11605
+ throw new Error(`SerpApi failed with status ${response.status}: ${response.statusText}\n${body}`);
11606
+ }
11607
+ const data = (await response.json());
11608
+ return (data.organic_results || []).map((item) => ({
11609
+ title: item.title,
11610
+ url: item.link,
11611
+ snippet: item.snippet || '',
11612
+ }));
11613
+ }
11614
+ }
11615
+
11616
+ /**
11617
+ * USE SEARCH ENGINE commitment definition
11618
+ *
11619
+ * The `USE SEARCH ENGINE` commitment indicates that the agent should utilize a search engine tool
11620
+ * to access and retrieve up-to-date information from the internet when necessary.
11621
+ *
11622
+ * The content following `USE SEARCH ENGINE` is an arbitrary text that the agent should know (e.g. search scope or instructions).
11623
+ *
11624
+ * Example usage in agent source:
11625
+ *
11626
+ * ```book
11627
+ * USE SEARCH ENGINE
11628
+ * USE SEARCH ENGINE Hledej informace o Přemyslovcích
11629
+ * ```
11630
+ *
11631
+ * @private [🪔] Maybe export the commitments through some package
11632
+ */
11633
+ class UseSearchEngineCommitmentDefinition extends BaseCommitmentDefinition {
11634
+ constructor() {
11635
+ super('USE SEARCH ENGINE', ['USE SEARCH']);
11636
+ }
11637
+ /**
11638
+ * Short one-line description of USE SEARCH ENGINE.
11639
+ */
11640
+ get description() {
11641
+ return 'Enable the agent to use a search engine tool for accessing internet information.';
11642
+ }
11643
+ /**
11644
+ * Icon for this commitment.
11645
+ */
11646
+ get icon() {
11647
+ return '🔍';
11648
+ }
11649
+ /**
11650
+ * Markdown documentation for USE SEARCH ENGINE commitment.
11651
+ */
11652
+ get documentation() {
11653
+ return spaceTrim$1(`
11654
+ # USE SEARCH ENGINE
11655
+
11656
+ Enables the agent to use a search engine tool to access and retrieve up-to-date information from the internet.
11657
+
11658
+ ## Key aspects
11659
+
11660
+ - The content following \`USE SEARCH ENGINE\` is an arbitrary text that the agent should know (e.g. search scope or instructions).
11661
+ - The actual search engine tool usage is handled by the agent runtime
11662
+ - Allows the agent to search for current information from the web
11663
+ - Useful for research tasks, finding facts, and accessing dynamic content
11664
+
11665
+ ## Examples
11666
+
11667
+ \`\`\`book
11668
+ Research Assistant
11669
+
11670
+ PERSONA You are a helpful research assistant specialized in finding current information
11671
+ USE SEARCH ENGINE
11672
+ RULE Always cite your sources when providing information from the web
11673
+ \`\`\`
11674
+
11675
+ \`\`\`book
11676
+ Fact Checker
11677
+
11678
+ PERSONA You are a fact checker
11679
+ USE SEARCH ENGINE
11680
+ ACTION Search for claims and verify them against reliable sources
11681
+ \`\`\`
11682
+ `);
11683
+ }
11684
+ applyToAgentModelRequirements(requirements, content) {
11685
+ // Get existing tools array or create new one
11686
+ const existingTools = requirements.tools || [];
11687
+ // Add 'web_search' to tools if not already present
11688
+ const updatedTools = existingTools.some((tool) => tool.name === 'web_search')
11689
+ ? existingTools
11690
+ : [
11691
+ ...existingTools,
11692
+ {
11693
+ name: 'web_search',
11694
+ description: spaceTrim$1(`
11695
+ Search the internet for information.
11696
+ Use this tool when you need to find up-to-date information or facts that you don't know.
11697
+ ${!content ? '' : `Search scope / instructions: ${content}`}
11698
+ `),
11699
+ parameters: {
11700
+ type: 'object',
11701
+ properties: {
11702
+ query: {
11703
+ type: 'string',
11704
+ description: 'The search query',
11705
+ },
11706
+ location: {
11707
+ type: 'string',
11708
+ description: 'The location for the search (e.g., "Austin, Texas, United States" or "Prague, Czechia")',
11709
+ },
11710
+ gl: {
11711
+ type: 'string',
11712
+ description: 'The country code (e.g., "us" for United States, "cz" for Czechia)',
11713
+ },
11714
+ hl: {
11715
+ type: 'string',
11716
+ description: 'The language code (e.g., "en" for English, "cs" for Czech)',
11717
+ },
11718
+ num: {
11719
+ type: 'integer',
11720
+ description: 'Number of results to return',
11721
+ },
11722
+ engine: {
11723
+ type: 'string',
11724
+ description: 'The search engine to use (e.g., "google", "bing", "yahoo", "baidu")',
11725
+ },
11726
+ google_domain: {
11727
+ type: 'string',
11728
+ description: 'The Google domain to use (e.g., "google.com", "google.cz")',
11729
+ },
11730
+ },
11731
+ required: ['query'],
11732
+ },
11733
+ },
11734
+ ];
11735
+ // Return requirements with updated tools and metadata
11736
+ return this.appendToSystemMessage({
11737
+ ...requirements,
11738
+ tools: updatedTools,
11739
+ metadata: {
11740
+ ...requirements.metadata,
11741
+ useSearchEngine: content || true,
11742
+ },
11743
+ }, spaceTrim$1(`
11744
+ You have access to the web search engine. Use it to find up-to-date information or facts that you don't know.
11745
+ When you need to know some information from the internet, use the tool provided to you.
11746
+ `));
11747
+ }
11748
+ /**
11749
+ * Gets human-readable titles for tool functions provided by this commitment.
11750
+ */
11751
+ getToolTitles() {
11752
+ return {
11753
+ web_search: 'Web search',
11754
+ };
11755
+ }
11756
+ /**
11757
+ * Gets the `web_search` tool function implementation.
11758
+ */
11759
+ getToolFunctions() {
11760
+ return {
11761
+ async web_search(args) {
11762
+ console.log('!!!! [Tool] web_search called', { args });
11763
+ const { query, ...options } = args;
11764
+ if (!query) {
11765
+ throw new Error('Search query is required');
11766
+ }
11767
+ const searchEngine = new SerpSearchEngine();
11768
+ const results = await searchEngine.search(query, options);
11769
+ return spaceTrim$1((block) => `
11770
+ Search results for "${query}"${Object.keys(options).length === 0
11771
+ ? ''
11772
+ : ` with options ${JSON.stringify(options)}`}:
11773
+
11774
+ ${block(results
11775
+ .map((result) => spaceTrim$1(`
11776
+ - **${result.title}**
11777
+ ${result.url}
11778
+ ${result.snippet}
11779
+ `))
11780
+ .join('\n\n'))}
11781
+ `);
11782
+ },
11783
+ };
11784
+ }
11785
+ }
11786
+ /**
11787
+ * Note: [💞] Ignore a discrepancy between file name and entity name
11788
+ */
11789
+
11790
+ /**
11791
+ * USE TIME commitment definition
11792
+ *
11793
+ * The `USE TIME` commitment indicates that the agent should be able to determine the current date and time.
11794
+ *
11795
+ * Example usage in agent source:
11796
+ *
11797
+ * ```book
11798
+ * USE TIME
11799
+ * ```
11800
+ *
11801
+ * @private [🪔] Maybe export the commitments through some package
11802
+ */
11803
+ class UseTimeCommitmentDefinition extends BaseCommitmentDefinition {
11804
+ constructor() {
11805
+ super('USE TIME', ['CURRENT TIME', 'TIME', 'DATE']);
11806
+ }
11807
+ /**
11808
+ * Short one-line description of USE TIME.
11809
+ */
11810
+ get description() {
11811
+ return 'Enable the agent to determine the current date and time.';
11812
+ }
11813
+ /**
11814
+ * Icon for this commitment.
11815
+ */
11816
+ get icon() {
11817
+ return '🕒';
11818
+ }
11819
+ /**
11820
+ * Markdown documentation for USE TIME commitment.
11821
+ */
11822
+ get documentation() {
11823
+ return spaceTrim$1(`
11824
+ # USE TIME
11825
+
11826
+ Enables the agent to determine the current date and time.
11827
+
11828
+ ## Key aspects
11829
+
11830
+ - This tool won't receive any input.
11831
+ - It outputs the current date and time as an ISO 8601 string.
11832
+ - Allows the agent to answer questions about the current time or date.
11833
+
11834
+ ## Examples
11835
+
11836
+ \`\`\`book
11837
+ Time-aware Assistant
11838
+
11839
+ PERSONA You are a helpful assistant who knows the current time.
11840
+ USE TIME
11841
+ \`\`\`
11842
+ `);
11843
+ }
11844
+ applyToAgentModelRequirements(requirements, content) {
11845
+ // Get existing tools array or create new one
11846
+ const existingTools = requirements.tools || [];
11847
+ // Add 'get_current_time' to tools if not already present
11848
+ const updatedTools = existingTools.some((tool) => tool.name === 'get_current_time')
11849
+ ? existingTools
11850
+ : [
11851
+ ...existingTools,
11852
+ {
11853
+ name: 'get_current_time',
11854
+ description: 'Get the current date and time in ISO 8601 format.',
11855
+ parameters: {
11856
+ type: 'object',
11857
+ properties: {
11858
+ timezone: {
11859
+ type: 'string',
11860
+ description: 'Optional timezone name (e.g. "Europe/Prague", "UTC", "America/New_York").',
11861
+ },
11862
+ },
11863
+ required: [],
11864
+ },
11865
+ },
11866
+ // <- TODO: !!!! define the function in LLM tools
11867
+ ];
11868
+ // Return requirements with updated tools and metadata
11869
+ return this.appendToSystemMessage({
11870
+ ...requirements,
11871
+ tools: updatedTools,
11872
+ metadata: {
11873
+ ...requirements.metadata,
11874
+ },
11875
+ }, spaceTrim$1(`
11876
+ You have access to the current date and time. Use it to answer questions about the current date and time.
11877
+ When you need to know the current date or time, use the tool provided to you.
11878
+ `));
11879
+ }
11880
+ /**
11881
+ * Gets human-readable titles for tool functions provided by this commitment.
11882
+ */
11883
+ getToolTitles() {
11884
+ return {
11885
+ get_current_time: 'Get current time',
11886
+ };
11887
+ }
11888
+ /**
11889
+ * Gets the `get_current_time` tool function implementation.
11890
+ */
11891
+ getToolFunctions() {
11892
+ return {
11893
+ async get_current_time(args) {
11894
+ var _a;
11895
+ console.log('!!!! [Tool] get_current_time called', { args });
11896
+ const { timezone } = args;
11897
+ if (!timezone) {
11898
+ return new Date().toISOString();
11899
+ }
11900
+ try {
11901
+ // Note: Returning ISO 8601 string but in the requested timezone
11902
+ const formatter = new Intl.DateTimeFormat('en-CA', {
11903
+ timeZone: timezone,
11904
+ year: 'numeric',
11905
+ month: '2-digit',
11906
+ day: '2-digit',
11907
+ hour: '2-digit',
11908
+ minute: '2-digit',
11909
+ second: '2-digit',
11910
+ hour12: false,
11911
+ timeZoneName: 'shortOffset',
11912
+ });
11913
+ const parts = formatter.formatToParts(new Date());
11914
+ const part = (type) => { var _a; return (_a = parts.find((p) => p.type === type)) === null || _a === void 0 ? void 0 : _a.value; };
11915
+ // en-CA format is YYYY-MM-DD
11916
+ 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', '')}`;
11917
+ return isoString;
11918
+ }
11919
+ catch (error) {
11920
+ // Fallback to UTC if timezone is invalid
11921
+ return new Date().toISOString();
11922
+ }
11923
+ },
11924
+ };
11925
+ }
11926
+ }
11927
+ /**
11928
+ * Note: [💞] Ignore a discrepancy between file name and entity name
11929
+ */
11930
+
11931
+ /**
11932
+ * Placeholder commitment definition for commitments that are not yet implemented
11933
+ *
11934
+ * This commitment simply adds its content 1:1 into the system message,
11935
+ * preserving the original behavior until proper implementation is added.
11936
+ *
11937
+ * @public exported from `@promptbook/core`
11938
+ */
11939
+ class NotYetImplementedCommitmentDefinition extends BaseCommitmentDefinition {
11940
+ constructor(type) {
11941
+ super(type);
11942
+ }
11943
+ /**
11944
+ * Short one-line description of a placeholder commitment.
11945
+ */
11946
+ get description() {
11947
+ return 'Placeholder commitment that appends content verbatim to the system message.';
11948
+ }
11949
+ /**
11950
+ * Icon for this commitment.
11951
+ */
11952
+ get icon() {
11953
+ return '🚧';
11954
+ }
11955
+ /**
11956
+ * Markdown documentation available at runtime.
11957
+ */
11958
+ get documentation() {
11959
+ return spaceTrim$1(`
11960
+ # ${this.type}
11961
+
11962
+ This commitment is not yet fully implemented.
11963
+
11964
+ ## Key aspects
11965
+
11966
+ - Content is appended directly to the system message.
11967
+ - No special processing or validation is performed.
11968
+ - Behavior preserved until proper implementation is added.
11969
+
11970
+ ## Status
11971
+
11972
+ - **Status:** Placeholder implementation
11973
+ - **Effect:** Appends content prefixed by commitment type
11974
+ - **Future:** Will be replaced with specialized logic
11975
+
11976
+ ## Examples
11977
+
11978
+ \`\`\`book
11979
+ Example Agent
11980
+
11981
+ PERSONA You are a helpful assistant
11982
+ ${this.type} Your content here
11983
+ RULE Always be helpful
11984
+ \`\`\`
11985
+ `);
11986
+ }
11987
+ applyToAgentModelRequirements(requirements, content) {
11988
+ const trimmedContent = content.trim();
11989
+ if (!trimmedContent) {
11990
+ return requirements;
11991
+ }
11992
+ // Add the commitment content 1:1 to the system message
11993
+ const commitmentLine = `${this.type} ${trimmedContent}`;
11994
+ return this.appendToSystemMessage(requirements, commitmentLine, '\n\n');
11995
+ }
11996
+ }
11997
+
11998
+ /**
11999
+ * Registry of all available commitment definitions
12000
+ * This array contains instances of all commitment definitions
12001
+ * This is the single source of truth for all commitments in the system
12002
+ *
12003
+ * @private Use functions to access commitments instead of this array directly
12004
+ */
12005
+ const COMMITMENT_REGISTRY = [
12006
+ // Fully implemented commitments
12007
+ new PersonaCommitmentDefinition('PERSONA'),
12008
+ new PersonaCommitmentDefinition('PERSONAE'),
12009
+ new KnowledgeCommitmentDefinition(),
12010
+ new MemoryCommitmentDefinition('MEMORY'),
12011
+ new MemoryCommitmentDefinition('MEMORIES'),
12012
+ new StyleCommitmentDefinition('STYLE'),
12013
+ new StyleCommitmentDefinition('STYLES'),
12014
+ new RuleCommitmentDefinition('RULES'),
12015
+ new RuleCommitmentDefinition('RULE'),
12016
+ new LanguageCommitmentDefinition('LANGUAGES'),
12017
+ new LanguageCommitmentDefinition('LANGUAGE'),
12018
+ new SampleCommitmentDefinition('SAMPLE'),
12019
+ new SampleCommitmentDefinition('EXAMPLE'),
12020
+ new FormatCommitmentDefinition('FORMAT'),
12021
+ new FormatCommitmentDefinition('FORMATS'),
12022
+ new FromCommitmentDefinition('FROM'),
12023
+ new ImportCommitmentDefinition('IMPORT'),
12024
+ new ImportCommitmentDefinition('IMPORTS'),
12025
+ new ModelCommitmentDefinition('MODEL'),
12026
+ new ModelCommitmentDefinition('MODELS'),
12027
+ new ActionCommitmentDefinition('ACTION'),
12028
+ new ActionCommitmentDefinition('ACTIONS'),
12029
+ new ComponentCommitmentDefinition(),
12030
+ new MetaImageCommitmentDefinition(),
12031
+ new MetaColorCommitmentDefinition(),
12032
+ new MetaFontCommitmentDefinition(),
12033
+ new MetaLinkCommitmentDefinition(),
12034
+ new MetaCommitmentDefinition(),
12035
+ new NoteCommitmentDefinition('NOTE'),
12036
+ new NoteCommitmentDefinition('NOTES'),
12037
+ new NoteCommitmentDefinition('COMMENT'),
12038
+ new NoteCommitmentDefinition('NONCE'),
12039
+ new NoteCommitmentDefinition('TODO'),
12040
+ new GoalCommitmentDefinition('GOAL'),
12041
+ new GoalCommitmentDefinition('GOALS'),
12042
+ new InitialMessageCommitmentDefinition(),
12043
+ new UserMessageCommitmentDefinition(),
12044
+ new AgentMessageCommitmentDefinition(),
12045
+ new MessageCommitmentDefinition('MESSAGE'),
12046
+ new MessageCommitmentDefinition('MESSAGES'),
12047
+ new ScenarioCommitmentDefinition('SCENARIO'),
12048
+ new ScenarioCommitmentDefinition('SCENARIOS'),
12049
+ new DeleteCommitmentDefinition('DELETE'),
12050
+ new DeleteCommitmentDefinition('CANCEL'),
12051
+ new DeleteCommitmentDefinition('DISCARD'),
12052
+ new DeleteCommitmentDefinition('REMOVE'),
12053
+ new DictionaryCommitmentDefinition(),
12054
+ new OpenCommitmentDefinition(),
12055
+ new ClosedCommitmentDefinition(),
12056
+ new UseBrowserCommitmentDefinition(),
12057
+ new UseSearchEngineCommitmentDefinition(),
12058
+ new UseTimeCommitmentDefinition(),
12059
+ new UseMcpCommitmentDefinition(),
12060
+ new UseCommitmentDefinition(),
12061
+ // Not yet implemented commitments (using placeholder)
12062
+ new NotYetImplementedCommitmentDefinition('EXPECT'),
12063
+ new NotYetImplementedCommitmentDefinition('BEHAVIOUR'),
12064
+ new NotYetImplementedCommitmentDefinition('BEHAVIOURS'),
12065
+ new NotYetImplementedCommitmentDefinition('AVOID'),
12066
+ new NotYetImplementedCommitmentDefinition('AVOIDANCE'),
12067
+ new NotYetImplementedCommitmentDefinition('CONTEXT'),
12068
+ // <- TODO: Prompt: Leverage aliases instead of duplicating commitment definitions
12069
+ ];
12070
+ /**
12071
+ * Gets all available commitment definitions
12072
+ * @returns Array of all commitment definitions
12073
+ *
12074
+ * @public exported from `@promptbook/core`
12075
+ */
12076
+ function getAllCommitmentDefinitions() {
12077
+ return $deepFreeze([...COMMITMENT_REGISTRY]);
12078
+ }
12079
+ /**
12080
+ * Gets all function implementations provided by all commitments
12081
+ *
12082
+ * @public exported from `@promptbook/core`
12083
+ */
12084
+ function getAllCommitmentsToolFunctions() {
12085
+ const allToolFunctions = {};
12086
+ for (const commitmentDefinition of getAllCommitmentDefinitions()) {
12087
+ const toolFunctions = commitmentDefinition.getToolFunctions();
12088
+ for (const [funcName, funcImpl] of Object.entries(toolFunctions)) {
12089
+ allToolFunctions[funcName] = funcImpl;
12090
+ }
12091
+ }
12092
+ return allToolFunctions;
12093
+ }
12094
+ /**
12095
+ * TODO: [🧠] Maybe create through standardized $register
12096
+ * Note: [💞] Ignore a discrepancy between file name and entity name
12097
+ */
12098
+
12099
+ /**
12100
+ * Extracts exactly ONE code block from markdown.
12101
+ *
12102
+ * - When there are multiple or no code blocks the function throws a `ParseError`
12103
+ *
12104
+ * Note: There are multiple similar functions:
12105
+ * - `extractBlock` just extracts the content of the code block which is also used as built-in function for postprocessing
12106
+ * - `extractJsonBlock` extracts exactly one valid JSON code block
12107
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
12108
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
12109
+ *
12110
+ * @param markdown any valid markdown
12111
+ * @returns code block with language and content
12112
+ * @public exported from `@promptbook/markdown-utils`
12113
+ * @throws {ParseError} if there is not exactly one code block in the markdown
12114
+ */
12115
+ function extractOneBlockFromMarkdown(markdown) {
12116
+ const codeBlocks = extractAllBlocksFromMarkdown(markdown);
12117
+ if (codeBlocks.length !== 1) {
12118
+ throw new ParseError(spaceTrim$2((block) => `
12119
+ There should be exactly 1 code block in task section, found ${codeBlocks.length} code blocks
12120
+
12121
+ ${block(codeBlocks.map((block, i) => `Block ${i + 1}:\n${block.content}`).join('\n\n\n'))}
12122
+ `));
12123
+ }
12124
+ return codeBlocks[0];
12125
+ }
12126
+ /***
12127
+ * TODO: [🍓][🌻] Decide of this is internal utility, external util OR validator/postprocessor
12128
+ */
12129
+
12130
+ /**
12131
+ * Extracts code block from markdown.
12132
+ *
12133
+ * - When there are multiple or no code blocks the function throws a `ParseError`
12134
+ *
12135
+ * Note: There are multiple similar function:
12136
+ * - `extractBlock` just extracts the content of the code block which is also used as build-in function for postprocessing
12137
+ * - `extractJsonBlock` extracts exactly one valid JSON code block
12138
+ * - `extractOneBlockFromMarkdown` extracts exactly one code block with language of the code block
12139
+ * - `extractAllBlocksFromMarkdown` extracts all code blocks with language of the code block
12140
+ *
12141
+ * @public exported from `@promptbook/markdown-utils`
12142
+ * @throws {ParseError} if there is not exactly one code block in the markdown
12143
+ */
12144
+ function extractBlock(markdown) {
12145
+ const { content } = extractOneBlockFromMarkdown(markdown);
12146
+ return content;
12147
+ }
12148
+
12149
+ /**
12150
+ * Function trimCodeBlock will trim starting and ending code block from the string if it is present.
12151
+ *
12152
+ * Note: [🔂] This function is idempotent.
12153
+ * Note: This is useful for post-processing of the result of the chat LLM model
12154
+ * when the model wraps the result in the (markdown) code block.
12155
+ *
12156
+ * @public exported from `@promptbook/markdown-utils`
12157
+ */
12158
+ function trimCodeBlock(value) {
12159
+ value = spaceTrim$1(value);
12160
+ if (!/^```[a-z]*(.*)```$/is.test(value)) {
12161
+ return value;
12162
+ }
12163
+ value = value.replace(/^```[a-z]*/i, '');
12164
+ value = value.replace(/```$/i, '');
12165
+ value = spaceTrim$1(value);
12166
+ return value;
12167
+ }
12168
+
12169
+ /**
12170
+ * Function trimEndOfCodeBlock will remove ending code block from the string if it is present.
12171
+ *
12172
+ * Note: This is useful for post-processing of the result of the completion LLM model
12173
+ * if you want to start code block in the prompt but you don't want to end it in the result.
12174
+ *
12175
+ * @public exported from `@promptbook/markdown-utils`
12176
+ */
12177
+ function trimEndOfCodeBlock(value) {
12178
+ value = spaceTrim$1(value);
12179
+ value = value.replace(/```$/g, '');
12180
+ value = spaceTrim$1(value);
12181
+ return value;
12182
+ }
12183
+
12184
+ /**
12185
+ * @private internal for `preserve`
12186
+ */
12187
+ const _preserved = [];
12188
+ /**
12189
+ * Does nothing, but preserves the function in the bundle
12190
+ * Compiler is tricked into thinking the function is used
12191
+ *
12192
+ * @param value any function to preserve
12193
+ * @returns nothing
12194
+ * @private within the repository
12195
+ */
12196
+ function $preserve(...value) {
12197
+ _preserved.push(...value);
12198
+ }
12199
+ /**
12200
+ * Note: [💞] Ignore a discrepancy between file name and entity name
12201
+ */
12202
+
12203
+ // Note: [💎]
12204
+ /**
12205
+ * ScriptExecutionTools for JavaScript implemented via eval
12206
+ *
12207
+ * Warning: It is used for testing and mocking
12208
+ * **NOT intended to use in the production** due to its unsafe nature, use `JavascriptExecutionTools` instead.
12209
+ *
12210
+ * @public exported from `@promptbook/javascript`
12211
+ */
12212
+ class JavascriptEvalExecutionTools {
12213
+ constructor(options) {
12214
+ this.options = options || {};
12215
+ }
12216
+ /**
12217
+ * Executes a JavaScript
12218
+ */
12219
+ async execute(options) {
12220
+ const { scriptLanguage, parameters } = options;
12221
+ let { script } = options;
12222
+ if (scriptLanguage !== 'javascript') {
12223
+ throw new PipelineExecutionError(`Script language ${scriptLanguage} not supported to be executed by JavascriptEvalExecutionTools`);
12224
+ }
12225
+ // Note: [💎]
12226
+ // Note: Using direct eval, following variables are in same scope as eval call so they are accessible from inside the evaluated script:
12227
+ const spaceTrim = (_) => spaceTrim$2(_);
12228
+ $preserve(spaceTrim);
12229
+ const removeQuotes$1 = removeQuotes;
12230
+ $preserve(removeQuotes$1);
12231
+ const unwrapResult$1 = unwrapResult;
12232
+ $preserve(unwrapResult$1);
12233
+ const trimEndOfCodeBlock$1 = trimEndOfCodeBlock;
12234
+ $preserve(trimEndOfCodeBlock$1);
8326
12235
  const trimCodeBlock$1 = trimCodeBlock;
8327
12236
  $preserve(trimCodeBlock$1);
8328
12237
  // TODO: DRY [🍯]
@@ -8398,6 +12307,13 @@ class JavascriptEvalExecutionTools {
8398
12307
  `const ${functionName} = buildinFunctions.${functionName};`)
8399
12308
  .join('\n');
8400
12309
  // TODO: DRY [🍯]
12310
+ const commitmentsFunctions = getAllCommitmentsToolFunctions();
12311
+ const commitmentsFunctionsStatement = Object.keys(commitmentsFunctions)
12312
+ .map((functionName) =>
12313
+ // Note: Custom functions are exposed to the current scope as variables
12314
+ `const ${functionName} = commitmentsFunctions.${functionName};`)
12315
+ .join('\n');
12316
+ // TODO: DRY [🍯]
8401
12317
  const customFunctions = this.options.functions || {};
8402
12318
  const customFunctionsStatement = Object.keys(customFunctions)
8403
12319
  .map((functionName) =>
@@ -8411,6 +12327,10 @@ class JavascriptEvalExecutionTools {
8411
12327
  // Build-in functions:
8412
12328
  ${block(buildinFunctionsStatement)}
8413
12329
 
12330
+ // Commitments functions:
12331
+ ${block(commitmentsFunctionsStatement)}
12332
+
12333
+
8414
12334
  // Custom functions:
8415
12335
  ${block(customFunctionsStatement || '// -- No custom functions --')}
8416
12336
 
@@ -8418,7 +12338,7 @@ class JavascriptEvalExecutionTools {
8418
12338
  ${block(Object.entries(parameters)
8419
12339
  .map(([key, value]) => `const ${key} = ${JSON.stringify(value)};`)
8420
12340
  .join('\n'))}
8421
- (()=>{ ${script} })()
12341
+ (async ()=>{ ${script} })()
8422
12342
  `);
8423
12343
  if (this.options.isVerbose) {
8424
12344
  console.info(spaceTrim$2((block) => `