@promptbook/javascript 0.105.0-1 → 0.105.0-11

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