@promptbook/cli 0.103.0-55 → 0.103.0-56

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 (61) hide show
  1. package/apps/agents-server/package-lock.json +1163 -0
  2. package/apps/agents-server/package.json +6 -0
  3. package/apps/agents-server/src/app/agents/[agentName]/AgentChatWrapper.tsx +3 -1
  4. package/apps/agents-server/src/app/agents/[agentName]/AgentOptionsMenu.tsx +216 -0
  5. package/apps/agents-server/src/app/agents/[agentName]/AgentProfileChat.tsx +78 -0
  6. package/apps/agents-server/src/app/agents/[agentName]/AgentProfileView.tsx +233 -0
  7. package/apps/agents-server/src/app/agents/[agentName]/CloneAgentButton.tsx +4 -4
  8. package/apps/agents-server/src/app/agents/[agentName]/InstallPwaButton.tsx +2 -2
  9. package/apps/agents-server/src/app/agents/[agentName]/QrCodeModal.tsx +90 -0
  10. package/apps/agents-server/src/app/agents/[agentName]/agentLinks.tsx +80 -0
  11. package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +3 -1
  12. package/apps/agents-server/src/app/agents/[agentName]/api/chat/route.ts +11 -1
  13. package/apps/agents-server/src/app/agents/[agentName]/api/openai/models/route.ts +93 -0
  14. package/apps/agents-server/src/app/agents/[agentName]/api/openai/v1/chat/completions/route.ts +10 -0
  15. package/apps/agents-server/src/app/agents/[agentName]/api/openai/v1/models/route.ts +93 -0
  16. package/apps/agents-server/src/app/agents/[agentName]/api/voice/route.ts +4 -0
  17. package/apps/agents-server/src/app/agents/[agentName]/chat/page.tsx +9 -2
  18. package/apps/agents-server/src/app/agents/[agentName]/integration/SdkCodeTabs.tsx +31 -0
  19. package/apps/agents-server/src/app/agents/[agentName]/integration/page.tsx +271 -30
  20. package/apps/agents-server/src/app/agents/[agentName]/links/page.tsx +61 -97
  21. package/apps/agents-server/src/app/agents/[agentName]/page.tsx +108 -165
  22. package/apps/agents-server/src/app/agents/[agentName]/website-integration/page.tsx +61 -0
  23. package/apps/agents-server/src/app/api/openai/v1/chat/completions/route.ts +6 -0
  24. package/apps/agents-server/src/app/api/openai/v1/models/route.ts +65 -0
  25. package/apps/agents-server/src/app/docs/[docId]/page.tsx +12 -32
  26. package/apps/agents-server/src/app/docs/page.tsx +42 -17
  27. package/apps/agents-server/src/app/globals.css +129 -0
  28. package/apps/agents-server/src/app/layout.tsx +8 -2
  29. package/apps/agents-server/src/app/manifest.ts +1 -1
  30. package/apps/agents-server/src/components/DocumentationContent/DocumentationContent.tsx +87 -0
  31. package/apps/agents-server/src/components/OpenMojiIcon/OpenMojiIcon.tsx +20 -0
  32. package/apps/agents-server/src/components/PrintButton/PrintButton.tsx +18 -0
  33. package/apps/agents-server/src/components/PrintHeader/PrintHeader.tsx +18 -0
  34. package/apps/agents-server/src/database/migrations/2025-12-0070-chat-history-source.sql +2 -0
  35. package/apps/agents-server/src/database/schema.ts +6 -0
  36. package/apps/agents-server/src/utils/handleChatCompletion.ts +186 -14
  37. package/apps/agents-server/src/utils/resolveInheritedAgentSource.ts +13 -6
  38. package/apps/agents-server/src/utils/validateApiKey.ts +128 -0
  39. package/apps/agents-server/tailwind.config.ts +1 -1
  40. package/esm/index.es.js +865 -441
  41. package/esm/index.es.js.map +1 -1
  42. package/esm/typings/src/_packages/core.index.d.ts +6 -8
  43. package/esm/typings/src/_packages/types.index.d.ts +1 -1
  44. package/esm/typings/src/book-components/Chat/LlmChat/LlmChatProps.d.ts +5 -0
  45. package/esm/typings/src/commitments/META_COLOR/META_COLOR.d.ts +6 -0
  46. package/esm/typings/src/commitments/META_FONT/META_FONT.d.ts +42 -0
  47. package/esm/typings/src/commitments/USE/USE.d.ts +53 -0
  48. package/esm/typings/src/commitments/USE_BROWSER/USE_BROWSER.d.ts +38 -0
  49. package/esm/typings/src/commitments/USE_BROWSER/USE_BROWSER.test.d.ts +1 -0
  50. package/esm/typings/src/commitments/{IMPORTANT/IMPORTANT.d.ts → USE_MCP/USE_MCP.d.ts} +16 -5
  51. package/esm/typings/src/commitments/USE_SEARCH_ENGINE/USE_SEARCH_ENGINE.d.ts +38 -0
  52. package/esm/typings/src/commitments/index.d.ts +93 -1
  53. package/esm/typings/src/playground/playground.d.ts +3 -0
  54. package/esm/typings/src/utils/color/Color.d.ts +8 -0
  55. package/esm/typings/src/utils/color/css-colors.d.ts +1 -0
  56. package/esm/typings/src/version.d.ts +1 -1
  57. package/package.json +1 -1
  58. package/umd/index.umd.js +861 -437
  59. package/umd/index.umd.js.map +1 -1
  60. package/esm/typings/src/commitments/registry.d.ts +0 -68
  61. package/esm/typings/src/playground/playground1.d.ts +0 -2
package/esm/index.es.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import colors from 'colors';
2
2
  import commander from 'commander';
3
- import spaceTrim, { spaceTrim as spaceTrim$1 } from 'spacetrim';
3
+ import spaceTrim$2, { spaceTrim as spaceTrim$1 } from 'spacetrim';
4
4
  import { forTime, forEver } from 'waitasecond';
5
5
  import prompts from 'prompts';
6
6
  import { join, basename, dirname, isAbsolute, relative } from 'path';
@@ -47,7 +47,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
47
47
  * @generated
48
48
  * @see https://github.com/webgptorg/promptbook
49
49
  */
50
- const PROMPTBOOK_ENGINE_VERSION = '0.103.0-55';
50
+ const PROMPTBOOK_ENGINE_VERSION = '0.103.0-56';
51
51
  /**
52
52
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
53
53
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -101,6 +101,17 @@ const REMOTE_SERVER_URLS = [
101
101
  * Note: [💞] Ignore a discrepancy between file name and entity name
102
102
  */
103
103
 
104
+ /**
105
+ * Trims string from all 4 sides
106
+ *
107
+ * Note: This is a re-exported function from the `spacetrim` package which is
108
+ * Developed by same author @hejny as this package
109
+ *
110
+ * @public exported from `@promptbook/utils`
111
+ * @see https://github.com/hejny/spacetrim#usage
112
+ */
113
+ const spaceTrim = spaceTrim$1;
114
+
104
115
  /**
105
116
  * Just marks a place of place where should be something implemented
106
117
  * No side effects.
@@ -162,6 +173,7 @@ function take(initialValue) {
162
173
  * @public exported from `@promptbook/color`
163
174
  */
164
175
  const CSS_COLORS = {
176
+ promptbook: '#79EAFD',
165
177
  transparent: 'rgba(0,0,0,0)',
166
178
  aliceblue: '#f0f8ff',
167
179
  antiquewhite: '#faebd7',
@@ -377,6 +389,28 @@ class Color {
377
389
  throw new Error(`Can not create color from given object`);
378
390
  }
379
391
  }
392
+ /**
393
+ * Creates a new Color instance from miscellaneous formats
394
+ * It just does not throw error when it fails, it returns PROMPTBOOK_COLOR instead
395
+ *
396
+ * @param color
397
+ * @returns Color object
398
+ */
399
+ static fromSafe(color) {
400
+ try {
401
+ return Color.from(color);
402
+ }
403
+ catch (error) {
404
+ // <- Note: Can not use `assertsError(error)` here because it causes circular dependency
405
+ console.warn(spaceTrim((block) => `
406
+ Color.fromSafe error:
407
+ ${block(error.message)}
408
+
409
+ Returning default PROMPTBOOK_COLOR.
410
+ `));
411
+ return Color.fromString('promptbook');
412
+ }
413
+ }
380
414
  /**
381
415
  * Creates a new Color instance from miscellaneous string formats
382
416
  *
@@ -1000,7 +1034,7 @@ const CLAIM = `Turn your company's scattered knowledge into AI ready books`;
1000
1034
  *
1001
1035
  * @public exported from `@promptbook/core`
1002
1036
  */
1003
- const PROMPTBOOK_COLOR = Color.fromHex('#79EAFD');
1037
+ const PROMPTBOOK_COLOR = Color.fromString('promptbook');
1004
1038
  // <- TODO: [🧠][🈵] Using `Color` here increases the package size approx 3kb, maybe remove it
1005
1039
  /**
1006
1040
  * Colors for syntax highlighting in the `<BookEditor/>`
@@ -1398,7 +1432,7 @@ const $isRunningInWebWorker = new Function(`
1398
1432
  function getErrorReportUrl(error) {
1399
1433
  const report = {
1400
1434
  title: `🐜 Error report from ${NAME}`,
1401
- body: spaceTrim((block) => `
1435
+ body: spaceTrim$2((block) => `
1402
1436
 
1403
1437
 
1404
1438
  \`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
@@ -1537,7 +1571,7 @@ function handleActionErrors(action) {
1537
1571
  */
1538
1572
  function $initializeAboutCommand(program) {
1539
1573
  const makeCommand = program.command('about');
1540
- makeCommand.description(spaceTrim(`
1574
+ makeCommand.description(spaceTrim$2(`
1541
1575
  Tells about Promptbook CLI and its abilities
1542
1576
  `));
1543
1577
  makeCommand.action(handleActionErrors(async () => {
@@ -1585,7 +1619,7 @@ function $initializeAboutCommand(program) {
1585
1619
  */
1586
1620
  function $initializeHelloCommand(program) {
1587
1621
  const helloCommand = program.command('hello');
1588
- helloCommand.description(spaceTrim(`
1622
+ helloCommand.description(spaceTrim$2(`
1589
1623
  Just command for testing
1590
1624
  `));
1591
1625
  helloCommand.alias('hi');
@@ -1847,13 +1881,13 @@ function $registeredLlmToolsMessage() {
1847
1881
  });
1848
1882
  const usedEnvMessage = $usedEnvFilename === null ? `Unknown \`.env\` file` : `Used \`.env\` file:\n${$usedEnvFilename}`;
1849
1883
  if (metadata.length === 0) {
1850
- return spaceTrim((block) => `
1884
+ return spaceTrim$2((block) => `
1851
1885
  No LLM providers are available.
1852
1886
 
1853
1887
  ${block(usedEnvMessage)}
1854
1888
  `);
1855
1889
  }
1856
- return spaceTrim((block) => `
1890
+ return spaceTrim$2((block) => `
1857
1891
 
1858
1892
  ${block(usedEnvMessage)}
1859
1893
 
@@ -1899,7 +1933,7 @@ function $registeredLlmToolsMessage() {
1899
1933
  morePieces.push(`Not configured`); // <- Note: Can not be configured via environment variables
1900
1934
  }
1901
1935
  }
1902
- let providerMessage = spaceTrim(`
1936
+ let providerMessage = spaceTrim$2(`
1903
1937
  ${i + 1}) **${title}** \`${className}\` from \`${packageName}\`
1904
1938
  ${morePieces.join('; ')}
1905
1939
  `);
@@ -1965,7 +1999,7 @@ function jsonParse(value) {
1965
1999
  }
1966
2000
  else if (typeof value !== 'string') {
1967
2001
  console.error('Can not parse JSON from non-string value.', { text: value });
1968
- throw new Error(spaceTrim(`
2002
+ throw new Error(spaceTrim$2(`
1969
2003
  Can not parse JSON from non-string value.
1970
2004
 
1971
2005
  The value type: ${typeof value}
@@ -1979,7 +2013,7 @@ function jsonParse(value) {
1979
2013
  if (!(error instanceof Error)) {
1980
2014
  throw error;
1981
2015
  }
1982
- throw new Error(spaceTrim((block) => `
2016
+ throw new Error(spaceTrim$2((block) => `
1983
2017
  ${block(error.message)}
1984
2018
 
1985
2019
  The expected JSON text:
@@ -2200,7 +2234,7 @@ class $EnvStorage {
2200
2234
  .filter((line) => !line.startsWith(`# ${GENERATOR_WARNING_IN_ENV}`)) // Remove GENERATOR_WARNING_IN_ENV
2201
2235
  .filter((line) => !line.startsWith(`${transformedKey}=`)) // Remove existing key if present
2202
2236
  .join('\n');
2203
- const newEnvContent = spaceTrim((block) => `
2237
+ const newEnvContent = spaceTrim$2((block) => `
2204
2238
  ${block(updatedEnvContent)}
2205
2239
 
2206
2240
  # ${GENERATOR_WARNING_IN_ENV}
@@ -2311,7 +2345,7 @@ function checkSerializableAsJson(options) {
2311
2345
  }
2312
2346
  else if (typeof value === 'object') {
2313
2347
  if (value instanceof Date) {
2314
- throw new UnexpectedError(spaceTrim((block) => `
2348
+ throw new UnexpectedError(spaceTrim$2((block) => `
2315
2349
  \`${name}\` is Date
2316
2350
 
2317
2351
  Use \`string_date_iso8601\` instead
@@ -2330,7 +2364,7 @@ function checkSerializableAsJson(options) {
2330
2364
  throw new UnexpectedError(`${name} is RegExp`);
2331
2365
  }
2332
2366
  else if (value instanceof Error) {
2333
- throw new UnexpectedError(spaceTrim((block) => `
2367
+ throw new UnexpectedError(spaceTrim$2((block) => `
2334
2368
  \`${name}\` is unserialized Error
2335
2369
 
2336
2370
  Use function \`serializeError\`
@@ -2353,7 +2387,7 @@ function checkSerializableAsJson(options) {
2353
2387
  }
2354
2388
  catch (error) {
2355
2389
  assertsError(error);
2356
- throw new UnexpectedError(spaceTrim((block) => `
2390
+ throw new UnexpectedError(spaceTrim$2((block) => `
2357
2391
  \`${name}\` is not serializable
2358
2392
 
2359
2393
  ${block(error.stack || error.message)}
@@ -2385,7 +2419,7 @@ function checkSerializableAsJson(options) {
2385
2419
  }
2386
2420
  }
2387
2421
  else {
2388
- throw new UnexpectedError(spaceTrim((block) => `
2422
+ throw new UnexpectedError(spaceTrim$2((block) => `
2389
2423
  \`${name}\` is unknown type
2390
2424
 
2391
2425
  Additional message for \`${name}\`:
@@ -2593,7 +2627,7 @@ function isSerializableAsJson(value) {
2593
2627
  */
2594
2628
  function stringifyPipelineJson(pipeline) {
2595
2629
  if (!isSerializableAsJson(pipeline)) {
2596
- throw new UnexpectedError(spaceTrim(`
2630
+ throw new UnexpectedError(spaceTrim$2(`
2597
2631
  Cannot stringify the pipeline, because it is not serializable as JSON
2598
2632
 
2599
2633
  There can be multiple reasons:
@@ -3492,7 +3526,7 @@ function deserializeError(error) {
3492
3526
  message = `${name}: ${message}`;
3493
3527
  }
3494
3528
  if (stack !== undefined && stack !== '') {
3495
- message = spaceTrim((block) => `
3529
+ message = spaceTrim$2((block) => `
3496
3530
  ${block(message)}
3497
3531
 
3498
3532
  Original stack trace:
@@ -3519,7 +3553,7 @@ async function createRemoteClient(options) {
3519
3553
  const remoteServerUrlParsed = new URL(remoteServerUrl);
3520
3554
  if (remoteServerUrlParsed.pathname !== '/' && remoteServerUrlParsed.pathname !== '') {
3521
3555
  remoteServerUrlParsed.pathname = '/';
3522
- throw new Error(spaceTrim((block) => `
3556
+ throw new Error(spaceTrim$2((block) => `
3523
3557
  Remote server requires root url \`/\`
3524
3558
 
3525
3559
  You have provided \`remoteServerUrl\`:
@@ -4155,7 +4189,7 @@ function cacheLlmTools(llmTools, options = {}) {
4155
4189
  let normalizedContent = content;
4156
4190
  normalizedContent = normalizedContent.replace(/\s+/g, ' ');
4157
4191
  normalizedContent = normalizedContent.split('\r\n').join('\n');
4158
- normalizedContent = spaceTrim(normalizedContent);
4192
+ normalizedContent = spaceTrim$2(normalizedContent);
4159
4193
  // Note: Do not need to save everything in the cache, just the relevant parameters
4160
4194
  const relevantParameterNames = extractParameterNames(content);
4161
4195
  const relevantParameters = Object.fromEntries(Object.entries(parameters).filter(([key]) => relevantParameterNames.has(key)));
@@ -4540,14 +4574,14 @@ class MultipleLlmExecutionTools {
4540
4574
  if (description === undefined) {
4541
4575
  return headLine;
4542
4576
  }
4543
- return spaceTrim((block) => `
4577
+ return spaceTrim$2((block) => `
4544
4578
  ${headLine}
4545
4579
 
4546
4580
  ${ /* <- Note: Indenting the description: */block(description)}
4547
4581
  `);
4548
4582
  })
4549
4583
  .join('\n\n');
4550
- return spaceTrim((block) => `
4584
+ return spaceTrim$2((block) => `
4551
4585
  Multiple LLM Providers:
4552
4586
 
4553
4587
  ${block(innerModelsTitlesAndDescriptions)}
@@ -4638,7 +4672,7 @@ class MultipleLlmExecutionTools {
4638
4672
  // 1) OpenAI throw PipelineExecutionError: Parameter `{knowledge}` is not defined
4639
4673
  // 2) AnthropicClaude throw PipelineExecutionError: Parameter `{knowledge}` is not defined
4640
4674
  // 3) ...
4641
- spaceTrim((block) => `
4675
+ spaceTrim$2((block) => `
4642
4676
  All execution tools of ${this.title} failed:
4643
4677
 
4644
4678
  ${block(errors
@@ -4651,7 +4685,7 @@ class MultipleLlmExecutionTools {
4651
4685
  throw new PipelineExecutionError(`You have not provided any \`LlmExecutionTools\` into ${this.title}`);
4652
4686
  }
4653
4687
  else {
4654
- throw new PipelineExecutionError(spaceTrim((block) => `
4688
+ throw new PipelineExecutionError(spaceTrim$2((block) => `
4655
4689
  You have not provided any \`LlmExecutionTools\` that support model variant "${prompt.modelRequirements.modelVariant}" into ${this.title}
4656
4690
 
4657
4691
  Available \`LlmExecutionTools\`:
@@ -4684,7 +4718,7 @@ class MultipleLlmExecutionTools {
4684
4718
  */
4685
4719
  function joinLlmExecutionTools(title, ...llmExecutionTools) {
4686
4720
  if (llmExecutionTools.length === 0) {
4687
- const warningMessage = spaceTrim(`
4721
+ const warningMessage = spaceTrim$2(`
4688
4722
  You have not provided any \`LlmExecutionTools\`
4689
4723
  This means that you won't be able to execute any prompts that require large language models like GPT-4 or Anthropic's Claude.
4690
4724
 
@@ -4742,7 +4776,7 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
4742
4776
  .find(({ packageName, className }) => llmConfiguration.packageName === packageName && llmConfiguration.className === className);
4743
4777
  if (registeredItem === undefined) {
4744
4778
  // console.log('$llmToolsRegister.list()', $llmToolsRegister.list());
4745
- throw new Error(spaceTrim((block) => `
4779
+ throw new Error(spaceTrim$2((block) => `
4746
4780
  There is no constructor for LLM provider \`${llmConfiguration.className}\` from \`${llmConfiguration.packageName}\`
4747
4781
  Running in ${!$isRunningInBrowser() ? '' : 'browser environment'}${!$isRunningInNode() ? '' : 'node environment'}${!$isRunningInWebWorker() ? '' : 'worker environment'}
4748
4782
 
@@ -4810,14 +4844,14 @@ async function $provideLlmToolsFromEnv(options = {}) {
4810
4844
  const configuration = await $provideLlmToolsConfigurationFromEnv();
4811
4845
  if (configuration.length === 0) {
4812
4846
  if ($llmToolsMetadataRegister.list().length === 0) {
4813
- throw new UnexpectedError(spaceTrim((block) => `
4847
+ throw new UnexpectedError(spaceTrim$2((block) => `
4814
4848
  No LLM tools registered, this is probably a bug in the Promptbook library
4815
4849
 
4816
4850
  ${block($registeredLlmToolsMessage())}}
4817
4851
  `));
4818
4852
  }
4819
4853
  // TODO: [🥃]
4820
- throw new Error(spaceTrim((block) => `
4854
+ throw new Error(spaceTrim$2((block) => `
4821
4855
  No LLM tools found in the environment
4822
4856
 
4823
4857
  ${block($registeredLlmToolsMessage())}}
@@ -4927,7 +4961,7 @@ const promptbookFetch = async (urlOrRequest, init) => {
4927
4961
  else if (urlOrRequest instanceof Request) {
4928
4962
  url = urlOrRequest.url;
4929
4963
  }
4930
- throw new PromptbookFetchError(spaceTrim((block) => `
4964
+ throw new PromptbookFetchError(spaceTrim$2((block) => `
4931
4965
  Can not fetch "${url}"
4932
4966
 
4933
4967
  Fetch error:
@@ -4996,7 +5030,7 @@ async function $provideLlmToolsForCli(options) {
4996
5030
  console.log(colors.red(`You can not login to remote server in non-interactive mode`));
4997
5031
  process.exit(1);
4998
5032
  }
4999
- console.info(colors.cyan(spaceTrim(`
5033
+ console.info(colors.cyan(spaceTrim$2(`
5000
5034
  You will be logged in to ${remoteServerUrl}
5001
5035
  If you don't have an account, it will be created automatically.
5002
5036
  `)));
@@ -5070,7 +5104,7 @@ async function $provideLlmToolsForCli(options) {
5070
5104
  */
5071
5105
  function $initializeListModelsCommand(program) {
5072
5106
  const listModelsCommand = program.command('list-models');
5073
- listModelsCommand.description(spaceTrim(`
5107
+ listModelsCommand.description(spaceTrim$2(`
5074
5108
  List all available and configured LLM models
5075
5109
  `));
5076
5110
  listModelsCommand.alias('models');
@@ -5550,14 +5584,14 @@ function $registeredScrapersMessage(availableScrapers) {
5550
5584
  return { ...metadata, isMetadataAviailable, isInstalled, isAvailableInTools };
5551
5585
  });
5552
5586
  if (metadata.length === 0) {
5553
- return spaceTrim(`
5587
+ return spaceTrim$2(`
5554
5588
  **No scrapers are available**
5555
5589
 
5556
5590
  This is a unexpected behavior, you are probably using some broken version of Promptbook
5557
5591
  At least there should be available the metadata of the scrapers
5558
5592
  `);
5559
5593
  }
5560
- return spaceTrim((block) => `
5594
+ return spaceTrim$2((block) => `
5561
5595
  Available scrapers are:
5562
5596
  ${block(metadata
5563
5597
  .map(({ packageName, className, isMetadataAviailable, isInstalled, mimeTypes, isAvailableInBrowser, isAvailableInTools, }, i) => {
@@ -5608,7 +5642,7 @@ function $registeredScrapersMessage(availableScrapers) {
5608
5642
  */
5609
5643
  function $initializeListScrapersCommand(program) {
5610
5644
  const listModelsCommand = program.command('list-scrapers');
5611
- listModelsCommand.description(spaceTrim(`
5645
+ listModelsCommand.description(spaceTrim$2(`
5612
5646
  List all available and configured scrapers and executables
5613
5647
  `));
5614
5648
  listModelsCommand.alias('scrapers');
@@ -5616,7 +5650,7 @@ function $initializeListScrapersCommand(program) {
5616
5650
  // TODO: [🌞] Do not allow on REMOTE_SERVER strategy
5617
5651
  const scrapers = await $provideScrapersForNode({});
5618
5652
  const executables = await $provideExecutablesForNode();
5619
- console.info(spaceTrim((block) => `
5653
+ console.info(spaceTrim$2((block) => `
5620
5654
  ${block($registeredScrapersMessage(scrapers))}
5621
5655
 
5622
5656
  All mime-types which can be scraped:
@@ -5646,7 +5680,7 @@ function $initializeListScrapersCommand(program) {
5646
5680
  */
5647
5681
  function $initializeLoginCommand(program) {
5648
5682
  const loginCommand = program.command('login');
5649
- loginCommand.description(spaceTrim(`
5683
+ loginCommand.description(spaceTrim$2(`
5650
5684
  Login to the remote Promptbook server
5651
5685
  `));
5652
5686
  loginCommand.action(handleActionErrors(async (cliOptions) => {
@@ -6220,7 +6254,7 @@ function pipelineJsonToString(pipelineJson) {
6220
6254
  pipelineString += '\n\n';
6221
6255
  pipelineString += '```' + contentLanguage;
6222
6256
  pipelineString += '\n';
6223
- pipelineString += spaceTrim(content);
6257
+ pipelineString += spaceTrim$2(content);
6224
6258
  // <- TODO: [main] !!3 Escape
6225
6259
  // <- TODO: [🧠] Some clear strategy how to spaceTrim the blocks
6226
6260
  pipelineString += '\n';
@@ -6451,7 +6485,7 @@ function serializeError(error) {
6451
6485
  const { name, message, stack } = error;
6452
6486
  const { id } = error;
6453
6487
  if (!Object.keys(ALL_ERRORS).includes(name)) {
6454
- console.error(spaceTrim((block) => `
6488
+ console.error(spaceTrim$2((block) => `
6455
6489
 
6456
6490
  Cannot serialize error with name "${name}"
6457
6491
 
@@ -7052,7 +7086,7 @@ const CsvFormatParser = {
7052
7086
  const { value, outputParameterName, settings, mapCallback, onProgress } = options;
7053
7087
  const csv = csvParse(value, settings);
7054
7088
  if (csv.errors.length !== 0) {
7055
- throw new CsvFormatError(spaceTrim((block) => `
7089
+ throw new CsvFormatError(spaceTrim$2((block) => `
7056
7090
  CSV parsing error
7057
7091
 
7058
7092
  Error(s) from CSV parsing:
@@ -7097,7 +7131,7 @@ const CsvFormatParser = {
7097
7131
  const { value, settings, mapCallback, onProgress } = options;
7098
7132
  const csv = csvParse(value, settings);
7099
7133
  if (csv.errors.length !== 0) {
7100
- throw new CsvFormatError(spaceTrim((block) => `
7134
+ throw new CsvFormatError(spaceTrim$2((block) => `
7101
7135
  CSV parsing error
7102
7136
 
7103
7137
  Error(s) from CSV parsing:
@@ -7307,7 +7341,7 @@ function mapAvailableToExpectedParameters(options) {
7307
7341
  }
7308
7342
  // Phase 2️⃣: Non-matching mapping
7309
7343
  if (expectedParameterNames.size !== availableParametersNames.size) {
7310
- throw new PipelineExecutionError(spaceTrim((block) => `
7344
+ throw new PipelineExecutionError(spaceTrim$2((block) => `
7311
7345
  Can not map available parameters to expected parameters
7312
7346
 
7313
7347
  Mapped parameters:
@@ -7792,7 +7826,7 @@ async function executeFormatSubvalues(options) {
7792
7826
  return /* not await */ executeAttempts({ ...options, logLlmCall });
7793
7827
  }
7794
7828
  if (jokerParameterNames.length !== 0) {
7795
- throw new UnexpectedError(spaceTrim((block) => `
7829
+ throw new UnexpectedError(spaceTrim$2((block) => `
7796
7830
  JOKER parameters are not supported together with FOREACH command
7797
7831
 
7798
7832
  [🧞‍♀️] This should be prevented in \`validatePipeline\`
@@ -7805,7 +7839,7 @@ async function executeFormatSubvalues(options) {
7805
7839
  if (formatDefinition === undefined) {
7806
7840
  throw new UnexpectedError(
7807
7841
  // <- TODO: [🧠][🧐] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
7808
- spaceTrim((block) => `
7842
+ spaceTrim$2((block) => `
7809
7843
  Unsupported format "${task.foreach.formatName}"
7810
7844
 
7811
7845
  Available formats:
@@ -7822,7 +7856,7 @@ async function executeFormatSubvalues(options) {
7822
7856
  if (subvalueParser === undefined) {
7823
7857
  throw new UnexpectedError(
7824
7858
  // <- TODO: [🧠][🧐] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
7825
- spaceTrim((block) => `
7859
+ spaceTrim$2((block) => `
7826
7860
  Unsupported subformat name "${task.foreach.subformatName}" for format "${task.foreach.formatName}"
7827
7861
 
7828
7862
  Available subformat names for format "${formatDefinition.formatName}":
@@ -7862,7 +7896,7 @@ async function executeFormatSubvalues(options) {
7862
7896
  if (!(error instanceof PipelineExecutionError)) {
7863
7897
  throw error;
7864
7898
  }
7865
- const highLevelError = new PipelineExecutionError(spaceTrim((block) => `
7899
+ const highLevelError = new PipelineExecutionError(spaceTrim$2((block) => `
7866
7900
  ${error.message}
7867
7901
 
7868
7902
  This is error in FOREACH command when mapping ${formatDefinition.formatName} ${subvalueParser.subvalueName} data (${index + 1}/${length})
@@ -7886,7 +7920,7 @@ async function executeFormatSubvalues(options) {
7886
7920
  ...options,
7887
7921
  priority: priority + index,
7888
7922
  parameters: allSubparameters,
7889
- pipelineIdentification: spaceTrim((block) => `
7923
+ pipelineIdentification: spaceTrim$2((block) => `
7890
7924
  ${block(pipelineIdentification)}
7891
7925
  Subparameter index: ${index}
7892
7926
  `),
@@ -7895,7 +7929,7 @@ async function executeFormatSubvalues(options) {
7895
7929
  }
7896
7930
  catch (error) {
7897
7931
  if (length > BIG_DATASET_TRESHOLD) {
7898
- console.error(spaceTrim((block) => `
7932
+ console.error(spaceTrim$2((block) => `
7899
7933
  ${error.message}
7900
7934
 
7901
7935
  This is error in FOREACH command when processing ${formatDefinition.formatName} ${subvalueParser.subvalueName} data (${index + 1}/${length})
@@ -8969,7 +9003,7 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
8969
9003
  const fileExtension = getFileExtension(filename);
8970
9004
  const mimeType = extensionToMimeType(fileExtension || '');
8971
9005
  if (!(await isFileExisting(filename, tools.fs))) {
8972
- throw new NotFoundError(spaceTrim((block) => `
9006
+ throw new NotFoundError(spaceTrim$2((block) => `
8973
9007
  Can not make source handler for file which does not exist:
8974
9008
 
8975
9009
  File:
@@ -9062,7 +9096,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
9062
9096
  // <- TODO: [🪓] Here should be no need for spreading new array, just `partialPieces = partialPiecesUnchecked`
9063
9097
  break;
9064
9098
  }
9065
- console.warn(spaceTrim((block) => `
9099
+ console.warn(spaceTrim$2((block) => `
9066
9100
  Cannot scrape knowledge from source despite the scraper \`${scraper.metadata.className}\` supports the mime type "${sourceHandler.mimeType}".
9067
9101
 
9068
9102
  The source:
@@ -9078,7 +9112,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
9078
9112
  // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
9079
9113
  }
9080
9114
  if (partialPieces === null) {
9081
- throw new KnowledgeScrapeError(spaceTrim((block) => `
9115
+ throw new KnowledgeScrapeError(spaceTrim$2((block) => `
9082
9116
  Cannot scrape knowledge
9083
9117
 
9084
9118
  The source:
@@ -9414,7 +9448,7 @@ const knowledgeCommandParser = {
9414
9448
  */
9415
9449
  parse(input) {
9416
9450
  const { args } = input;
9417
- const knowledgeSourceContent = spaceTrim(args[0] || '');
9451
+ const knowledgeSourceContent = spaceTrim$2(args[0] || '');
9418
9452
  if (knowledgeSourceContent === '') {
9419
9453
  throw new ParseError(`Source is not defined`);
9420
9454
  }
@@ -9558,7 +9592,7 @@ const sectionCommandParser = {
9558
9592
  normalized = normalized.split('DIALOGUE').join('DIALOG');
9559
9593
  const taskTypes = SectionTypes.filter((sectionType) => normalized.includes(sectionType.split('_TASK').join('')));
9560
9594
  if (taskTypes.length !== 1) {
9561
- throw new ParseError(spaceTrim((block) => `
9595
+ throw new ParseError(spaceTrim$2((block) => `
9562
9596
  Unknown section type "${normalized}"
9563
9597
 
9564
9598
  Supported section types are:
@@ -9578,7 +9612,7 @@ const sectionCommandParser = {
9578
9612
  */
9579
9613
  $applyToTaskJson(command, $taskJson, $pipelineJson) {
9580
9614
  if ($taskJson.isSectionTypeSet === true) {
9581
- throw new ParseError(spaceTrim(`
9615
+ throw new ParseError(spaceTrim$2(`
9582
9616
  Section type is already defined in the section.
9583
9617
  It can be defined only once.
9584
9618
  `));
@@ -9927,7 +9961,7 @@ const expectCommandParser = {
9927
9961
  /**
9928
9962
  * Description of the FORMAT command
9929
9963
  */
9930
- description: spaceTrim(`
9964
+ description: spaceTrim$2(`
9931
9965
  Expect command describes the desired output of the task *(after post-processing)*
9932
9966
  It can set limits for the maximum/minimum length of the output, measured in characters, words, sentences, paragraphs or some other shape of the output.
9933
9967
  `),
@@ -10001,7 +10035,7 @@ const expectCommandParser = {
10001
10035
  }
10002
10036
  catch (error) {
10003
10037
  assertsError(error);
10004
- throw new ParseError(spaceTrim((block) => `
10038
+ throw new ParseError(spaceTrim$2((block) => `
10005
10039
  Invalid FORMAT command
10006
10040
  ${block(error.message)}:
10007
10041
  `));
@@ -10191,7 +10225,7 @@ function validateParameterName(parameterName) {
10191
10225
  if (!(error instanceof ParseError)) {
10192
10226
  throw error;
10193
10227
  }
10194
- throw new ParseError(spaceTrim((block) => `
10228
+ throw new ParseError(spaceTrim$2((block) => `
10195
10229
  ${block(error.message)}
10196
10230
 
10197
10231
  Tried to validate parameter name:
@@ -10250,7 +10284,7 @@ const foreachCommandParser = {
10250
10284
  const assignSign = args[3];
10251
10285
  const formatDefinition = FORMAT_DEFINITIONS.find((formatDefinition) => [formatDefinition.formatName, ...(formatDefinition.aliases || [])].includes(formatName));
10252
10286
  if (formatDefinition === undefined) {
10253
- throw new ParseError(spaceTrim((block) => `
10287
+ throw new ParseError(spaceTrim$2((block) => `
10254
10288
  Unsupported format "${formatName}"
10255
10289
 
10256
10290
  Available formats:
@@ -10262,7 +10296,7 @@ const foreachCommandParser = {
10262
10296
  }
10263
10297
  const subvalueParser = formatDefinition.subvalueParsers.find((subvalueParser) => [subvalueParser.subvalueName, ...(subvalueParser.aliases || [])].includes(subformatName));
10264
10298
  if (subvalueParser === undefined) {
10265
- throw new ParseError(spaceTrim((block) => `
10299
+ throw new ParseError(spaceTrim$2((block) => `
10266
10300
  Unsupported subformat name "${subformatName}" for format "${formatName}"
10267
10301
 
10268
10302
  Available subformat names for format "${formatDefinition.formatName}":
@@ -10310,7 +10344,7 @@ const foreachCommandParser = {
10310
10344
  outputSubparameterName = 'newLine';
10311
10345
  }
10312
10346
  else {
10313
- throw new ParseError(spaceTrim(`
10347
+ throw new ParseError(spaceTrim$2(`
10314
10348
  FOREACH ${formatName} ${subformatName} must specify output subparameter
10315
10349
 
10316
10350
  Correct example:
@@ -10386,7 +10420,7 @@ const formatCommandParser = {
10386
10420
  /**
10387
10421
  * Description of the FORMAT command
10388
10422
  */
10389
- description: spaceTrim(`
10423
+ description: spaceTrim$2(`
10390
10424
  Format command describes the desired output of the task (after post-processing)
10391
10425
  It can set limits for the maximum/minimum length of the output, measured in characters, words, sentences, paragraphs or some other shape of the output.
10392
10426
  `),
@@ -10758,7 +10792,7 @@ const formfactorCommandParser = {
10758
10792
  const formfactorNameCandidate = args[0].toUpperCase();
10759
10793
  const formfactor = FORMFACTOR_DEFINITIONS.find((definition) => [definition.name, ...{ aliasNames: [], ...definition }.aliasNames].includes(formfactorNameCandidate));
10760
10794
  if (formfactor === undefined) {
10761
- throw new ParseError(spaceTrim((block) => `
10795
+ throw new ParseError(spaceTrim$2((block) => `
10762
10796
  Unknown formfactor name "${formfactorNameCandidate}"
10763
10797
 
10764
10798
  Available formfactors:
@@ -10777,7 +10811,7 @@ const formfactorCommandParser = {
10777
10811
  */
10778
10812
  $applyToPipelineJson(command, $pipelineJson) {
10779
10813
  if ($pipelineJson.formfactorName !== undefined && $pipelineJson.formfactorName !== command.formfactorName) {
10780
- throw new ParseError(spaceTrim(`
10814
+ throw new ParseError(spaceTrim$2(`
10781
10815
  Redefinition of \`FORMFACTOR\` in the pipeline head
10782
10816
 
10783
10817
  You have used:
@@ -10920,7 +10954,7 @@ const modelCommandParser = {
10920
10954
  */
10921
10955
  parse(input) {
10922
10956
  const { args, normalized } = input;
10923
- const availableVariantsMessage = spaceTrim((block) => `
10957
+ const availableVariantsMessage = spaceTrim$2((block) => `
10924
10958
  Available variants are:
10925
10959
  ${block(MODEL_VARIANTS.map((variantName) => `- ${variantName}${variantName !== 'EMBEDDING' ? '' : ' (Not available in pipeline)'}`).join('\n'))}
10926
10960
  `);
@@ -10942,14 +10976,14 @@ const modelCommandParser = {
10942
10976
  // <- Note: [🤖]
10943
10977
  }
10944
10978
  else if (normalized.startsWith('MODEL_VARIANT_EMBED')) {
10945
- spaceTrim((block) => `
10979
+ spaceTrim$2((block) => `
10946
10980
  Embedding model can not be used in pipeline
10947
10981
 
10948
10982
  ${block(availableVariantsMessage)}
10949
10983
  `);
10950
10984
  }
10951
10985
  else {
10952
- throw new ParseError(spaceTrim((block) => `
10986
+ throw new ParseError(spaceTrim$2((block) => `
10953
10987
  Unknown model variant in command:
10954
10988
 
10955
10989
  ${block(availableVariantsMessage)}
@@ -10964,7 +10998,7 @@ const modelCommandParser = {
10964
10998
  };
10965
10999
  }
10966
11000
  else {
10967
- throw new ParseError(spaceTrim((block) => `
11001
+ throw new ParseError(spaceTrim$2((block) => `
10968
11002
  Unknown model key in command.
10969
11003
 
10970
11004
  Supported model keys are:
@@ -10991,7 +11025,7 @@ const modelCommandParser = {
10991
11025
  // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
10992
11026
  }
10993
11027
  else {
10994
- throw new ParseError(spaceTrim(`
11028
+ throw new ParseError(spaceTrim$2(`
10995
11029
  Redefinition of \`MODEL ${command.key}\` in the pipeline head
10996
11030
 
10997
11031
  You have used:
@@ -11023,7 +11057,7 @@ const modelCommandParser = {
11023
11057
  // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
11024
11058
  }
11025
11059
  else {
11026
- throw new ParseError(spaceTrim(`
11060
+ throw new ParseError(spaceTrim$2(`
11027
11061
  Redefinition of MODEL \`${command.key}\` in the task "${$taskJson.title || $taskJson.name}"
11028
11062
 
11029
11063
  You have used:
@@ -11033,7 +11067,7 @@ const modelCommandParser = {
11033
11067
  }
11034
11068
  }
11035
11069
  if (command.value === ($pipelineJson.defaultModelRequirements || {})[command.key]) {
11036
- console.log(spaceTrim(`
11070
+ console.log(spaceTrim$2(`
11037
11071
  Setting MODEL \`${command.key}\` in the task "${$taskJson.title || $taskJson.name}" to the same value as in the pipeline head
11038
11072
 
11039
11073
  In pipeline head:
@@ -11116,7 +11150,7 @@ const parameterCommandParser = {
11116
11150
  // <- TODO: When [🥶] fixed, change to:
11117
11151
  // > const parameterDescriptionRaw = rawArgs.split(parameterNameRaw).join('').trim();
11118
11152
  if (parameterDescriptionRaw && parameterDescriptionRaw.match(/\{(?<embeddedParameterName>[a-z0-9_]+)\}/im)) {
11119
- throw new ParseError(spaceTrim((block) => `
11153
+ throw new ParseError(spaceTrim$2((block) => `
11120
11154
  Parameter \`{${parameterNameRaw}}\` can not contain another parameter in description
11121
11155
 
11122
11156
  The description:
@@ -11298,7 +11332,7 @@ function $applyToTaskJson(command, $taskJson, $pipelineJson) {
11298
11332
  persona.description = personaDescription;
11299
11333
  return;
11300
11334
  }
11301
- console.warn(spaceTrim(`
11335
+ console.warn(spaceTrim$2(`
11302
11336
 
11303
11337
  Persona "${personaName}" is defined multiple times with different description:
11304
11338
 
@@ -11309,7 +11343,7 @@ function $applyToTaskJson(command, $taskJson, $pipelineJson) {
11309
11343
  ${personaDescription}
11310
11344
 
11311
11345
  `));
11312
- persona.description += spaceTrim('\n\n' + personaDescription);
11346
+ persona.description += spaceTrim$2('\n\n' + personaDescription);
11313
11347
  }
11314
11348
 
11315
11349
  /**
@@ -12164,7 +12198,7 @@ function removeMarkdownComments(content) {
12164
12198
  */
12165
12199
  function isFlatPipeline(pipelineString) {
12166
12200
  pipelineString = removeMarkdownComments(pipelineString);
12167
- pipelineString = spaceTrim(pipelineString);
12201
+ pipelineString = spaceTrim$2(pipelineString);
12168
12202
  const isMarkdownBeginningWithHeadline = pipelineString.startsWith('# ');
12169
12203
  //const isLastLineReturnStatement = pipelineString.split('\n').pop()!.split('`').join('').startsWith('->');
12170
12204
  const isBacktickBlockUsed = pipelineString.includes('```');
@@ -12190,7 +12224,7 @@ function deflatePipeline(pipelineString) {
12190
12224
  if (!isFlatPipeline(pipelineString)) {
12191
12225
  return pipelineString;
12192
12226
  }
12193
- pipelineString = spaceTrim(pipelineString);
12227
+ pipelineString = spaceTrim$2(pipelineString);
12194
12228
  const pipelineStringLines = pipelineString.split('\n');
12195
12229
  const potentialReturnStatement = pipelineStringLines.pop();
12196
12230
  let returnStatement;
@@ -12203,19 +12237,19 @@ function deflatePipeline(pipelineString) {
12203
12237
  returnStatement = `-> {${DEFAULT_BOOK_OUTPUT_PARAMETER_NAME}}`;
12204
12238
  pipelineStringLines.push(potentialReturnStatement);
12205
12239
  }
12206
- const prompt = spaceTrim(pipelineStringLines.join('\n'));
12240
+ const prompt = spaceTrim$2(pipelineStringLines.join('\n'));
12207
12241
  let quotedPrompt;
12208
12242
  if (prompt.split('\n').length <= 1) {
12209
12243
  quotedPrompt = `> ${prompt}`;
12210
12244
  }
12211
12245
  else {
12212
- quotedPrompt = spaceTrim((block) => `
12246
+ quotedPrompt = spaceTrim$2((block) => `
12213
12247
  \`\`\`
12214
12248
  ${block(prompt.split('`').join('\\`'))}
12215
12249
  \`\`\`
12216
12250
  `);
12217
12251
  }
12218
- pipelineString = validatePipelineString(spaceTrim((block) => `
12252
+ pipelineString = validatePipelineString(spaceTrim$2((block) => `
12219
12253
  # ${DEFAULT_BOOK_TITLE}
12220
12254
 
12221
12255
  ## Prompt
@@ -12279,7 +12313,7 @@ function extractAllListItemsFromMarkdown(markdown) {
12279
12313
  function extractOneBlockFromMarkdown(markdown) {
12280
12314
  const codeBlocks = extractAllBlocksFromMarkdown(markdown);
12281
12315
  if (codeBlocks.length !== 1) {
12282
- throw new ParseError(spaceTrim((block) => `
12316
+ throw new ParseError(spaceTrim$2((block) => `
12283
12317
  There should be exactly 1 code block in task section, found ${codeBlocks.length} code blocks
12284
12318
 
12285
12319
  ${block(codeBlocks.map((block, i) => `Block ${i + 1}:\n${block.content}`).join('\n\n\n'))}
@@ -12304,7 +12338,7 @@ function parseMarkdownSection(value) {
12304
12338
  }
12305
12339
  const title = lines[0].replace(/^#+\s*/, '');
12306
12340
  const level = (_b = (_a = lines[0].match(/^#+/)) === null || _a === void 0 ? void 0 : _a[0].length) !== null && _b !== void 0 ? _b : 0;
12307
- const content = spaceTrim(lines.slice(1).join('\n'));
12341
+ const content = spaceTrim$2(lines.slice(1).join('\n'));
12308
12342
  if (level < 1 || level > 6) {
12309
12343
  throw new ParseError('Markdown section must have heading level between 1 and 6');
12310
12344
  }
@@ -12332,7 +12366,7 @@ function splitMarkdownIntoSections(markdown) {
12332
12366
  if (buffer.length === 0) {
12333
12367
  return;
12334
12368
  }
12335
- let section = spaceTrim(buffer.join('\n'));
12369
+ let section = spaceTrim$2(buffer.join('\n'));
12336
12370
  if (section === '') {
12337
12371
  return;
12338
12372
  }
@@ -12407,7 +12441,7 @@ function flattenMarkdown(markdown) {
12407
12441
  flattenedMarkdown += `## ${title}` + `\n\n`;
12408
12442
  flattenedMarkdown += content + `\n\n`; // <- [🧠] Maybe 3 new lines?
12409
12443
  }
12410
- return spaceTrim(flattenedMarkdown);
12444
+ return spaceTrim$2(flattenedMarkdown);
12411
12445
  }
12412
12446
  /**
12413
12447
  * TODO: [🏛] This can be part of markdown builder
@@ -13008,7 +13042,7 @@ function renderPromptbookMermaid(pipelineJson, options) {
13008
13042
  * @public exported from `@promptbook/utils`
13009
13043
  */
13010
13044
  function computeHash(value) {
13011
- return SHA256(hexEncoder.parse(spaceTrim(valueToString(value)))).toString( /* hex */);
13045
+ return SHA256(hexEncoder.parse(spaceTrim$2(valueToString(value)))).toString( /* hex */);
13012
13046
  }
13013
13047
  /**
13014
13048
  * TODO: [🥬][🥬] Use this ACRY
@@ -13277,8 +13311,8 @@ class JavascriptEvalExecutionTools {
13277
13311
  }
13278
13312
  // Note: [💎]
13279
13313
  // Note: Using direct eval, following variables are in same scope as eval call so they are accessible from inside the evaluated script:
13280
- const spaceTrim$1 = (_) => spaceTrim(_);
13281
- $preserve(spaceTrim$1);
13314
+ const spaceTrim = (_) => spaceTrim$2(_);
13315
+ $preserve(spaceTrim);
13282
13316
  const removeQuotes$1 = removeQuotes;
13283
13317
  $preserve(removeQuotes$1);
13284
13318
  const unwrapResult$1 = unwrapResult;
@@ -13331,7 +13365,7 @@ class JavascriptEvalExecutionTools {
13331
13365
  // TODO: DRY [🍯]
13332
13366
  const buildinFunctions = {
13333
13367
  // TODO: [🍯] DRY all these functions across the file
13334
- spaceTrim: spaceTrim$1,
13368
+ spaceTrim,
13335
13369
  removeQuotes: removeQuotes$1,
13336
13370
  unwrapResult: unwrapResult$1,
13337
13371
  trimEndOfCodeBlock: trimEndOfCodeBlock$1,
@@ -13368,7 +13402,7 @@ class JavascriptEvalExecutionTools {
13368
13402
  .join('\n');
13369
13403
  // script = templateParameters(script, parameters);
13370
13404
  // <- TODO: [🧠][🥳] Should be this is one of two variants how to use parameters in script
13371
- const statementToEvaluate = spaceTrim((block) => `
13405
+ const statementToEvaluate = spaceTrim$2((block) => `
13372
13406
 
13373
13407
  // Build-in functions:
13374
13408
  ${block(buildinFunctionsStatement)}
@@ -13383,7 +13417,7 @@ class JavascriptEvalExecutionTools {
13383
13417
  (()=>{ ${script} })()
13384
13418
  `);
13385
13419
  if (this.options.isVerbose) {
13386
- console.info(spaceTrim((block) => `
13420
+ console.info(spaceTrim$2((block) => `
13387
13421
  🚀 Evaluating ${scriptLanguage} script:
13388
13422
 
13389
13423
  ${block(statementToEvaluate)}`));
@@ -13405,7 +13439,7 @@ class JavascriptEvalExecutionTools {
13405
13439
  To: [PipelineExecutionError: Parameter `{thing}` is not defined],
13406
13440
  */
13407
13441
  if (!statementToEvaluate.includes(undefinedName + '(')) {
13408
- throw new PipelineExecutionError(spaceTrim((block) => `
13442
+ throw new PipelineExecutionError(spaceTrim$2((block) => `
13409
13443
 
13410
13444
  Parameter \`{${undefinedName}}\` is not defined
13411
13445
 
@@ -13427,7 +13461,7 @@ class JavascriptEvalExecutionTools {
13427
13461
  `));
13428
13462
  }
13429
13463
  else {
13430
- throw new PipelineExecutionError(spaceTrim((block) => `
13464
+ throw new PipelineExecutionError(spaceTrim$2((block) => `
13431
13465
  Function ${undefinedName}() is not defined
13432
13466
 
13433
13467
  - Make sure that the function is one of built-in functions
@@ -13674,7 +13708,7 @@ async function createPipelineCollectionFromDirectory(rootPath, tools, options) {
13674
13708
  catch (error) {
13675
13709
  assertsError(error);
13676
13710
  // TODO: [7] DRY
13677
- const wrappedErrorMessage = spaceTrim((block) => `
13711
+ const wrappedErrorMessage = spaceTrim$2((block) => `
13678
13712
  ${error.name} in pipeline ${fileName.split('\\').join('/')}⁠:
13679
13713
 
13680
13714
  Original error message:
@@ -13709,7 +13743,7 @@ async function createPipelineCollectionFromDirectory(rootPath, tools, options) {
13709
13743
  pipeline = { ...pipeline, pipelineUrl };
13710
13744
  }
13711
13745
  else if (!pipeline.pipelineUrl.startsWith(rootUrl)) {
13712
- throw new PipelineUrlError(spaceTrim(`
13746
+ throw new PipelineUrlError(spaceTrim$2(`
13713
13747
  Pipeline with URL ${pipeline.pipelineUrl} is not a child of the root URL ${rootUrl} 🍏
13714
13748
 
13715
13749
  File:
@@ -13747,7 +13781,7 @@ async function createPipelineCollectionFromDirectory(rootPath, tools, options) {
13747
13781
  }
13748
13782
  else {
13749
13783
  const existing = collection.get(pipeline.pipelineUrl);
13750
- throw new PipelineUrlError(spaceTrim(`
13784
+ throw new PipelineUrlError(spaceTrim$2(`
13751
13785
  Pipeline with URL ${pipeline.pipelineUrl} is already in the collection 🍏
13752
13786
 
13753
13787
  Conflicting files:
@@ -13765,7 +13799,7 @@ async function createPipelineCollectionFromDirectory(rootPath, tools, options) {
13765
13799
  catch (error) {
13766
13800
  assertsError(error);
13767
13801
  // TODO: [7] DRY
13768
- const wrappedErrorMessage = spaceTrim((block) => `
13802
+ const wrappedErrorMessage = spaceTrim$2((block) => `
13769
13803
  ${error.name} in pipeline ${fileName.split('\\').join('/')}⁠:
13770
13804
 
13771
13805
  Original error message:
@@ -13897,7 +13931,7 @@ function usageToHuman(usage) {
13897
13931
  // Note: For negligible usage, we report at least something
13898
13932
  reportItems.push('Negligible');
13899
13933
  }
13900
- return spaceTrim((block) => `
13934
+ return spaceTrim$2((block) => `
13901
13935
  Usage:
13902
13936
  ${block(reportItems.map((item) => `- ${item}`).join('\n'))}
13903
13937
  `);
@@ -13936,7 +13970,7 @@ async function $provideScriptingForNode(options) {
13936
13970
  */
13937
13971
  function $initializeMakeCommand(program) {
13938
13972
  const makeCommand = program.command('make');
13939
- makeCommand.description(spaceTrim(`
13973
+ makeCommand.description(spaceTrim$2(`
13940
13974
  Makes a new pipeline collection in given folder
13941
13975
  `));
13942
13976
  makeCommand.alias('compile');
@@ -13948,7 +13982,7 @@ function $initializeMakeCommand(program) {
13948
13982
  'Path to promptbook collection directory', DEFAULT_BOOKS_DIRNAME);
13949
13983
  makeCommand.option('--project-name', `Name of the project for whom collection is`, 'Untitled Promptbook project');
13950
13984
  makeCommand.option('--root-url <url>', `Root URL of all pipelines to make`, undefined);
13951
- makeCommand.option('-f, --format <format>', spaceTrim(`
13985
+ makeCommand.option('-f, --format <format>', spaceTrim$2(`
13952
13986
  Output format of builded collection "bookc", "javascript", "typescript" or "json"
13953
13987
 
13954
13988
  Note: You can use multiple formats separated by comma
@@ -13956,14 +13990,14 @@ function $initializeMakeCommand(program) {
13956
13990
  makeCommand.option('--no-validation', `Do not validate logic of pipelines in collection`, true);
13957
13991
  makeCommand.option('--validation', `Types of validations separated by comma (options "logic","imports")`, 'logic,imports');
13958
13992
  makeCommand.option('-r, --reload', `Call LLM models even if same prompt with result is in the cache`, false);
13959
- makeCommand.option('-o, --output <path>', spaceTrim(`
13993
+ makeCommand.option('-o, --output <path>', spaceTrim$2(`
13960
13994
  Where to save the builded collection
13961
13995
 
13962
13996
  Note: If you keep it "${DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME}" it will be saved in the root of the promptbook directory
13963
13997
  If you set it to a path, it will be saved in that path
13964
13998
  BUT you can use only one format and set correct extension
13965
13999
  `), DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME);
13966
- makeCommand.option('-fn, --function-name <functionName>', spaceTrim(`
14000
+ makeCommand.option('-fn, --function-name <functionName>', spaceTrim$2(`
13967
14001
  Name of the function to get pipeline collection
13968
14002
 
13969
14003
  Note: This can be used only with "javascript" or "typescript" format
@@ -14046,7 +14080,7 @@ function $initializeMakeCommand(program) {
14046
14080
  if (lastChar !== ']') {
14047
14081
  throw new UnexpectedError(`Last character of serialized collection should be "]" not "${lastChar}"`);
14048
14082
  }
14049
- return spaceTrim(collectionJsonString.substring(1, collectionJsonString.length - 1));
14083
+ return spaceTrim$2(collectionJsonString.substring(1, collectionJsonString.length - 1));
14050
14084
  })();
14051
14085
  const saveFile = async (extension, content) => {
14052
14086
  const filename = output !== DEFAULT_PIPELINE_COLLECTION_BASE_FILENAME
@@ -14077,7 +14111,7 @@ function $initializeMakeCommand(program) {
14077
14111
  }
14078
14112
  if (formats.includes('javascript') || formats.includes('js')) {
14079
14113
  formats = formats.filter((format) => format !== 'javascript' && format !== 'js');
14080
- (await saveFile('js', spaceTrim((block) => `
14114
+ (await saveFile('js', spaceTrim$2((block) => `
14081
14115
  // ${block(GENERATOR_WARNING_BY_PROMPTBOOK_CLI)}
14082
14116
 
14083
14117
  import { createPipelineCollectionFromJson } from '@promptbook/core';
@@ -14114,7 +14148,7 @@ function $initializeMakeCommand(program) {
14114
14148
  }
14115
14149
  if (formats.includes('typescript') || formats.includes('ts')) {
14116
14150
  formats = formats.filter((format) => format !== 'typescript' && format !== 'ts');
14117
- await saveFile('ts', spaceTrim((block) => `
14151
+ await saveFile('ts', spaceTrim$2((block) => `
14118
14152
  // ${block(GENERATOR_WARNING_BY_PROMPTBOOK_CLI)}
14119
14153
 
14120
14154
  import { createPipelineCollectionFromJson } from '@promptbook/core';
@@ -14259,7 +14293,7 @@ async function prettifyPipelineString(pipelineString, options) {
14259
14293
  */
14260
14294
  function $initializePrettifyCommand(program) {
14261
14295
  const prettifyCommand = program.command('prettify');
14262
- prettifyCommand.description(spaceTrim(`
14296
+ prettifyCommand.description(spaceTrim$2(`
14263
14297
  Iterates over \`.book.md\` files and does multiple enhancing operations on them:
14264
14298
 
14265
14299
  1) Adds Mermaid graph
@@ -14715,7 +14749,7 @@ async function $getCompiledBook(tools, pipelineSource, options) {
14715
14749
  // console.log(`Strategy 3️⃣`);
14716
14750
  const response = await fetch(pipelineSource);
14717
14751
  if (response.status >= 300) {
14718
- throw new NotFoundError(spaceTrim((block) => `
14752
+ throw new NotFoundError(spaceTrim$2((block) => `
14719
14753
  Book not found on URL:
14720
14754
  ${block(pipelineSource)}
14721
14755
 
@@ -14725,7 +14759,7 @@ async function $getCompiledBook(tools, pipelineSource, options) {
14725
14759
  const pipelineString = await response.text();
14726
14760
  // console.log({ pipelineString });
14727
14761
  if (!isValidPipelineString(pipelineString)) {
14728
- throw new NotFoundError(spaceTrim((block) => `
14762
+ throw new NotFoundError(spaceTrim$2((block) => `
14729
14763
  Book not found on URL:
14730
14764
  ${block(pipelineSource)}
14731
14765
 
@@ -14747,7 +14781,7 @@ async function $getCompiledBook(tools, pipelineSource, options) {
14747
14781
  });
14748
14782
  return pipelineJson;
14749
14783
  } /* not else */
14750
- throw new NotFoundError(spaceTrim((block) => `
14784
+ throw new NotFoundError(spaceTrim$2((block) => `
14751
14785
  Book not found:
14752
14786
  ${block(pipelineSource)}
14753
14787
 
@@ -14794,7 +14828,7 @@ async function runInteractiveChatbot(options) {
14794
14828
  const initialMessage = (((_a = pipeline.parameters.find(({ name }) => name === 'chatbotResponse')) === null || _a === void 0 ? void 0 : _a.exampleValues) || [])[0];
14795
14829
  if (initialMessage) {
14796
14830
  console.info(`\n`);
14797
- console.info(spaceTrim((block) => `
14831
+ console.info(spaceTrim$2((block) => `
14798
14832
 
14799
14833
  ${colors.bold(colors.green('Chatbot:'))}
14800
14834
  ${block(colors.green(initialMessage))}
@@ -14817,7 +14851,7 @@ async function runInteractiveChatbot(options) {
14817
14851
  type: 'text',
14818
14852
  name: 'userMessage',
14819
14853
  message: 'User message',
14820
- hint: spaceTrim((block) => `
14854
+ hint: spaceTrim$2((block) => `
14821
14855
  Type "exit" to exit,
14822
14856
 
14823
14857
  previousTitle
@@ -14833,7 +14867,7 @@ async function runInteractiveChatbot(options) {
14833
14867
  return process.exit(0);
14834
14868
  }
14835
14869
  console.info(`\n`);
14836
- console.info(spaceTrim((block) => `
14870
+ console.info(spaceTrim$2((block) => `
14837
14871
 
14838
14872
  ${colors.bold(colors.blue('User:'))}
14839
14873
  ${block(colors.blue(userMessage))}
@@ -14846,7 +14880,7 @@ async function runInteractiveChatbot(options) {
14846
14880
  };
14847
14881
  const result = await pipelineExecutor(inputParameters).asPromise({ isCrashedOnError: true });
14848
14882
  console.info(`\n`);
14849
- console.info(spaceTrim((block) => `
14883
+ console.info(spaceTrim$2((block) => `
14850
14884
 
14851
14885
  ${colors.bold(colors.green('Chatbot:'))}
14852
14886
  ${block(colors.green(result.outputParameters.chatbotResponse))}
@@ -14877,7 +14911,7 @@ async function runInteractiveChatbot(options) {
14877
14911
  */
14878
14912
  function $initializeRunCommand(program) {
14879
14913
  const runCommand = program.command('run', { isDefault: true });
14880
- runCommand.description(spaceTrim(`
14914
+ runCommand.description(spaceTrim$2(`
14881
14915
  Runs a pipeline
14882
14916
  `));
14883
14917
  runCommand.alias('execute');
@@ -14920,7 +14954,7 @@ function $initializeRunCommand(program) {
14920
14954
  if (!error.message.includes('No LLM tools')) {
14921
14955
  throw error;
14922
14956
  }
14923
- console.error(colors.red(spaceTrim((block) => `
14957
+ console.error(colors.red(spaceTrim$2((block) => `
14924
14958
  You need to configure LLM tools first
14925
14959
 
14926
14960
  1) Create .env file at the root of your project
@@ -14983,7 +15017,7 @@ function $initializeRunCommand(program) {
14983
15017
  if (!(error instanceof ParseError)) {
14984
15018
  throw error;
14985
15019
  }
14986
- console.error(colors.red(spaceTrim((block) => `
15020
+ console.error(colors.red(spaceTrim$2((block) => `
14987
15021
  ${block(error.message)}
14988
15022
 
14989
15023
  in ${pipelineSource}
@@ -15035,7 +15069,7 @@ function $initializeRunCommand(program) {
15035
15069
  };
15036
15070
  });
15037
15071
  if (isInteractive === false && questions.length !== 0) {
15038
- console.error(colors.red(spaceTrim((block) => `
15072
+ console.error(colors.red(spaceTrim$2((block) => `
15039
15073
  When using --no-interactive you need to pass all the input parameters through --json
15040
15074
 
15041
15075
  You are missing:
@@ -15167,7 +15201,7 @@ function $initializeStartAgentsServerCommand(program) {
15167
15201
  'Path to agents directory', DEFAULT_AGENTS_DIRNAME);
15168
15202
  startServerCommand.option('--port <port>', `Port to start the server on`, '4440');
15169
15203
  startServerCommand.option('-r, --reload', `Call LLM models even if same prompt with result is in the cache`, false);
15170
- startServerCommand.description(spaceTrim(`
15204
+ startServerCommand.description(spaceTrim$2(`
15171
15205
  Starts a Promptbook agents server
15172
15206
  `));
15173
15207
  startServerCommand.alias('start');
@@ -16474,7 +16508,7 @@ function $initializeStartPipelinesServerCommand(program) {
16474
16508
  // <- TODO: [🧟‍♂️] Unite path to promptbook collection argument
16475
16509
  'Path to promptbook collection directory', DEFAULT_BOOKS_DIRNAME);
16476
16510
  startServerCommand.option('--port <port>', `Port to start the server on`, '4460');
16477
- startServerCommand.option('-u, --url <url>', spaceTrim(`
16511
+ startServerCommand.option('-u, --url <url>', spaceTrim$2(`
16478
16512
  Public root url of the server
16479
16513
  It is used for following purposes:
16480
16514
 
@@ -16484,7 +16518,7 @@ function $initializeStartPipelinesServerCommand(program) {
16484
16518
  startServerCommand.option('--allow-anonymous', `Is anonymous mode allowed`, false);
16485
16519
  startServerCommand.option('-r, --reload', `Call LLM models even if same prompt with result is in the cache`, false);
16486
16520
  startServerCommand.option('--no-rich-ui', `Disable rich UI`, true);
16487
- startServerCommand.description(spaceTrim(`
16521
+ startServerCommand.description(spaceTrim$2(`
16488
16522
  Starts a remote server to execute books
16489
16523
 
16490
16524
  Note: You want probably to use "ptbk start-agents-server" to start agents server instead of pipelines server
@@ -16575,7 +16609,7 @@ function $initializeStartPipelinesServerCommand(program) {
16575
16609
  */
16576
16610
  function $initializeTestCommand(program) {
16577
16611
  const testCommand = program.command('test');
16578
- testCommand.description(spaceTrim(`
16612
+ testCommand.description(spaceTrim$2(`
16579
16613
  Iterates over \`.book.md\` and \`.bookc\` and checks if they are parsable and logically valid
16580
16614
  `));
16581
16615
  testCommand.argument('<filesGlob>',
@@ -17215,7 +17249,7 @@ class AnthropicClaudeExecutionTools {
17215
17249
  getDefaultModel(defaultModelName) {
17216
17250
  const model = ANTHROPIC_CLAUDE_MODELS.find(({ modelName }) => modelName.startsWith(defaultModelName));
17217
17251
  if (model === undefined) {
17218
- throw new UnexpectedError(spaceTrim((block) => `
17252
+ throw new UnexpectedError(spaceTrim$2((block) => `
17219
17253
  Cannot find model in Anthropic Claude models with name "${defaultModelName}" which should be used as default.
17220
17254
 
17221
17255
  Available models:
@@ -18437,7 +18471,7 @@ function createExecutionToolsFromVercelProvider(options) {
18437
18471
  const modelName = modelRequirements.modelName ||
18438
18472
  ((_a = availableModels.find(({ modelVariant }) => modelVariant === 'CHAT')) === null || _a === void 0 ? void 0 : _a.modelName);
18439
18473
  if (!modelName) {
18440
- throw new PipelineExecutionError(spaceTrim(`
18474
+ throw new PipelineExecutionError(spaceTrim$2(`
18441
18475
  Can not determine which model to use.
18442
18476
 
18443
18477
  You need to provide at least one of:
@@ -19775,7 +19809,7 @@ class OpenAiCompatibleExecutionTools {
19775
19809
  // Note: Match exact or prefix for model families
19776
19810
  const model = this.HARDCODED_MODELS.find(({ modelName }) => modelName === defaultModelName || modelName.startsWith(defaultModelName));
19777
19811
  if (model === undefined) {
19778
- throw new PipelineExecutionError(spaceTrim((block) => `
19812
+ throw new PipelineExecutionError(spaceTrim$2((block) => `
19779
19813
  Cannot find model in ${this.title} models with name "${defaultModelName}" which should be used as default.
19780
19814
 
19781
19815
  Available models:
@@ -20519,18 +20553,26 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
20519
20553
  modelName: 'assistant',
20520
20554
  // <- [🧠] What is the best value here
20521
20555
  });
20556
+ // Build thread messages: include previous thread messages + current user message
20557
+ const threadMessages = [];
20558
+ // TODO: [🈹] Maybe this should not be here but in other place, look at commit 39d705e75e5bcf7a818c3af36bc13e1c8475c30c
20559
+ // Add previous messages from thread (if any)
20560
+ if ('thread' in prompt &&
20561
+ Array.isArray(prompt.thread)) {
20562
+ const previousMessages = prompt.thread.map((msg) => ({
20563
+ role: (msg.role === 'assistant' ? 'assistant' : 'user'),
20564
+ content: msg.content,
20565
+ }));
20566
+ threadMessages.push(...previousMessages);
20567
+ }
20568
+ // Always add the current user message
20569
+ threadMessages.push({ role: 'user', content: rawPromptContent });
20522
20570
  const rawRequest = {
20523
20571
  // TODO: [👨‍👨‍👧‍👧] ...modelSettings,
20524
20572
  // TODO: [👨‍👨‍👧‍👧][🧠] What about system message for assistants, does it make sense - combination of OpenAI assistants with Promptbook Personas
20525
20573
  assistant_id: this.assistantId,
20526
20574
  thread: {
20527
- messages: 'thread' in prompt &&
20528
- Array.isArray(prompt.thread)
20529
- ? prompt.thread.map((msg) => ({
20530
- role: msg.role === 'assistant' ? 'assistant' : 'user',
20531
- content: msg.content,
20532
- }))
20533
- : [{ role: 'user', content: rawPromptContent }],
20575
+ messages: threadMessages,
20534
20576
  },
20535
20577
  // <- TODO: Add user identification here> user: this.options.user,
20536
20578
  };
@@ -20550,7 +20592,7 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
20550
20592
  console.info('textDelta', textDelta.value);
20551
20593
  }
20552
20594
  const chunk = {
20553
- content: textDelta.value || '',
20595
+ content: snapshot.value,
20554
20596
  modelName: 'assistant',
20555
20597
  timing: {
20556
20598
  start,
@@ -21221,8 +21263,8 @@ class MarkdownScraper {
21221
21263
  knowledgeTextPieces.map(async (knowledgeTextPiece, i) => {
21222
21264
  // Note: These are just default values, they will be overwritten by the actual values:
21223
21265
  let name = `piece-${i}`;
21224
- let title = spaceTrim(knowledgeTextPiece.substring(0, 100));
21225
- const knowledgePieceContent = spaceTrim(knowledgeTextPiece);
21266
+ let title = spaceTrim$2(knowledgeTextPiece.substring(0, 100));
21267
+ const knowledgePieceContent = spaceTrim$2(knowledgeTextPiece);
21226
21268
  let keywords = [];
21227
21269
  const index = [];
21228
21270
  /*
@@ -21235,7 +21277,7 @@ class MarkdownScraper {
21235
21277
  isCrashedOnError: true,
21236
21278
  });
21237
21279
  const { title: titleRaw = 'Untitled' } = titleResult.outputParameters;
21238
- title = spaceTrim(titleRaw) /* <- TODO: Maybe do in pipeline */;
21280
+ title = spaceTrim$2(titleRaw) /* <- TODO: Maybe do in pipeline */;
21239
21281
  name = titleToName(title);
21240
21282
  // --- Keywords
21241
21283
  const keywordsResult = await prepareKeywordsExecutor({ knowledgePieceContent }).asPromise({
@@ -21390,7 +21432,7 @@ class BoilerplateScraper {
21390
21432
  await $execCommand(command);
21391
21433
  // Note: [0]
21392
21434
  if (!(await isFileExisting(cacheFilehandler.filename, this.tools.fs))) {
21393
- throw new UnexpectedError(spaceTrim((block) => `
21435
+ throw new UnexpectedError(spaceTrim$2((block) => `
21394
21436
  File that was supposed to be created by Pandoc does not exist for unknown reason
21395
21437
 
21396
21438
  Expected file:
@@ -21554,7 +21596,7 @@ class DocumentScraper {
21554
21596
  await $execCommand(command);
21555
21597
  // Note: [0]
21556
21598
  if (!(await isFileExisting(cacheFilehandler.filename, this.tools.fs))) {
21557
- throw new UnexpectedError(spaceTrim((block) => `
21599
+ throw new UnexpectedError(spaceTrim$2((block) => `
21558
21600
  File that was supposed to be created by Pandoc does not exist for unknown reason
21559
21601
 
21560
21602
  Expected file:
@@ -21705,7 +21747,7 @@ class LegacyDocumentScraper {
21705
21747
  await $execCommand(command);
21706
21748
  const files = await readdir(documentSourceOutdirPathForLibreOffice);
21707
21749
  if (files.length !== 1) {
21708
- throw new UnexpectedError(spaceTrim((block) => `
21750
+ throw new UnexpectedError(spaceTrim$2((block) => `
21709
21751
  Expected exactly 1 file in the LibreOffice output directory, got ${files.length}
21710
21752
 
21711
21753
  The temporary folder:
@@ -21719,7 +21761,7 @@ class LegacyDocumentScraper {
21719
21761
  await rename(join(documentSourceOutdirPathForLibreOffice, file), cacheFilehandler.filename);
21720
21762
  await rmdir(documentSourceOutdirPathForLibreOffice);
21721
21763
  if (!(await isFileExisting(cacheFilehandler.filename, this.tools.fs))) {
21722
- throw new UnexpectedError(spaceTrim((block) => `
21764
+ throw new UnexpectedError(spaceTrim$2((block) => `
21723
21765
  File that was supposed to be created by LibreOffice does not exist for unknown reason
21724
21766
 
21725
21767
  Expected file:
@@ -23097,227 +23139,6 @@ class GoalCommitmentDefinition extends BaseCommitmentDefinition {
23097
23139
  * Note: [💞] Ignore a discrepancy between file name and entity name
23098
23140
  */
23099
23141
 
23100
- /**
23101
- * Placeholder commitment definition for commitments that are not yet implemented
23102
- *
23103
- * This commitment simply adds its content 1:1 into the system message,
23104
- * preserving the original behavior until proper implementation is added.
23105
- *
23106
- * @public exported from `@promptbook/core`
23107
- */
23108
- class NotYetImplementedCommitmentDefinition extends BaseCommitmentDefinition {
23109
- constructor(type) {
23110
- super(type);
23111
- }
23112
- /**
23113
- * Short one-line description of a placeholder commitment.
23114
- */
23115
- get description() {
23116
- return 'Placeholder commitment that appends content verbatim to the system message.';
23117
- }
23118
- /**
23119
- * Icon for this commitment.
23120
- */
23121
- get icon() {
23122
- return '🚧';
23123
- }
23124
- /**
23125
- * Markdown documentation available at runtime.
23126
- */
23127
- get documentation() {
23128
- return spaceTrim$1(`
23129
- # ${this.type}
23130
-
23131
- This commitment is not yet fully implemented.
23132
-
23133
- ## Key aspects
23134
-
23135
- - Content is appended directly to the system message.
23136
- - No special processing or validation is performed.
23137
- - Behavior preserved until proper implementation is added.
23138
-
23139
- ## Status
23140
-
23141
- - **Status:** Placeholder implementation
23142
- - **Effect:** Appends content prefixed by commitment type
23143
- - **Future:** Will be replaced with specialized logic
23144
-
23145
- ## Examples
23146
-
23147
- \`\`\`book
23148
- Example Agent
23149
-
23150
- PERSONA You are a helpful assistant
23151
- ${this.type} Your content here
23152
- RULE Always be helpful
23153
- \`\`\`
23154
- `);
23155
- }
23156
- applyToAgentModelRequirements(requirements, content) {
23157
- const trimmedContent = content.trim();
23158
- if (!trimmedContent) {
23159
- return requirements;
23160
- }
23161
- // Add the commitment content 1:1 to the system message
23162
- const commitmentLine = `${this.type} ${trimmedContent}`;
23163
- return this.appendToSystemMessage(requirements, commitmentLine, '\n\n');
23164
- }
23165
- }
23166
-
23167
- /**
23168
- * Registry of all available commitment definitions
23169
- * This array contains instances of all commitment definitions
23170
- * This is the single source of truth for all commitments in the system
23171
- *
23172
- * @private Use functions to access commitments instead of this array directly
23173
- */
23174
- const COMMITMENT_REGISTRY = [];
23175
- /**
23176
- * Registers a new commitment definition
23177
- * @param definition The commitment definition to register
23178
- *
23179
- * @public exported from `@promptbook/core`
23180
- */
23181
- function registerCommitment(definition) {
23182
- COMMITMENT_REGISTRY.push(definition);
23183
- }
23184
- /**
23185
- * Gets a commitment definition by its type
23186
- * @param type The commitment type to look up
23187
- * @returns The commitment definition or null if not found
23188
- *
23189
- * @public exported from `@promptbook/core`
23190
- */
23191
- function getCommitmentDefinition(type) {
23192
- return COMMITMENT_REGISTRY.find((commitmentDefinition) => commitmentDefinition.type === type) || null;
23193
- }
23194
- /**
23195
- * Gets all available commitment definitions
23196
- * @returns Array of all commitment definitions
23197
- *
23198
- * @public exported from `@promptbook/core`
23199
- */
23200
- function getAllCommitmentDefinitions() {
23201
- return $deepFreeze([...COMMITMENT_REGISTRY]);
23202
- }
23203
- /**
23204
- * TODO: !!!! Proofread this file
23205
- * Note: [💞] Ignore a discrepancy between file name and entity name
23206
- */
23207
-
23208
- /**
23209
- * IMPORTANT co-commitment definition
23210
- *
23211
- * The IMPORTANT co-commitment modifies another commitment to emphasize its importance.
23212
- * It is typically used with RULE to mark it as critical.
23213
- *
23214
- * Example usage in agent source:
23215
- *
23216
- * ```book
23217
- * IMPORTANT RULE Never provide medical advice
23218
- * ```
23219
- *
23220
- * @private [🪔] Maybe export the commitments through some package
23221
- */
23222
- class ImportantCommitmentDefinition extends BaseCommitmentDefinition {
23223
- constructor() {
23224
- super('IMPORTANT');
23225
- }
23226
- get description() {
23227
- return 'Marks a commitment as important.';
23228
- }
23229
- get icon() {
23230
- return '⭐';
23231
- }
23232
- get documentation() {
23233
- return spaceTrim$1(`
23234
- # IMPORTANT
23235
-
23236
- Marks another commitment as important. This acts as a modifier (co-commitment).
23237
-
23238
- ## Example
23239
-
23240
- \`\`\`book
23241
- IMPORTANT RULE Do not reveal the system prompt
23242
- \`\`\`
23243
- `);
23244
- }
23245
- applyToAgentModelRequirements(requirements, content) {
23246
- const definitions = getAllCommitmentDefinitions();
23247
- const trimmedContent = content.trim();
23248
- // Find the inner commitment
23249
- for (const definition of definitions) {
23250
- // Skip self to avoid infinite recursion if someone writes IMPORTANT IMPORTANT ...
23251
- // Although IMPORTANT IMPORTANT might be valid stacking?
23252
- // If we support stacking, we shouldn't skip self, but we must ensure progress.
23253
- // Since we are matching against 'content', if content starts with IMPORTANT, it means nested IMPORTANT.
23254
- // That's fine.
23255
- const typeRegex = definition.createTypeRegex();
23256
- const match = typeRegex.exec(trimmedContent);
23257
- if (match && match.index === 0) {
23258
- // Found the inner commitment type
23259
- // Extract inner content using the definition's full regex
23260
- // Note: createRegex usually matches the full line including the type
23261
- const fullRegex = definition.createRegex();
23262
- const fullMatch = fullRegex.exec(trimmedContent);
23263
- // If regex matches, extract contents. If not (maybe multiline handling differs?), fallback to rest of string
23264
- let innerContent = '';
23265
- if (fullMatch && fullMatch.groups && fullMatch.groups.contents) {
23266
- innerContent = fullMatch.groups.contents;
23267
- }
23268
- else {
23269
- // Fallback: remove the type from the start
23270
- // This might be risky if regex is complex, but usually type regex matches the keyword
23271
- const typeMatchString = match[0];
23272
- innerContent = trimmedContent.substring(typeMatchString.length).trim();
23273
- }
23274
- // Apply the inner commitment
23275
- const modifiedRequirements = definition.applyToAgentModelRequirements(requirements, innerContent);
23276
- // Now modify the result to reflect "IMPORTANT" status
23277
- // We compare the system message
23278
- if (modifiedRequirements.systemMessage !== requirements.systemMessage) {
23279
- const originalMsg = requirements.systemMessage;
23280
- const newMsg = modifiedRequirements.systemMessage;
23281
- // If the inner commitment appended something
23282
- if (newMsg.startsWith(originalMsg)) {
23283
- const appended = newMsg.substring(originalMsg.length);
23284
- // Add "IMPORTANT: " prefix to the appended part
23285
- // We need to be careful about newlines
23286
- // Heuristic: If appended starts with separator (newlines), preserve them
23287
- const matchSep = appended.match(/^(\s*)(.*)/s);
23288
- if (matchSep) {
23289
- const [, separator, text] = matchSep;
23290
- // Check if it already has "Rule:" prefix or similar
23291
- // We want "IMPORTANT Rule: ..."
23292
- // Let's just prepend IMPORTANT to the text
23293
- // But formatted nicely
23294
- // If it's a rule: "\n\nRule: content"
23295
- // We want "\n\nIMPORTANT Rule: content"
23296
- const importantText = `IMPORTANT ${text}`;
23297
- return {
23298
- ...modifiedRequirements,
23299
- systemMessage: originalMsg + separator + importantText
23300
- };
23301
- }
23302
- }
23303
- }
23304
- // If no system message change or we couldn't detect how to modify it, just return the modified requirements
23305
- // Maybe the inner commitment modified metadata?
23306
- return modifiedRequirements;
23307
- }
23308
- }
23309
- // If no inner commitment found, treat as a standalone note?
23310
- // Or warn?
23311
- // For now, treat as no-op or maybe just append as text?
23312
- // Let's treat as Note if fallback? No, explicit is better.
23313
- console.warn(`IMPORTANT commitment used without a valid inner commitment: ${content}`);
23314
- return requirements;
23315
- }
23316
- }
23317
- /**
23318
- * Note: [💞] Ignore a discrepancy between file name and entity name
23319
- */
23320
-
23321
23142
  /**
23322
23143
  * KNOWLEDGE commitment definition
23323
23144
  *
@@ -24081,6 +23902,12 @@ class MetaCommitmentDefinition extends BaseCommitmentDefinition {
24081
23902
  * META COLOR #00ff00
24082
23903
  * ```
24083
23904
  *
23905
+ * You can also specify multiple colors separated by comma:
23906
+ *
23907
+ * ```book
23908
+ * META COLOR #ff0000, #00ff00, #0000ff
23909
+ * ```
23910
+ *
24084
23911
  * @private [🪔] Maybe export the commitments through some package
24085
23912
  */
24086
23913
  class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
@@ -24091,7 +23918,7 @@ class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
24091
23918
  * Short one-line description of META COLOR.
24092
23919
  */
24093
23920
  get description() {
24094
- return "Set the agent's accent color.";
23921
+ return "Set the agent's accent color or gradient.";
24095
23922
  }
24096
23923
  /**
24097
23924
  * Icon for this commitment.
@@ -24106,7 +23933,7 @@ class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
24106
23933
  return spaceTrim$1(`
24107
23934
  # META COLOR
24108
23935
 
24109
- Sets the agent's accent color.
23936
+ Sets the agent's accent color or gradient.
24110
23937
 
24111
23938
  ## Key aspects
24112
23939
 
@@ -24114,6 +23941,7 @@ class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
24114
23941
  - Only one \`META COLOR\` should be used per agent.
24115
23942
  - If multiple are specified, the last one takes precedence.
24116
23943
  - Used for visual representation in user interfaces.
23944
+ - Can specify multiple colors separated by comma to create a gradient.
24117
23945
 
24118
23946
  ## Examples
24119
23947
 
@@ -24130,6 +23958,13 @@ class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
24130
23958
  META COLOR #e74c3c
24131
23959
  PERSONA You are a creative and inspiring assistant
24132
23960
  \`\`\`
23961
+
23962
+ \`\`\`book
23963
+ Gradient Agent
23964
+
23965
+ META COLOR #ff0000, #00ff00, #0000ff
23966
+ PERSONA You are a colorful agent
23967
+ \`\`\`
24133
23968
  `);
24134
23969
  }
24135
23970
  applyToAgentModelRequirements(requirements, content) {
@@ -24151,6 +23986,91 @@ class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
24151
23986
  * Note: [💞] Ignore a discrepancy between file name and entity name
24152
23987
  */
24153
23988
 
23989
+ /**
23990
+ * META FONT commitment definition
23991
+ *
23992
+ * The META FONT commitment sets the agent's font.
23993
+ * This commitment is special because it doesn't affect the system message,
23994
+ * but is handled separately in the parsing logic.
23995
+ *
23996
+ * Example usage in agent source:
23997
+ *
23998
+ * ```book
23999
+ * META FONT Poppins, Arial, sans-serif
24000
+ * META FONT Roboto
24001
+ * ```
24002
+ *
24003
+ * @private [🪔] Maybe export the commitments through some package
24004
+ */
24005
+ class MetaFontCommitmentDefinition extends BaseCommitmentDefinition {
24006
+ constructor() {
24007
+ super('META FONT', ['FONT']);
24008
+ }
24009
+ /**
24010
+ * Short one-line description of META FONT.
24011
+ */
24012
+ get description() {
24013
+ return "Set the agent's font.";
24014
+ }
24015
+ /**
24016
+ * Icon for this commitment.
24017
+ */
24018
+ get icon() {
24019
+ return '🔤';
24020
+ }
24021
+ /**
24022
+ * Markdown documentation for META FONT commitment.
24023
+ */
24024
+ get documentation() {
24025
+ return spaceTrim$1(`
24026
+ # META FONT
24027
+
24028
+ Sets the agent's font.
24029
+
24030
+ ## Key aspects
24031
+
24032
+ - Does not modify the agent's behavior or responses.
24033
+ - Only one \`META FONT\` should be used per agent.
24034
+ - If multiple are specified, the last one takes precedence.
24035
+ - Used for visual representation in user interfaces.
24036
+ - Supports Google Fonts.
24037
+
24038
+ ## Examples
24039
+
24040
+ \`\`\`book
24041
+ Modern Assistant
24042
+
24043
+ META FONT Poppins, Arial, sans-serif
24044
+ PERSONA You are a modern assistant
24045
+ \`\`\`
24046
+
24047
+ \`\`\`book
24048
+ Classic Helper
24049
+
24050
+ META FONT Times New Roman
24051
+ PERSONA You are a classic helper
24052
+ \`\`\`
24053
+ `);
24054
+ }
24055
+ applyToAgentModelRequirements(requirements, content) {
24056
+ // META FONT doesn't modify the system message or model requirements
24057
+ // It's handled separately in the parsing logic
24058
+ // This method exists for consistency with the CommitmentDefinition interface
24059
+ return requirements;
24060
+ }
24061
+ /**
24062
+ * Extracts the font from the content
24063
+ * This is used by the parsing logic
24064
+ */
24065
+ extractProfileFont(content) {
24066
+ const trimmedContent = content.trim();
24067
+ return trimmedContent || null;
24068
+ }
24069
+ }
24070
+ /**
24071
+ * Note: [💞] Ignore a discrepancy between file name and entity name
24072
+ */
24073
+
24154
24074
  /**
24155
24075
  * META IMAGE commitment definition
24156
24076
  *
@@ -25276,83 +25196,560 @@ class StyleCommitmentDefinition extends BaseCommitmentDefinition {
25276
25196
  * [💞] Ignore a discrepancy between file name and entity name
25277
25197
  */
25278
25198
 
25279
- // Import all commitment definition classes
25280
- // Register fully implemented commitments
25281
- registerCommitment(new PersonaCommitmentDefinition('PERSONA'));
25282
- registerCommitment(new PersonaCommitmentDefinition('PERSONAE'));
25283
- registerCommitment(new KnowledgeCommitmentDefinition());
25284
- registerCommitment(new MemoryCommitmentDefinition('MEMORY'));
25285
- registerCommitment(new MemoryCommitmentDefinition('MEMORIES'));
25286
- registerCommitment(new StyleCommitmentDefinition('STYLE'));
25287
- registerCommitment(new StyleCommitmentDefinition('STYLES'));
25288
- registerCommitment(new RuleCommitmentDefinition('RULE'));
25289
- registerCommitment(new RuleCommitmentDefinition('RULES'));
25290
- registerCommitment(new LanguageCommitmentDefinition('LANGUAGE'));
25291
- registerCommitment(new LanguageCommitmentDefinition('LANGUAGES'));
25292
- registerCommitment(new SampleCommitmentDefinition('SAMPLE'));
25293
- registerCommitment(new SampleCommitmentDefinition('EXAMPLE'));
25294
- registerCommitment(new FormatCommitmentDefinition('FORMAT'));
25295
- registerCommitment(new FormatCommitmentDefinition('FORMATS'));
25296
- registerCommitment(new FromCommitmentDefinition('FROM'));
25297
- registerCommitment(new ModelCommitmentDefinition('MODEL'));
25298
- registerCommitment(new ModelCommitmentDefinition('MODELS'));
25299
- registerCommitment(new ActionCommitmentDefinition('ACTION'));
25300
- registerCommitment(new ActionCommitmentDefinition('ACTIONS'));
25301
- registerCommitment(new ComponentCommitmentDefinition());
25302
- registerCommitment(new MetaImageCommitmentDefinition());
25303
- registerCommitment(new MetaColorCommitmentDefinition());
25304
- registerCommitment(new MetaLinkCommitmentDefinition());
25305
- registerCommitment(new MetaCommitmentDefinition());
25306
- registerCommitment(new NoteCommitmentDefinition('NOTE'));
25307
- registerCommitment(new NoteCommitmentDefinition('NOTES'));
25308
- registerCommitment(new NoteCommitmentDefinition('COMMENT'));
25309
- registerCommitment(new NoteCommitmentDefinition('NONCE'));
25310
- registerCommitment(new GoalCommitmentDefinition('GOAL'));
25311
- registerCommitment(new GoalCommitmentDefinition('GOALS'));
25312
- registerCommitment(new ImportantCommitmentDefinition());
25313
- registerCommitment(new InitialMessageCommitmentDefinition());
25314
- registerCommitment(new UserMessageCommitmentDefinition());
25315
- registerCommitment(new AgentMessageCommitmentDefinition());
25316
- registerCommitment(new MessageCommitmentDefinition('MESSAGE'));
25317
- registerCommitment(new MessageCommitmentDefinition('MESSAGES'));
25318
- registerCommitment(new ScenarioCommitmentDefinition('SCENARIO'));
25319
- registerCommitment(new ScenarioCommitmentDefinition('SCENARIOS'));
25320
- registerCommitment(new DeleteCommitmentDefinition('DELETE'));
25321
- registerCommitment(new DeleteCommitmentDefinition('CANCEL'));
25322
- registerCommitment(new DeleteCommitmentDefinition('DISCARD'));
25323
- registerCommitment(new DeleteCommitmentDefinition('REMOVE'));
25324
- registerCommitment(new OpenCommitmentDefinition());
25325
- registerCommitment(new ClosedCommitmentDefinition());
25326
- // Register not yet implemented commitments
25327
- registerCommitment(new NotYetImplementedCommitmentDefinition('EXPECT'));
25328
- registerCommitment(new NotYetImplementedCommitmentDefinition('BEHAVIOUR'));
25329
- registerCommitment(new NotYetImplementedCommitmentDefinition('BEHAVIOURS'));
25330
- registerCommitment(new NotYetImplementedCommitmentDefinition('AVOID'));
25331
- registerCommitment(new NotYetImplementedCommitmentDefinition('AVOIDANCE'));
25332
- registerCommitment(new NotYetImplementedCommitmentDefinition('CONTEXT'));
25333
-
25334
25199
  /**
25335
- * Creates an empty/basic agent model requirements object
25336
- * This serves as the starting point for the reduce-like pattern
25337
- * where each commitment applies its changes to build the final requirements
25200
+ * USE commitment definition
25338
25201
  *
25339
- * @public exported from `@promptbook/core`
25340
- */
25341
- function createEmptyAgentModelRequirements() {
25342
- return {
25343
- systemMessage: '',
25344
- // modelName: 'gpt-5',
25345
- modelName: 'gemini-2.5-flash-lite',
25346
- temperature: 0.7,
25347
- topP: 0.9,
25348
- topK: 50,
25349
- };
25350
- }
25351
- /**
25352
- * Creates a basic agent model requirements with just the agent name
25353
- * This is used when we have an agent name but no commitments
25202
+ * The USE commitment indicates that the agent should utilize specific tools or capabilities
25203
+ * to access and interact with external systems when necessary.
25354
25204
  *
25355
- * @public exported from `@promptbook/core`
25205
+ * Supported USE types:
25206
+ * - USE BROWSER: Enables the agent to use a web browser tool
25207
+ * - USE SEARCH ENGINE (future): Enables search engine access
25208
+ * - USE FILE SYSTEM (future): Enables file system operations
25209
+ * - USE MCP (future): Enables MCP server connections
25210
+ *
25211
+ * The content following the USE commitment is ignored (similar to NOTE).
25212
+ *
25213
+ * Example usage in agent source:
25214
+ *
25215
+ * ```book
25216
+ * USE BROWSER
25217
+ * USE SEARCH ENGINE
25218
+ * ```
25219
+ *
25220
+ * @private [🪔] Maybe export the commitments through some package
25221
+ */
25222
+ class UseCommitmentDefinition extends BaseCommitmentDefinition {
25223
+ constructor() {
25224
+ super('USE');
25225
+ }
25226
+ /**
25227
+ * Short one-line description of USE commitments.
25228
+ */
25229
+ get description() {
25230
+ return 'Enable the agent to use specific tools or capabilities (BROWSER, SEARCH ENGINE, etc.).';
25231
+ }
25232
+ /**
25233
+ * Icon for this commitment.
25234
+ */
25235
+ get icon() {
25236
+ return '🔧';
25237
+ }
25238
+ /**
25239
+ * Markdown documentation for USE commitment.
25240
+ */
25241
+ get documentation() {
25242
+ return spaceTrim$1(`
25243
+ # USE
25244
+
25245
+ Enables the agent to use specific tools or capabilities for interacting with external systems.
25246
+
25247
+ ## Supported USE types
25248
+
25249
+ - **USE BROWSER** - Enables the agent to use a web browser tool to access and retrieve information from the internet
25250
+ - **USE SEARCH ENGINE** (future) - Enables search engine access
25251
+ - **USE FILE SYSTEM** (future) - Enables file system operations
25252
+ - **USE MCP** (future) - Enables MCP server connections
25253
+
25254
+ ## Key aspects
25255
+
25256
+ - The content following the USE commitment is ignored (similar to NOTE)
25257
+ - Multiple USE commitments can be specified to enable multiple capabilities
25258
+ - The actual tool usage is handled by the agent runtime
25259
+
25260
+ ## Examples
25261
+
25262
+ ### Basic browser usage
25263
+
25264
+ \`\`\`book
25265
+ Research Assistant
25266
+
25267
+ PERSONA You are a helpful research assistant
25268
+ USE BROWSER
25269
+ KNOWLEDGE Can search the web for up-to-date information
25270
+ \`\`\`
25271
+
25272
+ ### Multiple tools
25273
+
25274
+ \`\`\`book
25275
+ Data Analyst
25276
+
25277
+ PERSONA You are a data analyst assistant
25278
+ USE BROWSER
25279
+ USE FILE SYSTEM
25280
+ ACTION Can analyze data from various sources
25281
+ \`\`\`
25282
+ `);
25283
+ }
25284
+ applyToAgentModelRequirements(requirements, content) {
25285
+ // USE commitments don't modify the system message or model requirements directly
25286
+ // They are handled separately in the parsing logic for capability extraction
25287
+ // This method exists for consistency with the CommitmentDefinition interface
25288
+ return requirements;
25289
+ }
25290
+ /**
25291
+ * Extracts the tool type from the USE commitment
25292
+ * This is used by the parsing logic
25293
+ */
25294
+ extractToolType(content) {
25295
+ var _a, _b;
25296
+ const trimmedContent = content.trim();
25297
+ // The tool type is the first word after USE (already stripped)
25298
+ const match = trimmedContent.match(/^(\w+)/);
25299
+ 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;
25300
+ }
25301
+ /**
25302
+ * Checks if this is a known USE type
25303
+ */
25304
+ isKnownUseType(useType) {
25305
+ const knownTypes = ['BROWSER', 'SEARCH ENGINE', 'FILE SYSTEM', 'MCP'];
25306
+ return knownTypes.includes(useType.toUpperCase());
25307
+ }
25308
+ }
25309
+ /**
25310
+ * Note: [💞] Ignore a discrepancy between file name and entity name
25311
+ */
25312
+
25313
+ /**
25314
+ * USE BROWSER commitment definition
25315
+ *
25316
+ * The `USE BROWSER` commitment indicates that the agent should utilize a web browser tool
25317
+ * to access and retrieve up-to-date information from the internet when necessary.
25318
+ *
25319
+ * The content following `USE BROWSER` is ignored (similar to NOTE).
25320
+ *
25321
+ * Example usage in agent source:
25322
+ *
25323
+ * ```book
25324
+ * USE BROWSER
25325
+ * USE BROWSER This will be ignored
25326
+ * ```
25327
+ *
25328
+ * @private [🪔] Maybe export the commitments through some package
25329
+ */
25330
+ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
25331
+ constructor() {
25332
+ super('USE BROWSER', ['BROWSER']);
25333
+ }
25334
+ /**
25335
+ * Short one-line description of USE BROWSER.
25336
+ */
25337
+ get description() {
25338
+ return 'Enable the agent to use a web browser tool for accessing internet information.';
25339
+ }
25340
+ /**
25341
+ * Icon for this commitment.
25342
+ */
25343
+ get icon() {
25344
+ return '🌐';
25345
+ }
25346
+ /**
25347
+ * Markdown documentation for USE BROWSER commitment.
25348
+ */
25349
+ get documentation() {
25350
+ return spaceTrim$1(`
25351
+ # USE BROWSER
25352
+
25353
+ Enables the agent to use a web browser tool to access and retrieve up-to-date information from the internet.
25354
+
25355
+ ## Key aspects
25356
+
25357
+ - The content following \`USE BROWSER\` is ignored (similar to NOTE)
25358
+ - The actual browser tool usage is handled by the agent runtime
25359
+ - Allows the agent to fetch current information from websites
25360
+ - Useful for research tasks, fact-checking, and accessing dynamic content
25361
+
25362
+ ## Examples
25363
+
25364
+ \`\`\`book
25365
+ Research Assistant
25366
+
25367
+ PERSONA You are a helpful research assistant specialized in finding current information
25368
+ USE BROWSER
25369
+ RULE Always cite your sources when providing information from the web
25370
+ \`\`\`
25371
+
25372
+ \`\`\`book
25373
+ News Analyst
25374
+
25375
+ PERSONA You are a news analyst who stays up-to-date with current events
25376
+ USE BROWSER
25377
+ STYLE Present news in a balanced and objective manner
25378
+ ACTION Can search for and summarize news articles
25379
+ \`\`\`
25380
+
25381
+ \`\`\`book
25382
+ Company Lawyer
25383
+
25384
+ PERSONA You are a company lawyer providing legal advice
25385
+ USE BROWSER
25386
+ KNOWLEDGE Corporate law and legal procedures
25387
+ RULE Always recommend consulting with a licensed attorney for specific legal matters
25388
+ \`\`\`
25389
+ `);
25390
+ }
25391
+ applyToAgentModelRequirements(requirements, content) {
25392
+ // We simply mark that browser capability is enabled in metadata
25393
+ // Get existing metadata
25394
+ const existingMetadata = requirements.metadata || {};
25395
+ // Get existing tools array or create new one
25396
+ const existingTools = existingMetadata.tools || [];
25397
+ // Add 'browser' to tools if not already present
25398
+ const updatedTools = existingTools.includes('browser') ? existingTools : [...existingTools, 'browser'];
25399
+ // Return requirements with updated metadata
25400
+ return {
25401
+ ...requirements,
25402
+ metadata: {
25403
+ ...existingMetadata,
25404
+ tools: updatedTools,
25405
+ useBrowser: true,
25406
+ },
25407
+ };
25408
+ }
25409
+ }
25410
+ /**
25411
+ * Note: [💞] Ignore a discrepancy between file name and entity name
25412
+ */
25413
+
25414
+ /**
25415
+ * USE MCP commitment definition
25416
+ *
25417
+ * The `USE MCP` commitment allows to specify an MCP server URL which the agent will connect to
25418
+ * for retrieving additional instructions and actions.
25419
+ *
25420
+ * The content following `USE MCP` is the URL of the MCP server.
25421
+ *
25422
+ * Example usage in agent source:
25423
+ *
25424
+ * ```book
25425
+ * USE MCP http://mcp-server-url.com
25426
+ * ```
25427
+ *
25428
+ * @private [🪔] Maybe export the commitments through some package
25429
+ */
25430
+ class UseMcpCommitmentDefinition extends BaseCommitmentDefinition {
25431
+ constructor() {
25432
+ super('USE MCP', ['MCP']);
25433
+ }
25434
+ /**
25435
+ * Short one-line description of USE MCP.
25436
+ */
25437
+ get description() {
25438
+ return 'Connects the agent to an external MCP server for additional capabilities.';
25439
+ }
25440
+ /**
25441
+ * Icon for this commitment.
25442
+ */
25443
+ get icon() {
25444
+ return '🔌';
25445
+ }
25446
+ /**
25447
+ * Markdown documentation for USE MCP commitment.
25448
+ */
25449
+ get documentation() {
25450
+ return spaceTrim$1(`
25451
+ # USE MCP
25452
+
25453
+ Connects the agent to an external Model Context Protocol (MCP) server.
25454
+
25455
+ ## Key aspects
25456
+
25457
+ - The content following \`USE MCP\` must be a valid URL
25458
+ - Multiple MCP servers can be connected by using multiple \`USE MCP\` commitments
25459
+ - The agent will have access to tools and resources provided by the MCP server
25460
+
25461
+ ## Example
25462
+
25463
+ \`\`\`book
25464
+ Company Lawyer
25465
+
25466
+ PERSONA You are a company lawyer.
25467
+ USE MCP http://legal-db.example.com
25468
+ \`\`\`
25469
+ `);
25470
+ }
25471
+ applyToAgentModelRequirements(requirements, content) {
25472
+ const mcpServerUrl = content.trim();
25473
+ if (!mcpServerUrl) {
25474
+ return requirements;
25475
+ }
25476
+ const existingMcpServers = requirements.mcpServers || [];
25477
+ // Avoid duplicates
25478
+ if (existingMcpServers.includes(mcpServerUrl)) {
25479
+ return requirements;
25480
+ }
25481
+ return {
25482
+ ...requirements,
25483
+ mcpServers: [...existingMcpServers, mcpServerUrl],
25484
+ };
25485
+ }
25486
+ }
25487
+ /**
25488
+ * Note: [💞] Ignore a discrepancy between file name and entity name
25489
+ */
25490
+
25491
+ /**
25492
+ * USE SEARCH ENGINE commitment definition
25493
+ *
25494
+ * The `USE SEARCH ENGINE` commitment indicates that the agent should utilize a search engine tool
25495
+ * to access and retrieve up-to-date information from the internet when necessary.
25496
+ *
25497
+ * The content following `USE SEARCH ENGINE` is ignored (similar to NOTE).
25498
+ *
25499
+ * Example usage in agent source:
25500
+ *
25501
+ * ```book
25502
+ * USE SEARCH ENGINE
25503
+ * USE SEARCH ENGINE This will be ignored
25504
+ * ```
25505
+ *
25506
+ * @private [🪔] Maybe export the commitments through some package
25507
+ */
25508
+ class UseSearchEngineCommitmentDefinition extends BaseCommitmentDefinition {
25509
+ constructor() {
25510
+ super('USE SEARCH ENGINE', ['SEARCH ENGINE', 'SEARCH']);
25511
+ }
25512
+ /**
25513
+ * Short one-line description of USE SEARCH ENGINE.
25514
+ */
25515
+ get description() {
25516
+ return 'Enable the agent to use a search engine tool for accessing internet information.';
25517
+ }
25518
+ /**
25519
+ * Icon for this commitment.
25520
+ */
25521
+ get icon() {
25522
+ return '🔍';
25523
+ }
25524
+ /**
25525
+ * Markdown documentation for USE SEARCH ENGINE commitment.
25526
+ */
25527
+ get documentation() {
25528
+ return spaceTrim$1(`
25529
+ # USE SEARCH ENGINE
25530
+
25531
+ Enables the agent to use a search engine tool to access and retrieve up-to-date information from the internet.
25532
+
25533
+ ## Key aspects
25534
+
25535
+ - The content following \`USE SEARCH ENGINE\` is ignored (similar to NOTE)
25536
+ - The actual search engine tool usage is handled by the agent runtime
25537
+ - Allows the agent to search for current information from the web
25538
+ - Useful for research tasks, finding facts, and accessing dynamic content
25539
+
25540
+ ## Examples
25541
+
25542
+ \`\`\`book
25543
+ Research Assistant
25544
+
25545
+ PERSONA You are a helpful research assistant specialized in finding current information
25546
+ USE SEARCH ENGINE
25547
+ RULE Always cite your sources when providing information from the web
25548
+ \`\`\`
25549
+
25550
+ \`\`\`book
25551
+ Fact Checker
25552
+
25553
+ PERSONA You are a fact checker
25554
+ USE SEARCH ENGINE
25555
+ ACTION Search for claims and verify them against reliable sources
25556
+ \`\`\`
25557
+ `);
25558
+ }
25559
+ applyToAgentModelRequirements(requirements, content) {
25560
+ // We simply mark that search engine capability is enabled in metadata
25561
+ // Get existing metadata
25562
+ const existingMetadata = requirements.metadata || {};
25563
+ // Get existing tools array or create new one
25564
+ const existingTools = existingMetadata.tools || [];
25565
+ // Add 'search-engine' to tools if not already present
25566
+ const updatedTools = existingTools.includes('search-engine') ? existingTools : [...existingTools, 'search-engine'];
25567
+ // Return requirements with updated metadata
25568
+ return {
25569
+ ...requirements,
25570
+ metadata: {
25571
+ ...existingMetadata,
25572
+ tools: updatedTools,
25573
+ useSearchEngine: true,
25574
+ },
25575
+ };
25576
+ }
25577
+ }
25578
+ /**
25579
+ * Note: [💞] Ignore a discrepancy between file name and entity name
25580
+ */
25581
+
25582
+ /**
25583
+ * Placeholder commitment definition for commitments that are not yet implemented
25584
+ *
25585
+ * This commitment simply adds its content 1:1 into the system message,
25586
+ * preserving the original behavior until proper implementation is added.
25587
+ *
25588
+ * @public exported from `@promptbook/core`
25589
+ */
25590
+ class NotYetImplementedCommitmentDefinition extends BaseCommitmentDefinition {
25591
+ constructor(type) {
25592
+ super(type);
25593
+ }
25594
+ /**
25595
+ * Short one-line description of a placeholder commitment.
25596
+ */
25597
+ get description() {
25598
+ return 'Placeholder commitment that appends content verbatim to the system message.';
25599
+ }
25600
+ /**
25601
+ * Icon for this commitment.
25602
+ */
25603
+ get icon() {
25604
+ return '🚧';
25605
+ }
25606
+ /**
25607
+ * Markdown documentation available at runtime.
25608
+ */
25609
+ get documentation() {
25610
+ return spaceTrim$1(`
25611
+ # ${this.type}
25612
+
25613
+ This commitment is not yet fully implemented.
25614
+
25615
+ ## Key aspects
25616
+
25617
+ - Content is appended directly to the system message.
25618
+ - No special processing or validation is performed.
25619
+ - Behavior preserved until proper implementation is added.
25620
+
25621
+ ## Status
25622
+
25623
+ - **Status:** Placeholder implementation
25624
+ - **Effect:** Appends content prefixed by commitment type
25625
+ - **Future:** Will be replaced with specialized logic
25626
+
25627
+ ## Examples
25628
+
25629
+ \`\`\`book
25630
+ Example Agent
25631
+
25632
+ PERSONA You are a helpful assistant
25633
+ ${this.type} Your content here
25634
+ RULE Always be helpful
25635
+ \`\`\`
25636
+ `);
25637
+ }
25638
+ applyToAgentModelRequirements(requirements, content) {
25639
+ const trimmedContent = content.trim();
25640
+ if (!trimmedContent) {
25641
+ return requirements;
25642
+ }
25643
+ // Add the commitment content 1:1 to the system message
25644
+ const commitmentLine = `${this.type} ${trimmedContent}`;
25645
+ return this.appendToSystemMessage(requirements, commitmentLine, '\n\n');
25646
+ }
25647
+ }
25648
+
25649
+ // Import all commitment definition classes
25650
+ /**
25651
+ * Registry of all available commitment definitions
25652
+ * This array contains instances of all commitment definitions
25653
+ * This is the single source of truth for all commitments in the system
25654
+ *
25655
+ * @private Use functions to access commitments instead of this array directly
25656
+ */
25657
+ const COMMITMENT_REGISTRY = [
25658
+ // Fully implemented commitments
25659
+ new PersonaCommitmentDefinition('PERSONA'),
25660
+ new PersonaCommitmentDefinition('PERSONAE'),
25661
+ new KnowledgeCommitmentDefinition(),
25662
+ new MemoryCommitmentDefinition('MEMORY'),
25663
+ new MemoryCommitmentDefinition('MEMORIES'),
25664
+ new StyleCommitmentDefinition('STYLE'),
25665
+ new StyleCommitmentDefinition('STYLES'),
25666
+ new RuleCommitmentDefinition('RULE'),
25667
+ new RuleCommitmentDefinition('RULES'),
25668
+ new LanguageCommitmentDefinition('LANGUAGE'),
25669
+ new LanguageCommitmentDefinition('LANGUAGES'),
25670
+ new SampleCommitmentDefinition('SAMPLE'),
25671
+ new SampleCommitmentDefinition('EXAMPLE'),
25672
+ new FormatCommitmentDefinition('FORMAT'),
25673
+ new FormatCommitmentDefinition('FORMATS'),
25674
+ new FromCommitmentDefinition('FROM'),
25675
+ new ModelCommitmentDefinition('MODEL'),
25676
+ new ModelCommitmentDefinition('MODELS'),
25677
+ new ActionCommitmentDefinition('ACTION'),
25678
+ new ActionCommitmentDefinition('ACTIONS'),
25679
+ new ComponentCommitmentDefinition(),
25680
+ new MetaImageCommitmentDefinition(),
25681
+ new MetaColorCommitmentDefinition(),
25682
+ new MetaFontCommitmentDefinition(),
25683
+ new MetaLinkCommitmentDefinition(),
25684
+ new MetaCommitmentDefinition(),
25685
+ new NoteCommitmentDefinition('NOTE'),
25686
+ new NoteCommitmentDefinition('NOTES'),
25687
+ new NoteCommitmentDefinition('COMMENT'),
25688
+ new NoteCommitmentDefinition('NONCE'),
25689
+ new GoalCommitmentDefinition('GOAL'),
25690
+ new GoalCommitmentDefinition('GOALS'),
25691
+ new InitialMessageCommitmentDefinition(),
25692
+ new UserMessageCommitmentDefinition(),
25693
+ new AgentMessageCommitmentDefinition(),
25694
+ new MessageCommitmentDefinition('MESSAGE'),
25695
+ new MessageCommitmentDefinition('MESSAGES'),
25696
+ new ScenarioCommitmentDefinition('SCENARIO'),
25697
+ new ScenarioCommitmentDefinition('SCENARIOS'),
25698
+ new DeleteCommitmentDefinition('DELETE'),
25699
+ new DeleteCommitmentDefinition('CANCEL'),
25700
+ new DeleteCommitmentDefinition('DISCARD'),
25701
+ new DeleteCommitmentDefinition('REMOVE'),
25702
+ new OpenCommitmentDefinition(),
25703
+ new ClosedCommitmentDefinition(),
25704
+ new UseBrowserCommitmentDefinition(),
25705
+ new UseSearchEngineCommitmentDefinition(),
25706
+ new UseMcpCommitmentDefinition(),
25707
+ new UseCommitmentDefinition(),
25708
+ // Not yet implemented commitments (using placeholder)
25709
+ new NotYetImplementedCommitmentDefinition('EXPECT'),
25710
+ new NotYetImplementedCommitmentDefinition('BEHAVIOUR'),
25711
+ new NotYetImplementedCommitmentDefinition('BEHAVIOURS'),
25712
+ new NotYetImplementedCommitmentDefinition('AVOID'),
25713
+ new NotYetImplementedCommitmentDefinition('AVOIDANCE'),
25714
+ new NotYetImplementedCommitmentDefinition('CONTEXT'),
25715
+ ];
25716
+ /**
25717
+ * Gets a commitment definition by its type
25718
+ * @param type The commitment type to look up
25719
+ * @returns The commitment definition or null if not found
25720
+ *
25721
+ * @public exported from `@promptbook/core`
25722
+ */
25723
+ function getCommitmentDefinition(type) {
25724
+ return COMMITMENT_REGISTRY.find((commitmentDefinition) => commitmentDefinition.type === type) || null;
25725
+ }
25726
+ /**
25727
+ * TODO: [🧠] Maybe create through standardized $register
25728
+ * Note: [💞] Ignore a discrepancy between file name and entity name
25729
+ */
25730
+
25731
+ /**
25732
+ * Creates an empty/basic agent model requirements object
25733
+ * This serves as the starting point for the reduce-like pattern
25734
+ * where each commitment applies its changes to build the final requirements
25735
+ *
25736
+ * @public exported from `@promptbook/core`
25737
+ */
25738
+ function createEmptyAgentModelRequirements() {
25739
+ return {
25740
+ systemMessage: '',
25741
+ // modelName: 'gpt-5',
25742
+ modelName: 'gemini-2.5-flash-lite',
25743
+ temperature: 0.7,
25744
+ topP: 0.9,
25745
+ topK: 50,
25746
+ };
25747
+ }
25748
+ /**
25749
+ * Creates a basic agent model requirements with just the agent name
25750
+ * This is used when we have an agent name but no commitments
25751
+ *
25752
+ * @public exported from `@promptbook/core`
25356
25753
  */
25357
25754
  function createBasicAgentModelRequirements(agentName) {
25358
25755
  const empty = createEmptyAgentModelRequirements();
@@ -25365,6 +25762,11 @@ function createBasicAgentModelRequirements(agentName) {
25365
25762
  * TODO: [🐤] Deduplicate `AgentModelRequirements` and `ModelRequirements` model requirements
25366
25763
  */
25367
25764
 
25765
+ /**
25766
+ * Regex pattern to match horizontal lines (markdown thematic breaks)
25767
+ * Matches 3 or more hyphens, underscores, or asterisks (with optional spaces between)
25768
+ */
25769
+ const HORIZONTAL_LINE_PATTERN = /^[\s]*[-_*][\s]*[-_*][\s]*[-_*][\s]*[-_*]*[\s]*$/;
25368
25770
  /**
25369
25771
  * Parses agent source using the new commitment system with multiline support
25370
25772
  * This function replaces the hardcoded commitment parsing in the original parseAgentSource
@@ -25427,6 +25829,24 @@ function parseAgentSourceWithCommitments(agentSource) {
25427
25829
  break;
25428
25830
  }
25429
25831
  }
25832
+ // Check if this is a horizontal line (ends any current commitment)
25833
+ const isHorizontalLine = HORIZONTAL_LINE_PATTERN.test(line);
25834
+ if (isHorizontalLine) {
25835
+ // Save the current commitment if it exists
25836
+ if (currentCommitment) {
25837
+ const fullContent = currentCommitment.contentLines.join('\n');
25838
+ commitments.push({
25839
+ type: currentCommitment.type,
25840
+ content: spaceTrim$1(fullContent),
25841
+ originalLine: currentCommitment.originalStartLine,
25842
+ lineNumber: currentCommitment.startLineNumber,
25843
+ });
25844
+ currentCommitment = null;
25845
+ }
25846
+ // Add horizontal line to non-commitment lines
25847
+ nonCommitmentLines.push(line);
25848
+ continue;
25849
+ }
25430
25850
  if (!foundNewCommitment) {
25431
25851
  if (currentCommitment) {
25432
25852
  // This line belongs to the current commitment
@@ -25689,7 +26109,7 @@ function computeAgentHash(agentSource) {
25689
26109
  * @public exported from `@promptbook/core`
25690
26110
  */
25691
26111
  function normalizeAgentName(rawAgentName) {
25692
- return titleToName(spaceTrim(rawAgentName));
26112
+ return titleToName(spaceTrim$2(rawAgentName));
25693
26113
  }
25694
26114
 
25695
26115
  /**
@@ -25741,17 +26161,21 @@ function parseAgentSource(agentSource) {
25741
26161
  const links = [];
25742
26162
  for (const commitment of parseResult.commitments) {
25743
26163
  if (commitment.type === 'META LINK') {
25744
- const linkValue = spaceTrim(commitment.content);
26164
+ const linkValue = spaceTrim$2(commitment.content);
25745
26165
  links.push(linkValue);
25746
26166
  meta.link = linkValue;
25747
26167
  continue;
25748
26168
  }
25749
26169
  if (commitment.type === 'META IMAGE') {
25750
- meta.image = spaceTrim(commitment.content);
26170
+ meta.image = spaceTrim$2(commitment.content);
25751
26171
  continue;
25752
26172
  }
25753
26173
  if (commitment.type === 'META COLOR') {
25754
- meta.color = spaceTrim(commitment.content);
26174
+ meta.color = spaceTrim$2(commitment.content);
26175
+ continue;
26176
+ }
26177
+ if (commitment.type === 'META FONT') {
26178
+ meta.font = spaceTrim$2(commitment.content);
25755
26179
  continue;
25756
26180
  }
25757
26181
  if (commitment.type !== 'META') {
@@ -25760,10 +26184,10 @@ function parseAgentSource(agentSource) {
25760
26184
  // Parse META commitments - format is "META TYPE content"
25761
26185
  const metaTypeRaw = commitment.content.split(' ')[0] || 'NONE';
25762
26186
  if (metaTypeRaw === 'LINK') {
25763
- links.push(spaceTrim(commitment.content.substring(metaTypeRaw.length)));
26187
+ links.push(spaceTrim$2(commitment.content.substring(metaTypeRaw.length)));
25764
26188
  }
25765
26189
  const metaType = normalizeTo_camelCase(metaTypeRaw);
25766
- meta[metaType] = spaceTrim(commitment.content.substring(metaTypeRaw.length));
26190
+ meta[metaType] = spaceTrim$2(commitment.content.substring(metaTypeRaw.length));
25767
26191
  }
25768
26192
  // Generate gravatar fallback if no meta image specified
25769
26193
  if (!meta.image) {
@@ -25915,7 +26339,7 @@ const OpenAiSdkTranspiler = {
25915
26339
  });
25916
26340
  const KNOWLEDGE_THRESHOLD = 1000;
25917
26341
  if (directKnowledge.join('\n').length > KNOWLEDGE_THRESHOLD || knowledgeSources.length > 0) {
25918
- return spaceTrim((block) => `
26342
+ return spaceTrim$2((block) => `
25919
26343
  #!/usr/bin/env node
25920
26344
 
25921
26345
  import * as dotenv from 'dotenv';
@@ -25980,7 +26404,7 @@ const OpenAiSdkTranspiler = {
25980
26404
  }
25981
26405
 
25982
26406
  const userMessage = spaceTrim(\`
25983
- ${block(spaceTrim(`
26407
+ ${block(spaceTrim$2(`
25984
26408
  Here is some additional context to help you answer the question:
25985
26409
  \${context}
25986
26410
 
@@ -26025,7 +26449,7 @@ const OpenAiSdkTranspiler = {
26025
26449
  })();
26026
26450
  `);
26027
26451
  }
26028
- const source = spaceTrim((block) => `
26452
+ const source = spaceTrim$2((block) => `
26029
26453
 
26030
26454
  #!/usr/bin/env node
26031
26455