@promptbook/components 0.112.0-12 → 0.112.0-15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/esm/index.es.js +289 -207
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/src/cli/cli-commands/coder/{find-fresh-emoji-tag.d.ts → find-fresh-emoji-tags.d.ts} +1 -1
  4. package/esm/src/cli/cli-commands/coder.d.ts +1 -1
  5. package/esm/src/commitments/USE_BROWSER/resolveRunBrowserToolForNode.d.ts +1 -1
  6. package/esm/src/commitments/USE_TIMEOUT/TimeoutToolNames.d.ts +1 -0
  7. package/esm/src/commitments/USE_TIMEOUT/TimeoutToolRuntimeAdapter.d.ts +51 -2
  8. package/esm/src/commitments/USE_TIMEOUT/USE_TIMEOUT.d.ts +2 -2
  9. package/esm/src/commitments/USE_TIMEOUT/getTimeoutToolRuntimeAdapterOrDisabledResult.d.ts +2 -2
  10. package/esm/src/commitments/USE_TIMEOUT/parseTimeoutToolArgs.d.ts +14 -1
  11. package/esm/src/execution/createPipelineExecutor/30-executeFormatSubvalues.d.ts +1 -1
  12. package/esm/src/llm-providers/anthropic-claude/anthropic-claude-models.d.ts +1 -1
  13. package/esm/src/llm-providers/deepseek/deepseek-models.d.ts +1 -1
  14. package/esm/src/llm-providers/google/google-models.d.ts +1 -1
  15. package/esm/src/llm-providers/openai/openai-models.d.ts +1 -1
  16. package/esm/src/scrapers/_boilerplate/BoilerplateScraper.d.ts +1 -2
  17. package/esm/src/scrapers/document/DocumentScraper.d.ts +1 -2
  18. package/esm/src/scrapers/document-legacy/LegacyDocumentScraper.d.ts +1 -2
  19. package/esm/src/scripting/javascript/postprocessing-functions.d.ts +1 -1
  20. package/esm/src/utils/parameters/mapAvailableToExpectedParameters.d.ts +1 -2
  21. package/esm/src/version.d.ts +1 -1
  22. package/package.json +1 -1
  23. package/umd/index.umd.js +456 -375
  24. package/umd/index.umd.js.map +1 -1
  25. package/umd/src/cli/cli-commands/coder/{find-fresh-emoji-tag.d.ts → find-fresh-emoji-tags.d.ts} +1 -1
  26. package/umd/src/cli/cli-commands/coder.d.ts +1 -1
  27. package/umd/src/commitments/USE_BROWSER/resolveRunBrowserToolForNode.d.ts +1 -1
  28. package/umd/src/commitments/USE_TIMEOUT/TimeoutToolNames.d.ts +1 -0
  29. package/umd/src/commitments/USE_TIMEOUT/TimeoutToolRuntimeAdapter.d.ts +51 -2
  30. package/umd/src/commitments/USE_TIMEOUT/USE_TIMEOUT.d.ts +2 -2
  31. package/umd/src/commitments/USE_TIMEOUT/getTimeoutToolRuntimeAdapterOrDisabledResult.d.ts +2 -2
  32. package/umd/src/commitments/USE_TIMEOUT/parseTimeoutToolArgs.d.ts +14 -1
  33. package/umd/src/execution/createPipelineExecutor/30-executeFormatSubvalues.d.ts +1 -1
  34. package/umd/src/llm-providers/anthropic-claude/anthropic-claude-models.d.ts +1 -1
  35. package/umd/src/llm-providers/deepseek/deepseek-models.d.ts +1 -1
  36. package/umd/src/llm-providers/google/google-models.d.ts +1 -1
  37. package/umd/src/llm-providers/openai/openai-models.d.ts +1 -1
  38. package/umd/src/scrapers/_boilerplate/BoilerplateScraper.d.ts +1 -2
  39. package/umd/src/scrapers/document/DocumentScraper.d.ts +1 -2
  40. package/umd/src/scrapers/document-legacy/LegacyDocumentScraper.d.ts +1 -2
  41. package/umd/src/scripting/javascript/postprocessing-functions.d.ts +1 -1
  42. package/umd/src/utils/parameters/mapAvailableToExpectedParameters.d.ts +1 -2
  43. package/umd/src/version.d.ts +1 -1
package/esm/index.es.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
2
  import { useMemo, useId, useState, useRef, useEffect, createContext, useContext, useCallback, forwardRef, memo } from 'react';
3
- import spaceTrim$2, { spaceTrim as spaceTrim$1 } from 'spacetrim';
3
+ import { spaceTrim as spaceTrim$1 } from 'spacetrim';
4
4
  import { SHA256 } from 'crypto-js';
5
5
  import hexEncoder from 'crypto-js/enc-hex';
6
6
  import { basename, join, dirname, isAbsolute } from 'path';
@@ -40,7 +40,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
40
40
  * @generated
41
41
  * @see https://github.com/webgptorg/promptbook
42
42
  */
43
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-12';
43
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-15';
44
44
  /**
45
45
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
46
46
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -446,42 +446,6 @@ function normalizeTo_camelCase(text, _isFirstLetterCapital = false) {
446
446
  * TODO: [🌺] Use some intermediate util splitWords
447
447
  */
448
448
 
449
- /**
450
- * Normalizes a domain-like string into a comparable hostname form.
451
- *
452
- * The returned value is lowercased and stripped to hostname only
453
- * (protocol, path, query, hash, and port are removed).
454
- *
455
- * @param rawDomain - Raw domain value (for example `my-agent.com` or `https://my-agent.com/path`).
456
- * @returns Normalized hostname or `null` when the value cannot be normalized.
457
- * @private utility for host/domain matching
458
- */
459
- function normalizeDomainForMatching(rawDomain) {
460
- const trimmedDomain = rawDomain.trim();
461
- if (!trimmedDomain) {
462
- return null;
463
- }
464
- const candidateUrl = hasHttpProtocol(trimmedDomain) ? trimmedDomain : `https://${trimmedDomain}`;
465
- try {
466
- const parsedUrl = new URL(candidateUrl);
467
- const normalizedHostname = parsedUrl.hostname.trim().toLowerCase();
468
- return normalizedHostname || null;
469
- }
470
- catch (_a) {
471
- return null;
472
- }
473
- }
474
- /**
475
- * Checks whether the value already includes an HTTP(S) protocol prefix.
476
- *
477
- * @param value - Raw value to inspect.
478
- * @returns True when the value starts with `http://` or `https://`.
479
- * @private utility for host/domain matching
480
- */
481
- function hasHttpProtocol(value) {
482
- return value.startsWith('http://') || value.startsWith('https://');
483
- }
484
-
485
449
  /**
486
450
  * Tests if given string is valid URL.
487
451
  *
@@ -598,6 +562,42 @@ function countOccurrences(value, searchedChar) {
598
562
  return count;
599
563
  }
600
564
 
565
+ /**
566
+ * Normalizes a domain-like string into a comparable hostname form.
567
+ *
568
+ * The returned value is lowercased and stripped to hostname only
569
+ * (protocol, path, query, hash, and port are removed).
570
+ *
571
+ * @param rawDomain - Raw domain value (for example `my-agent.com` or `https://my-agent.com/path`).
572
+ * @returns Normalized hostname or `null` when the value cannot be normalized.
573
+ * @private utility for host/domain matching
574
+ */
575
+ function normalizeDomainForMatching(rawDomain) {
576
+ const trimmedDomain = rawDomain.trim();
577
+ if (!trimmedDomain) {
578
+ return null;
579
+ }
580
+ const candidateUrl = hasHttpProtocol(trimmedDomain) ? trimmedDomain : `https://${trimmedDomain}`;
581
+ try {
582
+ const parsedUrl = new URL(candidateUrl);
583
+ const normalizedHostname = parsedUrl.hostname.trim().toLowerCase();
584
+ return normalizedHostname || null;
585
+ }
586
+ catch (_a) {
587
+ return null;
588
+ }
589
+ }
590
+ /**
591
+ * Checks whether the value already includes an HTTP(S) protocol prefix.
592
+ *
593
+ * @param value - Raw value to inspect.
594
+ * @returns True when the value starts with `http://` or `https://`.
595
+ * @private utility for host/domain matching
596
+ */
597
+ function hasHttpProtocol(value) {
598
+ return value.startsWith('http://') || value.startsWith('https://');
599
+ }
600
+
601
601
  /**
602
602
  * Trims string from all 4 sides
603
603
  *
@@ -1796,7 +1796,7 @@ false);
1796
1796
  function getErrorReportUrl(error) {
1797
1797
  const report = {
1798
1798
  title: `🐜 Error report from ${NAME}`,
1799
- body: spaceTrim$2((block) => `
1799
+ body: spaceTrim$1((block) => `
1800
1800
 
1801
1801
 
1802
1802
  \`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
@@ -1991,7 +1991,7 @@ function valueToString(value) {
1991
1991
  * @public exported from `@promptbook/utils`
1992
1992
  */
1993
1993
  function computeHash(value) {
1994
- return SHA256(hexEncoder.parse(spaceTrim$2(valueToString(value)))).toString( /* hex */);
1994
+ return SHA256(hexEncoder.parse(spaceTrim$1(valueToString(value)))).toString( /* hex */);
1995
1995
  }
1996
1996
  /**
1997
1997
  * TODO: [🥬][🥬] Use this ACRY
@@ -2098,7 +2098,7 @@ function checkSerializableAsJson(options) {
2098
2098
  }
2099
2099
  else if (typeof value === 'object') {
2100
2100
  if (value instanceof Date) {
2101
- throw new UnexpectedError(spaceTrim$2((block) => `
2101
+ throw new UnexpectedError(spaceTrim$1((block) => `
2102
2102
  \`${name}\` is Date
2103
2103
 
2104
2104
  Use \`string_date_iso8601\` instead
@@ -2117,7 +2117,7 @@ function checkSerializableAsJson(options) {
2117
2117
  throw new UnexpectedError(`${name} is RegExp`);
2118
2118
  }
2119
2119
  else if (value instanceof Error) {
2120
- throw new UnexpectedError(spaceTrim$2((block) => `
2120
+ throw new UnexpectedError(spaceTrim$1((block) => `
2121
2121
  \`${name}\` is unserialized Error
2122
2122
 
2123
2123
  Use function \`serializeError\`
@@ -2140,7 +2140,7 @@ function checkSerializableAsJson(options) {
2140
2140
  }
2141
2141
  catch (error) {
2142
2142
  assertsError(error);
2143
- throw new UnexpectedError(spaceTrim$2((block) => `
2143
+ throw new UnexpectedError(spaceTrim$1((block) => `
2144
2144
  \`${name}\` is not serializable
2145
2145
 
2146
2146
  ${block(error.stack || error.message)}
@@ -2172,7 +2172,7 @@ function checkSerializableAsJson(options) {
2172
2172
  }
2173
2173
  }
2174
2174
  else {
2175
- throw new UnexpectedError(spaceTrim$2((block) => `
2175
+ throw new UnexpectedError(spaceTrim$1((block) => `
2176
2176
  \`${name}\` is unknown type
2177
2177
 
2178
2178
  Additional message for \`${name}\`:
@@ -3174,7 +3174,7 @@ function deserializeError(error, isStackAddedToMessage = true) {
3174
3174
  message = `${name}: ${message}`;
3175
3175
  }
3176
3176
  if (isStackAddedToMessage && stack !== undefined && stack !== '') {
3177
- message = spaceTrim$2((block) => `
3177
+ message = spaceTrim$1((block) => `
3178
3178
  ${block(message)}
3179
3179
 
3180
3180
  Original stack trace:
@@ -3195,7 +3195,7 @@ function serializeError(error) {
3195
3195
  const { name, message, stack } = error;
3196
3196
  const { id } = error;
3197
3197
  if (!Object.keys(ALL_ERRORS).includes(name)) {
3198
- console.error(spaceTrim$2((block) => `
3198
+ console.error(spaceTrim$1((block) => `
3199
3199
 
3200
3200
  Cannot serialize error with name "${name}"
3201
3201
 
@@ -3301,7 +3301,7 @@ function jsonParse(value) {
3301
3301
  }
3302
3302
  else if (typeof value !== 'string') {
3303
3303
  console.error('Can not parse JSON from non-string value.', { text: value });
3304
- throw new Error(spaceTrim$2(`
3304
+ throw new Error(spaceTrim$1(`
3305
3305
  Can not parse JSON from non-string value.
3306
3306
 
3307
3307
  The value type: ${typeof value}
@@ -3315,7 +3315,7 @@ function jsonParse(value) {
3315
3315
  if (!(error instanceof Error)) {
3316
3316
  throw error;
3317
3317
  }
3318
- throw new Error(spaceTrim$2((block) => `
3318
+ throw new Error(spaceTrim$1((block) => `
3319
3319
  ${block(error.message)}
3320
3320
 
3321
3321
  The expected JSON text:
@@ -3675,7 +3675,7 @@ function buildParametersSection(items) {
3675
3675
  const entries = items
3676
3676
  .flatMap((item) => formatParameterListItem(item).split(/\r?\n/))
3677
3677
  .filter((line) => line !== '');
3678
- return spaceTrim$2((block) => `
3678
+ return spaceTrim$1((block) => `
3679
3679
  **Parameters:**
3680
3680
  ${block(entries.join('\n'))}
3681
3681
 
@@ -3748,7 +3748,7 @@ function isPromptString(value) {
3748
3748
  */
3749
3749
  function prompt(strings, ...values) {
3750
3750
  if (values.length === 0) {
3751
- return new PromptString(spaceTrim$2(strings.join('')));
3751
+ return new PromptString(spaceTrim$1(strings.join('')));
3752
3752
  }
3753
3753
  const stringsWithHiddenParameters = strings.map((stringsItem) => ParameterEscaping.hideBrackets(stringsItem));
3754
3754
  const parameterMetadata = values.map((value) => {
@@ -3789,7 +3789,7 @@ function prompt(strings, ...values) {
3789
3789
  ? `${result}${stringsItem}`
3790
3790
  : `${result}${stringsItem}${ParameterSection.formatParameterPlaceholder(parameterName)}`;
3791
3791
  }, '');
3792
- pipelineString = spaceTrim$2(pipelineString);
3792
+ pipelineString = spaceTrim$1(pipelineString);
3793
3793
  try {
3794
3794
  pipelineString = templateParameters(pipelineString, parameters);
3795
3795
  }
@@ -3798,7 +3798,7 @@ function prompt(strings, ...values) {
3798
3798
  throw error;
3799
3799
  }
3800
3800
  console.error({ pipelineString, parameters, parameterNames: parameterNamesOrdered, error });
3801
- throw new UnexpectedError(spaceTrim$2((block) => `
3801
+ throw new UnexpectedError(spaceTrim$1((block) => `
3802
3802
  Internal error in prompt template literal
3803
3803
 
3804
3804
  ${block(JSON.stringify({ strings, values }, null, 4))}}
@@ -5911,7 +5911,7 @@ function serializeToPromptbookJavascript(value) {
5911
5911
  imports.push(`import { Color } from '@promptbook/color';`);
5912
5912
  }
5913
5913
  else if (typeof value === 'string') {
5914
- const trimmed = spaceTrim$2(value);
5914
+ const trimmed = spaceTrim$1(value);
5915
5915
  if (trimmed.includes('\n')) {
5916
5916
  // Multiline string -> use `spaceTrim`
5917
5917
  serializedValue = `spaceTrim(\`\n${value.replace(/`/g, '\\`')}\n\`)`;
@@ -6168,7 +6168,7 @@ function isValidPipelineUrl(url) {
6168
6168
  * @public exported from `@promptbook/core`
6169
6169
  */
6170
6170
  function normalizeAgentName(rawAgentName) {
6171
- return titleToName(spaceTrim$2(rawAgentName));
6171
+ return titleToName(spaceTrim$1(rawAgentName));
6172
6172
  }
6173
6173
 
6174
6174
  /**
@@ -15543,9 +15543,9 @@ function createTimeoutSystemMessage(extraInstructions) {
15543
15543
  return spaceTrim$1((block) => `
15544
15544
  Timeout scheduling:
15545
15545
  - Use "set_timeout" to wake this same chat thread in the future.
15546
- - Timers are thread-scoped, not global for the whole agent.
15546
+ - Use "list_timeouts" to review timeouts across all chats for the same user+agent scope.
15547
+ - "cancel_timeout" accepts a timeout id from any chat in this same user+agent scope.
15547
15548
  - When one timeout elapses, you will receive a new user-like message that explicitly says it is a timeout wake-up and includes the \`timeoutId\`.
15548
- - Use "cancel_timeout" when a previously scheduled timeout is no longer relevant.
15549
15549
  - Do not claim a timer was set or cancelled unless the tool confirms it.
15550
15550
  ${block(extraInstructions)}
15551
15551
  `);
@@ -15606,13 +15606,6 @@ function parseToolExecutionEnvelope(rawValue) {
15606
15606
  * @private internal utility of USE TIMEOUT
15607
15607
  */
15608
15608
  function createDisabledTimeoutResult(action, message) {
15609
- if (action === 'set') {
15610
- return {
15611
- action,
15612
- status: 'disabled',
15613
- message,
15614
- };
15615
- }
15616
15609
  return {
15617
15610
  action,
15618
15611
  status: 'disabled',
@@ -15639,6 +15632,18 @@ function getTimeoutToolRuntimeAdapterOrDisabledResult(action, runtimeContext) {
15639
15632
  }
15640
15633
  }
15641
15634
 
15635
+ /**
15636
+ * Default number of rows returned by `list_timeouts`.
15637
+ *
15638
+ * @private internal USE TIMEOUT constant
15639
+ */
15640
+ const DEFAULT_LIST_TIMEOUTS_LIMIT = 20;
15641
+ /**
15642
+ * Hard cap for `list_timeouts` page size.
15643
+ *
15644
+ * @private internal USE TIMEOUT constant
15645
+ */
15646
+ const MAX_LIST_TIMEOUTS_LIMIT = 100;
15642
15647
  /**
15643
15648
  * Parses and validates `USE TIMEOUT` tool arguments.
15644
15649
  *
@@ -15673,6 +15678,31 @@ const parseTimeoutToolArgs = {
15673
15678
  }
15674
15679
  return { timeoutId };
15675
15680
  },
15681
+ /**
15682
+ * Parses `list_timeouts` input.
15683
+ */
15684
+ list(args) {
15685
+ if (args.includeFinished !== undefined && typeof args.includeFinished !== 'boolean') {
15686
+ throw new PipelineExecutionError(spaceTrim$1(`
15687
+ Timeout \`includeFinished\` must be a boolean when provided.
15688
+ `));
15689
+ }
15690
+ const parsedLimit = args.limit === undefined ? DEFAULT_LIST_TIMEOUTS_LIMIT : Math.floor(Number(args.limit));
15691
+ if (!Number.isFinite(parsedLimit) || parsedLimit <= 0) {
15692
+ throw new PipelineExecutionError(spaceTrim$1(`
15693
+ Timeout \`limit\` must be a positive number.
15694
+ `));
15695
+ }
15696
+ if (parsedLimit > MAX_LIST_TIMEOUTS_LIMIT) {
15697
+ throw new PipelineExecutionError(spaceTrim$1(`
15698
+ Timeout \`limit\` must be at most \`${MAX_LIST_TIMEOUTS_LIMIT}\`.
15699
+ `));
15700
+ }
15701
+ return {
15702
+ includeFinished: args.includeFinished === true,
15703
+ limit: parsedLimit,
15704
+ };
15705
+ },
15676
15706
  };
15677
15707
 
15678
15708
  /**
@@ -15683,6 +15713,7 @@ const parseTimeoutToolArgs = {
15683
15713
  const TimeoutToolNames = {
15684
15714
  set: 'set_timeout',
15685
15715
  cancel: 'cancel_timeout',
15716
+ list: 'list_timeouts',
15686
15717
  };
15687
15718
 
15688
15719
  /**
@@ -15782,6 +15813,35 @@ function createTimeoutToolFunctions() {
15782
15813
  return JSON.stringify(result);
15783
15814
  }
15784
15815
  },
15816
+ async [TimeoutToolNames.list](args) {
15817
+ const runtimeContext = resolveTimeoutRuntimeContext(args);
15818
+ const { adapter, disabledResult } = getTimeoutToolRuntimeAdapterOrDisabledResult('list', runtimeContext);
15819
+ if (!adapter || disabledResult) {
15820
+ return JSON.stringify(disabledResult);
15821
+ }
15822
+ try {
15823
+ const parsedArgs = parseTimeoutToolArgs.list(args);
15824
+ const listedTimeouts = await adapter.listTimeouts(parsedArgs, runtimeContext);
15825
+ const result = {
15826
+ action: 'list',
15827
+ status: 'listed',
15828
+ items: listedTimeouts.items,
15829
+ total: listedTimeouts.total,
15830
+ };
15831
+ return createToolExecutionEnvelope({
15832
+ assistantMessage: listedTimeouts.total === 1 ? 'Found 1 timeout.' : `Found ${listedTimeouts.total} timeouts.`,
15833
+ toolResult: result,
15834
+ });
15835
+ }
15836
+ catch (error) {
15837
+ const result = {
15838
+ action: 'list',
15839
+ status: 'error',
15840
+ message: error instanceof Error ? error.message : String(error),
15841
+ };
15842
+ return JSON.stringify(result);
15843
+ }
15844
+ },
15785
15845
  };
15786
15846
  }
15787
15847
 
@@ -15815,26 +15875,45 @@ function createTimeoutTools(existingTools = []) {
15815
15875
  if (!tools.some((tool) => tool.name === TimeoutToolNames.cancel)) {
15816
15876
  tools.push({
15817
15877
  name: TimeoutToolNames.cancel,
15818
- description: 'Cancel one previously scheduled timeout in the current chat thread.',
15878
+ description: 'Cancel one previously scheduled timeout within the same user+agent scope, even if it was set in another chat.',
15819
15879
  parameters: {
15820
15880
  type: 'object',
15821
15881
  properties: {
15822
15882
  timeoutId: {
15823
15883
  type: 'string',
15824
- description: 'Identifier returned earlier by `set_timeout`.',
15884
+ description: 'Identifier returned earlier by `set_timeout` or `list_timeouts`.',
15825
15885
  },
15826
15886
  },
15827
15887
  required: ['timeoutId'],
15828
15888
  },
15829
15889
  });
15830
15890
  }
15891
+ if (!tools.some((tool) => tool.name === TimeoutToolNames.list)) {
15892
+ tools.push({
15893
+ name: TimeoutToolNames.list,
15894
+ description: 'List scheduled timeouts across all chats for this same user+agent scope so they can be reviewed or cancelled.',
15895
+ parameters: {
15896
+ type: 'object',
15897
+ properties: {
15898
+ includeFinished: {
15899
+ type: 'boolean',
15900
+ description: 'When true, include completed, failed, and cancelled rows in addition to active timeouts.',
15901
+ },
15902
+ limit: {
15903
+ type: 'number',
15904
+ description: 'Maximum number of rows to return (default 20, max 100).',
15905
+ },
15906
+ },
15907
+ },
15908
+ });
15909
+ }
15831
15910
  return tools;
15832
15911
  }
15833
15912
 
15834
15913
  /**
15835
15914
  * `USE TIMEOUT` commitment definition.
15836
15915
  *
15837
- * The `USE TIMEOUT` commitment enables thread-scoped timers that wake the same chat later.
15916
+ * The `USE TIMEOUT` commitment enables timeout wake-ups and scoped timeout management.
15838
15917
  *
15839
15918
  * @private [🪔] Maybe export the commitments through some package
15840
15919
  */
@@ -15849,7 +15928,7 @@ class UseTimeoutCommitmentDefinition extends BaseCommitmentDefinition {
15849
15928
  * Short one-line description of `USE TIMEOUT`.
15850
15929
  */
15851
15930
  get description() {
15852
- return 'Enable thread-scoped timers that can wake the same chat in the future.';
15931
+ return 'Enable timeout wake-ups plus scoped timeout listing/cancellation across chats.';
15853
15932
  }
15854
15933
  /**
15855
15934
  * Icon for this commitment.
@@ -15864,14 +15943,15 @@ class UseTimeoutCommitmentDefinition extends BaseCommitmentDefinition {
15864
15943
  return spaceTrim$1(`
15865
15944
  # USE TIMEOUT
15866
15945
 
15867
- Enables the agent to schedule thread-scoped timeout wake-ups.
15946
+ Enables timeout wake-ups and timeout management for the same user+agent scope.
15868
15947
 
15869
15948
  ## Key aspects
15870
15949
 
15871
15950
  - The agent uses \`set_timeout\` to schedule a future wake-up in the same chat thread.
15872
15951
  - The tool returns immediately while the timeout is stored and executed by the runtime later.
15873
15952
  - The wake-up arrives as a new user-like timeout message in the same conversation.
15874
- - The agent can cancel an existing timeout by \`timeoutId\` via \`cancel_timeout\`.
15953
+ - The agent can inspect known timeouts via \`list_timeouts\`.
15954
+ - The agent can cancel an existing timeout by \`timeoutId\` via \`cancel_timeout\`, including timeouts created in another chat.
15875
15955
  - Commitment content is treated as optional timeout policy instructions.
15876
15956
 
15877
15957
  ## Examples
@@ -15900,6 +15980,7 @@ class UseTimeoutCommitmentDefinition extends BaseCommitmentDefinition {
15900
15980
  return {
15901
15981
  [TimeoutToolNames.set]: 'Set timer',
15902
15982
  [TimeoutToolNames.cancel]: 'Cancel timer',
15983
+ [TimeoutToolNames.list]: 'List timers',
15903
15984
  };
15904
15985
  }
15905
15986
  /**
@@ -16994,7 +17075,7 @@ function parseAgentSource(agentSource) {
16994
17075
  continue;
16995
17076
  }
16996
17077
  if (commitment.type === 'FROM') {
16997
- const content = spaceTrim$2(commitment.content).split(/\r?\n/)[0] || '';
17078
+ const content = spaceTrim$1(commitment.content).split(/\r?\n/)[0] || '';
16998
17079
  if (content === 'Adam' || content === '' /* <- Note: Adam is implicit */) {
16999
17080
  continue;
17000
17081
  }
@@ -17017,7 +17098,7 @@ function parseAgentSource(agentSource) {
17017
17098
  continue;
17018
17099
  }
17019
17100
  if (commitment.type === 'IMPORT') {
17020
- const content = spaceTrim$2(commitment.content).split(/\r?\n/)[0] || '';
17101
+ const content = spaceTrim$1(commitment.content).split(/\r?\n/)[0] || '';
17021
17102
  let label = content;
17022
17103
  let iconName = 'ExternalLink'; // Import remote
17023
17104
  try {
@@ -17055,7 +17136,7 @@ function parseAgentSource(agentSource) {
17055
17136
  continue;
17056
17137
  }
17057
17138
  if (commitment.type === 'KNOWLEDGE') {
17058
- const content = spaceTrim$2(commitment.content);
17139
+ const content = spaceTrim$1(commitment.content);
17059
17140
  const extractedUrls = extractUrlsFromText(content);
17060
17141
  let label = content;
17061
17142
  let iconName = 'Book';
@@ -17114,7 +17195,7 @@ function parseAgentSource(agentSource) {
17114
17195
  continue;
17115
17196
  }
17116
17197
  if (commitment.type === 'META LINK') {
17117
- const linkValue = spaceTrim$2(commitment.content);
17198
+ const linkValue = spaceTrim$1(commitment.content);
17118
17199
  links.push(linkValue);
17119
17200
  meta.link = linkValue;
17120
17201
  continue;
@@ -17124,11 +17205,11 @@ function parseAgentSource(agentSource) {
17124
17205
  continue;
17125
17206
  }
17126
17207
  if (commitment.type === 'META IMAGE') {
17127
- meta.image = spaceTrim$2(commitment.content);
17208
+ meta.image = spaceTrim$1(commitment.content);
17128
17209
  continue;
17129
17210
  }
17130
17211
  if (commitment.type === 'META DESCRIPTION') {
17131
- meta.description = spaceTrim$2(commitment.content);
17212
+ meta.description = spaceTrim$1(commitment.content);
17132
17213
  continue;
17133
17214
  }
17134
17215
  if (commitment.type === 'META DISCLAIMER') {
@@ -17136,7 +17217,7 @@ function parseAgentSource(agentSource) {
17136
17217
  continue;
17137
17218
  }
17138
17219
  if (commitment.type === 'META INPUT PLACEHOLDER') {
17139
- meta.inputPlaceholder = spaceTrim$2(commitment.content);
17220
+ meta.inputPlaceholder = spaceTrim$1(commitment.content);
17140
17221
  continue;
17141
17222
  }
17142
17223
  if (commitment.type === 'MESSAGE SUFFIX') {
@@ -17152,7 +17233,7 @@ function parseAgentSource(agentSource) {
17152
17233
  continue;
17153
17234
  }
17154
17235
  if (commitment.type === 'META VOICE') {
17155
- meta.voice = spaceTrim$2(commitment.content);
17236
+ meta.voice = spaceTrim$1(commitment.content);
17156
17237
  continue;
17157
17238
  }
17158
17239
  if (commitment.type !== 'META') {
@@ -17161,10 +17242,10 @@ function parseAgentSource(agentSource) {
17161
17242
  // Parse META commitments - format is "META TYPE content"
17162
17243
  const metaTypeRaw = commitment.content.split(' ')[0] || 'NONE';
17163
17244
  if (metaTypeRaw === 'LINK') {
17164
- links.push(spaceTrim$2(commitment.content.substring(metaTypeRaw.length)));
17245
+ links.push(spaceTrim$1(commitment.content.substring(metaTypeRaw.length)));
17165
17246
  }
17166
17247
  const metaType = normalizeTo_camelCase(metaTypeRaw);
17167
- meta[metaType] = spaceTrim$2(commitment.content.substring(metaTypeRaw.length));
17248
+ meta[metaType] = spaceTrim$1(commitment.content.substring(metaTypeRaw.length));
17168
17249
  }
17169
17250
  // Generate fullname fallback if no meta fullname specified
17170
17251
  if (!meta.fullname) {
@@ -17195,7 +17276,7 @@ function parseAgentSource(agentSource) {
17195
17276
  * @returns The content with normalized separators
17196
17277
  */
17197
17278
  function normalizeSeparator(content) {
17198
- const trimmed = spaceTrim$2(content);
17279
+ const trimmed = spaceTrim$1(content);
17199
17280
  if (trimmed.includes(',')) {
17200
17281
  return trimmed;
17201
17282
  }
@@ -17208,7 +17289,7 @@ function normalizeSeparator(content) {
17208
17289
  * @returns Normalized domain or a trimmed fallback.
17209
17290
  */
17210
17291
  function normalizeMetaDomain(content) {
17211
- const trimmed = spaceTrim$2(content);
17292
+ const trimmed = spaceTrim$1(content);
17212
17293
  return normalizeDomainForMatching(trimmed) || trimmed.toLowerCase();
17213
17294
  }
17214
17295
  /**
@@ -17349,7 +17430,7 @@ function validateBook(source) {
17349
17430
  * @deprecated Use `$generateBookBoilerplate` instead
17350
17431
  * @public exported from `@promptbook/core`
17351
17432
  */
17352
- const DEFAULT_BOOK = padBook(validateBook(spaceTrim$2(`
17433
+ const DEFAULT_BOOK = padBook(validateBook(spaceTrim$1(`
17353
17434
  AI Avatar
17354
17435
 
17355
17436
  PERSONA A friendly AI assistant that helps you with your tasks
@@ -18144,7 +18225,7 @@ const PUBLIC_AGENTS_SERVERS = [
18144
18225
  function aboutPromptbookInformation(options) {
18145
18226
  const { isServersInfoIncluded = true, isRuntimeEnvironmentInfoIncluded = true } = options || {};
18146
18227
  const fullInfoPieces = [];
18147
- const basicInfo = spaceTrim$2(`
18228
+ const basicInfo = spaceTrim$1(`
18148
18229
 
18149
18230
  # ${NAME}
18150
18231
 
@@ -18156,7 +18237,7 @@ function aboutPromptbookInformation(options) {
18156
18237
  `);
18157
18238
  fullInfoPieces.push(basicInfo);
18158
18239
  if (isServersInfoIncluded) {
18159
- const serversInfo = spaceTrim$2((block) => `
18240
+ const serversInfo = spaceTrim$1((block) => `
18160
18241
 
18161
18242
  ## Servers
18162
18243
 
@@ -18170,7 +18251,7 @@ function aboutPromptbookInformation(options) {
18170
18251
  ...runtimeEnvironment,
18171
18252
  isCostPrevented: IS_COST_PREVENTED,
18172
18253
  };
18173
- const environmentInfo = spaceTrim$2((block) => `
18254
+ const environmentInfo = spaceTrim$1((block) => `
18174
18255
 
18175
18256
  ## Environment
18176
18257
 
@@ -18180,7 +18261,7 @@ function aboutPromptbookInformation(options) {
18180
18261
  `);
18181
18262
  fullInfoPieces.push(environmentInfo);
18182
18263
  }
18183
- const fullInfo = spaceTrim$2(fullInfoPieces.join('\n\n'));
18264
+ const fullInfo = spaceTrim$1(fullInfoPieces.join('\n\n'));
18184
18265
  return fullInfo;
18185
18266
  }
18186
18267
  /**
@@ -21463,7 +21544,7 @@ function getTextColor(bgColor) {
21463
21544
  const luminance = 0.299 * r + 0.587 * g + 0.114 * b;
21464
21545
  return luminance > 186 ? '#0f172a' : '#f8fafc';
21465
21546
  }
21466
- const HERO_ILLUSTRATION_SVG = spaceTrim$2(() => `
21547
+ const HERO_ILLUSTRATION_SVG = spaceTrim$1(() => `
21467
21548
  <svg width="320" height="220" viewBox="0 0 320 220" fill="none" xmlns="http://www.w3.org/2000/svg">
21468
21549
  <defs>
21469
21550
  <linearGradient id="heroGradient" x1="0" y1="0" x2="320" y2="220">
@@ -21481,7 +21562,7 @@ const HERO_ILLUSTRATION_SVG = spaceTrim$2(() => `
21481
21562
  <rect x="62" y="130" width="196" height="20" rx="10" fill="rgba(255,255,255,0.15)" />
21482
21563
  </svg>
21483
21564
  `);
21484
- const BRAND_MARK_SVG = spaceTrim$2(() => `
21565
+ const BRAND_MARK_SVG = spaceTrim$1(() => `
21485
21566
  <svg width="92" height="92" viewBox="0 0 92 92" fill="none" xmlns="http://www.w3.org/2000/svg">
21486
21567
  <defs>
21487
21568
  <linearGradient id="badgeGradient" x1="0" y1="0" x2="92" y2="92">
@@ -21631,7 +21712,7 @@ function buildAttachmentsMarkup(message) {
21631
21712
  const href = hasUrl ? ` href="${escapeHtml$1((_a = attachment.url) !== null && _a !== void 0 ? _a : '#')}" target="_blank" rel="noopener"` : '';
21632
21713
  const name = escapeHtml$1(attachment.name || 'Attachment');
21633
21714
  const meta = escapeHtml$1(attachment.type || 'file');
21634
- return spaceTrim$2(`
21715
+ return spaceTrim$1(`
21635
21716
  <${tag} class="attachment-chip"${href}>
21636
21717
  <span class="attachment-icon">📎</span>
21637
21718
  <span class="attachment-name">${name}</span>
@@ -21656,7 +21737,7 @@ function buildCitationsMarkup(message) {
21656
21737
  const urlLink = citation.url
21657
21738
  ? `<a class="citation-link" href="${escapeHtml$1(citation.url)}" target="_blank" rel="noopener">Open source</a>`
21658
21739
  : '';
21659
- return spaceTrim$2(`
21740
+ return spaceTrim$1(`
21660
21741
  <article class="citation-chip">
21661
21742
  <div class="citation-header">
21662
21743
  <span class="citation-badge">${escapeHtml$1(citation.id)}</span>
@@ -21688,7 +21769,7 @@ function renderMessageBlock(message, participants) {
21688
21769
  const avatarMarkup = visuals.avatarSrc
21689
21770
  ? `<img class="message-avatar-img" src="${escapeHtml$1(visuals.avatarSrc)}" alt="${escapeHtml$1(visuals.displayName)}" />`
21690
21771
  : `<span class="message-avatar-fallback" style="background:${visuals.accentColor};color:${bubbleTextColor};">${escapeHtml$1(visuals.avatarLabel)}</span>`;
21691
- return spaceTrim$2(`
21772
+ return spaceTrim$1(`
21692
21773
  <article class="message-block ${alignmentClass}">
21693
21774
  <div class="message-avatar">${avatarMarkup}</div>
21694
21775
  <div class="message-card" style="--bubble-color:${visuals.accentColor};--bubble-text:${bubbleTextColor};">
@@ -21739,7 +21820,7 @@ const htmlSaveFormatDefinition = {
21739
21820
  const messageMarkup = messages.length > 0
21740
21821
  ? messages.map((message) => renderMessageBlock(message, participantLookup)).join('')
21741
21822
  : '<div class="empty-state">No messages yet. Send a note to capture this chat.</div>';
21742
- return spaceTrim$2(`
21823
+ return spaceTrim$1(`
21743
21824
  <!DOCTYPE html>
21744
21825
  <html lang="en">
21745
21826
  <head>
@@ -22144,7 +22225,7 @@ const htmlSaveFormatDefinition = {
22144
22225
  <p class="hero-subtitle">${escapeHtml$1(heroSubtitle)}</p>
22145
22226
  <div class="stat-grid">
22146
22227
  ${statCards
22147
- .map((stat) => spaceTrim$2(`
22228
+ .map((stat) => spaceTrim$1(`
22148
22229
  <div class="stat-card">
22149
22230
  <span class="stat-value">${escapeHtml$1(stat.value)}</span>
22150
22231
  <span class="stat-label">${escapeHtml$1(stat.label)}</span>
@@ -22399,7 +22480,7 @@ const reactSaveFormatDefinition = {
22399
22480
  const { imports: participantsImports, value: participantsValue } = serializeToPromptbookJavascript(participants);
22400
22481
  const { imports: messagesImports, value: messagesValue } = serializeToPromptbookJavascript(messages);
22401
22482
  const uniqueImports = Array.from(new Set([`import { Chat } from '@promptbook/components';`, ...participantsImports, ...messagesImports])).filter((imp) => !!imp && imp.trim().length > 0);
22402
- return spaceTrim$2((block) => `
22483
+ return spaceTrim$1((block) => `
22403
22484
  "use client";
22404
22485
 
22405
22486
  ${block(uniqueImports.join('\n'))}
@@ -23895,7 +23976,7 @@ function ChatInputArea(props) {
23895
23976
  type: uploadedFile.file.type,
23896
23977
  url: uploadedFile.content,
23897
23978
  }));
23898
- if (spaceTrim$2(messageContent) === '' && attachments.length === 0) {
23979
+ if (spaceTrim$1(messageContent) === '' && attachments.length === 0) {
23899
23980
  throw new Error(`You need to write some text or upload a file`);
23900
23981
  }
23901
23982
  if (soundSystem) {
@@ -23957,7 +24038,7 @@ function ChatInputArea(props) {
23957
24038
  }
23958
24039
  const resolvedAction = resolveChatEnterAction(resolvedBehavior, false);
23959
24040
  if (resolvedAction === 'SEND') {
23960
- const hasTextToSend = spaceTrim$2(snapshot.value) !== '' || snapshot.attachmentIds.length > 0;
24041
+ const hasTextToSend = spaceTrim$1(snapshot.value) !== '' || snapshot.attachmentIds.length > 0;
23961
24042
  if (!hasTextToSend) {
23962
24043
  return;
23963
24044
  }
@@ -24234,7 +24315,7 @@ function pipelineJsonToString(pipelineJson) {
24234
24315
  pipelineString += '\n\n';
24235
24316
  pipelineString += '```' + contentLanguage;
24236
24317
  pipelineString += '\n';
24237
- pipelineString += spaceTrim$2(content);
24318
+ pipelineString += spaceTrim$1(content);
24238
24319
  // <- TODO: [main] !!3 Escape
24239
24320
  // <- TODO: [🧠] Some clear strategy how to spaceTrim the blocks
24240
24321
  pipelineString += '\n';
@@ -25258,14 +25339,14 @@ class MultipleLlmExecutionTools {
25258
25339
  if (description === undefined) {
25259
25340
  return headLine;
25260
25341
  }
25261
- return spaceTrim$2((block) => `
25342
+ return spaceTrim$1((block) => `
25262
25343
  ${headLine}
25263
25344
 
25264
25345
  ${ /* <- Note: Indenting the description: */block(description)}
25265
25346
  `);
25266
25347
  })
25267
25348
  .join('\n\n');
25268
- return spaceTrim$2((block) => `
25349
+ return spaceTrim$1((block) => `
25269
25350
  Multiple LLM Providers:
25270
25351
 
25271
25352
  ${block(innerModelsTitlesAndDescriptions)}
@@ -25367,7 +25448,7 @@ class MultipleLlmExecutionTools {
25367
25448
  // 1) OpenAI throw PipelineExecutionError: Parameter `{knowledge}` is not defined
25368
25449
  // 2) AnthropicClaude throw PipelineExecutionError: Parameter `{knowledge}` is not defined
25369
25450
  // 3) ...
25370
- spaceTrim$2((block) => `
25451
+ spaceTrim$1((block) => `
25371
25452
  All execution tools of ${this.title} failed:
25372
25453
 
25373
25454
  ${block(errors
@@ -25380,7 +25461,7 @@ class MultipleLlmExecutionTools {
25380
25461
  throw new PipelineExecutionError(`You have not provided any \`LlmExecutionTools\` into ${this.title}`);
25381
25462
  }
25382
25463
  else {
25383
- throw new PipelineExecutionError(spaceTrim$2((block) => `
25464
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
25384
25465
  You have not provided any \`LlmExecutionTools\` that support model variant "${prompt.modelRequirements.modelVariant}" into ${this.title}
25385
25466
 
25386
25467
  Available \`LlmExecutionTools\`:
@@ -25417,7 +25498,7 @@ class MultipleLlmExecutionTools {
25417
25498
  */
25418
25499
  function joinLlmExecutionTools(title, ...llmExecutionTools) {
25419
25500
  if (llmExecutionTools.length === 0) {
25420
- const warningMessage = spaceTrim$2(`
25501
+ const warningMessage = spaceTrim$1(`
25421
25502
  You have not provided any \`LlmExecutionTools\`
25422
25503
  This means that you won't be able to execute any prompts that require large language models like GPT-4 or Anthropic's Claude.
25423
25504
 
@@ -25594,14 +25675,14 @@ function $registeredScrapersMessage(availableScrapers) {
25594
25675
  return { ...metadata, isMetadataAviailable, isInstalled, isAvailableInTools };
25595
25676
  });
25596
25677
  if (metadata.length === 0) {
25597
- return spaceTrim$2(`
25678
+ return spaceTrim$1(`
25598
25679
  **No scrapers are available**
25599
25680
 
25600
25681
  This is a unexpected behavior, you are probably using some broken version of Promptbook
25601
25682
  At least there should be available the metadata of the scrapers
25602
25683
  `);
25603
25684
  }
25604
- return spaceTrim$2((block) => `
25685
+ return spaceTrim$1((block) => `
25605
25686
  Available scrapers are:
25606
25687
  ${block(metadata
25607
25688
  .map(({ packageName, className, isMetadataAviailable, isInstalled, mimeTypes, isAvailableInBrowser, isAvailableInTools, }, i) => {
@@ -25728,7 +25809,7 @@ const promptbookFetch = async (urlOrRequest, init) => {
25728
25809
  else if (urlOrRequest instanceof Request) {
25729
25810
  url = urlOrRequest.url;
25730
25811
  }
25731
- throw new PromptbookFetchError(spaceTrim$2((block) => `
25812
+ throw new PromptbookFetchError(spaceTrim$1((block) => `
25732
25813
  Can not fetch "${url}"
25733
25814
 
25734
25815
  Fetch error:
@@ -25888,7 +25969,7 @@ async function makeKnowledgeSourceHandler(knowledgeSource, tools, options) {
25888
25969
  const fileExtension = getFileExtension(filename);
25889
25970
  const mimeType = extensionToMimeType(fileExtension || '');
25890
25971
  if (!(await isFileExisting(filename, tools.fs))) {
25891
- throw new NotFoundError(spaceTrim$2((block) => `
25972
+ throw new NotFoundError(spaceTrim$1((block) => `
25892
25973
  Can not make source handler for file which does not exist:
25893
25974
 
25894
25975
  File:
@@ -25981,7 +26062,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
25981
26062
  // <- TODO: [🪓] Here should be no need for spreading new array, just `partialPieces = partialPiecesUnchecked`
25982
26063
  break;
25983
26064
  }
25984
- console.warn(spaceTrim$2((block) => `
26065
+ console.warn(spaceTrim$1((block) => `
25985
26066
  Cannot scrape knowledge from source despite the scraper \`${scraper.metadata.className}\` supports the mime type "${sourceHandler.mimeType}".
25986
26067
 
25987
26068
  The source:
@@ -25997,7 +26078,7 @@ async function prepareKnowledgePieces(knowledgeSources, tools, options) {
25997
26078
  // <- TODO: [🏮] Some standard way how to transform errors into warnings and how to handle non-critical fails during the tasks
25998
26079
  }
25999
26080
  if (partialPieces === null) {
26000
- throw new KnowledgeScrapeError(spaceTrim$2((block) => `
26081
+ throw new KnowledgeScrapeError(spaceTrim$1((block) => `
26001
26082
  Cannot scrape knowledge
26002
26083
 
26003
26084
  The source:
@@ -26434,7 +26515,7 @@ const CsvFormatParser = {
26434
26515
  const { value, outputParameterName, settings, mapCallback, onProgress } = options;
26435
26516
  const csv = csvParse(value, settings);
26436
26517
  if (csv.errors.length !== 0) {
26437
- throw new CsvFormatError(spaceTrim$2((block) => `
26518
+ throw new CsvFormatError(spaceTrim$1((block) => `
26438
26519
  CSV parsing error
26439
26520
 
26440
26521
  Error(s) from CSV parsing:
@@ -26479,7 +26560,7 @@ const CsvFormatParser = {
26479
26560
  const { value, settings, mapCallback, onProgress } = options;
26480
26561
  const csv = csvParse(value, settings);
26481
26562
  if (csv.errors.length !== 0) {
26482
- throw new CsvFormatError(spaceTrim$2((block) => `
26563
+ throw new CsvFormatError(spaceTrim$1((block) => `
26483
26564
  CSV parsing error
26484
26565
 
26485
26566
  Error(s) from CSV parsing:
@@ -26665,7 +26746,7 @@ function mapAvailableToExpectedParameters(options) {
26665
26746
  }
26666
26747
  // Phase 2️⃣: Non-matching mapping
26667
26748
  if (expectedParameterNames.size !== availableParametersNames.size) {
26668
- throw new PipelineExecutionError(spaceTrim$2((block) => `
26749
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
26669
26750
  Can not map available parameters to expected parameters
26670
26751
 
26671
26752
  Mapped parameters:
@@ -27238,7 +27319,7 @@ async function executeFormatSubvalues(options) {
27238
27319
  return /* not await */ executeAttempts({ ...options, logLlmCall });
27239
27320
  }
27240
27321
  if (jokerParameterNames.length !== 0) {
27241
- throw new UnexpectedError(spaceTrim$2((block) => `
27322
+ throw new UnexpectedError(spaceTrim$1((block) => `
27242
27323
  JOKER parameters are not supported together with FOREACH command
27243
27324
 
27244
27325
  [🧞‍♀️] This should be prevented in \`validatePipeline\`
@@ -27251,7 +27332,7 @@ async function executeFormatSubvalues(options) {
27251
27332
  if (formatDefinition === undefined) {
27252
27333
  throw new UnexpectedError(
27253
27334
  // <- TODO: [🧠][🧐] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
27254
- spaceTrim$2((block) => `
27335
+ spaceTrim$1((block) => `
27255
27336
  Unsupported format "${task.foreach.formatName}"
27256
27337
 
27257
27338
  Available formats:
@@ -27268,7 +27349,7 @@ async function executeFormatSubvalues(options) {
27268
27349
  if (subvalueParser === undefined) {
27269
27350
  throw new UnexpectedError(
27270
27351
  // <- TODO: [🧠][🧐] Should be formats fixed per promptbook version or behave as plugins (=> change UnexpectedError)
27271
- spaceTrim$2((block) => `
27352
+ spaceTrim$1((block) => `
27272
27353
  Unsupported subformat name "${task.foreach.subformatName}" for format "${task.foreach.formatName}"
27273
27354
 
27274
27355
  Available subformat names for format "${formatDefinition.formatName}":
@@ -27308,7 +27389,7 @@ async function executeFormatSubvalues(options) {
27308
27389
  if (!(error instanceof PipelineExecutionError)) {
27309
27390
  throw error;
27310
27391
  }
27311
- const highLevelError = new PipelineExecutionError(spaceTrim$2((block) => `
27392
+ const highLevelError = new PipelineExecutionError(spaceTrim$1((block) => `
27312
27393
  ${error.message}
27313
27394
 
27314
27395
  This is error in FOREACH command when mapping ${formatDefinition.formatName} ${subvalueParser.subvalueName} data (${index + 1}/${length})
@@ -27332,7 +27413,7 @@ async function executeFormatSubvalues(options) {
27332
27413
  ...options,
27333
27414
  priority: priority + index,
27334
27415
  parameters: allSubparameters,
27335
- pipelineIdentification: spaceTrim$2((block) => `
27416
+ pipelineIdentification: spaceTrim$1((block) => `
27336
27417
  ${block(pipelineIdentification)}
27337
27418
  Subparameter index: ${index}
27338
27419
  `),
@@ -27341,7 +27422,7 @@ async function executeFormatSubvalues(options) {
27341
27422
  }
27342
27423
  catch (error) {
27343
27424
  if (length > BIG_DATASET_TRESHOLD) {
27344
- console.error(spaceTrim$2((block) => `
27425
+ console.error(spaceTrim$1((block) => `
27345
27426
  ${error.message}
27346
27427
 
27347
27428
  This is error in FOREACH command when processing ${formatDefinition.formatName} ${subvalueParser.subvalueName} data (${index + 1}/${length})
@@ -28772,7 +28853,7 @@ import { assertsError } from '../../errors/assertsError';
28772
28853
  /**
28773
28854
  * Description of the FORMAT command
28774
28855
  */
28775
- description: spaceTrim$2(`
28856
+ description: spaceTrim$1(`
28776
28857
  Expect command describes the desired output of the task *(after post-processing)*
28777
28858
  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.
28778
28859
  `),
@@ -28846,7 +28927,7 @@ import { assertsError } from '../../errors/assertsError';
28846
28927
  }
28847
28928
  catch (error) {
28848
28929
  assertsError(error);
28849
- throw new ParseError(spaceTrim$2((block) => `
28930
+ throw new ParseError(spaceTrim$1((block) => `
28850
28931
  Invalid FORMAT command
28851
28932
  ${block(error.message)}:
28852
28933
  `));
@@ -28912,7 +28993,7 @@ import { assertsError } from '../../errors/assertsError';
28912
28993
  /**
28913
28994
  * Description of the FORMAT command
28914
28995
  */
28915
- description: spaceTrim$2(`
28996
+ description: spaceTrim$1(`
28916
28997
  Format command describes the desired output of the task (after post-processing)
28917
28998
  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.
28918
28999
  `),
@@ -29502,7 +29583,7 @@ function pricing(value) {
29502
29583
  /**
29503
29584
  * List of available OpenAI models with pricing
29504
29585
  *
29505
- * Note: Synced with official API docs at 2025-11-19
29586
+ * Note: Synced with official API docs at 2026-03-22
29506
29587
  *
29507
29588
  * @see https://platform.openai.com/docs/models/
29508
29589
  * @see https://openai.com/api/pricing/
@@ -29624,8 +29705,8 @@ const OPENAI_MODELS = exportJson({
29624
29705
  modelName: 'gpt-4.1',
29625
29706
  modelDescription: 'Smartest non-reasoning model with 128K context window. Enhanced version of GPT-4 with improved instruction following, better factual accuracy, and reduced hallucinations. Features advanced function calling capabilities and superior performance on coding tasks. Ideal for applications requiring high intelligence without reasoning overhead.',
29626
29707
  pricing: {
29627
- prompt: pricing(`$3.00 / 1M tokens`),
29628
- output: pricing(`$12.00 / 1M tokens`),
29708
+ prompt: pricing(`$2.00 / 1M tokens`),
29709
+ output: pricing(`$8.00 / 1M tokens`),
29629
29710
  },
29630
29711
  },
29631
29712
  /**/
@@ -29636,8 +29717,8 @@ const OPENAI_MODELS = exportJson({
29636
29717
  modelName: 'gpt-4.1-mini',
29637
29718
  modelDescription: 'Smaller, faster version of GPT-4.1 with 128K context window. Balances intelligence and efficiency with 3x faster inference than base GPT-4.1. Maintains strong capabilities across text generation, reasoning, and coding while offering better cost-performance ratio for most applications.',
29638
29719
  pricing: {
29639
- prompt: pricing(`$0.80 / 1M tokens`),
29640
- output: pricing(`$3.20 / 1M tokens`),
29720
+ prompt: pricing(`$0.40 / 1M tokens`),
29721
+ output: pricing(`$1.60 / 1M tokens`),
29641
29722
  },
29642
29723
  },
29643
29724
  /**/
@@ -29648,8 +29729,8 @@ const OPENAI_MODELS = exportJson({
29648
29729
  modelName: 'gpt-4.1-nano',
29649
29730
  modelDescription: 'Fastest, most cost-efficient version of GPT-4.1 with 128K context window. Optimized for high-throughput applications requiring good quality at minimal cost. Features 5x faster inference than GPT-4.1 while maintaining adequate performance for most general-purpose tasks.',
29650
29731
  pricing: {
29651
- prompt: pricing(`$0.20 / 1M tokens`),
29652
- output: pricing(`$0.80 / 1M tokens`),
29732
+ prompt: pricing(`$0.10 / 1M tokens`),
29733
+ output: pricing(`$0.40 / 1M tokens`),
29653
29734
  },
29654
29735
  },
29655
29736
  /**/
@@ -29660,8 +29741,8 @@ const OPENAI_MODELS = exportJson({
29660
29741
  modelName: 'o3',
29661
29742
  modelDescription: 'Advanced reasoning model with 128K context window specializing in complex logical, mathematical, and analytical tasks. Successor to o1 with enhanced step-by-step problem-solving capabilities and superior performance on STEM-focused problems. Ideal for professional applications requiring deep analytical thinking and precise reasoning.',
29662
29743
  pricing: {
29663
- prompt: pricing(`$15.00 / 1M tokens`),
29664
- output: pricing(`$60.00 / 1M tokens`),
29744
+ prompt: pricing(`$2.00 / 1M tokens`),
29745
+ output: pricing(`$8.00 / 1M tokens`),
29665
29746
  },
29666
29747
  },
29667
29748
  /**/
@@ -29672,8 +29753,8 @@ const OPENAI_MODELS = exportJson({
29672
29753
  modelName: 'o3-pro',
29673
29754
  modelDescription: 'Enhanced version of o3 with more compute allocated for better responses on the most challenging problems. Features extended reasoning time and improved accuracy on complex analytical tasks. Designed for applications where maximum reasoning quality is more important than response speed.',
29674
29755
  pricing: {
29675
- prompt: pricing(`$30.00 / 1M tokens`),
29676
- output: pricing(`$120.00 / 1M tokens`),
29756
+ prompt: pricing(`$20.00 / 1M tokens`),
29757
+ output: pricing(`$80.00 / 1M tokens`),
29677
29758
  },
29678
29759
  },
29679
29760
  /**/
@@ -29684,8 +29765,8 @@ const OPENAI_MODELS = exportJson({
29684
29765
  modelName: 'o4-mini',
29685
29766
  modelDescription: 'Fast, cost-efficient reasoning model with 128K context window. Successor to o1-mini with improved analytical capabilities while maintaining speed advantages. Features enhanced mathematical reasoning and logical problem-solving at significantly lower cost than full reasoning models.',
29686
29767
  pricing: {
29687
- prompt: pricing(`$4.00 / 1M tokens`),
29688
- output: pricing(`$16.00 / 1M tokens`),
29768
+ prompt: pricing(`$1.10 / 1M tokens`),
29769
+ output: pricing(`$4.40 / 1M tokens`),
29689
29770
  },
29690
29771
  },
29691
29772
  /**/
@@ -30043,8 +30124,8 @@ const OPENAI_MODELS = exportJson({
30043
30124
  modelName: 'gpt-4o-2024-05-13',
30044
30125
  modelDescription: 'May 2024 version of GPT-4o with 128K context window. Features enhanced multimodal capabilities including superior image understanding (up to 20MP), audio processing, and improved reasoning. Optimized for 2x lower latency than GPT-4 Turbo while maintaining high performance. Includes knowledge up to October 2023. Ideal for production applications requiring reliable multimodal capabilities.',
30045
30126
  pricing: {
30046
- prompt: pricing(`$5.00 / 1M tokens`),
30047
- output: pricing(`$15.00 / 1M tokens`),
30127
+ prompt: pricing(`$2.50 / 1M tokens`),
30128
+ output: pricing(`$10.00 / 1M tokens`),
30048
30129
  },
30049
30130
  },
30050
30131
  /**/
@@ -30055,8 +30136,8 @@ const OPENAI_MODELS = exportJson({
30055
30136
  modelName: 'gpt-4o',
30056
30137
  modelDescription: "OpenAI's most advanced general-purpose multimodal model with 128K context window. Optimized for balanced performance, speed, and cost with 2x faster responses than GPT-4 Turbo. Features excellent vision processing, audio understanding, reasoning, and text generation quality. Represents optimal balance of capability and efficiency for most advanced applications.",
30057
30138
  pricing: {
30058
- prompt: pricing(`$5.00 / 1M tokens`),
30059
- output: pricing(`$15.00 / 1M tokens`),
30139
+ prompt: pricing(`$2.50 / 1M tokens`),
30140
+ output: pricing(`$10.00 / 1M tokens`),
30060
30141
  },
30061
30142
  },
30062
30143
  /**/
@@ -30127,8 +30208,8 @@ const OPENAI_MODELS = exportJson({
30127
30208
  modelName: 'o3-mini',
30128
30209
  modelDescription: 'Cost-effective reasoning model with 128K context window optimized for academic and scientific problem-solving. Features efficient performance on STEM tasks with specialized capabilities in mathematics, physics, chemistry, and computer science. Offers 80% of O1 performance on technical domains at significantly lower cost. Ideal for educational applications and research support.',
30129
30210
  pricing: {
30130
- prompt: pricing(`$3.00 / 1M tokens`),
30131
- output: pricing(`$12.00 / 1M tokens`),
30211
+ prompt: pricing(`$1.10 / 1M tokens`),
30212
+ output: pricing(`$4.40 / 1M tokens`),
30132
30213
  },
30133
30214
  },
30134
30215
  /**/
@@ -30228,53 +30309,6 @@ resultContent, rawResponse, duration = ZERO_VALUE) {
30228
30309
  * TODO: [🤝] DRY Maybe some common abstraction between `computeOpenAiUsage` and `computeAnthropicClaudeUsage`
30229
30310
  */
30230
30311
 
30231
- /**
30232
- * Maps Promptbook tools to OpenAI tools.
30233
- *
30234
- * @private
30235
- */
30236
- function mapToolsToOpenAi(tools) {
30237
- return tools.map((tool) => ({
30238
- type: 'function',
30239
- function: {
30240
- name: tool.name,
30241
- description: tool.description,
30242
- parameters: tool.parameters,
30243
- },
30244
- }));
30245
- }
30246
-
30247
- /**
30248
- * Builds a tool invocation script that injects hidden runtime context into tool args.
30249
- *
30250
- * @private utility of OpenAI tool execution wrappers
30251
- */
30252
- function buildToolInvocationScript(options) {
30253
- const { functionName, functionArgsExpression } = options;
30254
- return `
30255
- const args = ${functionArgsExpression};
30256
- const runtimeContextRaw =
30257
- typeof ${TOOL_RUNTIME_CONTEXT_PARAMETER} === 'undefined'
30258
- ? undefined
30259
- : ${TOOL_RUNTIME_CONTEXT_PARAMETER};
30260
-
30261
- if (runtimeContextRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
30262
- args.${TOOL_RUNTIME_CONTEXT_ARGUMENT} = runtimeContextRaw;
30263
- }
30264
-
30265
- const toolProgressTokenRaw =
30266
- typeof ${TOOL_PROGRESS_TOKEN_PARAMETER} === 'undefined'
30267
- ? undefined
30268
- : ${TOOL_PROGRESS_TOKEN_PARAMETER};
30269
-
30270
- if (toolProgressTokenRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
30271
- args.${TOOL_PROGRESS_TOKEN_ARGUMENT} = toolProgressTokenRaw;
30272
- }
30273
-
30274
- return await ${functionName}(args);
30275
- `;
30276
- }
30277
-
30278
30312
  /**
30279
30313
  * Parses an OpenAI error message to identify which parameter is unsupported
30280
30314
  *
@@ -30331,6 +30365,53 @@ function isUnsupportedParameterError(error) {
30331
30365
  errorMessage.includes('does not support'));
30332
30366
  }
30333
30367
 
30368
+ /**
30369
+ * Builds a tool invocation script that injects hidden runtime context into tool args.
30370
+ *
30371
+ * @private utility of OpenAI tool execution wrappers
30372
+ */
30373
+ function buildToolInvocationScript(options) {
30374
+ const { functionName, functionArgsExpression } = options;
30375
+ return `
30376
+ const args = ${functionArgsExpression};
30377
+ const runtimeContextRaw =
30378
+ typeof ${TOOL_RUNTIME_CONTEXT_PARAMETER} === 'undefined'
30379
+ ? undefined
30380
+ : ${TOOL_RUNTIME_CONTEXT_PARAMETER};
30381
+
30382
+ if (runtimeContextRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
30383
+ args.${TOOL_RUNTIME_CONTEXT_ARGUMENT} = runtimeContextRaw;
30384
+ }
30385
+
30386
+ const toolProgressTokenRaw =
30387
+ typeof ${TOOL_PROGRESS_TOKEN_PARAMETER} === 'undefined'
30388
+ ? undefined
30389
+ : ${TOOL_PROGRESS_TOKEN_PARAMETER};
30390
+
30391
+ if (toolProgressTokenRaw !== undefined && args && typeof args === 'object' && !Array.isArray(args)) {
30392
+ args.${TOOL_PROGRESS_TOKEN_ARGUMENT} = toolProgressTokenRaw;
30393
+ }
30394
+
30395
+ return await ${functionName}(args);
30396
+ `;
30397
+ }
30398
+
30399
+ /**
30400
+ * Maps Promptbook tools to OpenAI tools.
30401
+ *
30402
+ * @private
30403
+ */
30404
+ function mapToolsToOpenAi(tools) {
30405
+ return tools.map((tool) => ({
30406
+ type: 'function',
30407
+ function: {
30408
+ name: tool.name,
30409
+ description: tool.description,
30410
+ parameters: tool.parameters,
30411
+ },
30412
+ }));
30413
+ }
30414
+
30334
30415
  /**
30335
30416
  * Provides access to the structured clone implementation when available.
30336
30417
  */
@@ -31297,7 +31378,7 @@ class OpenAiCompatibleExecutionTools {
31297
31378
  // Note: Match exact or prefix for model families
31298
31379
  const model = this.HARDCODED_MODELS.find(({ modelName }) => modelName === defaultModelName || modelName.startsWith(defaultModelName));
31299
31380
  if (model === undefined) {
31300
- throw new PipelineExecutionError(spaceTrim$2((block) => `
31381
+ throw new PipelineExecutionError(spaceTrim$1((block) => `
31301
31382
  Cannot find model in ${this.title} models with name "${defaultModelName}" which should be used as default.
31302
31383
 
31303
31384
  Available models:
@@ -32223,7 +32304,7 @@ class OpenAiVectorStoreHandler extends OpenAiExecutionTools {
32223
32304
  }
32224
32305
  }
32225
32306
 
32226
- const DEFAULT_AGENT_KIT_MODEL_NAME = 'gpt-5-mini-2025-08-07';
32307
+ const DEFAULT_AGENT_KIT_MODEL_NAME = 'gpt-5.4-nano';
32227
32308
  /**
32228
32309
  * Creates one structured log entry for streamed tool-call updates.
32229
32310
  *
@@ -32718,7 +32799,7 @@ class OpenAiAgentKitExecutionTools extends OpenAiVectorStoreHandler {
32718
32799
  }),
32719
32800
  ],
32720
32801
  };
32721
- const errorMessage = spaceTrim$2((block) => `
32802
+ const errorMessage = spaceTrim$1((block) => `
32722
32803
 
32723
32804
  The invoked tool \`${functionName}\` failed with error:
32724
32805
 
@@ -33436,7 +33517,7 @@ class OpenAiAssistantExecutionTools extends OpenAiVectorStoreHandler {
33436
33517
  assertsError(error);
33437
33518
  const serializedError = serializeError(error);
33438
33519
  errors = [serializedError];
33439
- functionResponse = spaceTrim$2((block) => `
33520
+ functionResponse = spaceTrim$1((block) => `
33440
33521
 
33441
33522
  The invoked tool \`${functionName}\` failed with error:
33442
33523
 
@@ -34444,7 +34525,7 @@ class SelfLearningManager {
34444
34525
  if (isJsonSchemaResponseFormat(responseFormat)) {
34445
34526
  const jsonSchema = responseFormat.json_schema;
34446
34527
  const schemaJson = JSON.stringify(jsonSchema, null, 4);
34447
- userMessageContent = spaceTrim$2((block) => `
34528
+ userMessageContent = spaceTrim$1((block) => `
34448
34529
  ${block(prompt.content)}
34449
34530
 
34450
34531
  NOTE Request was made through OpenAI Compatible API with \`response_format\` of type \`json_schema\` with the following schema:
@@ -34475,12 +34556,12 @@ class SelfLearningManager {
34475
34556
  const formattedAgentMessage = formatAgentMessageForJsonMode(result.content, usesJsonSchemaMode);
34476
34557
  const teacherInstructions = extractOpenTeacherInstructions(agentSource);
34477
34558
  const teacherInstructionsSection = teacherInstructions
34478
- ? spaceTrim$2((block) => `
34559
+ ? spaceTrim$1((block) => `
34479
34560
  **Teacher instructions:**
34480
34561
  ${block(teacherInstructions)}
34481
34562
  `)
34482
34563
  : '';
34483
- const teacherPromptContent = spaceTrim$2((block) => `
34564
+ const teacherPromptContent = spaceTrim$1((block) => `
34484
34565
 
34485
34566
  You are a teacher agent helping another agent to learn from its interactions.
34486
34567
 
@@ -34513,7 +34594,7 @@ class SelfLearningManager {
34513
34594
  ? '- This interaction used JSON mode, so the agent answer should stay as a formatted JSON code block.'
34514
34595
  : ''}
34515
34596
  ${block(isInitialMessageMissing
34516
- ? spaceTrim$2(`
34597
+ ? spaceTrim$1(`
34517
34598
  - The agent source does not have an INITIAL MESSAGE defined, generate one.
34518
34599
  - The INITIAL MESSAGE should be welcoming, informative about the agent capabilities and also should give some quick options to start the conversation with the agent.
34519
34600
  - The quick option looks like \`[👋 Hello](?message=Hello, how are you?)\`
@@ -34556,7 +34637,7 @@ class SelfLearningManager {
34556
34637
  */
34557
34638
  appendToAgentSource(section) {
34558
34639
  const currentSource = this.options.getAgentSource();
34559
- const newSource = padBook(validateBook(spaceTrim$2(currentSource) + section));
34640
+ const newSource = padBook(validateBook(spaceTrim$1(currentSource) + section));
34560
34641
  this.options.updateAgentSource(newSource);
34561
34642
  }
34562
34643
  }
@@ -34584,13 +34665,13 @@ function formatAgentMessageForJsonMode(content, isJsonMode) {
34584
34665
  }
34585
34666
  const parsedJson = tryParseJson(content);
34586
34667
  if (parsedJson === null) {
34587
- return spaceTrim$2((block) => `
34668
+ return spaceTrim$1((block) => `
34588
34669
  \`\`\`json
34589
34670
  ${block(content)}
34590
34671
  \`\`\`
34591
34672
  `);
34592
34673
  }
34593
- return spaceTrim$2((block) => `
34674
+ return spaceTrim$1((block) => `
34594
34675
  \`\`\`json
34595
34676
  ${block(JSON.stringify(parsedJson, null, 4))}
34596
34677
  \`\`\`
@@ -34622,7 +34703,7 @@ function formatSelfLearningSample(options) {
34622
34703
  const internalMessagesSection = options.internalMessages
34623
34704
  .map((internalMessage) => formatInternalLearningMessage(internalMessage))
34624
34705
  .join('\n\n');
34625
- return spaceTrim$2((block) => `
34706
+ return spaceTrim$1((block) => `
34626
34707
 
34627
34708
  USER MESSAGE
34628
34709
  ${block(options.userMessageContent)}
@@ -34640,7 +34721,7 @@ function formatSelfLearningSample(options) {
34640
34721
  * @private function of Agent
34641
34722
  */
34642
34723
  function formatInternalLearningMessage(internalMessage) {
34643
- return spaceTrim$2((block) => `
34724
+ return spaceTrim$1((block) => `
34644
34725
  INTERNAL MESSAGE
34645
34726
  ${block(stringifyInternalLearningPayload(internalMessage))}
34646
34727
  `);
@@ -35144,7 +35225,7 @@ function book(strings, ...values) {
35144
35225
  const bookString = prompt(strings, ...values).toString();
35145
35226
  if (!isValidPipelineString(bookString)) {
35146
35227
  // TODO: Make the CustomError for this
35147
- throw new Error(spaceTrim$2(`
35228
+ throw new Error(spaceTrim$1(`
35148
35229
  The string is not a valid pipeline string
35149
35230
 
35150
35231
  book\`
@@ -35154,7 +35235,7 @@ function book(strings, ...values) {
35154
35235
  }
35155
35236
  if (!isValidBook(bookString)) {
35156
35237
  // TODO: Make the CustomError for this
35157
- throw new Error(spaceTrim$2(`
35238
+ throw new Error(spaceTrim$1(`
35158
35239
  The string is not a valid book
35159
35240
 
35160
35241
  book\`
@@ -35423,7 +35504,7 @@ function buildRemoteAgentSource(profile, meta) {
35423
35504
  .filter((line) => Boolean(line))
35424
35505
  .join('\n');
35425
35506
  const personaBlock = profile.personaDescription
35426
- ? spaceTrim$2((block) => `
35507
+ ? spaceTrim$1((block) => `
35427
35508
  PERSONA
35428
35509
  ${block(profile.personaDescription || '')}
35429
35510
  `)
@@ -35459,7 +35540,7 @@ class RemoteAgent extends Agent {
35459
35540
  // <- TODO: [🐱‍🚀] What about closed-source agents?
35460
35541
  // <- TODO: [🐱‍🚀] Maybe use promptbookFetch
35461
35542
  if (!profileResponse.ok) {
35462
- throw new Error(spaceTrim$2((block) => `
35543
+ throw new Error(spaceTrim$1((block) => `
35463
35544
  Failed to fetch remote agent profile:
35464
35545
 
35465
35546
  Agent URL:
@@ -38141,6 +38222,7 @@ const TOOL_TITLES = {
38141
38222
  useTime: { title: 'Checking time', emoji: '🕒' },
38142
38223
  set_timeout: { title: 'Setting timer', emoji: '⏱️' },
38143
38224
  cancel_timeout: { title: 'Cancelling timer', emoji: '⏱️' },
38225
+ list_timeouts: { title: 'Listing timers', emoji: '⏱️' },
38144
38226
  get_user_location: { title: 'Checking location', emoji: '📍' },
38145
38227
  send_email: { title: 'Sending email', emoji: '📧' },
38146
38228
  useEmail: { title: 'Sending email', emoji: '📧' },
@@ -38505,11 +38587,11 @@ function splitMessageContentByImagePrompts(content) {
38505
38587
  });
38506
38588
  }
38507
38589
  const decodedPrompt = decodePrompt(rawPrompt);
38508
- const prompt = spaceTrim$2(decodedPrompt) || decodedPrompt || 'Generated image';
38590
+ const prompt = spaceTrim$1(decodedPrompt) || decodedPrompt || 'Generated image';
38509
38591
  const decodedAlt = decodePrompt(alt);
38510
38592
  segments.push({
38511
38593
  type: 'image',
38512
- alt: spaceTrim$2(decodedAlt) || 'Generated image',
38594
+ alt: spaceTrim$1(decodedAlt) || 'Generated image',
38513
38595
  prompt,
38514
38596
  });
38515
38597
  lastIndex = start + fullMatch.length;
@@ -39209,7 +39291,7 @@ async function fetchGeneratedImageUrl(filename) {
39209
39291
  * @private internal component of `<ChatMessageItem/>`
39210
39292
  */
39211
39293
  function ImagePromptRenderer({ alt, prompt }) {
39212
- const trimmedPrompt = useMemo(() => spaceTrim$2(prompt), [prompt]);
39294
+ const trimmedPrompt = useMemo(() => spaceTrim$1(prompt), [prompt]);
39213
39295
  const filename = useMemo(() => constructImageFilename({
39214
39296
  prompt: trimmedPrompt,
39215
39297
  }), [trimmedPrompt]);
@@ -42871,7 +42953,7 @@ function AgentChat(props) {
42871
42953
  id: AGENT_CHAT_INITIAL_MESSAGE_ID,
42872
42954
  sender: 'AGENT',
42873
42955
  content: agent.initialMessage ||
42874
- spaceTrim$2(`
42956
+ spaceTrim$1(`
42875
42957
 
42876
42958
  Hello! I am ${agent.meta.fullname || agent.agentName || 'an AI Agent'}.
42877
42959