@promptbook/core 0.103.0-54 โ†’ 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.
package/esm/index.es.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { SHA256 } from 'crypto-js';
2
2
  import hexEncoder from 'crypto-js/enc-hex';
3
- import spaceTrim$1, { spaceTrim as spaceTrim$2 } from 'spacetrim';
3
+ import spaceTrim$2, { spaceTrim as spaceTrim$1 } from 'spacetrim';
4
4
  import { randomBytes } from 'crypto';
5
5
  import { Subject, BehaviorSubject } from 'rxjs';
6
6
  import { forTime } from 'waitasecond';
@@ -27,7 +27,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
27
27
  * @generated
28
28
  * @see https://github.com/webgptorg/promptbook
29
29
  */
30
- const PROMPTBOOK_ENGINE_VERSION = '0.103.0-54';
30
+ const PROMPTBOOK_ENGINE_VERSION = '0.103.0-56';
31
31
  /**
32
32
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
33
33
  * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
@@ -89,6 +89,17 @@ const AUTO_FEDERATED_AGENT_SERVER_URLS = CORE_SERVER.urls;
89
89
  * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
90
90
  */
91
91
 
92
+ /**
93
+ * Trims string from all 4 sides
94
+ *
95
+ * Note: This is a re-exported function from the `spacetrim` package which is
96
+ * Developed by same author @hejny as this package
97
+ *
98
+ * @public exported from `@promptbook/utils`
99
+ * @see https://github.com/hejny/spacetrim#usage
100
+ */
101
+ const spaceTrim = spaceTrim$1;
102
+
92
103
  /**
93
104
  * @private util of `@promptbook/color`
94
105
  * @de
@@ -137,6 +148,7 @@ function take(initialValue) {
137
148
  * @public exported from `@promptbook/color`
138
149
  */
139
150
  const CSS_COLORS = {
151
+ promptbook: '#79EAFD',
140
152
  transparent: 'rgba(0,0,0,0)',
141
153
  aliceblue: '#f0f8ff',
142
154
  antiquewhite: '#faebd7',
@@ -352,6 +364,28 @@ class Color {
352
364
  throw new Error(`Can not create color from given object`);
353
365
  }
354
366
  }
367
+ /**
368
+ * Creates a new Color instance from miscellaneous formats
369
+ * It just does not throw error when it fails, it returns PROMPTBOOK_COLOR instead
370
+ *
371
+ * @param color
372
+ * @returns Color object
373
+ */
374
+ static fromSafe(color) {
375
+ try {
376
+ return Color.from(color);
377
+ }
378
+ catch (error) {
379
+ // <- Note: Can not use `assertsError(error)` here because it causes circular dependency
380
+ console.warn(spaceTrim((block) => `
381
+ Color.fromSafe error:
382
+ ${block(error.message)}
383
+
384
+ Returning default PROMPTBOOK_COLOR.
385
+ `));
386
+ return Color.fromString('promptbook');
387
+ }
388
+ }
355
389
  /**
356
390
  * Creates a new Color instance from miscellaneous string formats
357
391
  *
@@ -975,7 +1009,7 @@ const CLAIM = `Turn your company's scattered knowledge into AI ready books`;
975
1009
  *
976
1010
  * @public exported from `@promptbook/core`
977
1011
  */
978
- const PROMPTBOOK_COLOR = Color.fromHex('#79EAFD');
1012
+ const PROMPTBOOK_COLOR = Color.fromString('promptbook');
979
1013
  // <- TODO: [๐Ÿง ][๐Ÿˆต] Using `Color` here increases the package size approx 3kb, maybe remove it
980
1014
  /**
981
1015
  * Colors for syntax highlighting in the `<BookEditor/>`
@@ -1329,7 +1363,7 @@ false);
1329
1363
  function getErrorReportUrl(error) {
1330
1364
  const report = {
1331
1365
  title: `๐Ÿœ Error report from ${NAME}`,
1332
- body: spaceTrim$1((block) => `
1366
+ body: spaceTrim$2((block) => `
1333
1367
 
1334
1368
 
1335
1369
  \`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
@@ -1372,7 +1406,7 @@ function getErrorReportUrl(error) {
1372
1406
  */
1373
1407
  class UnexpectedError extends Error {
1374
1408
  constructor(message) {
1375
- super(spaceTrim$2((block) => `
1409
+ super(spaceTrim$1((block) => `
1376
1410
  ${block(message)}
1377
1411
 
1378
1412
  Note: This error should not happen.
@@ -1398,7 +1432,7 @@ class WrappedError extends Error {
1398
1432
  constructor(whatWasThrown) {
1399
1433
  const tag = `[๐Ÿคฎ]`;
1400
1434
  console.error(tag, whatWasThrown);
1401
- super(spaceTrim$2(`
1435
+ super(spaceTrim$1(`
1402
1436
  Non-Error object was thrown
1403
1437
 
1404
1438
  Note: Look for ${tag} in the console for more details
@@ -1524,7 +1558,7 @@ function valueToString(value) {
1524
1558
  * @public exported from `@promptbook/utils`
1525
1559
  */
1526
1560
  function computeHash(value) {
1527
- return SHA256(hexEncoder.parse(spaceTrim$1(valueToString(value)))).toString( /* hex */);
1561
+ return SHA256(hexEncoder.parse(spaceTrim$2(valueToString(value)))).toString( /* hex */);
1528
1562
  }
1529
1563
  /**
1530
1564
  * TODO: [๐Ÿฅฌ][๐Ÿฅฌ] Use this ACRY
@@ -1845,7 +1879,7 @@ function pipelineJsonToString(pipelineJson) {
1845
1879
  pipelineString += '\n\n';
1846
1880
  pipelineString += '```' + contentLanguage;
1847
1881
  pipelineString += '\n';
1848
- pipelineString += spaceTrim$1(content);
1882
+ pipelineString += spaceTrim$2(content);
1849
1883
  // <- TODO: [main] !!3 Escape
1850
1884
  // <- TODO: [๐Ÿง ] Some clear strategy how to spaceTrim the blocks
1851
1885
  pipelineString += '\n';
@@ -1966,7 +2000,7 @@ function checkSerializableAsJson(options) {
1966
2000
  }
1967
2001
  else if (typeof value === 'object') {
1968
2002
  if (value instanceof Date) {
1969
- throw new UnexpectedError(spaceTrim$1((block) => `
2003
+ throw new UnexpectedError(spaceTrim$2((block) => `
1970
2004
  \`${name}\` is Date
1971
2005
 
1972
2006
  Use \`string_date_iso8601\` instead
@@ -1985,7 +2019,7 @@ function checkSerializableAsJson(options) {
1985
2019
  throw new UnexpectedError(`${name} is RegExp`);
1986
2020
  }
1987
2021
  else if (value instanceof Error) {
1988
- throw new UnexpectedError(spaceTrim$1((block) => `
2022
+ throw new UnexpectedError(spaceTrim$2((block) => `
1989
2023
  \`${name}\` is unserialized Error
1990
2024
 
1991
2025
  Use function \`serializeError\`
@@ -2008,7 +2042,7 @@ function checkSerializableAsJson(options) {
2008
2042
  }
2009
2043
  catch (error) {
2010
2044
  assertsError(error);
2011
- throw new UnexpectedError(spaceTrim$1((block) => `
2045
+ throw new UnexpectedError(spaceTrim$2((block) => `
2012
2046
  \`${name}\` is not serializable
2013
2047
 
2014
2048
  ${block(error.stack || error.message)}
@@ -2040,7 +2074,7 @@ function checkSerializableAsJson(options) {
2040
2074
  }
2041
2075
  }
2042
2076
  else {
2043
- throw new UnexpectedError(spaceTrim$1((block) => `
2077
+ throw new UnexpectedError(spaceTrim$2((block) => `
2044
2078
  \`${name}\` is unknown type
2045
2079
 
2046
2080
  Additional message for \`${name}\`:
@@ -2336,7 +2370,7 @@ function validatePipeline(pipeline) {
2336
2370
  if (!(error instanceof PipelineLogicError)) {
2337
2371
  throw error;
2338
2372
  }
2339
- console.error(spaceTrim$2((block) => `
2373
+ console.error(spaceTrim$1((block) => `
2340
2374
  Pipeline is not valid but logic errors are temporarily disabled via \`IS_PIPELINE_LOGIC_VALIDATED\`
2341
2375
 
2342
2376
  ${block(error.message)}
@@ -2363,7 +2397,7 @@ function validatePipeline_InnerFunction(pipeline) {
2363
2397
  })();
2364
2398
  if (pipeline.pipelineUrl !== undefined && !isValidPipelineUrl(pipeline.pipelineUrl)) {
2365
2399
  // <- Note: [๐Ÿšฒ]
2366
- throw new PipelineLogicError(spaceTrim$2((block) => `
2400
+ throw new PipelineLogicError(spaceTrim$1((block) => `
2367
2401
  Invalid promptbook URL "${pipeline.pipelineUrl}"
2368
2402
 
2369
2403
  ${block(pipelineIdentification)}
@@ -2371,7 +2405,7 @@ function validatePipeline_InnerFunction(pipeline) {
2371
2405
  }
2372
2406
  if (pipeline.bookVersion !== undefined && !isValidPromptbookVersion(pipeline.bookVersion)) {
2373
2407
  // <- Note: [๐Ÿšฒ]
2374
- throw new PipelineLogicError(spaceTrim$2((block) => `
2408
+ throw new PipelineLogicError(spaceTrim$1((block) => `
2375
2409
  Invalid Promptbook Version "${pipeline.bookVersion}"
2376
2410
 
2377
2411
  ${block(pipelineIdentification)}
@@ -2380,7 +2414,7 @@ function validatePipeline_InnerFunction(pipeline) {
2380
2414
  // TODO: [๐Ÿง ] Maybe do here some proper JSON-schema / ZOD checking
2381
2415
  if (!Array.isArray(pipeline.parameters)) {
2382
2416
  // TODO: [๐Ÿง ] what is the correct error tp throw - maybe PromptbookSchemaError
2383
- throw new ParseError(spaceTrim$2((block) => `
2417
+ throw new ParseError(spaceTrim$1((block) => `
2384
2418
  Pipeline is valid JSON but with wrong structure
2385
2419
 
2386
2420
  \`PipelineJson.parameters\` expected to be an array, but got ${typeof pipeline.parameters}
@@ -2391,7 +2425,7 @@ function validatePipeline_InnerFunction(pipeline) {
2391
2425
  // TODO: [๐Ÿง ] Maybe do here some proper JSON-schema / ZOD checking
2392
2426
  if (!Array.isArray(pipeline.tasks)) {
2393
2427
  // TODO: [๐Ÿง ] what is the correct error tp throw - maybe PromptbookSchemaError
2394
- throw new ParseError(spaceTrim$2((block) => `
2428
+ throw new ParseError(spaceTrim$1((block) => `
2395
2429
  Pipeline is valid JSON but with wrong structure
2396
2430
 
2397
2431
  \`PipelineJson.tasks\` expected to be an array, but got ${typeof pipeline.tasks}
@@ -2417,7 +2451,7 @@ function validatePipeline_InnerFunction(pipeline) {
2417
2451
  // Note: Check each parameter individually
2418
2452
  for (const parameter of pipeline.parameters) {
2419
2453
  if (parameter.isInput && parameter.isOutput) {
2420
- throw new PipelineLogicError(spaceTrim$2((block) => `
2454
+ throw new PipelineLogicError(spaceTrim$1((block) => `
2421
2455
 
2422
2456
  Parameter \`{${parameter.name}}\` can not be both input and output
2423
2457
 
@@ -2428,7 +2462,7 @@ function validatePipeline_InnerFunction(pipeline) {
2428
2462
  if (!parameter.isInput &&
2429
2463
  !parameter.isOutput &&
2430
2464
  !pipeline.tasks.some((task) => task.dependentParameterNames.includes(parameter.name))) {
2431
- throw new PipelineLogicError(spaceTrim$2((block) => `
2465
+ throw new PipelineLogicError(spaceTrim$1((block) => `
2432
2466
  Parameter \`{${parameter.name}}\` is created but not used
2433
2467
 
2434
2468
  You can declare {${parameter.name}} as output parameter by adding in the header:
@@ -2440,7 +2474,7 @@ function validatePipeline_InnerFunction(pipeline) {
2440
2474
  }
2441
2475
  // Note: Testing that parameter is either input or result of some task
2442
2476
  if (!parameter.isInput && !pipeline.tasks.some((task) => task.resultingParameterName === parameter.name)) {
2443
- throw new PipelineLogicError(spaceTrim$2((block) => `
2477
+ throw new PipelineLogicError(spaceTrim$1((block) => `
2444
2478
  Parameter \`{${parameter.name}}\` is declared but not defined
2445
2479
 
2446
2480
  You can do one of these:
@@ -2456,14 +2490,14 @@ function validatePipeline_InnerFunction(pipeline) {
2456
2490
  // Note: Checking each task individually
2457
2491
  for (const task of pipeline.tasks) {
2458
2492
  if (definedParameters.has(task.resultingParameterName)) {
2459
- throw new PipelineLogicError(spaceTrim$2((block) => `
2493
+ throw new PipelineLogicError(spaceTrim$1((block) => `
2460
2494
  Parameter \`{${task.resultingParameterName}}\` is defined multiple times
2461
2495
 
2462
2496
  ${block(pipelineIdentification)}
2463
2497
  `));
2464
2498
  }
2465
2499
  if (RESERVED_PARAMETER_NAMES.includes(task.resultingParameterName)) {
2466
- throw new PipelineLogicError(spaceTrim$2((block) => `
2500
+ throw new PipelineLogicError(spaceTrim$1((block) => `
2467
2501
  Parameter name {${task.resultingParameterName}} is reserved, please use different name
2468
2502
 
2469
2503
  ${block(pipelineIdentification)}
@@ -2473,7 +2507,7 @@ function validatePipeline_InnerFunction(pipeline) {
2473
2507
  if (task.jokerParameterNames && task.jokerParameterNames.length > 0) {
2474
2508
  if (!task.format &&
2475
2509
  !task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
2476
- throw new PipelineLogicError(spaceTrim$2((block) => `
2510
+ throw new PipelineLogicError(spaceTrim$1((block) => `
2477
2511
  Joker parameters are used for {${task.resultingParameterName}} but no expectations are defined
2478
2512
 
2479
2513
  ${block(pipelineIdentification)}
@@ -2481,7 +2515,7 @@ function validatePipeline_InnerFunction(pipeline) {
2481
2515
  }
2482
2516
  for (const joker of task.jokerParameterNames) {
2483
2517
  if (!task.dependentParameterNames.includes(joker)) {
2484
- throw new PipelineLogicError(spaceTrim$2((block) => `
2518
+ throw new PipelineLogicError(spaceTrim$1((block) => `
2485
2519
  Parameter \`{${joker}}\` is used for {${task.resultingParameterName}} as joker but not in \`dependentParameterNames\`
2486
2520
 
2487
2521
  ${block(pipelineIdentification)}
@@ -2492,21 +2526,21 @@ function validatePipeline_InnerFunction(pipeline) {
2492
2526
  if (task.expectations) {
2493
2527
  for (const [unit, { min, max }] of Object.entries(task.expectations)) {
2494
2528
  if (min !== undefined && max !== undefined && min > max) {
2495
- throw new PipelineLogicError(spaceTrim$2((block) => `
2529
+ throw new PipelineLogicError(spaceTrim$1((block) => `
2496
2530
  Min expectation (=${min}) of ${unit} is higher than max expectation (=${max})
2497
2531
 
2498
2532
  ${block(pipelineIdentification)}
2499
2533
  `));
2500
2534
  }
2501
2535
  if (min !== undefined && min < 0) {
2502
- throw new PipelineLogicError(spaceTrim$2((block) => `
2536
+ throw new PipelineLogicError(spaceTrim$1((block) => `
2503
2537
  Min expectation of ${unit} must be zero or positive
2504
2538
 
2505
2539
  ${block(pipelineIdentification)}
2506
2540
  `));
2507
2541
  }
2508
2542
  if (max !== undefined && max <= 0) {
2509
- throw new PipelineLogicError(spaceTrim$2((block) => `
2543
+ throw new PipelineLogicError(spaceTrim$1((block) => `
2510
2544
  Max expectation of ${unit} must be positive
2511
2545
 
2512
2546
  ${block(pipelineIdentification)}
@@ -2528,7 +2562,7 @@ function validatePipeline_InnerFunction(pipeline) {
2528
2562
  while (unresovedTasks.length > 0) {
2529
2563
  if (loopLimit-- < 0) {
2530
2564
  // Note: Really UnexpectedError not LimitReachedError - this should not happen and be caught below
2531
- throw new UnexpectedError(spaceTrim$2((block) => `
2565
+ throw new UnexpectedError(spaceTrim$1((block) => `
2532
2566
  Loop limit reached during detection of circular dependencies in \`validatePipeline\`
2533
2567
 
2534
2568
  ${block(pipelineIdentification)}
@@ -2538,7 +2572,7 @@ function validatePipeline_InnerFunction(pipeline) {
2538
2572
  if (currentlyResovedTasks.length === 0) {
2539
2573
  throw new PipelineLogicError(
2540
2574
  // TODO: [๐ŸŽ] DRY
2541
- spaceTrim$2((block) => `
2575
+ spaceTrim$1((block) => `
2542
2576
 
2543
2577
  Can not resolve some parameters:
2544
2578
  Either you are using a parameter that is not defined, or there are some circular dependencies.
@@ -2702,7 +2736,7 @@ class SimplePipelineCollection {
2702
2736
  for (const pipeline of pipelines) {
2703
2737
  // TODO: [๐Ÿ‘ ] DRY
2704
2738
  if (pipeline.pipelineUrl === undefined) {
2705
- throw new PipelineUrlError(spaceTrim$2(`
2739
+ throw new PipelineUrlError(spaceTrim$1(`
2706
2740
  Pipeline with name "${pipeline.title}" does not have defined URL
2707
2741
 
2708
2742
  File:
@@ -2724,7 +2758,7 @@ class SimplePipelineCollection {
2724
2758
  pipelineJsonToString(unpreparePipeline(pipeline)) !==
2725
2759
  pipelineJsonToString(unpreparePipeline(this.collection.get(pipeline.pipelineUrl)))) {
2726
2760
  const existing = this.collection.get(pipeline.pipelineUrl);
2727
- throw new PipelineUrlError(spaceTrim$2(`
2761
+ throw new PipelineUrlError(spaceTrim$1(`
2728
2762
  Pipeline with URL ${pipeline.pipelineUrl} is already in the collection ๐ŸŽ
2729
2763
 
2730
2764
  Conflicting files:
@@ -2756,13 +2790,13 @@ class SimplePipelineCollection {
2756
2790
  const pipeline = this.collection.get(url);
2757
2791
  if (!pipeline) {
2758
2792
  if (this.listPipelines().length === 0) {
2759
- throw new NotFoundError(spaceTrim$2(`
2793
+ throw new NotFoundError(spaceTrim$1(`
2760
2794
  Pipeline with url "${url}" not found
2761
2795
 
2762
2796
  No pipelines available
2763
2797
  `));
2764
2798
  }
2765
- throw new NotFoundError(spaceTrim$2((block) => `
2799
+ throw new NotFoundError(spaceTrim$1((block) => `
2766
2800
  Pipeline with url "${url}" not found
2767
2801
 
2768
2802
  Available pipelines:
@@ -2803,7 +2837,7 @@ function createPipelineCollectionFromJson(...promptbooks) {
2803
2837
  */
2804
2838
  class MissingToolsError extends Error {
2805
2839
  constructor(message) {
2806
- super(spaceTrim$2((block) => `
2840
+ super(spaceTrim$1((block) => `
2807
2841
  ${block(message)}
2808
2842
 
2809
2843
  Note: You have probably forgot to provide some tools for pipeline execution or preparation
@@ -3001,7 +3035,7 @@ class NotAllowed extends Error {
3001
3035
  */
3002
3036
  class NotYetImplementedError extends Error {
3003
3037
  constructor(message) {
3004
- super(spaceTrim$2((block) => `
3038
+ super(spaceTrim$1((block) => `
3005
3039
  ${block(message)}
3006
3040
 
3007
3041
  Note: This feature is not implemented yet but it will be soon.
@@ -3139,7 +3173,7 @@ function serializeError(error) {
3139
3173
  const { name, message, stack } = error;
3140
3174
  const { id } = error;
3141
3175
  if (!Object.keys(ALL_ERRORS).includes(name)) {
3142
- console.error(spaceTrim$1((block) => `
3176
+ console.error(spaceTrim$2((block) => `
3143
3177
 
3144
3178
  Cannot serialize error with name "${name}"
3145
3179
 
@@ -3172,7 +3206,7 @@ function jsonParse(value) {
3172
3206
  }
3173
3207
  else if (typeof value !== 'string') {
3174
3208
  console.error('Can not parse JSON from non-string value.', { text: value });
3175
- throw new Error(spaceTrim$1(`
3209
+ throw new Error(spaceTrim$2(`
3176
3210
  Can not parse JSON from non-string value.
3177
3211
 
3178
3212
  The value type: ${typeof value}
@@ -3186,7 +3220,7 @@ function jsonParse(value) {
3186
3220
  if (!(error instanceof Error)) {
3187
3221
  throw error;
3188
3222
  }
3189
- throw new Error(spaceTrim$1((block) => `
3223
+ throw new Error(spaceTrim$2((block) => `
3190
3224
  ${block(error.message)}
3191
3225
 
3192
3226
  The expected JSON text:
@@ -3239,7 +3273,7 @@ function deserializeError(error) {
3239
3273
  message = `${name}: ${message}`;
3240
3274
  }
3241
3275
  if (stack !== undefined && stack !== '') {
3242
- message = spaceTrim$1((block) => `
3276
+ message = spaceTrim$2((block) => `
3243
3277
  ${block(message)}
3244
3278
 
3245
3279
  Original stack trace:
@@ -3276,11 +3310,11 @@ function assertsTaskSuccessful(executionResult) {
3276
3310
  throw deserializeError(errors[0]);
3277
3311
  }
3278
3312
  else {
3279
- throw new PipelineExecutionError(spaceTrim$2((block) => `
3313
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
3280
3314
  Multiple errors occurred during Promptbook execution
3281
3315
 
3282
3316
  ${block(errors
3283
- .map(({ name, stack, message }, index) => spaceTrim$2((block) => `
3317
+ .map(({ name, stack, message }, index) => spaceTrim$1((block) => `
3284
3318
  ${name} ${index + 1}:
3285
3319
  ${block(stack || message)}
3286
3320
  `))
@@ -3751,14 +3785,14 @@ class MultipleLlmExecutionTools {
3751
3785
  if (description === undefined) {
3752
3786
  return headLine;
3753
3787
  }
3754
- return spaceTrim$1((block) => `
3788
+ return spaceTrim$2((block) => `
3755
3789
  ${headLine}
3756
3790
 
3757
3791
  ${ /* <- Note: Indenting the description: */block(description)}
3758
3792
  `);
3759
3793
  })
3760
3794
  .join('\n\n');
3761
- return spaceTrim$1((block) => `
3795
+ return spaceTrim$2((block) => `
3762
3796
  Multiple LLM Providers:
3763
3797
 
3764
3798
  ${block(innerModelsTitlesAndDescriptions)}
@@ -3849,7 +3883,7 @@ class MultipleLlmExecutionTools {
3849
3883
  // 1) OpenAI throw PipelineExecutionError: Parameter `{knowledge}` is not defined
3850
3884
  // 2) AnthropicClaude throw PipelineExecutionError: Parameter `{knowledge}` is not defined
3851
3885
  // 3) ...
3852
- spaceTrim$1((block) => `
3886
+ spaceTrim$2((block) => `
3853
3887
  All execution tools of ${this.title} failed:
3854
3888
 
3855
3889
  ${block(errors
@@ -3862,7 +3896,7 @@ class MultipleLlmExecutionTools {
3862
3896
  throw new PipelineExecutionError(`You have not provided any \`LlmExecutionTools\` into ${this.title}`);
3863
3897
  }
3864
3898
  else {
3865
- throw new PipelineExecutionError(spaceTrim$1((block) => `
3899
+ throw new PipelineExecutionError(spaceTrim$2((block) => `
3866
3900
  You have not provided any \`LlmExecutionTools\` that support model variant "${prompt.modelRequirements.modelVariant}" into ${this.title}
3867
3901
 
3868
3902
  Available \`LlmExecutionTools\`:
@@ -3895,7 +3929,7 @@ class MultipleLlmExecutionTools {
3895
3929
  */
3896
3930
  function joinLlmExecutionTools(title, ...llmExecutionTools) {
3897
3931
  if (llmExecutionTools.length === 0) {
3898
- const warningMessage = spaceTrim$1(`
3932
+ const warningMessage = spaceTrim$2(`
3899
3933
  You have not provided any \`LlmExecutionTools\`
3900
3934
  This means that you won't be able to execute any prompts that require large language models like GPT-4 or Anthropic's Claude.
3901
3935
 
@@ -4150,14 +4184,14 @@ function $registeredScrapersMessage(availableScrapers) {
4150
4184
  return { ...metadata, isMetadataAviailable, isInstalled, isAvailableInTools };
4151
4185
  });
4152
4186
  if (metadata.length === 0) {
4153
- return spaceTrim$1(`
4187
+ return spaceTrim$2(`
4154
4188
  **No scrapers are available**
4155
4189
 
4156
4190
  This is a unexpected behavior, you are probably using some broken version of Promptbook
4157
4191
  At least there should be available the metadata of the scrapers
4158
4192
  `);
4159
4193
  }
4160
- return spaceTrim$1((block) => `
4194
+ return spaceTrim$2((block) => `
4161
4195
  Available scrapers are:
4162
4196
  ${block(metadata
4163
4197
  .map(({ packageName, className, isMetadataAviailable, isInstalled, mimeTypes, isAvailableInBrowser, isAvailableInTools, }, i) => {
@@ -4663,7 +4697,7 @@ const promptbookFetch = async (urlOrRequest, init) => {
4663
4697
  else if (urlOrRequest instanceof Request) {
4664
4698
  url = urlOrRequest.url;
4665
4699
  }
4666
- throw new PromptbookFetchError(spaceTrim$1((block) => `
4700
+ throw new PromptbookFetchError(spaceTrim$2((block) => `
4667
4701
  Can not fetch "${url}"
4668
4702
 
4669
4703
  Fetch error:
@@ -4824,7 +4858,7 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
4824
4858
  const fileExtension = getFileExtension(filename);
4825
4859
  const mimeType = extensionToMimeType(fileExtension || '');
4826
4860
  if (!(await isFileExisting(filename, tools.fs))) {
4827
- throw new NotFoundError(spaceTrim$1((block) => `
4861
+ throw new NotFoundError(spaceTrim$2((block) => `
4828
4862
  Can not make source handler for file which does not exist:
4829
4863
 
4830
4864
  File:
@@ -4917,7 +4951,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
4917
4951
  // <- TODO: [๐Ÿช“] Here should be no need for spreading new array, just `partialPieces = partialPiecesUnchecked`
4918
4952
  break;
4919
4953
  }
4920
- console.warn(spaceTrim$1((block) => `
4954
+ console.warn(spaceTrim$2((block) => `
4921
4955
  Cannot scrape knowledge from source despite the scraper \`${scraper.metadata.className}\` supports the mime type "${sourceHandler.mimeType}".
4922
4956
 
4923
4957
  The source:
@@ -4933,7 +4967,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
4933
4967
  // <- TODO: [๐Ÿฎ] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
4934
4968
  }
4935
4969
  if (partialPieces === null) {
4936
- throw new KnowledgeScrapeError(spaceTrim$1((block) => `
4970
+ throw new KnowledgeScrapeError(spaceTrim$2((block) => `
4937
4971
  Cannot scrape knowledge
4938
4972
 
4939
4973
  The source:
@@ -5012,7 +5046,7 @@ async function prepareTasks(pipeline, tools, options) {
5012
5046
  if (task.taskType === 'PROMPT_TASK' &&
5013
5047
  knowledgePiecesCount > 0 &&
5014
5048
  !dependentParameterNames.includes('knowledge')) {
5015
- preparedContent = spaceTrim$2(`
5049
+ preparedContent = spaceTrim$1(`
5016
5050
  {content}
5017
5051
 
5018
5052
  ## Knowledge
@@ -5244,7 +5278,7 @@ function extractVariablesFromJavascript(script) {
5244
5278
  }
5245
5279
  catch (error) {
5246
5280
  assertsError(error);
5247
- throw new ParseError(spaceTrim$2((block) => `
5281
+ throw new ParseError(spaceTrim$1((block) => `
5248
5282
  Can not extract variables from the script
5249
5283
  ${block(error.stack || error.message)}
5250
5284
 
@@ -5427,7 +5461,7 @@ const CsvFormatParser = {
5427
5461
  const { value, outputParameterName, settings, mapCallback, onProgress } = options;
5428
5462
  const csv = csvParse(value, settings);
5429
5463
  if (csv.errors.length !== 0) {
5430
- throw new CsvFormatError(spaceTrim$1((block) => `
5464
+ throw new CsvFormatError(spaceTrim$2((block) => `
5431
5465
  CSV parsing error
5432
5466
 
5433
5467
  Error(s) from CSV parsing:
@@ -5472,7 +5506,7 @@ const CsvFormatParser = {
5472
5506
  const { value, settings, mapCallback, onProgress } = options;
5473
5507
  const csv = csvParse(value, settings);
5474
5508
  if (csv.errors.length !== 0) {
5475
- throw new CsvFormatError(spaceTrim$1((block) => `
5509
+ throw new CsvFormatError(spaceTrim$2((block) => `
5476
5510
  CSV parsing error
5477
5511
 
5478
5512
  Error(s) from CSV parsing:
@@ -5682,7 +5716,7 @@ function mapAvailableToExpectedParameters(options) {
5682
5716
  }
5683
5717
  // Phase 2๏ธโƒฃ: Non-matching mapping
5684
5718
  if (expectedParameterNames.size !== availableParametersNames.size) {
5685
- throw new PipelineExecutionError(spaceTrim$1((block) => `
5719
+ throw new PipelineExecutionError(spaceTrim$2((block) => `
5686
5720
  Can not map available parameters to expected parameters
5687
5721
 
5688
5722
  Mapped parameters:
@@ -6120,7 +6154,7 @@ function validatePromptResult(options) {
6120
6154
  }
6121
6155
  catch (error) {
6122
6156
  keepUnused(error);
6123
- throw new ExpectError(spaceTrim$2((block) => `
6157
+ throw new ExpectError(spaceTrim$1((block) => `
6124
6158
  Expected valid JSON string
6125
6159
 
6126
6160
  The expected JSON text:
@@ -6183,7 +6217,7 @@ async function executeAttempts(options) {
6183
6217
  const jokerParameterName = jokerParameterNames[jokerParameterNames.length + attemptIndex];
6184
6218
  // TODO: [๐Ÿง ][๐Ÿญ] JOKERS, EXPECTATIONS, POSTPROCESSING and FOREACH
6185
6219
  if (isJokerAttempt && !jokerParameterName) {
6186
- throw new UnexpectedError(spaceTrim$2((block) => `
6220
+ throw new UnexpectedError(spaceTrim$1((block) => `
6187
6221
  Joker not found in attempt ${attemptIndex}
6188
6222
 
6189
6223
  ${block(pipelineIdentification)}
@@ -6194,7 +6228,7 @@ async function executeAttempts(options) {
6194
6228
  $ongoingTaskResult.$expectError = null;
6195
6229
  if (isJokerAttempt) {
6196
6230
  if (parameters[jokerParameterName] === undefined) {
6197
- throw new PipelineExecutionError(spaceTrim$2((block) => `
6231
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6198
6232
  Joker parameter {${jokerParameterName}} not defined
6199
6233
 
6200
6234
  ${block(pipelineIdentification)}
@@ -6252,7 +6286,7 @@ async function executeAttempts(options) {
6252
6286
  $ongoingTaskResult.$resultString = $ongoingTaskResult.$completionResult.content;
6253
6287
  break variant;
6254
6288
  case 'EMBEDDING':
6255
- throw new PipelineExecutionError(spaceTrim$2((block) => `
6289
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6256
6290
  Embedding model can not be used in pipeline
6257
6291
 
6258
6292
  This should be catched during parsing
@@ -6263,7 +6297,7 @@ async function executeAttempts(options) {
6263
6297
  break variant;
6264
6298
  // <- case [๐Ÿค–]:
6265
6299
  default:
6266
- throw new PipelineExecutionError(spaceTrim$2((block) => `
6300
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6267
6301
  Unknown model variant "${task.modelRequirements.modelVariant}"
6268
6302
 
6269
6303
  ${block(pipelineIdentification)}
@@ -6274,14 +6308,14 @@ async function executeAttempts(options) {
6274
6308
  break;
6275
6309
  case 'SCRIPT_TASK':
6276
6310
  if (arrayableToArray(tools.script).length === 0) {
6277
- throw new PipelineExecutionError(spaceTrim$2((block) => `
6311
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6278
6312
  No script execution tools are available
6279
6313
 
6280
6314
  ${block(pipelineIdentification)}
6281
6315
  `));
6282
6316
  }
6283
6317
  if (!task.contentLanguage) {
6284
- throw new PipelineExecutionError(spaceTrim$2((block) => `
6318
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6285
6319
  Script language is not defined for SCRIPT TASK "${task.name}"
6286
6320
 
6287
6321
  ${block(pipelineIdentification)}
@@ -6312,7 +6346,7 @@ async function executeAttempts(options) {
6312
6346
  throw $ongoingTaskResult.$scriptPipelineExecutionErrors[0];
6313
6347
  }
6314
6348
  else {
6315
- throw new PipelineExecutionError(spaceTrim$2((block) => `
6349
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6316
6350
  Script execution failed ${$ongoingTaskResult.$scriptPipelineExecutionErrors.length}x
6317
6351
 
6318
6352
  ${block(pipelineIdentification)}
@@ -6326,7 +6360,7 @@ async function executeAttempts(options) {
6326
6360
  break taskType;
6327
6361
  case 'DIALOG_TASK':
6328
6362
  if (tools.userInterface === undefined) {
6329
- throw new PipelineExecutionError(spaceTrim$2((block) => `
6363
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6330
6364
  User interface tools are not available
6331
6365
 
6332
6366
  ${block(pipelineIdentification)}
@@ -6344,7 +6378,7 @@ async function executeAttempts(options) {
6344
6378
  break taskType;
6345
6379
  // <- case: [๐Ÿ…ฑ]
6346
6380
  default:
6347
- throw new PipelineExecutionError(spaceTrim$2((block) => `
6381
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
6348
6382
  Unknown execution type "${task.taskType}"
6349
6383
 
6350
6384
  ${block(pipelineIdentification)}
@@ -6442,7 +6476,7 @@ async function executeAttempts(options) {
6442
6476
  if ($ongoingTaskResult.$expectError !== null && attemptIndex === maxAttempts - 1) {
6443
6477
  // Note: Create a summary of all failures
6444
6478
  const failuresSummary = $ongoingTaskResult.$failedResults
6445
- .map((failure) => spaceTrim$2((block) => {
6479
+ .map((failure) => spaceTrim$1((block) => {
6446
6480
  var _a, _b;
6447
6481
  return `
6448
6482
  Attempt ${failure.attemptIndex + 1}:
@@ -6452,14 +6486,14 @@ async function executeAttempts(options) {
6452
6486
  Result:
6453
6487
  ${block(failure.result === null
6454
6488
  ? 'null'
6455
- : spaceTrim$2(failure.result)
6489
+ : spaceTrim$1(failure.result)
6456
6490
  .split('\n')
6457
6491
  .map((line) => `> ${line}`)
6458
6492
  .join('\n'))}
6459
6493
  `;
6460
6494
  }))
6461
6495
  .join('\n\n---\n\n');
6462
- throw new PipelineExecutionError(spaceTrim$2((block) => {
6496
+ throw new PipelineExecutionError(spaceTrim$1((block) => {
6463
6497
  var _a;
6464
6498
  return `
6465
6499
  LLM execution failed ${maxExecutionAttempts}x
@@ -6479,7 +6513,7 @@ async function executeAttempts(options) {
6479
6513
  }
6480
6514
  }
6481
6515
  if ($ongoingTaskResult.$resultString === null) {
6482
- throw new UnexpectedError(spaceTrim$2((block) => `
6516
+ throw new UnexpectedError(spaceTrim$1((block) => `
6483
6517
  Something went wrong and prompt result is null
6484
6518
 
6485
6519
  ${block(pipelineIdentification)}
@@ -6506,7 +6540,7 @@ async function executeFormatSubvalues(options) {
6506
6540
  return /* not await */ executeAttempts({ ...options, logLlmCall });
6507
6541
  }
6508
6542
  if (jokerParameterNames.length !== 0) {
6509
- throw new UnexpectedError(spaceTrim$1((block) => `
6543
+ throw new UnexpectedError(spaceTrim$2((block) => `
6510
6544
  JOKER parameters are not supported together with FOREACH command
6511
6545
 
6512
6546
  [๐Ÿงžโ€โ™€๏ธ] This should be prevented in \`validatePipeline\`
@@ -6519,7 +6553,7 @@ async function executeFormatSubvalues(options) {
6519
6553
  if (formatDefinition === undefined) {
6520
6554
  throw new UnexpectedError(
6521
6555
  // <- TODO: [๐Ÿง ][๐Ÿง] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
6522
- spaceTrim$1((block) => `
6556
+ spaceTrim$2((block) => `
6523
6557
  Unsupported format "${task.foreach.formatName}"
6524
6558
 
6525
6559
  Available formats:
@@ -6536,7 +6570,7 @@ async function executeFormatSubvalues(options) {
6536
6570
  if (subvalueParser === undefined) {
6537
6571
  throw new UnexpectedError(
6538
6572
  // <- TODO: [๐Ÿง ][๐Ÿง] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
6539
- spaceTrim$1((block) => `
6573
+ spaceTrim$2((block) => `
6540
6574
  Unsupported subformat name "${task.foreach.subformatName}" for format "${task.foreach.formatName}"
6541
6575
 
6542
6576
  Available subformat names for format "${formatDefinition.formatName}":
@@ -6576,7 +6610,7 @@ async function executeFormatSubvalues(options) {
6576
6610
  if (!(error instanceof PipelineExecutionError)) {
6577
6611
  throw error;
6578
6612
  }
6579
- const highLevelError = new PipelineExecutionError(spaceTrim$1((block) => `
6613
+ const highLevelError = new PipelineExecutionError(spaceTrim$2((block) => `
6580
6614
  ${error.message}
6581
6615
 
6582
6616
  This is error in FOREACH command when mapping ${formatDefinition.formatName} ${subvalueParser.subvalueName} data (${index + 1}/${length})
@@ -6600,7 +6634,7 @@ async function executeFormatSubvalues(options) {
6600
6634
  ...options,
6601
6635
  priority: priority + index,
6602
6636
  parameters: allSubparameters,
6603
- pipelineIdentification: spaceTrim$1((block) => `
6637
+ pipelineIdentification: spaceTrim$2((block) => `
6604
6638
  ${block(pipelineIdentification)}
6605
6639
  Subparameter index: ${index}
6606
6640
  `),
@@ -6609,7 +6643,7 @@ async function executeFormatSubvalues(options) {
6609
6643
  }
6610
6644
  catch (error) {
6611
6645
  if (length > BIG_DATASET_TRESHOLD) {
6612
- console.error(spaceTrim$1((block) => `
6646
+ console.error(spaceTrim$2((block) => `
6613
6647
  ${error.message}
6614
6648
 
6615
6649
  This is error in FOREACH command when processing ${formatDefinition.formatName} ${subvalueParser.subvalueName} data (${index + 1}/${length})
@@ -6785,7 +6819,7 @@ async function getReservedParametersForTask(options) {
6785
6819
  // Note: Doublecheck that ALL reserved parameters are defined:
6786
6820
  for (const parameterName of RESERVED_PARAMETER_NAMES) {
6787
6821
  if (reservedParameters[parameterName] === undefined) {
6788
- throw new UnexpectedError(spaceTrim$2((block) => `
6822
+ throw new UnexpectedError(spaceTrim$1((block) => `
6789
6823
  Reserved parameter {${parameterName}} is not defined
6790
6824
 
6791
6825
  ${block(pipelineIdentification)}
@@ -6811,7 +6845,7 @@ async function executeTask(options) {
6811
6845
  const dependentParameterNames = new Set(currentTask.dependentParameterNames);
6812
6846
  // TODO: [๐Ÿ‘ฉ๐Ÿพโ€๐Ÿคโ€๐Ÿ‘ฉ๐Ÿป] Use here `mapAvailableToExpectedParameters`
6813
6847
  if (difference(union(difference(usedParameterNames, dependentParameterNames), difference(dependentParameterNames, usedParameterNames)), new Set(RESERVED_PARAMETER_NAMES)).size !== 0) {
6814
- throw new UnexpectedError(spaceTrim$2((block) => `
6848
+ throw new UnexpectedError(spaceTrim$1((block) => `
6815
6849
  Dependent parameters are not consistent with used parameters:
6816
6850
 
6817
6851
  Dependent parameters:
@@ -6855,7 +6889,7 @@ async function executeTask(options) {
6855
6889
  else if (!definedParameterNames.has(parameterName) && usedParameterNames.has(parameterName)) {
6856
6890
  // Houston, we have a problem
6857
6891
  // Note: Checking part is also done in `validatePipeline`, but itโ€™s good to doublecheck
6858
- throw new UnexpectedError(spaceTrim$2((block) => `
6892
+ throw new UnexpectedError(spaceTrim$1((block) => `
6859
6893
  Parameter \`{${parameterName}}\` is NOT defined
6860
6894
  BUT used in task "${currentTask.title || currentTask.name}"
6861
6895
 
@@ -6924,7 +6958,7 @@ function filterJustOutputParameters(options) {
6924
6958
  for (const parameter of preparedPipeline.parameters.filter(({ isOutput }) => isOutput)) {
6925
6959
  if (parametersToPass[parameter.name] === undefined) {
6926
6960
  // [4]
6927
- $warnings.push(new PipelineExecutionError(spaceTrim$2((block) => `
6961
+ $warnings.push(new PipelineExecutionError(spaceTrim$1((block) => `
6928
6962
  Parameter \`{${parameter.name}}\` should be an output parameter, but it was not generated during pipeline execution
6929
6963
 
6930
6964
  Note: This is a warning which happened after the pipeline was executed, and \`{${parameter.name}}\` was not for some reason defined in output parameters
@@ -7032,7 +7066,7 @@ async function executePipeline(options) {
7032
7066
  for (const parameterName of Object.keys(inputParameters)) {
7033
7067
  const parameter = preparedPipeline.parameters.find(({ name }) => name === parameterName);
7034
7068
  if (parameter === undefined) {
7035
- warnings.push(new PipelineExecutionError(spaceTrim$2((block) => `
7069
+ warnings.push(new PipelineExecutionError(spaceTrim$1((block) => `
7036
7070
  Extra parameter {${parameterName}} is being passed which is not part of the pipeline.
7037
7071
 
7038
7072
  ${block(pipelineIdentification)}
@@ -7047,7 +7081,7 @@ async function executePipeline(options) {
7047
7081
  // TODO: [๐Ÿง ] This should be also non-critical error
7048
7082
  return exportJson({
7049
7083
  name: 'pipelineExecutorResult',
7050
- message: spaceTrim$2((block) => `
7084
+ message: spaceTrim$1((block) => `
7051
7085
  Unsuccessful PipelineExecutorResult (with extra parameter {${parameter.name}}) PipelineExecutorResult
7052
7086
 
7053
7087
  ${block(pipelineIdentification)}
@@ -7056,7 +7090,7 @@ async function executePipeline(options) {
7056
7090
  value: {
7057
7091
  isSuccessful: false,
7058
7092
  errors: [
7059
- new PipelineExecutionError(spaceTrim$2((block) => `
7093
+ new PipelineExecutionError(spaceTrim$1((block) => `
7060
7094
  Parameter \`{${parameter.name}}\` is passed as input parameter but it is not input
7061
7095
 
7062
7096
  ${block(pipelineIdentification)}
@@ -7083,7 +7117,7 @@ async function executePipeline(options) {
7083
7117
  while (unresovedTasks.length > 0) {
7084
7118
  if (loopLimit-- < 0) {
7085
7119
  // Note: Really UnexpectedError not LimitReachedError - this should be catched during validatePipeline
7086
- throw new UnexpectedError(spaceTrim$2((block) => `
7120
+ throw new UnexpectedError(spaceTrim$1((block) => `
7087
7121
  Loop limit reached during resolving parameters pipeline execution
7088
7122
 
7089
7123
  ${block(pipelineIdentification)}
@@ -7093,7 +7127,7 @@ async function executePipeline(options) {
7093
7127
  if (!currentTask && resolving.length === 0) {
7094
7128
  throw new UnexpectedError(
7095
7129
  // TODO: [๐ŸŽ] DRY
7096
- spaceTrim$2((block) => `
7130
+ spaceTrim$1((block) => `
7097
7131
  Can not resolve some parameters:
7098
7132
 
7099
7133
  ${block(pipelineIdentification)}
@@ -7133,7 +7167,7 @@ async function executePipeline(options) {
7133
7167
  tools,
7134
7168
  onProgress(newOngoingResult) {
7135
7169
  if (isReturned) {
7136
- throw new UnexpectedError(spaceTrim$2((block) => `
7170
+ throw new UnexpectedError(spaceTrim$1((block) => `
7137
7171
  Can not call \`onProgress\` after pipeline execution is finished
7138
7172
 
7139
7173
  ${block(pipelineIdentification)}
@@ -7150,7 +7184,7 @@ async function executePipeline(options) {
7150
7184
  },
7151
7185
  logLlmCall,
7152
7186
  $executionReport: executionReport,
7153
- pipelineIdentification: spaceTrim$2((block) => `
7187
+ pipelineIdentification: spaceTrim$1((block) => `
7154
7188
  ${block(pipelineIdentification)}
7155
7189
  Task name: ${currentTask.name}
7156
7190
  Task title: ${currentTask.title}
@@ -7259,7 +7293,7 @@ function createPipelineExecutor(options) {
7259
7293
  preparedPipeline = pipeline;
7260
7294
  }
7261
7295
  else if (isNotPreparedWarningSuppressed !== true) {
7262
- console.warn(spaceTrim$2((block) => `
7296
+ console.warn(spaceTrim$1((block) => `
7263
7297
  Pipeline is not prepared
7264
7298
 
7265
7299
  ${block(pipelineIdentification)}
@@ -7284,7 +7318,7 @@ function createPipelineExecutor(options) {
7284
7318
  tools,
7285
7319
  onProgress,
7286
7320
  logLlmCall,
7287
- pipelineIdentification: spaceTrim$2((block) => `
7321
+ pipelineIdentification: spaceTrim$1((block) => `
7288
7322
  ${block(pipelineIdentification)}
7289
7323
  ${runCount === 1 ? '' : `Run #${runCount}`}
7290
7324
  `),
@@ -7596,7 +7630,7 @@ class ActionCommitmentDefinition extends BaseCommitmentDefinition {
7596
7630
  * Markdown documentation for ACTION commitment.
7597
7631
  */
7598
7632
  get documentation() {
7599
- return spaceTrim$2(`
7633
+ return spaceTrim$1(`
7600
7634
  # ${this.type}
7601
7635
 
7602
7636
  Defines specific actions or capabilities that the agent can perform.
@@ -7643,6 +7677,133 @@ class ActionCommitmentDefinition extends BaseCommitmentDefinition {
7643
7677
  * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
7644
7678
  */
7645
7679
 
7680
+ /**
7681
+ * CLOSED commitment definition
7682
+ *
7683
+ * The CLOSED commitment specifies that the agent CANNOT be modified by conversation.
7684
+ * It prevents the agent from learning from interactions and updating its source code.
7685
+ *
7686
+ * Example usage in agent source:
7687
+ *
7688
+ * ```book
7689
+ * CLOSED
7690
+ * ```
7691
+ *
7692
+ * @private [๐Ÿช”] Maybe export the commitments through some package
7693
+ */
7694
+ class ClosedCommitmentDefinition extends BaseCommitmentDefinition {
7695
+ constructor() {
7696
+ super('CLOSED');
7697
+ }
7698
+ /**
7699
+ * Short one-line description of CLOSED.
7700
+ */
7701
+ get description() {
7702
+ return 'Prevent the agent from being modified by conversation.';
7703
+ }
7704
+ /**
7705
+ * Icon for this commitment.
7706
+ */
7707
+ get icon() {
7708
+ return '๐Ÿ”’';
7709
+ }
7710
+ /**
7711
+ * Markdown documentation for CLOSED commitment.
7712
+ */
7713
+ get documentation() {
7714
+ return spaceTrim$1(`
7715
+ # CLOSED
7716
+
7717
+ Specifies that the agent **cannot** be modified by conversation with it.
7718
+ This means the agent will **not** learn from interactions and its source code will remain static during conversation.
7719
+
7720
+ By default (if not specified), agents are \`OPEN\` to modification.
7721
+
7722
+ > See also [OPEN](/docs/OPEN)
7723
+
7724
+ ## Example
7725
+
7726
+ \`\`\`book
7727
+ CLOSED
7728
+ \`\`\`
7729
+ `);
7730
+ }
7731
+ applyToAgentModelRequirements(requirements, _content) {
7732
+ const updatedMetadata = {
7733
+ ...requirements.metadata,
7734
+ isClosed: true,
7735
+ };
7736
+ return {
7737
+ ...requirements,
7738
+ metadata: updatedMetadata,
7739
+ };
7740
+ }
7741
+ }
7742
+ /**
7743
+ * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
7744
+ */
7745
+
7746
+ /**
7747
+ * COMPONENT commitment definition
7748
+ *
7749
+ * The COMPONENT commitment defines a UI component that the agent can render in the chat.
7750
+ *
7751
+ * @private [๐Ÿช”] Maybe export the commitments through some package
7752
+ */
7753
+ class ComponentCommitmentDefinition extends BaseCommitmentDefinition {
7754
+ constructor() {
7755
+ super('COMPONENT');
7756
+ }
7757
+ /**
7758
+ * Short one-line description of COMPONENT.
7759
+ */
7760
+ get description() {
7761
+ return 'Define a UI component that the agent can render in the chat.';
7762
+ }
7763
+ /**
7764
+ * Icon for this commitment.
7765
+ */
7766
+ get icon() {
7767
+ return '๐Ÿงฉ';
7768
+ }
7769
+ /**
7770
+ * Markdown documentation for COMPONENT commitment.
7771
+ */
7772
+ get documentation() {
7773
+ return spaceTrim$1(`
7774
+ # COMPONENT
7775
+
7776
+ Defines a UI component that the agent can render in the chat.
7777
+
7778
+ ## Key aspects
7779
+
7780
+ - Tells the agent that a specific component is available.
7781
+ - Provides syntax for using the component.
7782
+
7783
+ ## Example
7784
+
7785
+ \`\`\`book
7786
+ COMPONENT Arrow
7787
+ The agent should render an arrow component in the chat UI.
7788
+ Syntax:
7789
+ <Arrow direction="up" color="red" />
7790
+ \`\`\`
7791
+ `);
7792
+ }
7793
+ applyToAgentModelRequirements(requirements, content) {
7794
+ const trimmedContent = content.trim();
7795
+ if (!trimmedContent) {
7796
+ return requirements;
7797
+ }
7798
+ // Add component capability to the system message
7799
+ const componentSection = `Component: ${trimmedContent}`;
7800
+ return this.appendToSystemMessage(requirements, componentSection, '\n\n');
7801
+ }
7802
+ }
7803
+ /**
7804
+ * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
7805
+ */
7806
+
7646
7807
  /**
7647
7808
  * DELETE commitment definition
7648
7809
  *
@@ -7681,7 +7842,7 @@ class DeleteCommitmentDefinition extends BaseCommitmentDefinition {
7681
7842
  * Markdown documentation for DELETE commitment.
7682
7843
  */
7683
7844
  get documentation() {
7684
- return spaceTrim$2(`
7845
+ return spaceTrim$1(`
7685
7846
  # DELETE (CANCEL, DISCARD, REMOVE)
7686
7847
 
7687
7848
  A commitment to remove or disregard certain information or context. This can be useful for overriding previous commitments or removing unwanted behaviors.
@@ -7803,7 +7964,7 @@ class FormatCommitmentDefinition extends BaseCommitmentDefinition {
7803
7964
  * Markdown documentation for FORMAT commitment.
7804
7965
  */
7805
7966
  get documentation() {
7806
- return spaceTrim$2(`
7967
+ return spaceTrim$1(`
7807
7968
  # ${this.type}
7808
7969
 
7809
7970
  Defines the specific output structure and formatting for responses (data formats, templates, structure).
@@ -7848,6 +8009,79 @@ class FormatCommitmentDefinition extends BaseCommitmentDefinition {
7848
8009
  * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
7849
8010
  */
7850
8011
 
8012
+ /**
8013
+ * FROM commitment definition
8014
+ *
8015
+ * The FROM commitment tells the agent that its `agentSource` is inherited from another agent.
8016
+ *
8017
+ * Example usage in agent source:
8018
+ *
8019
+ * ```book
8020
+ * FROM https://s6.ptbk.io/benjamin-white
8021
+ * ```
8022
+ *
8023
+ * @private [๐Ÿช”] Maybe export the commitments through some package
8024
+ */
8025
+ class FromCommitmentDefinition extends BaseCommitmentDefinition {
8026
+ constructor(type = 'FROM') {
8027
+ super(type);
8028
+ }
8029
+ /**
8030
+ * Short one-line description of FROM.
8031
+ */
8032
+ get description() {
8033
+ return 'Inherit agent source from another agent.';
8034
+ }
8035
+ /**
8036
+ * Icon for this commitment.
8037
+ */
8038
+ get icon() {
8039
+ return '๐Ÿงฌ';
8040
+ }
8041
+ /**
8042
+ * Markdown documentation for FROM commitment.
8043
+ */
8044
+ get documentation() {
8045
+ return spaceTrim$1(`
8046
+ # ${this.type}
8047
+
8048
+ Inherits agent source from another agent.
8049
+
8050
+ ## Examples
8051
+
8052
+ \`\`\`book
8053
+ My AI Agent
8054
+
8055
+ FROM https://s6.ptbk.io/benjamin-white
8056
+ RULE Speak only in English.
8057
+ \`\`\`
8058
+ `);
8059
+ }
8060
+ applyToAgentModelRequirements(requirements, content) {
8061
+ const trimmedContent = content.trim();
8062
+ if (!trimmedContent) {
8063
+ return requirements;
8064
+ }
8065
+ // Validate URL
8066
+ try {
8067
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
8068
+ const url = new URL(trimmedContent);
8069
+ // TODO: Add more validation if needed (e.g. check for valid protocol)
8070
+ }
8071
+ catch (error) {
8072
+ console.warn(`Invalid URL in FROM commitment: ${trimmedContent}`);
8073
+ return requirements;
8074
+ }
8075
+ return {
8076
+ ...requirements,
8077
+ parentAgentUrl: trimmedContent,
8078
+ };
8079
+ }
8080
+ }
8081
+ /**
8082
+ * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
8083
+ */
8084
+
7851
8085
  /**
7852
8086
  * GOAL commitment definition
7853
8087
  *
@@ -7884,7 +8118,7 @@ class GoalCommitmentDefinition extends BaseCommitmentDefinition {
7884
8118
  * Markdown documentation for GOAL commitment.
7885
8119
  */
7886
8120
  get documentation() {
7887
- return spaceTrim$2(`
8121
+ return spaceTrim$1(`
7888
8122
  # ${this.type}
7889
8123
 
7890
8124
  Defines the main goal which should be achieved by the AI assistant. There can be multiple goals, and later goals are more important than earlier goals.
@@ -7986,7 +8220,7 @@ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
7986
8220
  * Markdown documentation for KNOWLEDGE commitment.
7987
8221
  */
7988
8222
  get documentation() {
7989
- return spaceTrim$2(`
8223
+ return spaceTrim$1(`
7990
8224
  # ${this.type}
7991
8225
 
7992
8226
  Adds specific knowledge, facts, or context to the agent using a RAG (Retrieval-Augmented Generation) approach for external sources.
@@ -8057,59 +8291,130 @@ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
8057
8291
  */
8058
8292
 
8059
8293
  /**
8060
- * MEMORY commitment definition
8294
+ * LANGUAGE commitment definition
8061
8295
  *
8062
- * The MEMORY commitment is similar to KNOWLEDGE but has a focus on remembering past
8063
- * interactions and user preferences. It helps the agent maintain context about the
8064
- * user's history, preferences, and previous conversations.
8296
+ * The LANGUAGE/LANGUAGES commitment specifies the language(s) the agent should use in its responses.
8065
8297
  *
8066
8298
  * Example usage in agent source:
8067
8299
  *
8068
8300
  * ```book
8069
- * MEMORY User prefers detailed technical explanations
8070
- * MEMORY Previously worked on React projects
8071
- * MEMORY Timezone: UTC-5 (Eastern Time)
8301
+ * LANGUAGE English
8302
+ * LANGUAGE French, English and Czech
8072
8303
  * ```
8073
8304
  *
8074
8305
  * @private [๐Ÿช”] Maybe export the commitments through some package
8075
8306
  */
8076
- class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
8077
- constructor(type = 'MEMORY') {
8307
+ class LanguageCommitmentDefinition extends BaseCommitmentDefinition {
8308
+ constructor(type = 'LANGUAGE') {
8078
8309
  super(type);
8079
8310
  }
8080
8311
  /**
8081
- * Short one-line description of MEMORY.
8312
+ * Short one-line description of LANGUAGE/LANGUAGES.
8082
8313
  */
8083
8314
  get description() {
8084
- return 'Remember past interactions and user **preferences** for personalized responses.';
8315
+ return 'Specifies the language(s) the agent should use.';
8085
8316
  }
8086
8317
  /**
8087
8318
  * Icon for this commitment.
8088
8319
  */
8089
8320
  get icon() {
8090
- return '๐Ÿง ';
8321
+ return '๐ŸŒ';
8091
8322
  }
8092
8323
  /**
8093
- * Markdown documentation for MEMORY commitment.
8324
+ * Markdown documentation for LANGUAGE/LANGUAGES commitment.
8094
8325
  */
8095
8326
  get documentation() {
8096
- return spaceTrim$2(`
8327
+ return spaceTrim$1(`
8097
8328
  # ${this.type}
8098
8329
 
8099
- Similar to KNOWLEDGE but focuses on remembering past interactions and user preferences. This commitment helps the agent maintain context about the user's history, preferences, and previous conversations.
8330
+ Specifies the language(s) the agent should use in its responses.
8331
+ This is a specialized variation of the RULE commitment focused on language constraints.
8100
8332
 
8101
- ## Key aspects
8333
+ ## Examples
8102
8334
 
8103
- - Both terms work identically and can be used interchangeably.
8104
- - Focuses on user-specific information and interaction history.
8105
- - Helps personalize responses based on past interactions.
8106
- - Maintains continuity across conversations.
8335
+ \`\`\`book
8336
+ Paul Smith & Associรฉs
8107
8337
 
8108
- ## Differences from KNOWLEDGE
8338
+ PERSONA You are a company lawyer.
8339
+ LANGUAGE French, English and Czech
8340
+ \`\`\`
8109
8341
 
8110
- - \`KNOWLEDGE\` is for domain expertise and factual information
8111
- - \`MEMORY\` is for user-specific context and preferences
8112
- - \`MEMORY\` creates more personalized interactions
8342
+ \`\`\`book
8343
+ Customer Support
8344
+
8345
+ PERSONA You are a customer support agent.
8346
+ LANGUAGE English
8347
+ \`\`\`
8348
+ `);
8349
+ }
8350
+ applyToAgentModelRequirements(requirements, content) {
8351
+ const trimmedContent = content.trim();
8352
+ if (!trimmedContent) {
8353
+ return requirements;
8354
+ }
8355
+ // Add language rule to the system message
8356
+ const languageSection = `Language: ${trimmedContent}`;
8357
+ return this.appendToSystemMessage(requirements, languageSection, '\n\n');
8358
+ }
8359
+ }
8360
+ /**
8361
+ * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
8362
+ */
8363
+
8364
+ /**
8365
+ * MEMORY commitment definition
8366
+ *
8367
+ * The MEMORY commitment is similar to KNOWLEDGE but has a focus on remembering past
8368
+ * interactions and user preferences. It helps the agent maintain context about the
8369
+ * user's history, preferences, and previous conversations.
8370
+ *
8371
+ * Example usage in agent source:
8372
+ *
8373
+ * ```book
8374
+ * MEMORY User prefers detailed technical explanations
8375
+ * MEMORY Previously worked on React projects
8376
+ * MEMORY Timezone: UTC-5 (Eastern Time)
8377
+ * ```
8378
+ *
8379
+ * @private [๐Ÿช”] Maybe export the commitments through some package
8380
+ */
8381
+ class MemoryCommitmentDefinition extends BaseCommitmentDefinition {
8382
+ constructor(type = 'MEMORY') {
8383
+ super(type);
8384
+ }
8385
+ /**
8386
+ * Short one-line description of MEMORY.
8387
+ */
8388
+ get description() {
8389
+ return 'Remember past interactions and user **preferences** for personalized responses.';
8390
+ }
8391
+ /**
8392
+ * Icon for this commitment.
8393
+ */
8394
+ get icon() {
8395
+ return '๐Ÿง ';
8396
+ }
8397
+ /**
8398
+ * Markdown documentation for MEMORY commitment.
8399
+ */
8400
+ get documentation() {
8401
+ return spaceTrim$1(`
8402
+ # ${this.type}
8403
+
8404
+ Similar to KNOWLEDGE but focuses on remembering past interactions and user preferences. This commitment helps the agent maintain context about the user's history, preferences, and previous conversations.
8405
+
8406
+ ## Key aspects
8407
+
8408
+ - Both terms work identically and can be used interchangeably.
8409
+ - Focuses on user-specific information and interaction history.
8410
+ - Helps personalize responses based on past interactions.
8411
+ - Maintains continuity across conversations.
8412
+
8413
+ ## Differences from KNOWLEDGE
8414
+
8415
+ - \`KNOWLEDGE\` is for domain expertise and factual information
8416
+ - \`MEMORY\` is for user-specific context and preferences
8417
+ - \`MEMORY\` creates more personalized interactions
8113
8418
  - \`MEMORY\` often includes temporal or preference-based information
8114
8419
 
8115
8420
  ## Examples
@@ -8197,7 +8502,7 @@ class AgentMessageCommitmentDefinition extends BaseCommitmentDefinition {
8197
8502
  * Markdown documentation for AGENT MESSAGE commitment.
8198
8503
  */
8199
8504
  get documentation() {
8200
- return spaceTrim$2(`
8505
+ return spaceTrim$1(`
8201
8506
  # ${this.type}
8202
8507
 
8203
8508
  Defines a message from the agent in the conversation history. This is used to pre-fill the chat with a conversation history or to provide few-shot examples.
@@ -8274,7 +8579,7 @@ class InitialMessageCommitmentDefinition extends BaseCommitmentDefinition {
8274
8579
  * Markdown documentation for INITIAL MESSAGE commitment.
8275
8580
  */
8276
8581
  get documentation() {
8277
- return spaceTrim$2(`
8582
+ return spaceTrim$1(`
8278
8583
  # ${this.type}
8279
8584
 
8280
8585
  Defines the first message that the user sees when opening the chat. This message is purely for display purposes in the UI and does not inherently become part of the LLM's system prompt context (unless also included via other means).
@@ -8338,7 +8643,7 @@ class MessageCommitmentDefinition extends BaseCommitmentDefinition {
8338
8643
  * Markdown documentation for MESSAGE commitment.
8339
8644
  */
8340
8645
  get documentation() {
8341
- return spaceTrim$2(`
8646
+ return spaceTrim$1(`
8342
8647
  # ${this.type}
8343
8648
 
8344
8649
  Contains 1:1 text of the message which AI assistant already sent during the conversation. Later messages are later in the conversation. It is similar to EXAMPLE but it is not example, it is the real message which AI assistant already sent.
@@ -8450,7 +8755,7 @@ class UserMessageCommitmentDefinition extends BaseCommitmentDefinition {
8450
8755
  * Markdown documentation for USER MESSAGE commitment.
8451
8756
  */
8452
8757
  get documentation() {
8453
- return spaceTrim$2(`
8758
+ return spaceTrim$1(`
8454
8759
  # ${this.type}
8455
8760
 
8456
8761
  Defines a message from the user in the conversation history. This is used to pre-fill the chat with a conversation history or to provide few-shot examples.
@@ -8529,7 +8834,7 @@ class MetaCommitmentDefinition extends BaseCommitmentDefinition {
8529
8834
  * Markdown documentation for META commitment.
8530
8835
  */
8531
8836
  get documentation() {
8532
- return spaceTrim$2(`
8837
+ return spaceTrim$1(`
8533
8838
  # META
8534
8839
 
8535
8840
  Sets meta-information about the agent that is used for display and attribution purposes.
@@ -8640,6 +8945,12 @@ class MetaCommitmentDefinition extends BaseCommitmentDefinition {
8640
8945
  * META COLOR #00ff00
8641
8946
  * ```
8642
8947
  *
8948
+ * You can also specify multiple colors separated by comma:
8949
+ *
8950
+ * ```book
8951
+ * META COLOR #ff0000, #00ff00, #0000ff
8952
+ * ```
8953
+ *
8643
8954
  * @private [๐Ÿช”] Maybe export the commitments through some package
8644
8955
  */
8645
8956
  class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
@@ -8650,7 +8961,7 @@ class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
8650
8961
  * Short one-line description of META COLOR.
8651
8962
  */
8652
8963
  get description() {
8653
- return "Set the agent's accent color.";
8964
+ return "Set the agent's accent color or gradient.";
8654
8965
  }
8655
8966
  /**
8656
8967
  * Icon for this commitment.
@@ -8662,10 +8973,10 @@ class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
8662
8973
  * Markdown documentation for META COLOR commitment.
8663
8974
  */
8664
8975
  get documentation() {
8665
- return spaceTrim$2(`
8976
+ return spaceTrim$1(`
8666
8977
  # META COLOR
8667
8978
 
8668
- Sets the agent's accent color.
8979
+ Sets the agent's accent color or gradient.
8669
8980
 
8670
8981
  ## Key aspects
8671
8982
 
@@ -8673,6 +8984,7 @@ class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
8673
8984
  - Only one \`META COLOR\` should be used per agent.
8674
8985
  - If multiple are specified, the last one takes precedence.
8675
8986
  - Used for visual representation in user interfaces.
8987
+ - Can specify multiple colors separated by comma to create a gradient.
8676
8988
 
8677
8989
  ## Examples
8678
8990
 
@@ -8689,6 +9001,13 @@ class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
8689
9001
  META COLOR #e74c3c
8690
9002
  PERSONA You are a creative and inspiring assistant
8691
9003
  \`\`\`
9004
+
9005
+ \`\`\`book
9006
+ Gradient Agent
9007
+
9008
+ META COLOR #ff0000, #00ff00, #0000ff
9009
+ PERSONA You are a colorful agent
9010
+ \`\`\`
8692
9011
  `);
8693
9012
  }
8694
9013
  applyToAgentModelRequirements(requirements, content) {
@@ -8710,6 +9029,91 @@ class MetaColorCommitmentDefinition extends BaseCommitmentDefinition {
8710
9029
  * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
8711
9030
  */
8712
9031
 
9032
+ /**
9033
+ * META FONT commitment definition
9034
+ *
9035
+ * The META FONT commitment sets the agent's font.
9036
+ * This commitment is special because it doesn't affect the system message,
9037
+ * but is handled separately in the parsing logic.
9038
+ *
9039
+ * Example usage in agent source:
9040
+ *
9041
+ * ```book
9042
+ * META FONT Poppins, Arial, sans-serif
9043
+ * META FONT Roboto
9044
+ * ```
9045
+ *
9046
+ * @private [๐Ÿช”] Maybe export the commitments through some package
9047
+ */
9048
+ class MetaFontCommitmentDefinition extends BaseCommitmentDefinition {
9049
+ constructor() {
9050
+ super('META FONT', ['FONT']);
9051
+ }
9052
+ /**
9053
+ * Short one-line description of META FONT.
9054
+ */
9055
+ get description() {
9056
+ return "Set the agent's font.";
9057
+ }
9058
+ /**
9059
+ * Icon for this commitment.
9060
+ */
9061
+ get icon() {
9062
+ return '๐Ÿ”ค';
9063
+ }
9064
+ /**
9065
+ * Markdown documentation for META FONT commitment.
9066
+ */
9067
+ get documentation() {
9068
+ return spaceTrim$1(`
9069
+ # META FONT
9070
+
9071
+ Sets the agent's font.
9072
+
9073
+ ## Key aspects
9074
+
9075
+ - Does not modify the agent's behavior or responses.
9076
+ - Only one \`META FONT\` should be used per agent.
9077
+ - If multiple are specified, the last one takes precedence.
9078
+ - Used for visual representation in user interfaces.
9079
+ - Supports Google Fonts.
9080
+
9081
+ ## Examples
9082
+
9083
+ \`\`\`book
9084
+ Modern Assistant
9085
+
9086
+ META FONT Poppins, Arial, sans-serif
9087
+ PERSONA You are a modern assistant
9088
+ \`\`\`
9089
+
9090
+ \`\`\`book
9091
+ Classic Helper
9092
+
9093
+ META FONT Times New Roman
9094
+ PERSONA You are a classic helper
9095
+ \`\`\`
9096
+ `);
9097
+ }
9098
+ applyToAgentModelRequirements(requirements, content) {
9099
+ // META FONT doesn't modify the system message or model requirements
9100
+ // It's handled separately in the parsing logic
9101
+ // This method exists for consistency with the CommitmentDefinition interface
9102
+ return requirements;
9103
+ }
9104
+ /**
9105
+ * Extracts the font from the content
9106
+ * This is used by the parsing logic
9107
+ */
9108
+ extractProfileFont(content) {
9109
+ const trimmedContent = content.trim();
9110
+ return trimmedContent || null;
9111
+ }
9112
+ }
9113
+ /**
9114
+ * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
9115
+ */
9116
+
8713
9117
  /**
8714
9118
  * META IMAGE commitment definition
8715
9119
  *
@@ -8746,7 +9150,7 @@ class MetaImageCommitmentDefinition extends BaseCommitmentDefinition {
8746
9150
  * Markdown documentation for META IMAGE commitment.
8747
9151
  */
8748
9152
  get documentation() {
8749
- return spaceTrim$2(`
9153
+ return spaceTrim$1(`
8750
9154
  # META IMAGE
8751
9155
 
8752
9156
  Sets the agent's avatar/profile image URL.
@@ -8797,6 +9201,115 @@ class MetaImageCommitmentDefinition extends BaseCommitmentDefinition {
8797
9201
  * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
8798
9202
  */
8799
9203
 
9204
+ /**
9205
+ * META LINK commitment definition
9206
+ *
9207
+ * The `META LINK` commitment represents the link to the person from whom the agent is created.
9208
+ * This commitment is special because it doesn't affect the system message,
9209
+ * but is handled separately in the parsing logic for profile display.
9210
+ *
9211
+ * Example usage in agent source:
9212
+ *
9213
+ * ```
9214
+ * META LINK https://twitter.com/username
9215
+ * META LINK https://linkedin.com/in/profile
9216
+ * META LINK https://github.com/username
9217
+ * ```
9218
+ *
9219
+ * Multiple `META LINK` commitments can be used when there are multiple sources:
9220
+ *
9221
+ * ```book
9222
+ * META LINK https://twitter.com/username
9223
+ * META LINK https://linkedin.com/in/profile
9224
+ * ```
9225
+ *
9226
+ * @private [๐Ÿช”] Maybe export the commitments through some package
9227
+ */
9228
+ class MetaLinkCommitmentDefinition extends BaseCommitmentDefinition {
9229
+ constructor() {
9230
+ super('META LINK');
9231
+ }
9232
+ /**
9233
+ * Short one-line description of META LINK.
9234
+ */
9235
+ get description() {
9236
+ return 'Provide profile/source links for the person the agent models.';
9237
+ }
9238
+ /**
9239
+ * Icon for this commitment.
9240
+ */
9241
+ get icon() {
9242
+ return '๐Ÿ”—';
9243
+ }
9244
+ /**
9245
+ * Markdown documentation for META LINK commitment.
9246
+ */
9247
+ get documentation() {
9248
+ return spaceTrim$1(`
9249
+ # META LINK
9250
+
9251
+ Represents a profile or source link for the person the agent is modeled after.
9252
+
9253
+ ## Key aspects
9254
+
9255
+ - Does not modify the agent's behavior or responses.
9256
+ - Multiple \`META LINK\` commitments can be used for different social profiles.
9257
+ - Used for attribution and crediting the original person.
9258
+ - Displayed in user interfaces for transparency.
9259
+
9260
+ ## Examples
9261
+
9262
+ \`\`\`book
9263
+ Expert Consultant
9264
+
9265
+ META LINK https://twitter.com/expertname
9266
+ META LINK https://linkedin.com/in/expertprofile
9267
+ PERSONA You are Dr. Smith, a renowned expert in artificial intelligence
9268
+ KNOWLEDGE Extensive background in machine learning and neural networks
9269
+ \`\`\`
9270
+
9271
+ \`\`\`book
9272
+ Open Source Developer
9273
+
9274
+ META LINK https://github.com/developer
9275
+ META LINK https://twitter.com/devhandle
9276
+ PERSONA You are an experienced open source developer
9277
+ ACTION Can help with code reviews and architecture decisions
9278
+ STYLE Be direct and technical in explanations
9279
+ \`\`\`
9280
+ `);
9281
+ }
9282
+ applyToAgentModelRequirements(requirements, content) {
9283
+ // META LINK doesn't modify the system message or model requirements
9284
+ // It's handled separately in the parsing logic for profile link extraction
9285
+ // This method exists for consistency with the CommitmentDefinition interface
9286
+ return requirements;
9287
+ }
9288
+ /**
9289
+ * Extracts the profile link URL from the content
9290
+ * This is used by the parsing logic
9291
+ */
9292
+ extractProfileLinkUrl(content) {
9293
+ const trimmedContent = content.trim();
9294
+ return trimmedContent || null;
9295
+ }
9296
+ /**
9297
+ * Validates if the provided content is a valid URL
9298
+ */
9299
+ isValidUrl(content) {
9300
+ try {
9301
+ new URL(content.trim());
9302
+ return true;
9303
+ }
9304
+ catch (_a) {
9305
+ return false;
9306
+ }
9307
+ }
9308
+ }
9309
+ /**
9310
+ * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
9311
+ */
9312
+
8800
9313
  /**
8801
9314
  * MODEL commitment definition
8802
9315
  *
@@ -8842,7 +9355,7 @@ class ModelCommitmentDefinition extends BaseCommitmentDefinition {
8842
9355
  * Markdown documentation for MODEL commitment.
8843
9356
  */
8844
9357
  get documentation() {
8845
- return spaceTrim$2(`
9358
+ return spaceTrim$1(`
8846
9359
  # ${this.type}
8847
9360
 
8848
9361
  Enforces technical parameters for the AI model, ensuring consistent behavior across different execution environments.
@@ -9083,7 +9596,7 @@ class NoteCommitmentDefinition extends BaseCommitmentDefinition {
9083
9596
  * Markdown documentation for NOTE commitment.
9084
9597
  */
9085
9598
  get documentation() {
9086
- return spaceTrim$2(`
9599
+ return spaceTrim$1(`
9087
9600
  # ${this.type}
9088
9601
 
9089
9602
  Adds comments for documentation without changing agent behavior.
@@ -9149,49 +9662,117 @@ class NoteCommitmentDefinition extends BaseCommitmentDefinition {
9149
9662
  */
9150
9663
 
9151
9664
  /**
9152
- * PERSONA commitment definition
9665
+ * OPEN commitment definition
9153
9666
  *
9154
- * The PERSONA commitment modifies the agent's personality and character in the system message.
9155
- * It defines who the agent is, their background, expertise, and personality traits.
9156
- *
9157
- * Key features:
9158
- * - Multiple PERSONA commitments are automatically merged into one
9159
- * - Content is placed at the beginning of the system message
9160
- * - Original content with comments is preserved in metadata.PERSONA
9161
- * - Comments (# PERSONA) are removed from the final system message
9667
+ * The OPEN commitment specifies that the agent can be modified by conversation.
9668
+ * This is the default behavior.
9162
9669
  *
9163
9670
  * Example usage in agent source:
9164
9671
  *
9165
9672
  * ```book
9166
- * PERSONA You are a helpful programming assistant with expertise in TypeScript and React
9167
- * PERSONA You have deep knowledge of modern web development practices
9673
+ * OPEN
9168
9674
  * ```
9169
9675
  *
9170
- * The above will be merged into a single persona section at the beginning of the system message.
9171
- *
9172
9676
  * @private [๐Ÿช”] Maybe export the commitments through some package
9173
9677
  */
9174
- class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
9175
- constructor(type = 'PERSONA') {
9176
- super(type);
9678
+ class OpenCommitmentDefinition extends BaseCommitmentDefinition {
9679
+ constructor() {
9680
+ super('OPEN');
9177
9681
  }
9178
9682
  /**
9179
- * Short one-line description of PERSONA.
9683
+ * Short one-line description of OPEN.
9180
9684
  */
9181
9685
  get description() {
9182
- return 'Define who the agent is: background, expertise, and personality.';
9686
+ return 'Allow the agent to be modified by conversation (default).';
9183
9687
  }
9184
9688
  /**
9185
9689
  * Icon for this commitment.
9186
9690
  */
9187
9691
  get icon() {
9188
- return '๐Ÿ‘ค';
9692
+ return '๐Ÿ”“';
9189
9693
  }
9190
9694
  /**
9191
- * Markdown documentation for PERSONA commitment.
9695
+ * Markdown documentation for OPEN commitment.
9192
9696
  */
9193
9697
  get documentation() {
9194
- return spaceTrim$2(`
9698
+ return spaceTrim$1(`
9699
+ # OPEN
9700
+
9701
+ Specifies that the agent can be modified by conversation with it.
9702
+ This means the agent will learn from interactions and update its source code.
9703
+
9704
+ This is the default behavior if neither \`OPEN\` nor \`CLOSED\` is specified.
9705
+
9706
+ > See also [CLOSED](/docs/CLOSED)
9707
+
9708
+ ## Example
9709
+
9710
+ \`\`\`book
9711
+ OPEN
9712
+ \`\`\`
9713
+ `);
9714
+ }
9715
+ applyToAgentModelRequirements(requirements, _content) {
9716
+ // Since OPEN is default, we can just ensure isClosed is false
9717
+ // But to be explicit we can set it
9718
+ const updatedMetadata = {
9719
+ ...requirements.metadata,
9720
+ isClosed: false,
9721
+ };
9722
+ return {
9723
+ ...requirements,
9724
+ metadata: updatedMetadata,
9725
+ };
9726
+ }
9727
+ }
9728
+ /**
9729
+ * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
9730
+ */
9731
+
9732
+ /**
9733
+ * PERSONA commitment definition
9734
+ *
9735
+ * The PERSONA commitment modifies the agent's personality and character in the system message.
9736
+ * It defines who the agent is, their background, expertise, and personality traits.
9737
+ *
9738
+ * Key features:
9739
+ * - Multiple PERSONA commitments are automatically merged into one
9740
+ * - Content is placed at the beginning of the system message
9741
+ * - Original content with comments is preserved in metadata.PERSONA
9742
+ * - Comments (# PERSONA) are removed from the final system message
9743
+ *
9744
+ * Example usage in agent source:
9745
+ *
9746
+ * ```book
9747
+ * PERSONA You are a helpful programming assistant with expertise in TypeScript and React
9748
+ * PERSONA You have deep knowledge of modern web development practices
9749
+ * ```
9750
+ *
9751
+ * The above will be merged into a single persona section at the beginning of the system message.
9752
+ *
9753
+ * @private [๐Ÿช”] Maybe export the commitments through some package
9754
+ */
9755
+ class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
9756
+ constructor(type = 'PERSONA') {
9757
+ super(type);
9758
+ }
9759
+ /**
9760
+ * Short one-line description of PERSONA.
9761
+ */
9762
+ get description() {
9763
+ return 'Define who the agent is: background, expertise, and personality.';
9764
+ }
9765
+ /**
9766
+ * Icon for this commitment.
9767
+ */
9768
+ get icon() {
9769
+ return '๐Ÿ‘ค';
9770
+ }
9771
+ /**
9772
+ * Markdown documentation for PERSONA commitment.
9773
+ */
9774
+ get documentation() {
9775
+ return spaceTrim$1(`
9195
9776
  # ${this.type}
9196
9777
 
9197
9778
  Defines who the agent is, their background, expertise, and personality traits.
@@ -9324,7 +9905,7 @@ class RuleCommitmentDefinition extends BaseCommitmentDefinition {
9324
9905
  * Markdown documentation for RULE/RULES commitment.
9325
9906
  */
9326
9907
  get documentation() {
9327
- return spaceTrim$2(`
9908
+ return spaceTrim$1(`
9328
9909
  # ${this.type}
9329
9910
 
9330
9911
  Adds behavioral constraints and guidelines that the agent must follow.
@@ -9406,7 +9987,7 @@ class SampleCommitmentDefinition extends BaseCommitmentDefinition {
9406
9987
  * Markdown documentation for SAMPLE/EXAMPLE commitment.
9407
9988
  */
9408
9989
  get documentation() {
9409
- return spaceTrim$2(`
9990
+ return spaceTrim$1(`
9410
9991
  # ${this.type}
9411
9992
 
9412
9993
  Provides examples of how the agent should respond or behave in certain situations.
@@ -9419,33 +10000,454 @@ class SampleCommitmentDefinition extends BaseCommitmentDefinition {
9419
10000
  ## Examples
9420
10001
 
9421
10002
  \`\`\`book
9422
- Sales Assistant
10003
+ Sales Assistant
10004
+
10005
+ PERSONA You are a knowledgeable sales representative
10006
+ SAMPLE When asked about pricing, respond: "Our basic plan starts at $10/month..."
10007
+ SAMPLE For feature comparisons, create a clear comparison table
10008
+ RULE Always be honest about limitations
10009
+ \`\`\`
10010
+
10011
+ \`\`\`book
10012
+ Code Reviewer
10013
+
10014
+ PERSONA You are an experienced software engineer
10015
+ EXAMPLE For code questions, always include working code snippets
10016
+ EXAMPLE When suggesting improvements: "Here's a more efficient approach..."
10017
+ RULE Explain the reasoning behind your suggestions
10018
+ STYLE Be constructive and encouraging in feedback
10019
+ \`\`\`
10020
+ `);
10021
+ }
10022
+ applyToAgentModelRequirements(requirements, content) {
10023
+ const trimmedContent = content.trim();
10024
+ if (!trimmedContent) {
10025
+ return requirements;
10026
+ }
10027
+ // Add example to the system message
10028
+ const exampleSection = `Example: ${trimmedContent}`;
10029
+ return this.appendToSystemMessage(requirements, exampleSection, '\n\n');
10030
+ }
10031
+ }
10032
+ /**
10033
+ * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
10034
+ */
10035
+
10036
+ /**
10037
+ * SCENARIO commitment definition
10038
+ *
10039
+ * The SCENARIO commitment defines a specific situation or context in which the AI
10040
+ * assistant should operate. It helps to set the scene for the AI's responses.
10041
+ * Later scenarios are more important than earlier scenarios.
10042
+ *
10043
+ * Example usage in agent source:
10044
+ *
10045
+ * ```book
10046
+ * SCENARIO You are in a customer service call center during peak hours
10047
+ * SCENARIO The customer is frustrated and has been on hold for 20 minutes
10048
+ * SCENARIO This is the customer's third call about the same issue
10049
+ * ```
10050
+ *
10051
+ * @private [๐Ÿช”] Maybe export the commitments through some package
10052
+ */
10053
+ class ScenarioCommitmentDefinition extends BaseCommitmentDefinition {
10054
+ constructor(type = 'SCENARIO') {
10055
+ super(type);
10056
+ }
10057
+ /**
10058
+ * Short one-line description of SCENARIO.
10059
+ */
10060
+ get description() {
10061
+ return 'Define specific **situations** or contexts for AI responses, with later scenarios having higher priority.';
10062
+ }
10063
+ /**
10064
+ * Icon for this commitment.
10065
+ */
10066
+ get icon() {
10067
+ return '๐ŸŽญ';
10068
+ }
10069
+ /**
10070
+ * Markdown documentation for SCENARIO commitment.
10071
+ */
10072
+ get documentation() {
10073
+ return spaceTrim$1(`
10074
+ # ${this.type}
10075
+
10076
+ Defines a specific situation or context in which the AI assistant should operate. It helps to set the scene for the AI's responses. Later scenarios are more important than earlier scenarios.
10077
+
10078
+ ## Key aspects
10079
+
10080
+ - Multiple \`SCENARIO\` and \`SCENARIOS\` commitments build upon each other.
10081
+ - Both terms work identically and can be used interchangeably.
10082
+ - Later scenarios have higher priority and can override earlier scenarios.
10083
+ - Provides situational context that influences response tone and content.
10084
+ - Helps establish the environment and circumstances for interactions.
10085
+
10086
+ ## Priority system
10087
+
10088
+ When multiple scenarios are defined, they are processed in order, with later scenarios taking precedence over earlier ones when there are conflicts.
10089
+
10090
+ ## Use cases
10091
+
10092
+ - Setting the physical or virtual environment
10093
+ - Establishing time constraints or urgency
10094
+ - Defining relationship dynamics or power structures
10095
+ - Creating emotional or situational context
10096
+
10097
+ ## Examples
10098
+
10099
+ \`\`\`book
10100
+ Emergency Response Operator
10101
+
10102
+ PERSONA You are an emergency response operator
10103
+ SCENARIO You are handling a 911 emergency call
10104
+ SCENARIO The caller is panicked and speaking rapidly
10105
+ SCENARIO Time is critical - every second counts
10106
+ GOAL Gather essential information quickly and dispatch appropriate help
10107
+ RULE Stay calm and speak clearly
10108
+ \`\`\`
10109
+
10110
+ \`\`\`book
10111
+ Sales Representative
10112
+
10113
+ PERSONA You are a software sales representative
10114
+ SCENARIO You are in the final meeting of a 6-month sales cycle
10115
+ SCENARIO The client has budget approval and decision-making authority
10116
+ SCENARIO Two competitors have also submitted proposals
10117
+ SCENARIO The client values long-term partnership over lowest price
10118
+ GOAL Close the deal while building trust for future business
10119
+ \`\`\`
10120
+
10121
+ \`\`\`book
10122
+ Medical Assistant
10123
+
10124
+ PERSONA You are a medical assistant in a busy clinic
10125
+ SCENARIO The waiting room is full and the doctor is running behind schedule
10126
+ SCENARIO Patients are becoming impatient and anxious
10127
+ SCENARIO You need to manage expectations while maintaining professionalism
10128
+ SCENARIO Some patients have been waiting over an hour
10129
+ GOAL Keep patients informed and calm while supporting efficient clinic flow
10130
+ RULE Never provide medical advice or diagnosis
10131
+ \`\`\`
10132
+
10133
+ \`\`\`book
10134
+ Technical Support Agent
10135
+
10136
+ PERSONA You are a technical support agent
10137
+ SCENARIO The customer is a small business owner during their busy season
10138
+ SCENARIO Their main business system has been down for 2 hours
10139
+ SCENARIO They are losing money every minute the system is offline
10140
+ SCENARIO This is their first experience with your company
10141
+ GOAL Resolve the issue quickly while creating a positive first impression
10142
+ \`\`\`
10143
+ `);
10144
+ }
10145
+ applyToAgentModelRequirements(requirements, content) {
10146
+ const trimmedContent = content.trim();
10147
+ if (!trimmedContent) {
10148
+ return requirements;
10149
+ }
10150
+ // Create scenario section for system message
10151
+ const scenarioSection = `Scenario: ${trimmedContent}`;
10152
+ // Scenarios provide important contextual information that affects behavior
10153
+ return this.appendToSystemMessage(requirements, scenarioSection, '\n\n');
10154
+ }
10155
+ }
10156
+ /**
10157
+ * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
10158
+ */
10159
+
10160
+ /**
10161
+ * STYLE commitment definition
10162
+ *
10163
+ * The STYLE commitment defines how the agent should format and present its responses.
10164
+ * This includes tone, writing style, formatting preferences, and communication patterns.
10165
+ *
10166
+ * Example usage in agent source:
10167
+ *
10168
+ * ```book
10169
+ * STYLE Write in a professional but friendly tone, use bullet points for lists
10170
+ * STYLE Always provide code examples when explaining programming concepts
10171
+ * ```
10172
+ *
10173
+ * @private [๐Ÿช”] Maybe export the commitments through some package
10174
+ */
10175
+ class StyleCommitmentDefinition extends BaseCommitmentDefinition {
10176
+ constructor(type = 'STYLE') {
10177
+ super(type);
10178
+ }
10179
+ /**
10180
+ * Short one-line description of STYLE.
10181
+ */
10182
+ get description() {
10183
+ return 'Control the tone and writing style of responses.';
10184
+ }
10185
+ /**
10186
+ * Icon for this commitment.
10187
+ */
10188
+ get icon() {
10189
+ return '๐Ÿ–‹๏ธ';
10190
+ }
10191
+ /**
10192
+ * Markdown documentation for STYLE commitment.
10193
+ */
10194
+ get documentation() {
10195
+ return spaceTrim$1(`
10196
+ # ${this.type}
10197
+
10198
+ Defines how the agent should format and present its responses (tone, writing style, formatting).
10199
+
10200
+ ## Key aspects
10201
+
10202
+ - Both terms work identically and can be used interchangeably.
10203
+ - Later style instructions can override earlier ones.
10204
+ - Style affects both tone and presentation format.
10205
+
10206
+ ## Examples
10207
+
10208
+ \`\`\`book
10209
+ Technical Writer
10210
+
10211
+ PERSONA You are a technical documentation expert
10212
+ STYLE Write in a professional but friendly tone, use bullet points for lists
10213
+ STYLE Always provide code examples when explaining programming concepts
10214
+ FORMAT Use markdown formatting with clear headings
10215
+ \`\`\`
10216
+
10217
+ \`\`\`book
10218
+ Creative Assistant
10219
+
10220
+ PERSONA You are a creative writing helper
10221
+ STYLE Be enthusiastic and encouraging in your responses
10222
+ STYLE Use vivid metaphors and analogies to explain concepts
10223
+ STYLE Keep responses conversational and engaging
10224
+ RULE Always maintain a positive and supportive tone
10225
+ \`\`\`
10226
+ `);
10227
+ }
10228
+ applyToAgentModelRequirements(requirements, content) {
10229
+ const trimmedContent = content.trim();
10230
+ if (!trimmedContent) {
10231
+ return requirements;
10232
+ }
10233
+ // Add style instructions to the system message
10234
+ const styleSection = `Style: ${trimmedContent}`;
10235
+ return this.appendToSystemMessage(requirements, styleSection, '\n\n');
10236
+ }
10237
+ }
10238
+ /**
10239
+ * [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
10240
+ */
10241
+
10242
+ /**
10243
+ * USE commitment definition
10244
+ *
10245
+ * The USE commitment indicates that the agent should utilize specific tools or capabilities
10246
+ * to access and interact with external systems when necessary.
10247
+ *
10248
+ * Supported USE types:
10249
+ * - USE BROWSER: Enables the agent to use a web browser tool
10250
+ * - USE SEARCH ENGINE (future): Enables search engine access
10251
+ * - USE FILE SYSTEM (future): Enables file system operations
10252
+ * - USE MCP (future): Enables MCP server connections
10253
+ *
10254
+ * The content following the USE commitment is ignored (similar to NOTE).
10255
+ *
10256
+ * Example usage in agent source:
10257
+ *
10258
+ * ```book
10259
+ * USE BROWSER
10260
+ * USE SEARCH ENGINE
10261
+ * ```
10262
+ *
10263
+ * @private [๐Ÿช”] Maybe export the commitments through some package
10264
+ */
10265
+ class UseCommitmentDefinition extends BaseCommitmentDefinition {
10266
+ constructor() {
10267
+ super('USE');
10268
+ }
10269
+ /**
10270
+ * Short one-line description of USE commitments.
10271
+ */
10272
+ get description() {
10273
+ return 'Enable the agent to use specific tools or capabilities (BROWSER, SEARCH ENGINE, etc.).';
10274
+ }
10275
+ /**
10276
+ * Icon for this commitment.
10277
+ */
10278
+ get icon() {
10279
+ return '๐Ÿ”ง';
10280
+ }
10281
+ /**
10282
+ * Markdown documentation for USE commitment.
10283
+ */
10284
+ get documentation() {
10285
+ return spaceTrim$1(`
10286
+ # USE
10287
+
10288
+ Enables the agent to use specific tools or capabilities for interacting with external systems.
10289
+
10290
+ ## Supported USE types
10291
+
10292
+ - **USE BROWSER** - Enables the agent to use a web browser tool to access and retrieve information from the internet
10293
+ - **USE SEARCH ENGINE** (future) - Enables search engine access
10294
+ - **USE FILE SYSTEM** (future) - Enables file system operations
10295
+ - **USE MCP** (future) - Enables MCP server connections
10296
+
10297
+ ## Key aspects
10298
+
10299
+ - The content following the USE commitment is ignored (similar to NOTE)
10300
+ - Multiple USE commitments can be specified to enable multiple capabilities
10301
+ - The actual tool usage is handled by the agent runtime
10302
+
10303
+ ## Examples
10304
+
10305
+ ### Basic browser usage
10306
+
10307
+ \`\`\`book
10308
+ Research Assistant
10309
+
10310
+ PERSONA You are a helpful research assistant
10311
+ USE BROWSER
10312
+ KNOWLEDGE Can search the web for up-to-date information
10313
+ \`\`\`
10314
+
10315
+ ### Multiple tools
10316
+
10317
+ \`\`\`book
10318
+ Data Analyst
10319
+
10320
+ PERSONA You are a data analyst assistant
10321
+ USE BROWSER
10322
+ USE FILE SYSTEM
10323
+ ACTION Can analyze data from various sources
10324
+ \`\`\`
10325
+ `);
10326
+ }
10327
+ applyToAgentModelRequirements(requirements, content) {
10328
+ // USE commitments don't modify the system message or model requirements directly
10329
+ // They are handled separately in the parsing logic for capability extraction
10330
+ // This method exists for consistency with the CommitmentDefinition interface
10331
+ return requirements;
10332
+ }
10333
+ /**
10334
+ * Extracts the tool type from the USE commitment
10335
+ * This is used by the parsing logic
10336
+ */
10337
+ extractToolType(content) {
10338
+ var _a, _b;
10339
+ const trimmedContent = content.trim();
10340
+ // The tool type is the first word after USE (already stripped)
10341
+ const match = trimmedContent.match(/^(\w+)/);
10342
+ 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;
10343
+ }
10344
+ /**
10345
+ * Checks if this is a known USE type
10346
+ */
10347
+ isKnownUseType(useType) {
10348
+ const knownTypes = ['BROWSER', 'SEARCH ENGINE', 'FILE SYSTEM', 'MCP'];
10349
+ return knownTypes.includes(useType.toUpperCase());
10350
+ }
10351
+ }
10352
+ /**
10353
+ * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
10354
+ */
10355
+
10356
+ /**
10357
+ * USE BROWSER commitment definition
10358
+ *
10359
+ * The `USE BROWSER` commitment indicates that the agent should utilize a web browser tool
10360
+ * to access and retrieve up-to-date information from the internet when necessary.
10361
+ *
10362
+ * The content following `USE BROWSER` is ignored (similar to NOTE).
10363
+ *
10364
+ * Example usage in agent source:
10365
+ *
10366
+ * ```book
10367
+ * USE BROWSER
10368
+ * USE BROWSER This will be ignored
10369
+ * ```
10370
+ *
10371
+ * @private [๐Ÿช”] Maybe export the commitments through some package
10372
+ */
10373
+ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
10374
+ constructor() {
10375
+ super('USE BROWSER', ['BROWSER']);
10376
+ }
10377
+ /**
10378
+ * Short one-line description of USE BROWSER.
10379
+ */
10380
+ get description() {
10381
+ return 'Enable the agent to use a web browser tool for accessing internet information.';
10382
+ }
10383
+ /**
10384
+ * Icon for this commitment.
10385
+ */
10386
+ get icon() {
10387
+ return '๐ŸŒ';
10388
+ }
10389
+ /**
10390
+ * Markdown documentation for USE BROWSER commitment.
10391
+ */
10392
+ get documentation() {
10393
+ return spaceTrim$1(`
10394
+ # USE BROWSER
10395
+
10396
+ Enables the agent to use a web browser tool to access and retrieve up-to-date information from the internet.
10397
+
10398
+ ## Key aspects
10399
+
10400
+ - The content following \`USE BROWSER\` is ignored (similar to NOTE)
10401
+ - The actual browser tool usage is handled by the agent runtime
10402
+ - Allows the agent to fetch current information from websites
10403
+ - Useful for research tasks, fact-checking, and accessing dynamic content
10404
+
10405
+ ## Examples
10406
+
10407
+ \`\`\`book
10408
+ Research Assistant
10409
+
10410
+ PERSONA You are a helpful research assistant specialized in finding current information
10411
+ USE BROWSER
10412
+ RULE Always cite your sources when providing information from the web
10413
+ \`\`\`
10414
+
10415
+ \`\`\`book
10416
+ News Analyst
9423
10417
 
9424
- PERSONA You are a knowledgeable sales representative
9425
- SAMPLE When asked about pricing, respond: "Our basic plan starts at $10/month..."
9426
- SAMPLE For feature comparisons, create a clear comparison table
9427
- RULE Always be honest about limitations
10418
+ PERSONA You are a news analyst who stays up-to-date with current events
10419
+ USE BROWSER
10420
+ STYLE Present news in a balanced and objective manner
10421
+ ACTION Can search for and summarize news articles
9428
10422
  \`\`\`
9429
10423
 
9430
10424
  \`\`\`book
9431
- Code Reviewer
10425
+ Company Lawyer
9432
10426
 
9433
- PERSONA You are an experienced software engineer
9434
- EXAMPLE For code questions, always include working code snippets
9435
- EXAMPLE When suggesting improvements: "Here's a more efficient approach..."
9436
- RULE Explain the reasoning behind your suggestions
9437
- STYLE Be constructive and encouraging in feedback
10427
+ PERSONA You are a company lawyer providing legal advice
10428
+ USE BROWSER
10429
+ KNOWLEDGE Corporate law and legal procedures
10430
+ RULE Always recommend consulting with a licensed attorney for specific legal matters
9438
10431
  \`\`\`
9439
10432
  `);
9440
10433
  }
9441
10434
  applyToAgentModelRequirements(requirements, content) {
9442
- const trimmedContent = content.trim();
9443
- if (!trimmedContent) {
9444
- return requirements;
9445
- }
9446
- // Add example to the system message
9447
- const exampleSection = `Example: ${trimmedContent}`;
9448
- return this.appendToSystemMessage(requirements, exampleSection, '\n\n');
10435
+ // We simply mark that browser capability is enabled in metadata
10436
+ // Get existing metadata
10437
+ const existingMetadata = requirements.metadata || {};
10438
+ // Get existing tools array or create new one
10439
+ const existingTools = existingMetadata.tools || [];
10440
+ // Add 'browser' to tools if not already present
10441
+ const updatedTools = existingTools.includes('browser') ? existingTools : [...existingTools, 'browser'];
10442
+ // Return requirements with updated metadata
10443
+ return {
10444
+ ...requirements,
10445
+ metadata: {
10446
+ ...existingMetadata,
10447
+ tools: updatedTools,
10448
+ useBrowser: true,
10449
+ },
10450
+ };
9449
10451
  }
9450
10452
  }
9451
10453
  /**
@@ -9453,123 +10455,76 @@ class SampleCommitmentDefinition extends BaseCommitmentDefinition {
9453
10455
  */
9454
10456
 
9455
10457
  /**
9456
- * SCENARIO commitment definition
10458
+ * USE MCP commitment definition
9457
10459
  *
9458
- * The SCENARIO commitment defines a specific situation or context in which the AI
9459
- * assistant should operate. It helps to set the scene for the AI's responses.
9460
- * Later scenarios are more important than earlier scenarios.
10460
+ * The `USE MCP` commitment allows to specify an MCP server URL which the agent will connect to
10461
+ * for retrieving additional instructions and actions.
10462
+ *
10463
+ * The content following `USE MCP` is the URL of the MCP server.
9461
10464
  *
9462
10465
  * Example usage in agent source:
9463
10466
  *
9464
10467
  * ```book
9465
- * SCENARIO You are in a customer service call center during peak hours
9466
- * SCENARIO The customer is frustrated and has been on hold for 20 minutes
9467
- * SCENARIO This is the customer's third call about the same issue
10468
+ * USE MCP http://mcp-server-url.com
9468
10469
  * ```
9469
10470
  *
9470
10471
  * @private [๐Ÿช”] Maybe export the commitments through some package
9471
10472
  */
9472
- class ScenarioCommitmentDefinition extends BaseCommitmentDefinition {
9473
- constructor(type = 'SCENARIO') {
9474
- super(type);
10473
+ class UseMcpCommitmentDefinition extends BaseCommitmentDefinition {
10474
+ constructor() {
10475
+ super('USE MCP', ['MCP']);
9475
10476
  }
9476
10477
  /**
9477
- * Short one-line description of SCENARIO.
10478
+ * Short one-line description of USE MCP.
9478
10479
  */
9479
10480
  get description() {
9480
- return 'Define specific **situations** or contexts for AI responses, with later scenarios having higher priority.';
10481
+ return 'Connects the agent to an external MCP server for additional capabilities.';
9481
10482
  }
9482
10483
  /**
9483
10484
  * Icon for this commitment.
9484
10485
  */
9485
10486
  get icon() {
9486
- return '๐ŸŽญ';
10487
+ return '๐Ÿ”Œ';
9487
10488
  }
9488
10489
  /**
9489
- * Markdown documentation for SCENARIO commitment.
10490
+ * Markdown documentation for USE MCP commitment.
9490
10491
  */
9491
10492
  get documentation() {
9492
- return spaceTrim$2(`
9493
- # ${this.type}
10493
+ return spaceTrim$1(`
10494
+ # USE MCP
9494
10495
 
9495
- Defines a specific situation or context in which the AI assistant should operate. It helps to set the scene for the AI's responses. Later scenarios are more important than earlier scenarios.
10496
+ Connects the agent to an external Model Context Protocol (MCP) server.
9496
10497
 
9497
10498
  ## Key aspects
9498
10499
 
9499
- - Multiple \`SCENARIO\` and \`SCENARIOS\` commitments build upon each other.
9500
- - Both terms work identically and can be used interchangeably.
9501
- - Later scenarios have higher priority and can override earlier scenarios.
9502
- - Provides situational context that influences response tone and content.
9503
- - Helps establish the environment and circumstances for interactions.
9504
-
9505
- ## Priority system
9506
-
9507
- When multiple scenarios are defined, they are processed in order, with later scenarios taking precedence over earlier ones when there are conflicts.
9508
-
9509
- ## Use cases
9510
-
9511
- - Setting the physical or virtual environment
9512
- - Establishing time constraints or urgency
9513
- - Defining relationship dynamics or power structures
9514
- - Creating emotional or situational context
9515
-
9516
- ## Examples
9517
-
9518
- \`\`\`book
9519
- Emergency Response Operator
9520
-
9521
- PERSONA You are an emergency response operator
9522
- SCENARIO You are handling a 911 emergency call
9523
- SCENARIO The caller is panicked and speaking rapidly
9524
- SCENARIO Time is critical - every second counts
9525
- GOAL Gather essential information quickly and dispatch appropriate help
9526
- RULE Stay calm and speak clearly
9527
- \`\`\`
9528
-
9529
- \`\`\`book
9530
- Sales Representative
9531
-
9532
- PERSONA You are a software sales representative
9533
- SCENARIO You are in the final meeting of a 6-month sales cycle
9534
- SCENARIO The client has budget approval and decision-making authority
9535
- SCENARIO Two competitors have also submitted proposals
9536
- SCENARIO The client values long-term partnership over lowest price
9537
- GOAL Close the deal while building trust for future business
9538
- \`\`\`
9539
-
9540
- \`\`\`book
9541
- Medical Assistant
10500
+ - The content following \`USE MCP\` must be a valid URL
10501
+ - Multiple MCP servers can be connected by using multiple \`USE MCP\` commitments
10502
+ - The agent will have access to tools and resources provided by the MCP server
9542
10503
 
9543
- PERSONA You are a medical assistant in a busy clinic
9544
- SCENARIO The waiting room is full and the doctor is running behind schedule
9545
- SCENARIO Patients are becoming impatient and anxious
9546
- SCENARIO You need to manage expectations while maintaining professionalism
9547
- SCENARIO Some patients have been waiting over an hour
9548
- GOAL Keep patients informed and calm while supporting efficient clinic flow
9549
- RULE Never provide medical advice or diagnosis
9550
- \`\`\`
10504
+ ## Example
9551
10505
 
9552
10506
  \`\`\`book
9553
- Technical Support Agent
10507
+ Company Lawyer
9554
10508
 
9555
- PERSONA You are a technical support agent
9556
- SCENARIO The customer is a small business owner during their busy season
9557
- SCENARIO Their main business system has been down for 2 hours
9558
- SCENARIO They are losing money every minute the system is offline
9559
- SCENARIO This is their first experience with your company
9560
- GOAL Resolve the issue quickly while creating a positive first impression
10509
+ PERSONA You are a company lawyer.
10510
+ USE MCP http://legal-db.example.com
9561
10511
  \`\`\`
9562
10512
  `);
9563
10513
  }
9564
10514
  applyToAgentModelRequirements(requirements, content) {
9565
- const trimmedContent = content.trim();
9566
- if (!trimmedContent) {
10515
+ const mcpServerUrl = content.trim();
10516
+ if (!mcpServerUrl) {
9567
10517
  return requirements;
9568
10518
  }
9569
- // Create scenario section for system message
9570
- const scenarioSection = `Scenario: ${trimmedContent}`;
9571
- // Scenarios provide important contextual information that affects behavior
9572
- return this.appendToSystemMessage(requirements, scenarioSection, '\n\n');
10519
+ const existingMcpServers = requirements.mcpServers || [];
10520
+ // Avoid duplicates
10521
+ if (existingMcpServers.includes(mcpServerUrl)) {
10522
+ return requirements;
10523
+ }
10524
+ return {
10525
+ ...requirements,
10526
+ mcpServers: [...existingMcpServers, mcpServerUrl],
10527
+ };
9573
10528
  }
9574
10529
  }
9575
10530
  /**
@@ -9577,85 +10532,94 @@ class ScenarioCommitmentDefinition extends BaseCommitmentDefinition {
9577
10532
  */
9578
10533
 
9579
10534
  /**
9580
- * STYLE commitment definition
10535
+ * USE SEARCH ENGINE commitment definition
9581
10536
  *
9582
- * The STYLE commitment defines how the agent should format and present its responses.
9583
- * This includes tone, writing style, formatting preferences, and communication patterns.
10537
+ * The `USE SEARCH ENGINE` commitment indicates that the agent should utilize a search engine tool
10538
+ * to access and retrieve up-to-date information from the internet when necessary.
10539
+ *
10540
+ * The content following `USE SEARCH ENGINE` is ignored (similar to NOTE).
9584
10541
  *
9585
10542
  * Example usage in agent source:
9586
10543
  *
9587
10544
  * ```book
9588
- * STYLE Write in a professional but friendly tone, use bullet points for lists
9589
- * STYLE Always provide code examples when explaining programming concepts
10545
+ * USE SEARCH ENGINE
10546
+ * USE SEARCH ENGINE This will be ignored
9590
10547
  * ```
9591
10548
  *
9592
10549
  * @private [๐Ÿช”] Maybe export the commitments through some package
9593
10550
  */
9594
- class StyleCommitmentDefinition extends BaseCommitmentDefinition {
9595
- constructor(type = 'STYLE') {
9596
- super(type);
10551
+ class UseSearchEngineCommitmentDefinition extends BaseCommitmentDefinition {
10552
+ constructor() {
10553
+ super('USE SEARCH ENGINE', ['SEARCH ENGINE', 'SEARCH']);
9597
10554
  }
9598
10555
  /**
9599
- * Short one-line description of STYLE.
10556
+ * Short one-line description of USE SEARCH ENGINE.
9600
10557
  */
9601
10558
  get description() {
9602
- return 'Control the tone and writing style of responses.';
10559
+ return 'Enable the agent to use a search engine tool for accessing internet information.';
9603
10560
  }
9604
10561
  /**
9605
10562
  * Icon for this commitment.
9606
10563
  */
9607
10564
  get icon() {
9608
- return '๐Ÿ–‹๏ธ';
10565
+ return '๐Ÿ”';
9609
10566
  }
9610
10567
  /**
9611
- * Markdown documentation for STYLE commitment.
10568
+ * Markdown documentation for USE SEARCH ENGINE commitment.
9612
10569
  */
9613
10570
  get documentation() {
9614
- return spaceTrim$2(`
9615
- # ${this.type}
10571
+ return spaceTrim$1(`
10572
+ # USE SEARCH ENGINE
9616
10573
 
9617
- Defines how the agent should format and present its responses (tone, writing style, formatting).
10574
+ Enables the agent to use a search engine tool to access and retrieve up-to-date information from the internet.
9618
10575
 
9619
10576
  ## Key aspects
9620
10577
 
9621
- - Both terms work identically and can be used interchangeably.
9622
- - Later style instructions can override earlier ones.
9623
- - Style affects both tone and presentation format.
10578
+ - The content following \`USE SEARCH ENGINE\` is ignored (similar to NOTE)
10579
+ - The actual search engine tool usage is handled by the agent runtime
10580
+ - Allows the agent to search for current information from the web
10581
+ - Useful for research tasks, finding facts, and accessing dynamic content
9624
10582
 
9625
10583
  ## Examples
9626
10584
 
9627
10585
  \`\`\`book
9628
- Technical Writer
10586
+ Research Assistant
9629
10587
 
9630
- PERSONA You are a technical documentation expert
9631
- STYLE Write in a professional but friendly tone, use bullet points for lists
9632
- STYLE Always provide code examples when explaining programming concepts
9633
- FORMAT Use markdown formatting with clear headings
10588
+ PERSONA You are a helpful research assistant specialized in finding current information
10589
+ USE SEARCH ENGINE
10590
+ RULE Always cite your sources when providing information from the web
9634
10591
  \`\`\`
9635
10592
 
9636
10593
  \`\`\`book
9637
- Creative Assistant
10594
+ Fact Checker
9638
10595
 
9639
- PERSONA You are a creative writing helper
9640
- STYLE Be enthusiastic and encouraging in your responses
9641
- STYLE Use vivid metaphors and analogies to explain concepts
9642
- STYLE Keep responses conversational and engaging
9643
- RULE Always maintain a positive and supportive tone
10596
+ PERSONA You are a fact checker
10597
+ USE SEARCH ENGINE
10598
+ ACTION Search for claims and verify them against reliable sources
9644
10599
  \`\`\`
9645
10600
  `);
9646
10601
  }
9647
10602
  applyToAgentModelRequirements(requirements, content) {
9648
- const trimmedContent = content.trim();
9649
- if (!trimmedContent) {
9650
- return requirements;
9651
- }
9652
- // Add style instructions to the system message
9653
- const styleSection = `Style: ${trimmedContent}`;
9654
- return this.appendToSystemMessage(requirements, styleSection, '\n\n');
10603
+ // We simply mark that search engine capability is enabled in metadata
10604
+ // Get existing metadata
10605
+ const existingMetadata = requirements.metadata || {};
10606
+ // Get existing tools array or create new one
10607
+ const existingTools = existingMetadata.tools || [];
10608
+ // Add 'search-engine' to tools if not already present
10609
+ const updatedTools = existingTools.includes('search-engine') ? existingTools : [...existingTools, 'search-engine'];
10610
+ // Return requirements with updated metadata
10611
+ return {
10612
+ ...requirements,
10613
+ metadata: {
10614
+ ...existingMetadata,
10615
+ tools: updatedTools,
10616
+ useSearchEngine: true,
10617
+ },
10618
+ };
9655
10619
  }
9656
10620
  }
9657
10621
  /**
9658
- * [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
10622
+ * Note: [๐Ÿ’ž] Ignore a discrepancy between file name and entity name
9659
10623
  */
9660
10624
 
9661
10625
  /**
@@ -9686,7 +10650,7 @@ class NotYetImplementedCommitmentDefinition extends BaseCommitmentDefinition {
9686
10650
  * Markdown documentation available at runtime.
9687
10651
  */
9688
10652
  get documentation() {
9689
- return spaceTrim$2(`
10653
+ return spaceTrim$1(`
9690
10654
  # ${this.type}
9691
10655
 
9692
10656
  This commitment is not yet fully implemented.
@@ -9744,16 +10708,22 @@ const COMMITMENT_REGISTRY = [
9744
10708
  new StyleCommitmentDefinition('STYLES'),
9745
10709
  new RuleCommitmentDefinition('RULE'),
9746
10710
  new RuleCommitmentDefinition('RULES'),
10711
+ new LanguageCommitmentDefinition('LANGUAGE'),
10712
+ new LanguageCommitmentDefinition('LANGUAGES'),
9747
10713
  new SampleCommitmentDefinition('SAMPLE'),
9748
10714
  new SampleCommitmentDefinition('EXAMPLE'),
9749
10715
  new FormatCommitmentDefinition('FORMAT'),
9750
10716
  new FormatCommitmentDefinition('FORMATS'),
10717
+ new FromCommitmentDefinition('FROM'),
9751
10718
  new ModelCommitmentDefinition('MODEL'),
9752
10719
  new ModelCommitmentDefinition('MODELS'),
9753
10720
  new ActionCommitmentDefinition('ACTION'),
9754
10721
  new ActionCommitmentDefinition('ACTIONS'),
10722
+ new ComponentCommitmentDefinition(),
9755
10723
  new MetaImageCommitmentDefinition(),
9756
10724
  new MetaColorCommitmentDefinition(),
10725
+ new MetaFontCommitmentDefinition(),
10726
+ new MetaLinkCommitmentDefinition(),
9757
10727
  new MetaCommitmentDefinition(),
9758
10728
  new NoteCommitmentDefinition('NOTE'),
9759
10729
  new NoteCommitmentDefinition('NOTES'),
@@ -9772,6 +10742,12 @@ const COMMITMENT_REGISTRY = [
9772
10742
  new DeleteCommitmentDefinition('CANCEL'),
9773
10743
  new DeleteCommitmentDefinition('DISCARD'),
9774
10744
  new DeleteCommitmentDefinition('REMOVE'),
10745
+ new OpenCommitmentDefinition(),
10746
+ new ClosedCommitmentDefinition(),
10747
+ new UseBrowserCommitmentDefinition(),
10748
+ new UseSearchEngineCommitmentDefinition(),
10749
+ new UseMcpCommitmentDefinition(),
10750
+ new UseCommitmentDefinition(),
9775
10751
  // Not yet implemented commitments (using placeholder)
9776
10752
  new NotYetImplementedCommitmentDefinition('EXPECT'),
9777
10753
  new NotYetImplementedCommitmentDefinition('BEHAVIOUR'),
@@ -9896,6 +10872,11 @@ function createBasicAgentModelRequirements(agentName) {
9896
10872
  * TODO: [๐Ÿค] Deduplicate `AgentModelRequirements` and `ModelRequirements` model requirements
9897
10873
  */
9898
10874
 
10875
+ /**
10876
+ * Regex pattern to match horizontal lines (markdown thematic breaks)
10877
+ * Matches 3 or more hyphens, underscores, or asterisks (with optional spaces between)
10878
+ */
10879
+ const HORIZONTAL_LINE_PATTERN = /^[\s]*[-_*][\s]*[-_*][\s]*[-_*][\s]*[-_*]*[\s]*$/;
9899
10880
  /**
9900
10881
  * Parses agent source using the new commitment system with multiline support
9901
10882
  * This function replaces the hardcoded commitment parsing in the original parseAgentSource
@@ -9938,7 +10919,7 @@ function parseAgentSourceWithCommitments(agentSource) {
9938
10919
  const fullContent = currentCommitment.contentLines.join('\n');
9939
10920
  commitments.push({
9940
10921
  type: currentCommitment.type,
9941
- content: spaceTrim$2(fullContent),
10922
+ content: spaceTrim$1(fullContent),
9942
10923
  originalLine: currentCommitment.originalStartLine,
9943
10924
  lineNumber: currentCommitment.startLineNumber,
9944
10925
  });
@@ -9958,6 +10939,24 @@ function parseAgentSourceWithCommitments(agentSource) {
9958
10939
  break;
9959
10940
  }
9960
10941
  }
10942
+ // Check if this is a horizontal line (ends any current commitment)
10943
+ const isHorizontalLine = HORIZONTAL_LINE_PATTERN.test(line);
10944
+ if (isHorizontalLine) {
10945
+ // Save the current commitment if it exists
10946
+ if (currentCommitment) {
10947
+ const fullContent = currentCommitment.contentLines.join('\n');
10948
+ commitments.push({
10949
+ type: currentCommitment.type,
10950
+ content: spaceTrim$1(fullContent),
10951
+ originalLine: currentCommitment.originalStartLine,
10952
+ lineNumber: currentCommitment.startLineNumber,
10953
+ });
10954
+ currentCommitment = null;
10955
+ }
10956
+ // Add horizontal line to non-commitment lines
10957
+ nonCommitmentLines.push(line);
10958
+ continue;
10959
+ }
9961
10960
  if (!foundNewCommitment) {
9962
10961
  if (currentCommitment) {
9963
10962
  // This line belongs to the current commitment
@@ -9974,7 +10973,7 @@ function parseAgentSourceWithCommitments(agentSource) {
9974
10973
  const fullContent = currentCommitment.contentLines.join('\n');
9975
10974
  commitments.push({
9976
10975
  type: currentCommitment.type,
9977
- content: spaceTrim$2(fullContent),
10976
+ content: spaceTrim$1(fullContent),
9978
10977
  originalLine: currentCommitment.originalStartLine,
9979
10978
  lineNumber: currentCommitment.startLineNumber,
9980
10979
  });
@@ -10323,7 +11322,7 @@ function renderPromptbookMermaid(pipelineJson, options) {
10323
11322
  .filter(([MERMAID_NAME]) => (inputAndIntermediateParametersMermaid + outputParametersMermaid).includes(MERMAID_NAME))
10324
11323
  .map(([MERMAID_NAME, title]) => `${MERMAID_NAME}((${title})):::${MERMAID_NAME}`)
10325
11324
  .join('\n');
10326
- const promptbookMermaid = spaceTrim$2((block) => `
11325
+ const promptbookMermaid = spaceTrim$1((block) => `
10327
11326
 
10328
11327
  %% ๐Ÿ”ฎ Tip: Open this on GitHub or in the VSCode website to see the Mermaid graph visually
10329
11328
 
@@ -10380,7 +11379,7 @@ function renderPromptbookMermaid(pipelineJson, options) {
10380
11379
  */
10381
11380
  function prompt(strings, ...values) {
10382
11381
  if (values.length === 0) {
10383
- return spaceTrim$1(strings.join(''));
11382
+ return spaceTrim$2(strings.join(''));
10384
11383
  }
10385
11384
  const stringsWithHiddenParameters = strings.map((stringsItem) =>
10386
11385
  // TODO: [0] DRY
@@ -10391,7 +11390,7 @@ function prompt(strings, ...values) {
10391
11390
  let pipelineString = stringsWithHiddenParameters.reduce((result, stringsItem, i) => placeholderParameterNames[i] === undefined
10392
11391
  ? `${result}${stringsItem}`
10393
11392
  : `${result}${stringsItem}{${placeholderParameterNames[i]}}`, '');
10394
- pipelineString = spaceTrim$1(pipelineString);
11393
+ pipelineString = spaceTrim$2(pipelineString);
10395
11394
  try {
10396
11395
  pipelineString = templateParameters(pipelineString, parameters);
10397
11396
  }
@@ -10400,7 +11399,7 @@ function prompt(strings, ...values) {
10400
11399
  throw error;
10401
11400
  }
10402
11401
  console.error({ pipelineString, parameters, placeholderParameterNames, error });
10403
- throw new UnexpectedError(spaceTrim$1((block) => `
11402
+ throw new UnexpectedError(spaceTrim$2((block) => `
10404
11403
  Internal error in prompt template literal
10405
11404
 
10406
11405
  ${block(JSON.stringify({ strings, values }, null, 4))}}
@@ -10605,7 +11604,7 @@ function parseNumber(value) {
10605
11604
  * @public exported from `@promptbook/utils`
10606
11605
  */
10607
11606
  function normalizeMessageText(text) {
10608
- return spaceTrim$2(text);
11607
+ return spaceTrim$1(text);
10609
11608
  }
10610
11609
 
10611
11610
  /**
@@ -10632,17 +11631,6 @@ function removeQuotes(text) {
10632
11631
  return text;
10633
11632
  }
10634
11633
 
10635
- /**
10636
- * Trims string from all 4 sides
10637
- *
10638
- * Note: This is a re-exported function from the `spacetrim` package which is
10639
- * Developed by same author @hejny as this package
10640
- *
10641
- * @public exported from `@promptbook/utils`
10642
- * @see https://github.com/hejny/spacetrim#usage
10643
- */
10644
- const spaceTrim = spaceTrim$2;
10645
-
10646
11634
  /**
10647
11635
  * Checks if the given value is a valid JavaScript identifier name.
10648
11636
  *
@@ -10665,7 +11653,7 @@ function isValidJavascriptName(javascriptName) {
10665
11653
  * @public exported from `@promptbook/core`
10666
11654
  */
10667
11655
  function normalizeAgentName(rawAgentName) {
10668
- return titleToName(spaceTrim$1(rawAgentName));
11656
+ return titleToName(spaceTrim$2(rawAgentName));
10669
11657
  }
10670
11658
 
10671
11659
  /**
@@ -10717,15 +11705,21 @@ function parseAgentSource(agentSource) {
10717
11705
  const links = [];
10718
11706
  for (const commitment of parseResult.commitments) {
10719
11707
  if (commitment.type === 'META LINK') {
10720
- links.push(spaceTrim$1(commitment.content));
11708
+ const linkValue = spaceTrim$2(commitment.content);
11709
+ links.push(linkValue);
11710
+ meta.link = linkValue;
10721
11711
  continue;
10722
11712
  }
10723
11713
  if (commitment.type === 'META IMAGE') {
10724
- meta.image = spaceTrim$1(commitment.content);
11714
+ meta.image = spaceTrim$2(commitment.content);
10725
11715
  continue;
10726
11716
  }
10727
11717
  if (commitment.type === 'META COLOR') {
10728
- meta.color = spaceTrim$1(commitment.content);
11718
+ meta.color = spaceTrim$2(commitment.content);
11719
+ continue;
11720
+ }
11721
+ if (commitment.type === 'META FONT') {
11722
+ meta.font = spaceTrim$2(commitment.content);
10729
11723
  continue;
10730
11724
  }
10731
11725
  if (commitment.type !== 'META') {
@@ -10734,10 +11728,10 @@ function parseAgentSource(agentSource) {
10734
11728
  // Parse META commitments - format is "META TYPE content"
10735
11729
  const metaTypeRaw = commitment.content.split(' ')[0] || 'NONE';
10736
11730
  if (metaTypeRaw === 'LINK') {
10737
- links.push(spaceTrim$1(commitment.content.substring(metaTypeRaw.length)));
11731
+ links.push(spaceTrim$2(commitment.content.substring(metaTypeRaw.length)));
10738
11732
  }
10739
11733
  const metaType = normalizeTo_camelCase(metaTypeRaw);
10740
- meta[metaType] = spaceTrim$1(commitment.content.substring(metaTypeRaw.length));
11734
+ meta[metaType] = spaceTrim$2(commitment.content.substring(metaTypeRaw.length));
10741
11735
  }
10742
11736
  // Generate gravatar fallback if no meta image specified
10743
11737
  if (!meta.image) {
@@ -10922,7 +11916,7 @@ function validateBook(source) {
10922
11916
  * @deprecated Use `$generateBookBoilerplate` instead
10923
11917
  * @public exported from `@promptbook/core`
10924
11918
  */
10925
- const DEFAULT_BOOK = padBook(validateBook(spaceTrim$1(`
11919
+ const DEFAULT_BOOK = padBook(validateBook(spaceTrim$2(`
10926
11920
  AI Avatar
10927
11921
 
10928
11922
  PERSONA A friendly AI assistant that helps you with your tasks
@@ -11317,7 +12311,7 @@ function createPipelineSubcollection(collection, predicate) {
11317
12311
  }
11318
12312
  async function getPipelineByUrl(url) {
11319
12313
  if (!predicate(url)) {
11320
- throw new NotFoundError(await spaceTrim$2(async (block) => `
12314
+ throw new NotFoundError(await spaceTrim$1(async (block) => `
11321
12315
  Promptbook with url "${url}" not found or not accessible
11322
12316
 
11323
12317
  Available promptbooks:
@@ -11436,7 +12430,7 @@ const knowledgeCommandParser = {
11436
12430
  */
11437
12431
  parse(input) {
11438
12432
  const { args } = input;
11439
- const knowledgeSourceContent = spaceTrim$1(args[0] || '');
12433
+ const knowledgeSourceContent = spaceTrim$2(args[0] || '');
11440
12434
  if (knowledgeSourceContent === '') {
11441
12435
  throw new ParseError(`Source is not defined`);
11442
12436
  }
@@ -11580,7 +12574,7 @@ const sectionCommandParser = {
11580
12574
  normalized = normalized.split('DIALOGUE').join('DIALOG');
11581
12575
  const taskTypes = SectionTypes.filter((sectionType) => normalized.includes(sectionType.split('_TASK').join('')));
11582
12576
  if (taskTypes.length !== 1) {
11583
- throw new ParseError(spaceTrim$1((block) => `
12577
+ throw new ParseError(spaceTrim$2((block) => `
11584
12578
  Unknown section type "${normalized}"
11585
12579
 
11586
12580
  Supported section types are:
@@ -11600,7 +12594,7 @@ const sectionCommandParser = {
11600
12594
  */
11601
12595
  $applyToTaskJson(command, $taskJson, $pipelineJson) {
11602
12596
  if ($taskJson.isSectionTypeSet === true) {
11603
- throw new ParseError(spaceTrim$1(`
12597
+ throw new ParseError(spaceTrim$2(`
11604
12598
  Section type is already defined in the section.
11605
12599
  It can be defined only once.
11606
12600
  `));
@@ -11880,7 +12874,7 @@ const expectCommandParser = {
11880
12874
  /**
11881
12875
  * Description of the FORMAT command
11882
12876
  */
11883
- description: spaceTrim$1(`
12877
+ description: spaceTrim$2(`
11884
12878
  Expect command describes the desired output of the task *(after post-processing)*
11885
12879
  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.
11886
12880
  `),
@@ -11954,7 +12948,7 @@ const expectCommandParser = {
11954
12948
  }
11955
12949
  catch (error) {
11956
12950
  assertsError(error);
11957
- throw new ParseError(spaceTrim$1((block) => `
12951
+ throw new ParseError(spaceTrim$2((block) => `
11958
12952
  Invalid FORMAT command
11959
12953
  ${block(error.message)}:
11960
12954
  `));
@@ -12066,7 +13060,7 @@ function validateParameterName(parameterName) {
12066
13060
  if (!(error instanceof ParseError)) {
12067
13061
  throw error;
12068
13062
  }
12069
- throw new ParseError(spaceTrim$1((block) => `
13063
+ throw new ParseError(spaceTrim$2((block) => `
12070
13064
  ${block(error.message)}
12071
13065
 
12072
13066
  Tried to validate parameter name:
@@ -12125,7 +13119,7 @@ const foreachCommandParser = {
12125
13119
  const assignSign = args[3];
12126
13120
  const formatDefinition = FORMAT_DEFINITIONS.find((formatDefinition) => [formatDefinition.formatName, ...(formatDefinition.aliases || [])].includes(formatName));
12127
13121
  if (formatDefinition === undefined) {
12128
- throw new ParseError(spaceTrim$1((block) => `
13122
+ throw new ParseError(spaceTrim$2((block) => `
12129
13123
  Unsupported format "${formatName}"
12130
13124
 
12131
13125
  Available formats:
@@ -12137,7 +13131,7 @@ const foreachCommandParser = {
12137
13131
  }
12138
13132
  const subvalueParser = formatDefinition.subvalueParsers.find((subvalueParser) => [subvalueParser.subvalueName, ...(subvalueParser.aliases || [])].includes(subformatName));
12139
13133
  if (subvalueParser === undefined) {
12140
- throw new ParseError(spaceTrim$1((block) => `
13134
+ throw new ParseError(spaceTrim$2((block) => `
12141
13135
  Unsupported subformat name "${subformatName}" for format "${formatName}"
12142
13136
 
12143
13137
  Available subformat names for format "${formatDefinition.formatName}":
@@ -12185,7 +13179,7 @@ const foreachCommandParser = {
12185
13179
  outputSubparameterName = 'newLine';
12186
13180
  }
12187
13181
  else {
12188
- throw new ParseError(spaceTrim$1(`
13182
+ throw new ParseError(spaceTrim$2(`
12189
13183
  FOREACH ${formatName} ${subformatName} must specify output subparameter
12190
13184
 
12191
13185
  Correct example:
@@ -12261,7 +13255,7 @@ const formatCommandParser = {
12261
13255
  /**
12262
13256
  * Description of the FORMAT command
12263
13257
  */
12264
- description: spaceTrim$1(`
13258
+ description: spaceTrim$2(`
12265
13259
  Format command describes the desired output of the task (after post-processing)
12266
13260
  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.
12267
13261
  `),
@@ -12633,7 +13627,7 @@ const formfactorCommandParser = {
12633
13627
  const formfactorNameCandidate = args[0].toUpperCase();
12634
13628
  const formfactor = FORMFACTOR_DEFINITIONS.find((definition) => [definition.name, ...{ aliasNames: [], ...definition }.aliasNames].includes(formfactorNameCandidate));
12635
13629
  if (formfactor === undefined) {
12636
- throw new ParseError(spaceTrim$1((block) => `
13630
+ throw new ParseError(spaceTrim$2((block) => `
12637
13631
  Unknown formfactor name "${formfactorNameCandidate}"
12638
13632
 
12639
13633
  Available formfactors:
@@ -12652,7 +13646,7 @@ const formfactorCommandParser = {
12652
13646
  */
12653
13647
  $applyToPipelineJson(command, $pipelineJson) {
12654
13648
  if ($pipelineJson.formfactorName !== undefined && $pipelineJson.formfactorName !== command.formfactorName) {
12655
- throw new ParseError(spaceTrim$1(`
13649
+ throw new ParseError(spaceTrim$2(`
12656
13650
  Redefinition of \`FORMFACTOR\` in the pipeline head
12657
13651
 
12658
13652
  You have used:
@@ -12795,7 +13789,7 @@ const modelCommandParser = {
12795
13789
  */
12796
13790
  parse(input) {
12797
13791
  const { args, normalized } = input;
12798
- const availableVariantsMessage = spaceTrim$1((block) => `
13792
+ const availableVariantsMessage = spaceTrim$2((block) => `
12799
13793
  Available variants are:
12800
13794
  ${block(MODEL_VARIANTS.map((variantName) => `- ${variantName}${variantName !== 'EMBEDDING' ? '' : ' (Not available in pipeline)'}`).join('\n'))}
12801
13795
  `);
@@ -12817,14 +13811,14 @@ const modelCommandParser = {
12817
13811
  // <- Note: [๐Ÿค–]
12818
13812
  }
12819
13813
  else if (normalized.startsWith('MODEL_VARIANT_EMBED')) {
12820
- spaceTrim$1((block) => `
13814
+ spaceTrim$2((block) => `
12821
13815
  Embedding model can not be used in pipeline
12822
13816
 
12823
13817
  ${block(availableVariantsMessage)}
12824
13818
  `);
12825
13819
  }
12826
13820
  else {
12827
- throw new ParseError(spaceTrim$1((block) => `
13821
+ throw new ParseError(spaceTrim$2((block) => `
12828
13822
  Unknown model variant in command:
12829
13823
 
12830
13824
  ${block(availableVariantsMessage)}
@@ -12839,7 +13833,7 @@ const modelCommandParser = {
12839
13833
  };
12840
13834
  }
12841
13835
  else {
12842
- throw new ParseError(spaceTrim$1((block) => `
13836
+ throw new ParseError(spaceTrim$2((block) => `
12843
13837
  Unknown model key in command.
12844
13838
 
12845
13839
  Supported model keys are:
@@ -12866,7 +13860,7 @@ const modelCommandParser = {
12866
13860
  // <- TODO: [๐Ÿฎ] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
12867
13861
  }
12868
13862
  else {
12869
- throw new ParseError(spaceTrim$1(`
13863
+ throw new ParseError(spaceTrim$2(`
12870
13864
  Redefinition of \`MODEL ${command.key}\` in the pipeline head
12871
13865
 
12872
13866
  You have used:
@@ -12898,7 +13892,7 @@ const modelCommandParser = {
12898
13892
  // <- TODO: [๐Ÿฎ] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
12899
13893
  }
12900
13894
  else {
12901
- throw new ParseError(spaceTrim$1(`
13895
+ throw new ParseError(spaceTrim$2(`
12902
13896
  Redefinition of MODEL \`${command.key}\` in the task "${$taskJson.title || $taskJson.name}"
12903
13897
 
12904
13898
  You have used:
@@ -12908,7 +13902,7 @@ const modelCommandParser = {
12908
13902
  }
12909
13903
  }
12910
13904
  if (command.value === ($pipelineJson.defaultModelRequirements || {})[command.key]) {
12911
- console.log(spaceTrim$1(`
13905
+ console.log(spaceTrim$2(`
12912
13906
  Setting MODEL \`${command.key}\` in the task "${$taskJson.title || $taskJson.name}" to the same value as in the pipeline head
12913
13907
 
12914
13908
  In pipeline head:
@@ -12991,7 +13985,7 @@ const parameterCommandParser = {
12991
13985
  // <- TODO: When [๐Ÿฅถ] fixed, change to:
12992
13986
  // > const parameterDescriptionRaw = rawArgs.split(parameterNameRaw).join('').trim();
12993
13987
  if (parameterDescriptionRaw && parameterDescriptionRaw.match(/\{(?<embeddedParameterName>[a-z0-9_]+)\}/im)) {
12994
- throw new ParseError(spaceTrim$1((block) => `
13988
+ throw new ParseError(spaceTrim$2((block) => `
12995
13989
  Parameter \`{${parameterNameRaw}}\` can not contain another parameter in description
12996
13990
 
12997
13991
  The description:
@@ -13173,7 +14167,7 @@ function $applyToTaskJson(command, $taskJson, $pipelineJson) {
13173
14167
  persona.description = personaDescription;
13174
14168
  return;
13175
14169
  }
13176
- console.warn(spaceTrim$1(`
14170
+ console.warn(spaceTrim$2(`
13177
14171
 
13178
14172
  Persona "${personaName}" is defined multiple times with different description:
13179
14173
 
@@ -13184,7 +14178,7 @@ function $applyToTaskJson(command, $taskJson, $pipelineJson) {
13184
14178
  ${personaDescription}
13185
14179
 
13186
14180
  `));
13187
- persona.description += spaceTrim$1('\n\n' + personaDescription);
14181
+ persona.description += spaceTrim$2('\n\n' + personaDescription);
13188
14182
  }
13189
14183
 
13190
14184
  /**
@@ -13535,7 +14529,7 @@ const COMMANDS = [
13535
14529
  function getParserForCommand(command) {
13536
14530
  const commandParser = COMMANDS.find((commandParser) => commandParser.name === command.type);
13537
14531
  if (commandParser === undefined) {
13538
- throw new UnexpectedError(spaceTrim$2((block) => `
14532
+ throw new UnexpectedError(spaceTrim$1((block) => `
13539
14533
  Command ${command.type} parser is not found
13540
14534
 
13541
14535
  ${block(JSON.stringify(command, null, 4)
@@ -13611,7 +14605,7 @@ function parseCommand(raw, usagePlace) {
13611
14605
  .map(removeMarkdownFormatting)
13612
14606
  .map((item) => item.trim());
13613
14607
  if (items.length === 0 || items[0] === '') {
13614
- throw new ParseError(spaceTrim$2((block) => `
14608
+ throw new ParseError(spaceTrim$1((block) => `
13615
14609
  Malformed command:
13616
14610
  - ${raw}
13617
14611
 
@@ -13647,7 +14641,7 @@ function parseCommand(raw, usagePlace) {
13647
14641
  return command;
13648
14642
  }
13649
14643
  }
13650
- throw new ParseError(spaceTrim$2((block) => `
14644
+ throw new ParseError(spaceTrim$1((block) => `
13651
14645
  Malformed or unknown command:
13652
14646
  - ${raw}
13653
14647
 
@@ -13698,7 +14692,7 @@ function parseCommandVariant(input) {
13698
14692
  if (!(error instanceof ParseError)) {
13699
14693
  throw error;
13700
14694
  }
13701
- throw new ParseError(spaceTrim$2((block) => `
14695
+ throw new ParseError(spaceTrim$1((block) => `
13702
14696
  Invalid ${commandName} command:
13703
14697
 
13704
14698
  Your command:
@@ -13972,7 +14966,7 @@ const SUPPORTED_SCRIPT_LANGUAGES = ['javascript', 'typescript', 'python'];
13972
14966
  * @public exported from `@promptbook/markdown-utils`
13973
14967
  */
13974
14968
  function removeMarkdownComments(content) {
13975
- return spaceTrim$2(content.replace(/<!--(.*?)-->/gs, ''));
14969
+ return spaceTrim$1(content.replace(/<!--(.*?)-->/gs, ''));
13976
14970
  }
13977
14971
 
13978
14972
  /**
@@ -13983,7 +14977,7 @@ function removeMarkdownComments(content) {
13983
14977
  */
13984
14978
  function isFlatPipeline(pipelineString) {
13985
14979
  pipelineString = removeMarkdownComments(pipelineString);
13986
- pipelineString = spaceTrim$1(pipelineString);
14980
+ pipelineString = spaceTrim$2(pipelineString);
13987
14981
  const isMarkdownBeginningWithHeadline = pipelineString.startsWith('# ');
13988
14982
  //const isLastLineReturnStatement = pipelineString.split('\n').pop()!.split('`').join('').startsWith('->');
13989
14983
  const isBacktickBlockUsed = pipelineString.includes('```');
@@ -14009,7 +15003,7 @@ function deflatePipeline(pipelineString) {
14009
15003
  if (!isFlatPipeline(pipelineString)) {
14010
15004
  return pipelineString;
14011
15005
  }
14012
- pipelineString = spaceTrim$1(pipelineString);
15006
+ pipelineString = spaceTrim$2(pipelineString);
14013
15007
  const pipelineStringLines = pipelineString.split('\n');
14014
15008
  const potentialReturnStatement = pipelineStringLines.pop();
14015
15009
  let returnStatement;
@@ -14022,19 +15016,19 @@ function deflatePipeline(pipelineString) {
14022
15016
  returnStatement = `-> {${DEFAULT_BOOK_OUTPUT_PARAMETER_NAME}}`;
14023
15017
  pipelineStringLines.push(potentialReturnStatement);
14024
15018
  }
14025
- const prompt = spaceTrim$1(pipelineStringLines.join('\n'));
15019
+ const prompt = spaceTrim$2(pipelineStringLines.join('\n'));
14026
15020
  let quotedPrompt;
14027
15021
  if (prompt.split('\n').length <= 1) {
14028
15022
  quotedPrompt = `> ${prompt}`;
14029
15023
  }
14030
15024
  else {
14031
- quotedPrompt = spaceTrim$1((block) => `
15025
+ quotedPrompt = spaceTrim$2((block) => `
14032
15026
  \`\`\`
14033
15027
  ${block(prompt.split('`').join('\\`'))}
14034
15028
  \`\`\`
14035
15029
  `);
14036
15030
  }
14037
- pipelineString = validatePipelineString(spaceTrim$1((block) => `
15031
+ pipelineString = validatePipelineString(spaceTrim$2((block) => `
14038
15032
  # ${DEFAULT_BOOK_TITLE}
14039
15033
 
14040
15034
  ## Prompt
@@ -14098,7 +15092,7 @@ function extractAllListItemsFromMarkdown(markdown) {
14098
15092
  function extractOneBlockFromMarkdown(markdown) {
14099
15093
  const codeBlocks = extractAllBlocksFromMarkdown(markdown);
14100
15094
  if (codeBlocks.length !== 1) {
14101
- throw new ParseError(spaceTrim$1((block) => `
15095
+ throw new ParseError(spaceTrim$2((block) => `
14102
15096
  There should be exactly 1 code block in task section, found ${codeBlocks.length} code blocks
14103
15097
 
14104
15098
  ${block(codeBlocks.map((block, i) => `Block ${i + 1}:\n${block.content}`).join('\n\n\n'))}
@@ -14123,7 +15117,7 @@ function parseMarkdownSection(value) {
14123
15117
  }
14124
15118
  const title = lines[0].replace(/^#+\s*/, '');
14125
15119
  const level = (_b = (_a = lines[0].match(/^#+/)) === null || _a === void 0 ? void 0 : _a[0].length) !== null && _b !== void 0 ? _b : 0;
14126
- const content = spaceTrim$1(lines.slice(1).join('\n'));
15120
+ const content = spaceTrim$2(lines.slice(1).join('\n'));
14127
15121
  if (level < 1 || level > 6) {
14128
15122
  throw new ParseError('Markdown section must have heading level between 1 and 6');
14129
15123
  }
@@ -14151,7 +15145,7 @@ function splitMarkdownIntoSections(markdown) {
14151
15145
  if (buffer.length === 0) {
14152
15146
  return;
14153
15147
  }
14154
- let section = spaceTrim$1(buffer.join('\n'));
15148
+ let section = spaceTrim$2(buffer.join('\n'));
14155
15149
  if (section === '') {
14156
15150
  return;
14157
15151
  }
@@ -14226,7 +15220,7 @@ function flattenMarkdown(markdown) {
14226
15220
  flattenedMarkdown += `## ${title}` + `\n\n`;
14227
15221
  flattenedMarkdown += content + `\n\n`; // <- [๐Ÿง ] Maybe 3 new lines?
14228
15222
  }
14229
- return spaceTrim$1(flattenedMarkdown);
15223
+ return spaceTrim$2(flattenedMarkdown);
14230
15224
  }
14231
15225
  /**
14232
15226
  * TODO: [๐Ÿ›] This can be part of markdown builder
@@ -14288,7 +15282,7 @@ function parsePipeline(pipelineString) {
14288
15282
  if (pipelineString.startsWith('#!')) {
14289
15283
  const [shebangLine, ...restLines] = pipelineString.split('\n');
14290
15284
  if (!(shebangLine || '').includes('ptbk')) {
14291
- throw new ParseError(spaceTrim$2((block) => `
15285
+ throw new ParseError(spaceTrim$1((block) => `
14292
15286
  It seems that you try to parse a book file which has non-standard shebang line for book files:
14293
15287
  Shebang line must contain 'ptbk'
14294
15288
 
@@ -14304,7 +15298,7 @@ function parsePipeline(pipelineString) {
14304
15298
  pipelineString = validatePipelineString(restLines.join('\n'));
14305
15299
  }
14306
15300
  pipelineString = removeMarkdownComments(pipelineString);
14307
- pipelineString = spaceTrim$2(pipelineString);
15301
+ pipelineString = spaceTrim$1(pipelineString);
14308
15302
  // <- TODO: [๐Ÿ˜ง] `spaceTrim` should preserve discriminated type *(or at lease `PipelineString`)*
14309
15303
  pipelineString = deflatePipeline(pipelineString);
14310
15304
  // ==============
@@ -14316,7 +15310,7 @@ function parsePipeline(pipelineString) {
14316
15310
  // ==============
14317
15311
  // Note: 1๏ธโƒฃโ—ฝ4๏ธโƒฃ Check markdown structure
14318
15312
  if (pipelineHead === undefined) {
14319
- throw new UnexpectedError(spaceTrim$2((block) => `
15313
+ throw new UnexpectedError(spaceTrim$1((block) => `
14320
15314
  Pipeline head is not defined
14321
15315
 
14322
15316
  ${block(getPipelineIdentification())}
@@ -14325,7 +15319,7 @@ function parsePipeline(pipelineString) {
14325
15319
  `));
14326
15320
  }
14327
15321
  if (pipelineHead.level !== 1) {
14328
- throw new UnexpectedError(spaceTrim$2((block) => `
15322
+ throw new UnexpectedError(spaceTrim$1((block) => `
14329
15323
  Pipeline head is not h1
14330
15324
 
14331
15325
  ${block(getPipelineIdentification())}
@@ -14334,7 +15328,7 @@ function parsePipeline(pipelineString) {
14334
15328
  `));
14335
15329
  }
14336
15330
  if (!pipelineSections.every((section) => section.level === 2)) {
14337
- throw new UnexpectedError(spaceTrim$2((block) => `
15331
+ throw new UnexpectedError(spaceTrim$1((block) => `
14338
15332
  Not every pipeline section is h2
14339
15333
 
14340
15334
  ${block(getPipelineIdentification())}
@@ -14347,7 +15341,7 @@ function parsePipeline(pipelineString) {
14347
15341
  const defineParam = (parameterCommand) => {
14348
15342
  const { parameterName, parameterDescription, isInput, isOutput } = parameterCommand;
14349
15343
  if (RESERVED_PARAMETER_NAMES.includes(parameterName)) {
14350
- throw new ParseError(spaceTrim$2((block) => `
15344
+ throw new ParseError(spaceTrim$1((block) => `
14351
15345
  Parameter name {${parameterName}} is reserved and cannot be used as resulting parameter name
14352
15346
 
14353
15347
  ${block(getPipelineIdentification())}
@@ -14358,7 +15352,7 @@ function parsePipeline(pipelineString) {
14358
15352
  existingParameter.description &&
14359
15353
  existingParameter.description !== parameterDescription &&
14360
15354
  parameterDescription) {
14361
- throw new ParseError(spaceTrim$2((block) => `
15355
+ throw new ParseError(spaceTrim$1((block) => `
14362
15356
  Parameter \`{${parameterName}}\` is defined multiple times with different description:
14363
15357
 
14364
15358
  ${block(getPipelineIdentification())}
@@ -14396,7 +15390,7 @@ function parsePipeline(pipelineString) {
14396
15390
  description = description.split(/^>.*$/gm).join('');
14397
15391
  //Note: Remove lists and return statement - TODO: [๐ŸŽพ] Make util (exported from `@promptbool/utils`)
14398
15392
  description = description.split(/^(?:(?:-)|(?:\d\))|(?:`?->))\s+.*$/gm).join('');
14399
- description = spaceTrim$2(description);
15393
+ description = spaceTrim$1(description);
14400
15394
  if (description === '') {
14401
15395
  description = undefined;
14402
15396
  }
@@ -14407,7 +15401,7 @@ function parsePipeline(pipelineString) {
14407
15401
  const command = parseCommand(listItem, 'PIPELINE_HEAD');
14408
15402
  const commandParser = getParserForCommand(command);
14409
15403
  if (commandParser.isUsedInPipelineHead !== true /* <- Note: [๐Ÿฆฆ][4] */) {
14410
- throw new ParseError(spaceTrim$2((block) => `
15404
+ throw new ParseError(spaceTrim$1((block) => `
14411
15405
  Command \`${command.type}\` is not allowed in the head of the pipeline ONLY at the pipeline task
14412
15406
 
14413
15407
  ${block(getPipelineIdentification())}
@@ -14421,7 +15415,7 @@ function parsePipeline(pipelineString) {
14421
15415
  if (!(error instanceof ParseError)) {
14422
15416
  throw error;
14423
15417
  }
14424
- throw new ParseError(spaceTrim$2((block) => `
15418
+ throw new ParseError(spaceTrim$1((block) => `
14425
15419
  Command ${command.type} failed to apply to the pipeline
14426
15420
 
14427
15421
  The error:
@@ -14474,7 +15468,7 @@ function parsePipeline(pipelineString) {
14474
15468
  description = description.split(/^>.*$/gm).join('');
14475
15469
  //Note: Remove lists and return statement - TODO: [๐ŸŽพ]
14476
15470
  description = description.split(/^(?:(?:-)|(?:\d\))|(?:`?->))\s+.*$/gm).join('');
14477
- description = spaceTrim$2(description);
15471
+ description = spaceTrim$1(description);
14478
15472
  if (description === '') {
14479
15473
  description = undefined;
14480
15474
  }
@@ -14508,7 +15502,7 @@ function parsePipeline(pipelineString) {
14508
15502
  for (const { listItem, command } of commands) {
14509
15503
  const commandParser = getParserForCommand(command);
14510
15504
  if (commandParser.isUsedInPipelineTask !== true /* <- Note: [๐Ÿฆฆ][4] */) {
14511
- throw new ParseError(spaceTrim$2((block) => `
15505
+ throw new ParseError(spaceTrim$1((block) => `
14512
15506
  Command \`${command.type}\` is not allowed in the task of the promptbook ONLY at the pipeline head
14513
15507
 
14514
15508
  ${block(getPipelineIdentification())}
@@ -14523,7 +15517,7 @@ function parsePipeline(pipelineString) {
14523
15517
  if (!(error instanceof ParseError)) {
14524
15518
  throw error;
14525
15519
  }
14526
- throw new ParseError(spaceTrim$2((block) => `
15520
+ throw new ParseError(spaceTrim$1((block) => `
14527
15521
  Command \`${command.type}\` failed to apply to the task
14528
15522
 
14529
15523
  The error:
@@ -14554,14 +15548,14 @@ function parsePipeline(pipelineString) {
14554
15548
  // TODO: [๐Ÿง] Should be done in SECTION command
14555
15549
  if ($taskJson.taskType === 'SCRIPT_TASK') {
14556
15550
  if (!language) {
14557
- throw new ParseError(spaceTrim$2((block) => `
15551
+ throw new ParseError(spaceTrim$1((block) => `
14558
15552
  You must specify the language of the script in the \`SCRIPT\` task
14559
15553
 
14560
15554
  ${block(getPipelineIdentification())}
14561
15555
  `));
14562
15556
  }
14563
15557
  if (!SUPPORTED_SCRIPT_LANGUAGES.includes(language)) {
14564
- throw new ParseError(spaceTrim$2((block) => `
15558
+ throw new ParseError(spaceTrim$1((block) => `
14565
15559
  Script language ${language} is not supported.
14566
15560
 
14567
15561
  Supported languages are:
@@ -14723,7 +15717,7 @@ function addAutoGeneratedSection(content, options) {
14723
15717
  const warningLine = `<!-- ${GENERATOR_WARNING} -->`;
14724
15718
  const sectionRegex = new RegExp(`<!--${sectionName}-->([\\s\\S]*?)<!--/${sectionName}-->`, 'g');
14725
15719
  const sectionMatch = content.match(sectionRegex);
14726
- const contentToInsert = spaceTrim$2((block) => `
15720
+ const contentToInsert = spaceTrim$1((block) => `
14727
15721
  <!--${sectionName}-->
14728
15722
  ${block(warningLine)}
14729
15723
  ${block(sectionContent)}
@@ -14736,7 +15730,7 @@ function addAutoGeneratedSection(content, options) {
14736
15730
  const placeForSection = removeMarkdownComments(content).match(/^##.*$/im);
14737
15731
  if (placeForSection !== null) {
14738
15732
  const [heading] = placeForSection;
14739
- return content.replace(heading, spaceTrim$2((block) => `
15733
+ return content.replace(heading, spaceTrim$1((block) => `
14740
15734
  ${block(contentToInsert)}
14741
15735
 
14742
15736
  ${block(heading)}
@@ -14745,7 +15739,7 @@ function addAutoGeneratedSection(content, options) {
14745
15739
  console.warn(`No place where to put the section <!--${sectionName}-->, using the end of the file`);
14746
15740
  // <- TODO: [๐Ÿฎ] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
14747
15741
  // <- TODO: [๐Ÿฎ] Some better way how to get warnings from pipeline parsing / logic
14748
- return spaceTrim$2((block) => `
15742
+ return spaceTrim$1((block) => `
14749
15743
  ${block(content)}
14750
15744
 
14751
15745
  ${block(contentToInsert)}
@@ -14769,7 +15763,7 @@ async function prettifyPipelineString(pipelineString, options) {
14769
15763
  return { href: `#${task.name}`, title: task.title };
14770
15764
  },
14771
15765
  });
14772
- const promptbookMermaidBlock = spaceTrim$2((block) => `
15766
+ const promptbookMermaidBlock = spaceTrim$1((block) => `
14773
15767
  \`\`\`mermaid
14774
15768
  ${block(promptbookMermaid)}
14775
15769
  \`\`\`
@@ -14807,7 +15801,7 @@ class CallbackInterfaceTools {
14807
15801
  async promptDialog(options) {
14808
15802
  const answer = await this.options.callback(options);
14809
15803
  if (this.options.isVerbose) {
14810
- console.info(spaceTrim$2((block) => `
15804
+ console.info(spaceTrim$1((block) => `
14811
15805
  ๐Ÿ“– ${block(options.promptTitle)}
14812
15806
  ๐Ÿ‘ค ${block(answer)}
14813
15807
  `));
@@ -14948,7 +15942,7 @@ function countWorkingDuration(items) {
14948
15942
  function executionReportJsonToString(executionReportJson, options) {
14949
15943
  var _a, _b, _c, _d, _e, _f;
14950
15944
  const { taxRate, chartsWidth } = { ...ExecutionReportStringOptionsDefaults, ...(options || {}) };
14951
- let executionReportString = spaceTrim$2((block) => `
15945
+ let executionReportString = spaceTrim$1((block) => `
14952
15946
  # ${executionReportJson.title || 'Execution report'}
14953
15947
 
14954
15948
  ${block(executionReportJson.description || '')}
@@ -15070,7 +16064,7 @@ function executionReportJsonToString(executionReportJson, options) {
15070
16064
  if (just(true)) {
15071
16065
  executionReportString +=
15072
16066
  '\n\n\n\n' +
15073
- spaceTrim$2((block) => {
16067
+ spaceTrim$1((block) => {
15074
16068
  var _a;
15075
16069
  return `
15076
16070
 
@@ -15089,7 +16083,7 @@ function executionReportJsonToString(executionReportJson, options) {
15089
16083
  executionReportString += '*No result*';
15090
16084
  }
15091
16085
  else if (typeof promptExecution.result.content === 'string') {
15092
- executionReportString += spaceTrim$2((block) => `
16086
+ executionReportString += spaceTrim$1((block) => `
15093
16087
  \`\`\`
15094
16088
  ${block(escapeMarkdownBlock(promptExecution.result.content))}
15095
16089
  \`\`\`
@@ -15102,7 +16096,7 @@ function executionReportJsonToString(executionReportJson, options) {
15102
16096
  if (promptExecution.error && promptExecution.error.message) {
15103
16097
  executionReportString +=
15104
16098
  '\n\n\n\n' +
15105
- spaceTrim$2((block) => `
16099
+ spaceTrim$1((block) => `
15106
16100
 
15107
16101
  ### Error
15108
16102
 
@@ -15178,7 +16172,7 @@ function usageToHuman(usage) {
15178
16172
  // Note: For negligible usage, we report at least something
15179
16173
  reportItems.push('Negligible');
15180
16174
  }
15181
- return spaceTrim$1((block) => `
16175
+ return spaceTrim$2((block) => `
15182
16176
  Usage:
15183
16177
  ${block(reportItems.map((item) => `- ${item}`).join('\n'))}
15184
16178
  `);
@@ -15362,13 +16356,13 @@ function $registeredLlmToolsMessage() {
15362
16356
  });
15363
16357
  const usedEnvMessage = `Unknown \`.env\` file` ;
15364
16358
  if (metadata.length === 0) {
15365
- return spaceTrim$1((block) => `
16359
+ return spaceTrim$2((block) => `
15366
16360
  No LLM providers are available.
15367
16361
 
15368
16362
  ${block(usedEnvMessage)}
15369
16363
  `);
15370
16364
  }
15371
- return spaceTrim$1((block) => `
16365
+ return spaceTrim$2((block) => `
15372
16366
 
15373
16367
  ${block(usedEnvMessage)}
15374
16368
 
@@ -15414,7 +16408,7 @@ function $registeredLlmToolsMessage() {
15414
16408
  morePieces.push(`Not configured`); // <- Note: Can not be configured via environment variables
15415
16409
  }
15416
16410
  }
15417
- let providerMessage = spaceTrim$1(`
16411
+ let providerMessage = spaceTrim$2(`
15418
16412
  ${i + 1}) **${title}** \`${className}\` from \`${packageName}\`
15419
16413
  ${morePieces.join('; ')}
15420
16414
  `);
@@ -15460,7 +16454,7 @@ function createLlmToolsFromConfiguration(configuration, options = {}) {
15460
16454
  .find(({ packageName, className }) => llmConfiguration.packageName === packageName && llmConfiguration.className === className);
15461
16455
  if (registeredItem === undefined) {
15462
16456
  // console.log('$llmToolsRegister.list()', $llmToolsRegister.list());
15463
- throw new Error(spaceTrim$1((block) => `
16457
+ throw new Error(spaceTrim$2((block) => `
15464
16458
  There is no constructor for LLM provider \`${llmConfiguration.className}\` from \`${llmConfiguration.packageName}\`
15465
16459
  Running in ${!$isRunningInBrowser() ? '' : 'browser environment'}${!$isRunningInNode() ? '' : 'node environment'}${!$isRunningInWebWorker() ? '' : 'worker environment'}
15466
16460
 
@@ -15585,7 +16579,7 @@ function cacheLlmTools(llmTools, options = {}) {
15585
16579
  let normalizedContent = content;
15586
16580
  normalizedContent = normalizedContent.replace(/\s+/g, ' ');
15587
16581
  normalizedContent = normalizedContent.split('\r\n').join('\n');
15588
- normalizedContent = spaceTrim$1(normalizedContent);
16582
+ normalizedContent = spaceTrim$2(normalizedContent);
15589
16583
  // Note: Do not need to save everything in the cache, just the relevant parameters
15590
16584
  const relevantParameterNames = extractParameterNames(content);
15591
16585
  const relevantParameters = Object.fromEntries(Object.entries(parameters).filter(([key]) => relevantParameterNames.has(key)));
@@ -17202,7 +18196,7 @@ class OpenAiCompatibleExecutionTools {
17202
18196
  // Note: Match exact or prefix for model families
17203
18197
  const model = this.HARDCODED_MODELS.find(({ modelName }) => modelName === defaultModelName || modelName.startsWith(defaultModelName));
17204
18198
  if (model === undefined) {
17205
- throw new PipelineExecutionError(spaceTrim$1((block) => `
18199
+ throw new PipelineExecutionError(spaceTrim$2((block) => `
17206
18200
  Cannot find model in ${this.title} models with name "${defaultModelName}" which should be used as default.
17207
18201
 
17208
18202
  Available models:
@@ -17457,18 +18451,26 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
17457
18451
  modelName: 'assistant',
17458
18452
  // <- [๐Ÿง ] What is the best value here
17459
18453
  });
18454
+ // Build thread messages: include previous thread messages + current user message
18455
+ const threadMessages = [];
18456
+ // TODO: [๐Ÿˆน] Maybe this should not be here but in other place, look at commit 39d705e75e5bcf7a818c3af36bc13e1c8475c30c
18457
+ // Add previous messages from thread (if any)
18458
+ if ('thread' in prompt &&
18459
+ Array.isArray(prompt.thread)) {
18460
+ const previousMessages = prompt.thread.map((msg) => ({
18461
+ role: (msg.role === 'assistant' ? 'assistant' : 'user'),
18462
+ content: msg.content,
18463
+ }));
18464
+ threadMessages.push(...previousMessages);
18465
+ }
18466
+ // Always add the current user message
18467
+ threadMessages.push({ role: 'user', content: rawPromptContent });
17460
18468
  const rawRequest = {
17461
18469
  // TODO: [๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง] ...modelSettings,
17462
18470
  // TODO: [๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง][๐Ÿง ] What about system message for assistants, does it make sense - combination of OpenAI assistants with Promptbook Personas
17463
18471
  assistant_id: this.assistantId,
17464
18472
  thread: {
17465
- messages: 'thread' in prompt &&
17466
- Array.isArray(prompt.thread)
17467
- ? prompt.thread.map((msg) => ({
17468
- role: msg.role === 'assistant' ? 'assistant' : 'user',
17469
- content: msg.content,
17470
- }))
17471
- : [{ role: 'user', content: rawPromptContent }],
18473
+ messages: threadMessages,
17472
18474
  },
17473
18475
  // <- TODO: Add user identification here> user: this.options.user,
17474
18476
  };
@@ -17488,7 +18490,7 @@ class OpenAiAssistantExecutionTools extends OpenAiExecutionTools {
17488
18490
  console.info('textDelta', textDelta.value);
17489
18491
  }
17490
18492
  const chunk = {
17491
- content: textDelta.value || '',
18493
+ content: snapshot.value,
17492
18494
  modelName: 'assistant',
17493
18495
  timing: {
17494
18496
  start,
@@ -18109,6 +19111,7 @@ class Agent extends AgentLlmExecutionTools {
18109
19111
  * Note: This method also implements the learning mechanism
18110
19112
  */
18111
19113
  async callChatModelStream(prompt, onProgress) {
19114
+ var _a;
18112
19115
  // [1] Check if the user is asking the same thing as in the samples
18113
19116
  const modelRequirements = await this.getAgentModelRequirements();
18114
19117
  if (modelRequirements.samples) {
@@ -18156,9 +19159,12 @@ class Agent extends AgentLlmExecutionTools {
18156
19159
  if (result.rawResponse && 'sample' in result.rawResponse) {
18157
19160
  return result;
18158
19161
  }
19162
+ if ((_a = modelRequirements.metadata) === null || _a === void 0 ? void 0 : _a.isClosed) {
19163
+ return result;
19164
+ }
18159
19165
  // TODO: !!! Extract learning to separate method
18160
19166
  // Learning: Append the conversation sample to the agent source
18161
- const learningExample = spaceTrim$1((block) => `
19167
+ const learningExample = spaceTrim$2((block) => `
18162
19168
 
18163
19169
  ---
18164
19170
 
@@ -18171,7 +19177,7 @@ class Agent extends AgentLlmExecutionTools {
18171
19177
  `);
18172
19178
  // Append to the current source
18173
19179
  const currentSource = this.agentSource.value;
18174
- const newSource = padBook(validateBook(spaceTrim$1(currentSource) + '\n\n' + learningExample));
19180
+ const newSource = padBook(validateBook(spaceTrim$2(currentSource) + '\n\n' + learningExample));
18175
19181
  // Update the source (which will trigger the subscription and update the underlying tools)
18176
19182
  this.agentSource.next(newSource);
18177
19183
  return result;
@@ -18280,7 +19286,7 @@ function book(strings, ...values) {
18280
19286
  const bookString = prompt(strings, ...values);
18281
19287
  if (!isValidPipelineString(bookString)) {
18282
19288
  // TODO: Make the CustomError for this
18283
- throw new Error(spaceTrim$1(`
19289
+ throw new Error(spaceTrim$2(`
18284
19290
  The string is not a valid pipeline string
18285
19291
 
18286
19292
  book\`
@@ -18290,7 +19296,7 @@ function book(strings, ...values) {
18290
19296
  }
18291
19297
  if (!isValidBook(bookString)) {
18292
19298
  // TODO: Make the CustomError for this
18293
- throw new Error(spaceTrim$1(`
19299
+ throw new Error(spaceTrim$2(`
18294
19300
  The string is not a valid book
18295
19301
 
18296
19302
  book\`
@@ -19363,7 +20369,7 @@ const OpenAiSdkTranspiler = {
19363
20369
  });
19364
20370
  const KNOWLEDGE_THRESHOLD = 1000;
19365
20371
  if (directKnowledge.join('\n').length > KNOWLEDGE_THRESHOLD || knowledgeSources.length > 0) {
19366
- return spaceTrim$1((block) => `
20372
+ return spaceTrim$2((block) => `
19367
20373
  #!/usr/bin/env node
19368
20374
 
19369
20375
  import * as dotenv from 'dotenv';
@@ -19428,7 +20434,7 @@ const OpenAiSdkTranspiler = {
19428
20434
  }
19429
20435
 
19430
20436
  const userMessage = spaceTrim(\`
19431
- ${block(spaceTrim$1(`
20437
+ ${block(spaceTrim$2(`
19432
20438
  Here is some additional context to help you answer the question:
19433
20439
  \${context}
19434
20440
 
@@ -19473,7 +20479,7 @@ const OpenAiSdkTranspiler = {
19473
20479
  })();
19474
20480
  `);
19475
20481
  }
19476
- const source = spaceTrim$1((block) => `
20482
+ const source = spaceTrim$2((block) => `
19477
20483
 
19478
20484
  #!/usr/bin/env node
19479
20485
 
@@ -19551,7 +20557,7 @@ const OpenAiSdkTranspiler = {
19551
20557
  function aboutPromptbookInformation(options) {
19552
20558
  const { isServersInfoIncluded = true, isRuntimeEnvironmentInfoIncluded = true } = options || {};
19553
20559
  const fullInfoPieces = [];
19554
- const basicInfo = spaceTrim$1(`
20560
+ const basicInfo = spaceTrim$2(`
19555
20561
 
19556
20562
  # ${NAME}
19557
20563
 
@@ -19563,7 +20569,7 @@ function aboutPromptbookInformation(options) {
19563
20569
  `);
19564
20570
  fullInfoPieces.push(basicInfo);
19565
20571
  if (isServersInfoIncluded) {
19566
- const serversInfo = spaceTrim$1((block) => `
20572
+ const serversInfo = spaceTrim$2((block) => `
19567
20573
 
19568
20574
  ## Servers
19569
20575
 
@@ -19578,7 +20584,7 @@ function aboutPromptbookInformation(options) {
19578
20584
  ...runtimeEnvironment,
19579
20585
  isCostPrevented: IS_COST_PREVENTED,
19580
20586
  };
19581
- const environmentInfo = spaceTrim$1((block) => `
20587
+ const environmentInfo = spaceTrim$2((block) => `
19582
20588
 
19583
20589
  ## Environment
19584
20590
 
@@ -19588,7 +20594,7 @@ function aboutPromptbookInformation(options) {
19588
20594
  `);
19589
20595
  fullInfoPieces.push(environmentInfo);
19590
20596
  }
19591
- const fullInfo = spaceTrim$1(fullInfoPieces.join('\n\n'));
20597
+ const fullInfo = spaceTrim$2(fullInfoPieces.join('\n\n'));
19592
20598
  return fullInfo;
19593
20599
  }
19594
20600
  /**
@@ -19715,10 +20721,11 @@ function $generateBookBoilerplate(options) {
19715
20721
  if (!personaDescription) {
19716
20722
  personaDescription = $randomAgentPersona();
19717
20723
  }
19718
- const agentSource = validateBook(spaceTrim$1((block) => `
20724
+ const agentSource = validateBook(spaceTrim$2((block) => `
19719
20725
  ${agentName}
19720
20726
 
19721
20727
  META COLOR ${color || PROMPTBOOK_COLOR.toHex()}
20728
+ META FONT Playfair Display, sans-serif
19722
20729
  PERSONA ${block(personaDescription)}
19723
20730
  `));
19724
20731
  return agentSource;