@promptbook/browser 0.105.0-0 → 0.105.0-10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +36 -77
  2. package/esm/index.es.js +591 -109
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/typings/src/_packages/browser.index.d.ts +2 -0
  5. package/esm/typings/src/_packages/core.index.d.ts +4 -0
  6. package/esm/typings/src/_packages/types.index.d.ts +16 -0
  7. package/esm/typings/src/_packages/utils.index.d.ts +2 -0
  8. package/esm/typings/src/book-2.0/agent-source/AgentBasicInformation.d.ts +15 -3
  9. package/esm/typings/src/book-2.0/agent-source/AgentModelRequirements.d.ts +11 -1
  10. package/esm/typings/src/book-2.0/agent-source/communication-samples.test.d.ts +1 -0
  11. package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.blocks.test.d.ts +1 -0
  12. package/esm/typings/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.import.test.d.ts +1 -0
  13. package/esm/typings/src/book-2.0/agent-source/parseAgentSource.import.test.d.ts +1 -0
  14. package/esm/typings/src/book-2.0/agent-source/parseAgentSourceWithCommitments.blocks.test.d.ts +1 -0
  15. package/esm/typings/src/book-components/Chat/AgentChat/AgentChatProps.d.ts +5 -0
  16. package/esm/typings/src/book-components/Chat/Chat/ChatMessageItem.d.ts +15 -1
  17. package/esm/typings/src/book-components/Chat/Chat/ChatProps.d.ts +20 -9
  18. package/esm/typings/src/book-components/Chat/LlmChat/LlmChatProps.d.ts +5 -0
  19. package/esm/typings/src/book-components/Chat/types/ChatMessage.d.ts +43 -0
  20. package/esm/typings/src/commitments/NOTE/NOTE.d.ts +2 -2
  21. package/esm/typings/src/commitments/USE_BROWSER/USE_BROWSER.d.ts +4 -0
  22. package/esm/typings/src/commitments/USE_SEARCH_ENGINE/USE_SEARCH_ENGINE.d.ts +10 -0
  23. package/esm/typings/src/commitments/USE_SEARCH_ENGINE/USE_SEARCH_ENGINE.test.d.ts +1 -0
  24. package/esm/typings/src/commitments/USE_TIME/USE_TIME.d.ts +44 -0
  25. package/esm/typings/src/commitments/USE_TIME/USE_TIME.test.d.ts +1 -0
  26. package/esm/typings/src/commitments/_base/BaseCommitmentDefinition.d.ts +14 -0
  27. package/esm/typings/src/commitments/_base/CommitmentDefinition.d.ts +14 -0
  28. package/esm/typings/src/commitments/index.d.ts +17 -2
  29. package/esm/typings/src/config.d.ts +1 -0
  30. package/esm/typings/src/execution/LlmExecutionTools.d.ts +3 -1
  31. package/esm/typings/src/import-plugins/$fileImportPlugins.d.ts +7 -0
  32. package/esm/typings/src/import-plugins/AgentFileImportPlugin.d.ts +7 -0
  33. package/esm/typings/src/import-plugins/FileImportPlugin.d.ts +24 -0
  34. package/esm/typings/src/import-plugins/JsonFileImportPlugin.d.ts +7 -0
  35. package/esm/typings/src/import-plugins/TextFileImportPlugin.d.ts +7 -0
  36. package/esm/typings/src/llm-providers/_common/utils/cache/cacheLlmTools.d.ts +2 -1
  37. package/esm/typings/src/llm-providers/_common/utils/count-total-usage/countUsage.d.ts +2 -2
  38. package/esm/typings/src/llm-providers/agent/Agent.d.ts +14 -2
  39. package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +3 -1
  40. package/esm/typings/src/llm-providers/agent/AgentOptions.d.ts +7 -0
  41. package/esm/typings/src/llm-providers/agent/RemoteAgent.d.ts +1 -0
  42. package/esm/typings/src/llm-providers/agent/RemoteAgentOptions.d.ts +1 -1
  43. package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +10 -0
  44. package/esm/typings/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +7 -0
  45. package/esm/typings/src/llm-providers/remote/RemoteLlmExecutionTools.d.ts +1 -1
  46. package/esm/typings/src/scripting/javascript/JavascriptExecutionToolsOptions.d.ts +6 -1
  47. package/esm/typings/src/search-engines/SearchEngine.d.ts +1 -1
  48. package/esm/typings/src/search-engines/_index.d.ts +6 -0
  49. package/esm/typings/src/search-engines/bing/BingSearchEngine.d.ts +1 -1
  50. package/esm/typings/src/search-engines/dummy/DummySearchEngine.d.ts +1 -1
  51. package/esm/typings/src/search-engines/google/GoogleSearchEngine.d.ts +18 -0
  52. package/esm/typings/src/search-engines/serp/SerpSearchEngine.d.ts +15 -0
  53. package/esm/typings/src/speech-recognition/BrowserSpeechRecognition.d.ts +21 -0
  54. package/esm/typings/src/speech-recognition/OpenAiSpeechRecognition.d.ts +32 -0
  55. package/esm/typings/src/types/ModelRequirements.d.ts +6 -12
  56. package/esm/typings/src/types/SpeechRecognition.d.ts +58 -0
  57. package/esm/typings/src/types/typeAliases.d.ts +4 -0
  58. package/esm/typings/src/utils/execCommand/$execCommandNormalizeOptions.d.ts +2 -3
  59. package/esm/typings/src/utils/execCommand/ExecCommandOptions.d.ts +7 -1
  60. package/esm/typings/src/utils/misc/linguisticHash.d.ts +6 -0
  61. package/esm/typings/src/utils/misc/linguisticHash.test.d.ts +1 -0
  62. package/esm/typings/src/utils/organization/keepImported.d.ts +9 -0
  63. package/esm/typings/src/utils/organization/keepTypeImported.d.ts +0 -1
  64. package/esm/typings/src/utils/random/$generateBookBoilerplate.d.ts +4 -0
  65. package/esm/typings/src/utils/random/$randomAgentPersona.d.ts +2 -1
  66. package/esm/typings/src/utils/random/$randomAgentRule.d.ts +14 -0
  67. package/esm/typings/src/version.d.ts +1 -1
  68. package/package.json +2 -2
  69. package/umd/index.umd.js +591 -108
  70. package/umd/index.umd.js.map +1 -1
package/esm/index.es.js CHANGED
@@ -19,7 +19,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
19
19
  * @generated
20
20
  * @see https://github.com/webgptorg/promptbook
21
21
  */
22
- const PROMPTBOOK_ENGINE_VERSION = '0.105.0-0';
22
+ const PROMPTBOOK_ENGINE_VERSION = '0.105.0-10';
23
23
  /**
24
24
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
25
25
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1071,6 +1071,7 @@ const PROMPTBOOK_COLOR = Color.fromString('promptbook');
1071
1071
  SEPARATOR: Color.fromHex('#cccccc'),
1072
1072
  COMMITMENT: Color.fromHex('#DA0F78'),
1073
1073
  PARAMETER: Color.fromHex('#8e44ad'),
1074
+ CODE_BLOCK: Color.fromHex('#7700ffff'),
1074
1075
  });
1075
1076
  // <- TODO: [🧠][🈵] Using `Color` here increases the package size approx 3kb, maybe remove it
1076
1077
  /**
@@ -1405,6 +1406,104 @@ async function $provideScrapersForBrowser(tools, options) {
1405
1406
  return scrapers;
1406
1407
  }
1407
1408
 
1409
+ /**
1410
+ * Speech recognition using Web Speech API `SpeechRecognition` available in modern browsers
1411
+ *
1412
+ * @public exported from `@promptbook/browser`
1413
+ */
1414
+ class BrowserSpeechRecognition {
1415
+ get state() {
1416
+ return this._state;
1417
+ }
1418
+ constructor() {
1419
+ this.recognition = null;
1420
+ this.callbacks = [];
1421
+ this._state = 'IDLE';
1422
+ if (typeof window !== 'undefined') {
1423
+ const SpeechRecognitionValue = window.SpeechRecognition ||
1424
+ window /* <- TODO: !!!! Make special windowAny */.webkitSpeechRecognition;
1425
+ if (SpeechRecognitionValue) {
1426
+ this.recognition = new SpeechRecognitionValue();
1427
+ this.recognition.continuous = true;
1428
+ this.recognition.interimResults = true;
1429
+ this.recognition.onstart = () => {
1430
+ this._state = 'RECORDING';
1431
+ this.emit({ type: 'START' });
1432
+ };
1433
+ this.recognition.onresult = (event) => {
1434
+ let finalTranscript = '';
1435
+ let interimTranscript = '';
1436
+ for (let i = event.resultIndex; i < event.results.length; ++i) {
1437
+ if (event.results[i].isFinal) {
1438
+ finalTranscript += event.results[i][0].transcript;
1439
+ }
1440
+ else {
1441
+ interimTranscript += event.results[i][0].transcript;
1442
+ }
1443
+ }
1444
+ const text = (finalTranscript + interimTranscript).trim();
1445
+ if (text) {
1446
+ this.emit({
1447
+ type: 'RESULT',
1448
+ text,
1449
+ isFinal: interimTranscript === '',
1450
+ });
1451
+ }
1452
+ };
1453
+ this.recognition.onerror = (event) => {
1454
+ this._state = 'ERROR';
1455
+ this.emit({ type: 'ERROR', message: event.error || 'Unknown error' });
1456
+ };
1457
+ this.recognition.onend = () => {
1458
+ this._state = 'IDLE';
1459
+ this.emit({ type: 'STOP' });
1460
+ };
1461
+ }
1462
+ }
1463
+ }
1464
+ $start(options = {}) {
1465
+ var _a;
1466
+ if (!this.recognition) {
1467
+ this.emit({ type: 'ERROR', message: 'Speech recognition is not supported in this browser.' });
1468
+ return;
1469
+ }
1470
+ if (this._state !== 'IDLE') {
1471
+ return;
1472
+ }
1473
+ this._state = 'STARTING';
1474
+ this.recognition.lang = options.language || 'en'; // Note: Web Speech API usually accepts ISO-639-1 or BCP-47
1475
+ this.recognition.interimResults = (_a = options.interimResults) !== null && _a !== void 0 ? _a : true;
1476
+ try {
1477
+ this.recognition.start();
1478
+ }
1479
+ catch (error) {
1480
+ this._state = 'ERROR';
1481
+ this.emit({ type: 'ERROR', message: error.message });
1482
+ }
1483
+ }
1484
+ $stop() {
1485
+ if (!this.recognition || this._state === 'IDLE') {
1486
+ return;
1487
+ }
1488
+ this.recognition.stop();
1489
+ }
1490
+ subscribe(callback) {
1491
+ this.callbacks.push(callback);
1492
+ return () => {
1493
+ this.callbacks = this.callbacks.filter((cb) => cb !== callback);
1494
+ };
1495
+ }
1496
+ emit(event) {
1497
+ for (const callback of this.callbacks) {
1498
+ callback(event);
1499
+ }
1500
+ }
1501
+ }
1502
+ /**
1503
+ * TODO: !!!! Search ACRY for `window` and put -> [🔵]
1504
+ * Note: [🔵] Code in this file should never be published outside of `@promptbook/browser`
1505
+ */
1506
+
1408
1507
  /**
1409
1508
  * Creates a PromptbookStorage backed by IndexedDB.
1410
1509
  * Uses a single object store named 'promptbook'.
@@ -2791,6 +2890,22 @@ class BaseCommitmentDefinition {
2791
2890
  return this.appendToSystemMessage(requirements, commentSection);
2792
2891
  }
2793
2892
  }
2893
+ /**
2894
+ * Gets tool function implementations provided by this commitment
2895
+ *
2896
+ * When the `applyToAgentModelRequirements` adds tools to the requirements, this method should return the corresponding function definitions.
2897
+ */
2898
+ getToolFunctions() {
2899
+ return {};
2900
+ }
2901
+ /**
2902
+ * Gets human-readable titles for tool functions provided by this commitment
2903
+ *
2904
+ * This is used in the UI to show a user-friendly name instead of the technical function name.
2905
+ */
2906
+ getToolTitles() {
2907
+ return {};
2908
+ }
2794
2909
  }
2795
2910
 
2796
2911
  /**
@@ -3406,79 +3521,6 @@ class FromCommitmentDefinition extends BaseCommitmentDefinition {
3406
3521
  * Note: [💞] Ignore a discrepancy between file name and entity name
3407
3522
  */
3408
3523
 
3409
- /**
3410
- * IMPORT commitment definition
3411
- *
3412
- * The IMPORT commitment tells the agent to import content from another agent at the current location.
3413
- *
3414
- * Example usage in agent source:
3415
- *
3416
- * ```book
3417
- * IMPORT https://s6.ptbk.io/benjamin-white
3418
- * ```
3419
- *
3420
- * @private [🪔] Maybe export the commitments through some package
3421
- */
3422
- class ImportCommitmentDefinition extends BaseCommitmentDefinition {
3423
- constructor(type = 'IMPORT') {
3424
- super(type);
3425
- }
3426
- /**
3427
- * Short one-line description of IMPORT.
3428
- */
3429
- get description() {
3430
- return 'Import content from another agent.';
3431
- }
3432
- /**
3433
- * Icon for this commitment.
3434
- */
3435
- get icon() {
3436
- return '📥';
3437
- }
3438
- /**
3439
- * Markdown documentation for IMPORT commitment.
3440
- */
3441
- get documentation() {
3442
- return spaceTrim$1(`
3443
- # ${this.type}
3444
-
3445
- Imports content from another agent at the location of the commitment.
3446
-
3447
- ## Examples
3448
-
3449
- \`\`\`book
3450
- My AI Agent
3451
-
3452
- IMPORT https://s6.ptbk.io/benjamin-white
3453
- RULE Speak only in English.
3454
- \`\`\`
3455
- `);
3456
- }
3457
- applyToAgentModelRequirements(requirements, content) {
3458
- const trimmedContent = content.trim();
3459
- if (!trimmedContent) {
3460
- return requirements;
3461
- }
3462
- if (!isValidAgentUrl(trimmedContent)) {
3463
- throw new Error(spaceTrim$1((block) => `
3464
- Invalid agent URL in IMPORT commitment: "${trimmedContent}"
3465
-
3466
- \`\`\`book
3467
- ${block(content)}
3468
- \`\`\`
3469
- `));
3470
- }
3471
- const importedAgentUrl = trimmedContent;
3472
- return {
3473
- ...requirements,
3474
- importedAgentUrls: [...(requirements.importedAgentUrls || []), importedAgentUrl],
3475
- };
3476
- }
3477
- }
3478
- /**
3479
- * Note: [💞] Ignore a discrepancy between file name and entity name
3480
- */
3481
-
3482
3524
  /**
3483
3525
  * GOAL commitment definition
3484
3526
  *
@@ -3579,6 +3621,87 @@ class GoalCommitmentDefinition extends BaseCommitmentDefinition {
3579
3621
  * Note: [💞] Ignore a discrepancy between file name and entity name
3580
3622
  */
3581
3623
 
3624
+ /**
3625
+ * IMPORT commitment definition
3626
+ *
3627
+ * The IMPORT commitment tells the agent to import content from another agent at the current location.
3628
+ *
3629
+ * Example usage in agent source:
3630
+ *
3631
+ * ```book
3632
+ * IMPORT https://s6.ptbk.io/benjamin-white
3633
+ * ```
3634
+ *
3635
+ * @private [🪔] Maybe export the commitments through some package
3636
+ */
3637
+ class ImportCommitmentDefinition extends BaseCommitmentDefinition {
3638
+ constructor(type = 'IMPORT') {
3639
+ super(type);
3640
+ }
3641
+ /**
3642
+ * Short one-line description of IMPORT.
3643
+ */
3644
+ get description() {
3645
+ return 'Import content from another agent or a generic text file.';
3646
+ }
3647
+ /**
3648
+ * Icon for this commitment.
3649
+ */
3650
+ get icon() {
3651
+ return '📥';
3652
+ }
3653
+ /**
3654
+ * Markdown documentation for IMPORT commitment.
3655
+ */
3656
+ get documentation() {
3657
+ return spaceTrim$1(`
3658
+ # ${this.type}
3659
+
3660
+ Imports content from another agent or a generic text file at the location of the commitment.
3661
+
3662
+ ## Examples
3663
+
3664
+ \`\`\`book
3665
+ My AI Agent
3666
+
3667
+ IMPORT https://s6.ptbk.io/benjamin-white
3668
+ IMPORT https://example.com/some-text-file.txt
3669
+ IMPORT ./path/to/local-file.json
3670
+ RULE Speak only in English.
3671
+ \`\`\`
3672
+ `);
3673
+ }
3674
+ applyToAgentModelRequirements(requirements, content) {
3675
+ const trimmedContent = content.trim();
3676
+ if (!trimmedContent) {
3677
+ return requirements;
3678
+ }
3679
+ if (isValidAgentUrl(trimmedContent)) {
3680
+ const importedAgentUrl = trimmedContent;
3681
+ return {
3682
+ ...requirements,
3683
+ importedAgentUrls: [...(requirements.importedAgentUrls || []), importedAgentUrl],
3684
+ };
3685
+ }
3686
+ if (isValidUrl(trimmedContent) || isValidFilePath(trimmedContent)) {
3687
+ return {
3688
+ ...requirements,
3689
+ importedFileUrls: [...(requirements.importedFileUrls || []), trimmedContent],
3690
+ };
3691
+ }
3692
+ throw new Error(spaceTrim$1((block) => `
3693
+ Invalid agent URL or file path in IMPORT commitment: "${trimmedContent}"
3694
+
3695
+ \`\`\`book
3696
+ ${block(content)}
3697
+ \`\`\`
3698
+ `));
3699
+ }
3700
+ }
3701
+ /**
3702
+ * Note: [💞] Ignore a discrepancy between file name and entity name
3703
+ */
3704
+
3582
3705
  /**
3583
3706
  * KNOWLEDGE commitment definition
3584
3707
  *
@@ -3998,7 +4121,13 @@ class InitialMessageCommitmentDefinition extends BaseCommitmentDefinition {
3998
4121
  `);
3999
4122
  }
4000
4123
  applyToAgentModelRequirements(requirements, content) {
4001
- return requirements;
4124
+ // INITIAL MESSAGE is for UI display purposes and for conversation history construction.
4125
+ const newSample = { question: null, answer: content };
4126
+ const newSamples = [...(requirements.samples || []), newSample];
4127
+ return {
4128
+ ...requirements,
4129
+ samples: newSamples,
4130
+ };
4002
4131
  }
4003
4132
  }
4004
4133
 
@@ -5030,27 +5159,16 @@ class NoteCommitmentDefinition extends BaseCommitmentDefinition {
5030
5159
  `);
5031
5160
  }
5032
5161
  applyToAgentModelRequirements(requirements, content) {
5033
- var _a;
5034
5162
  // The NOTE commitment makes no changes to the system message or model requirements
5035
5163
  // It only stores the note content in metadata for documentation purposes
5036
- const trimmedContent = content.trim();
5037
- if (!trimmedContent) {
5164
+ const trimmedContent = spaceTrim$1(content);
5165
+ if (trimmedContent === '') {
5038
5166
  return requirements;
5039
5167
  }
5040
- // Get existing note content from metadata
5041
- const existingNoteContent = ((_a = requirements.metadata) === null || _a === void 0 ? void 0 : _a.NOTE) || '';
5042
- // Merge the new content with existing note content
5043
- // When multiple NOTE commitments exist, they are aggregated together
5044
- const mergedNoteContent = existingNoteContent ? `${existingNoteContent}\n${trimmedContent}` : trimmedContent;
5045
- // Store the merged note content in metadata for debugging and inspection
5046
- const updatedMetadata = {
5047
- ...requirements.metadata,
5048
- NOTE: mergedNoteContent,
5049
- };
5050
- // Return requirements with updated metadata but no changes to system message
5168
+ // Return requirements with updated notes but no changes to system message
5051
5169
  return {
5052
5170
  ...requirements,
5053
- metadata: updatedMetadata,
5171
+ notes: [...(requirements.notes || []), trimmedContent],
5054
5172
  };
5055
5173
  }
5056
5174
  }
@@ -5834,6 +5952,14 @@ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
5834
5952
  \`\`\`
5835
5953
  `);
5836
5954
  }
5955
+ /**
5956
+ * Gets human-readable titles for tool functions provided by this commitment.
5957
+ */
5958
+ getToolTitles() {
5959
+ return {
5960
+ web_browser: 'Web browser',
5961
+ };
5962
+ }
5837
5963
  applyToAgentModelRequirements(requirements, content) {
5838
5964
  // Get existing tools array or create new one
5839
5965
  const existingTools = requirements.tools || [];
@@ -5862,14 +5988,17 @@ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
5862
5988
  },
5863
5989
  ]);
5864
5990
  // Return requirements with updated tools and metadata
5865
- return {
5991
+ return this.appendToSystemMessage({
5866
5992
  ...requirements,
5867
5993
  tools: updatedTools,
5868
5994
  metadata: {
5869
5995
  ...requirements.metadata,
5870
5996
  useBrowser: true,
5871
5997
  },
5872
- };
5998
+ }, spaceTrim$1(`
5999
+ You have access to the web browser. Use it to access specific websites or browse the internet.
6000
+ When you need to know some information from a specific website, use the tool provided to you.
6001
+ `));
5873
6002
  }
5874
6003
  }
5875
6004
  /**
@@ -5953,6 +6082,49 @@ class UseMcpCommitmentDefinition extends BaseCommitmentDefinition {
5953
6082
  * Note: [💞] Ignore a discrepancy between file name and entity name
5954
6083
  */
5955
6084
 
6085
+ /**
6086
+ * A search engine implementation that uses the SerpApi to fetch Google search results.
6087
+ *
6088
+ * @private <- TODO: !!!! Export via some package
6089
+ */
6090
+ class SerpSearchEngine {
6091
+ get title() {
6092
+ return 'SerpApi Search Engine';
6093
+ }
6094
+ get description() {
6095
+ return 'Search engine that uses SerpApi to fetch Google search results';
6096
+ }
6097
+ checkConfiguration() {
6098
+ if (!process.env.SERP_API_KEY) {
6099
+ throw new Error('SERP_API_KEY is not configured');
6100
+ }
6101
+ }
6102
+ async search(query, options = {}) {
6103
+ const apiKey = process.env.SERP_API_KEY;
6104
+ if (!apiKey) {
6105
+ throw new Error('SERP_API_KEY is not configured');
6106
+ }
6107
+ const url = new URL('https://serpapi.com/search');
6108
+ url.searchParams.set('api_key', apiKey);
6109
+ url.searchParams.set('engine', 'google');
6110
+ url.searchParams.set('q', query);
6111
+ for (const [key, value] of Object.entries(options)) {
6112
+ url.searchParams.set(key, String(value));
6113
+ }
6114
+ const response = await fetch(url.toString());
6115
+ if (!response.ok) {
6116
+ const body = await response.text();
6117
+ throw new Error(`SerpApi failed with status ${response.status}: ${response.statusText}\n${body}`);
6118
+ }
6119
+ const data = (await response.json());
6120
+ return (data.organic_results || []).map((item) => ({
6121
+ title: item.title,
6122
+ url: item.link,
6123
+ snippet: item.snippet || '',
6124
+ }));
6125
+ }
6126
+ }
6127
+
5956
6128
  /**
5957
6129
  * USE SEARCH ENGINE commitment definition
5958
6130
  *
@@ -5972,7 +6144,7 @@ class UseMcpCommitmentDefinition extends BaseCommitmentDefinition {
5972
6144
  */
5973
6145
  class UseSearchEngineCommitmentDefinition extends BaseCommitmentDefinition {
5974
6146
  constructor() {
5975
- super('USE SEARCH ENGINE', ['SEARCH ENGINE', 'SEARCH']);
6147
+ super('USE SEARCH ENGINE', ['USE SEARCH']);
5976
6148
  }
5977
6149
  /**
5978
6150
  * Short one-line description of USE SEARCH ENGINE.
@@ -6029,18 +6201,13 @@ class UseSearchEngineCommitmentDefinition extends BaseCommitmentDefinition {
6029
6201
  ? existingTools
6030
6202
  : [
6031
6203
  ...existingTools,
6032
- { type: 'web_search' },
6033
- // <- Note: [🔰] This is just using simple native search tool by OpenAI @see https://platform.openai.com/docs/guides/tools-web-search
6034
- // In future we will use proper MCP search tool:
6035
- /*
6036
-
6037
6204
  {
6038
6205
  name: 'web_search',
6039
- description: spaceTrim(`
6040
- Search the internet for information.
6041
- Use this tool when you need to find up-to-date information or facts that you don't know.
6042
- ${!content ? '' : `Search scope / instructions: ${content}`}
6043
- `),
6206
+ description: spaceTrim$1(`
6207
+ Search the internet for information.
6208
+ Use this tool when you need to find up-to-date information or facts that you don't know.
6209
+ ${!content ? '' : `Search scope / instructions: ${content}`}
6210
+ `),
6044
6211
  parameters: {
6045
6212
  type: 'object',
6046
6213
  properties: {
@@ -6048,20 +6215,224 @@ class UseSearchEngineCommitmentDefinition extends BaseCommitmentDefinition {
6048
6215
  type: 'string',
6049
6216
  description: 'The search query',
6050
6217
  },
6218
+ location: {
6219
+ type: 'string',
6220
+ description: 'The location for the search (e.g., "Austin, Texas, United States" or "Prague, Czechia")',
6221
+ },
6222
+ gl: {
6223
+ type: 'string',
6224
+ description: 'The country code (e.g., "us" for United States, "cz" for Czechia)',
6225
+ },
6226
+ hl: {
6227
+ type: 'string',
6228
+ description: 'The language code (e.g., "en" for English, "cs" for Czech)',
6229
+ },
6230
+ num: {
6231
+ type: 'integer',
6232
+ description: 'Number of results to return',
6233
+ },
6234
+ engine: {
6235
+ type: 'string',
6236
+ description: 'The search engine to use (e.g., "google", "bing", "yahoo", "baidu")',
6237
+ },
6238
+ google_domain: {
6239
+ type: 'string',
6240
+ description: 'The Google domain to use (e.g., "google.com", "google.cz")',
6241
+ },
6051
6242
  },
6052
6243
  required: ['query'],
6053
6244
  },
6054
6245
  },
6055
- */
6056
6246
  ];
6057
6247
  // Return requirements with updated tools and metadata
6058
- return {
6248
+ return this.appendToSystemMessage({
6059
6249
  ...requirements,
6060
6250
  tools: updatedTools,
6061
6251
  metadata: {
6062
6252
  ...requirements.metadata,
6063
6253
  useSearchEngine: content || true,
6064
6254
  },
6255
+ }, spaceTrim$1(`
6256
+ You have access to the web search engine. Use it to find up-to-date information or facts that you don't know.
6257
+ When you need to know some information from the internet, use the tool provided to you.
6258
+ `));
6259
+ }
6260
+ /**
6261
+ * Gets human-readable titles for tool functions provided by this commitment.
6262
+ */
6263
+ getToolTitles() {
6264
+ return {
6265
+ web_search: 'Web search',
6266
+ };
6267
+ }
6268
+ /**
6269
+ * Gets the `web_search` tool function implementation.
6270
+ */
6271
+ getToolFunctions() {
6272
+ return {
6273
+ async web_search(args) {
6274
+ console.log('!!!! [Tool] web_search called', { args });
6275
+ const { query, ...options } = args;
6276
+ if (!query) {
6277
+ throw new Error('Search query is required');
6278
+ }
6279
+ const searchEngine = new SerpSearchEngine();
6280
+ const results = await searchEngine.search(query, options);
6281
+ return spaceTrim$1((block) => `
6282
+ Search results for "${query}"${Object.keys(options).length === 0
6283
+ ? ''
6284
+ : ` with options ${JSON.stringify(options)}`}:
6285
+
6286
+ ${block(results
6287
+ .map((result) => spaceTrim$1(`
6288
+ - **${result.title}**
6289
+ ${result.url}
6290
+ ${result.snippet}
6291
+ `))
6292
+ .join('\n\n'))}
6293
+ `);
6294
+ },
6295
+ };
6296
+ }
6297
+ }
6298
+ /**
6299
+ * Note: [💞] Ignore a discrepancy between file name and entity name
6300
+ */
6301
+
6302
+ /**
6303
+ * USE TIME commitment definition
6304
+ *
6305
+ * The `USE TIME` commitment indicates that the agent should be able to determine the current date and time.
6306
+ *
6307
+ * Example usage in agent source:
6308
+ *
6309
+ * ```book
6310
+ * USE TIME
6311
+ * ```
6312
+ *
6313
+ * @private [🪔] Maybe export the commitments through some package
6314
+ */
6315
+ class UseTimeCommitmentDefinition extends BaseCommitmentDefinition {
6316
+ constructor() {
6317
+ super('USE TIME', ['CURRENT TIME', 'TIME', 'DATE']);
6318
+ }
6319
+ /**
6320
+ * Short one-line description of USE TIME.
6321
+ */
6322
+ get description() {
6323
+ return 'Enable the agent to determine the current date and time.';
6324
+ }
6325
+ /**
6326
+ * Icon for this commitment.
6327
+ */
6328
+ get icon() {
6329
+ return '🕒';
6330
+ }
6331
+ /**
6332
+ * Markdown documentation for USE TIME commitment.
6333
+ */
6334
+ get documentation() {
6335
+ return spaceTrim$1(`
6336
+ # USE TIME
6337
+
6338
+ Enables the agent to determine the current date and time.
6339
+
6340
+ ## Key aspects
6341
+
6342
+ - This tool won't receive any input.
6343
+ - It outputs the current date and time as an ISO 8601 string.
6344
+ - Allows the agent to answer questions about the current time or date.
6345
+
6346
+ ## Examples
6347
+
6348
+ \`\`\`book
6349
+ Time-aware Assistant
6350
+
6351
+ PERSONA You are a helpful assistant who knows the current time.
6352
+ USE TIME
6353
+ \`\`\`
6354
+ `);
6355
+ }
6356
+ applyToAgentModelRequirements(requirements, content) {
6357
+ // Get existing tools array or create new one
6358
+ const existingTools = requirements.tools || [];
6359
+ // Add 'get_current_time' to tools if not already present
6360
+ const updatedTools = existingTools.some((tool) => tool.name === 'get_current_time')
6361
+ ? existingTools
6362
+ : [
6363
+ ...existingTools,
6364
+ {
6365
+ name: 'get_current_time',
6366
+ description: 'Get the current date and time in ISO 8601 format.',
6367
+ parameters: {
6368
+ type: 'object',
6369
+ properties: {
6370
+ timezone: {
6371
+ type: 'string',
6372
+ description: 'Optional timezone name (e.g. "Europe/Prague", "UTC", "America/New_York").',
6373
+ },
6374
+ },
6375
+ required: [],
6376
+ },
6377
+ },
6378
+ // <- TODO: !!!! define the function in LLM tools
6379
+ ];
6380
+ // Return requirements with updated tools and metadata
6381
+ return this.appendToSystemMessage({
6382
+ ...requirements,
6383
+ tools: updatedTools,
6384
+ metadata: {
6385
+ ...requirements.metadata,
6386
+ },
6387
+ }, spaceTrim$1(`
6388
+ You have access to the current date and time. Use it to answer questions about the current date and time.
6389
+ When you need to know the current date or time, use the tool provided to you.
6390
+ `));
6391
+ }
6392
+ /**
6393
+ * Gets human-readable titles for tool functions provided by this commitment.
6394
+ */
6395
+ getToolTitles() {
6396
+ return {
6397
+ get_current_time: 'Get current time',
6398
+ };
6399
+ }
6400
+ /**
6401
+ * Gets the `get_current_time` tool function implementation.
6402
+ */
6403
+ getToolFunctions() {
6404
+ return {
6405
+ async get_current_time(args) {
6406
+ var _a;
6407
+ console.log('!!!! [Tool] get_current_time called', { args });
6408
+ const { timezone } = args;
6409
+ if (!timezone) {
6410
+ return new Date().toISOString();
6411
+ }
6412
+ try {
6413
+ // Note: Returning ISO 8601 string but in the requested timezone
6414
+ const formatter = new Intl.DateTimeFormat('en-CA', {
6415
+ timeZone: timezone,
6416
+ year: 'numeric',
6417
+ month: '2-digit',
6418
+ day: '2-digit',
6419
+ hour: '2-digit',
6420
+ minute: '2-digit',
6421
+ second: '2-digit',
6422
+ hour12: false,
6423
+ timeZoneName: 'shortOffset',
6424
+ });
6425
+ const parts = formatter.formatToParts(new Date());
6426
+ const part = (type) => { var _a; return (_a = parts.find((p) => p.type === type)) === null || _a === void 0 ? void 0 : _a.value; };
6427
+ // en-CA format is YYYY-MM-DD
6428
+ const isoString = `${part('year')}-${part('month')}-${part('day')}T${part('hour')}:${part('minute')}:${part('second')}${(_a = part('timeZoneName')) === null || _a === void 0 ? void 0 : _a.replace('GMT', '')}`;
6429
+ return isoString;
6430
+ }
6431
+ catch (error) {
6432
+ // Fallback to UTC if timezone is invalid
6433
+ return new Date().toISOString();
6434
+ }
6435
+ },
6065
6436
  };
6066
6437
  }
6067
6438
  }
@@ -6136,7 +6507,6 @@ class NotYetImplementedCommitmentDefinition extends BaseCommitmentDefinition {
6136
6507
  }
6137
6508
  }
6138
6509
 
6139
- // Import all commitment definition classes
6140
6510
  /**
6141
6511
  * Registry of all available commitment definitions
6142
6512
  * This array contains instances of all commitment definitions
@@ -6153,10 +6523,10 @@ const COMMITMENT_REGISTRY = [
6153
6523
  new MemoryCommitmentDefinition('MEMORIES'),
6154
6524
  new StyleCommitmentDefinition('STYLE'),
6155
6525
  new StyleCommitmentDefinition('STYLES'),
6156
- new RuleCommitmentDefinition('RULE'),
6157
6526
  new RuleCommitmentDefinition('RULES'),
6158
- new LanguageCommitmentDefinition('LANGUAGE'),
6527
+ new RuleCommitmentDefinition('RULE'),
6159
6528
  new LanguageCommitmentDefinition('LANGUAGES'),
6529
+ new LanguageCommitmentDefinition('LANGUAGE'),
6160
6530
  new SampleCommitmentDefinition('SAMPLE'),
6161
6531
  new SampleCommitmentDefinition('EXAMPLE'),
6162
6532
  new FormatCommitmentDefinition('FORMAT'),
@@ -6178,6 +6548,7 @@ const COMMITMENT_REGISTRY = [
6178
6548
  new NoteCommitmentDefinition('NOTES'),
6179
6549
  new NoteCommitmentDefinition('COMMENT'),
6180
6550
  new NoteCommitmentDefinition('NONCE'),
6551
+ new NoteCommitmentDefinition('TODO'),
6181
6552
  new GoalCommitmentDefinition('GOAL'),
6182
6553
  new GoalCommitmentDefinition('GOALS'),
6183
6554
  new InitialMessageCommitmentDefinition(),
@@ -6196,6 +6567,7 @@ const COMMITMENT_REGISTRY = [
6196
6567
  new ClosedCommitmentDefinition(),
6197
6568
  new UseBrowserCommitmentDefinition(),
6198
6569
  new UseSearchEngineCommitmentDefinition(),
6570
+ new UseTimeCommitmentDefinition(),
6199
6571
  new UseMcpCommitmentDefinition(),
6200
6572
  new UseCommitmentDefinition(),
6201
6573
  // Not yet implemented commitments (using placeholder)
@@ -6205,6 +6577,7 @@ const COMMITMENT_REGISTRY = [
6205
6577
  new NotYetImplementedCommitmentDefinition('AVOID'),
6206
6578
  new NotYetImplementedCommitmentDefinition('AVOIDANCE'),
6207
6579
  new NotYetImplementedCommitmentDefinition('CONTEXT'),
6580
+ // <- TODO: Prompt: Leverage aliases instead of duplicating commitment definitions
6208
6581
  ];
6209
6582
  /**
6210
6583
  * TODO: [🧠] Maybe create through standardized $register
@@ -6289,11 +6662,37 @@ function parseAgentSourceWithCommitments(agentSource) {
6289
6662
  let currentCommitment = null;
6290
6663
  // Process lines starting from after the agent name line
6291
6664
  const startIndex = agentNameLineIndex >= 0 ? agentNameLineIndex + 1 : 0;
6665
+ let isInsideCodeBlock = false;
6292
6666
  for (let i = startIndex; i < lines.length; i++) {
6293
6667
  const line = lines[i];
6294
6668
  if (line === undefined) {
6295
6669
  continue;
6296
6670
  }
6671
+ const trimmedLine = line.trim();
6672
+ // Check if this line starts or ends a code block
6673
+ if (trimmedLine.startsWith('```')) {
6674
+ isInsideCodeBlock = !isInsideCodeBlock;
6675
+ if (currentCommitment) {
6676
+ // If we are inside a commitment, the code block is part of it
6677
+ currentCommitment.contentLines.push(line);
6678
+ }
6679
+ else {
6680
+ // If we are not inside a commitment, the code block is non-commitment
6681
+ nonCommitmentLines.push(line);
6682
+ }
6683
+ continue;
6684
+ }
6685
+ if (isInsideCodeBlock) {
6686
+ if (currentCommitment) {
6687
+ // If we are inside a commitment and a code block, the line is part of the commitment
6688
+ currentCommitment.contentLines.push(line);
6689
+ }
6690
+ else {
6691
+ // If we are inside a code block but not a commitment, the line is non-commitment
6692
+ nonCommitmentLines.push(line);
6693
+ }
6694
+ continue;
6695
+ }
6297
6696
  // Check if this line starts a new commitment
6298
6697
  let foundNewCommitment = false;
6299
6698
  for (const definition of COMMITMENT_REGISTRY) {
@@ -6467,7 +6866,24 @@ function parseAgentSource(agentSource) {
6467
6866
  const meta = {};
6468
6867
  const links = [];
6469
6868
  const capabilities = [];
6869
+ const samples = [];
6870
+ let pendingUserMessage = null;
6470
6871
  for (const commitment of parseResult.commitments) {
6872
+ if (commitment.type === 'INITIAL MESSAGE') {
6873
+ samples.push({ question: null, answer: commitment.content });
6874
+ continue;
6875
+ }
6876
+ if (commitment.type === 'USER MESSAGE') {
6877
+ pendingUserMessage = commitment.content;
6878
+ continue;
6879
+ }
6880
+ if (commitment.type === 'AGENT MESSAGE') {
6881
+ if (pendingUserMessage !== null) {
6882
+ samples.push({ question: pendingUserMessage, answer: commitment.content });
6883
+ pendingUserMessage = null;
6884
+ }
6885
+ continue;
6886
+ }
6471
6887
  if (commitment.type === 'USE BROWSER') {
6472
6888
  capabilities.push({
6473
6889
  type: 'browser',
@@ -6484,6 +6900,71 @@ function parseAgentSource(agentSource) {
6484
6900
  });
6485
6901
  continue;
6486
6902
  }
6903
+ if (commitment.type === 'USE SEARCH') {
6904
+ capabilities.push({
6905
+ type: 'search-engine',
6906
+ label: 'Search Internet',
6907
+ iconName: 'Search',
6908
+ });
6909
+ continue;
6910
+ }
6911
+ if (commitment.type === 'USE TIME') {
6912
+ capabilities.push({
6913
+ type: 'time',
6914
+ label: 'Time',
6915
+ iconName: 'Clock',
6916
+ });
6917
+ continue;
6918
+ }
6919
+ if (commitment.type === 'FROM') {
6920
+ const content = spaceTrim$2(commitment.content).split('\n')[0] || '';
6921
+ if (content === 'Adam' || content === '' /* <- Note: Adam is implicit */) {
6922
+ continue;
6923
+ }
6924
+ let label = content;
6925
+ let iconName = 'SquareArrowOutUpRight'; // Inheritance remote
6926
+ if (content.startsWith('./') || content.startsWith('../') || content.startsWith('/')) {
6927
+ label = content.split('/').pop() || content;
6928
+ iconName = 'SquareArrowUpRight'; // Inheritance local
6929
+ }
6930
+ if (content === 'VOID') {
6931
+ label = 'VOID';
6932
+ iconName = 'ShieldAlert'; // [🧠] Or some other icon for VOID
6933
+ }
6934
+ capabilities.push({
6935
+ type: 'inheritance',
6936
+ label,
6937
+ iconName,
6938
+ agentUrl: content,
6939
+ });
6940
+ continue;
6941
+ }
6942
+ if (commitment.type === 'IMPORT') {
6943
+ const content = spaceTrim$2(commitment.content).split('\n')[0] || '';
6944
+ let label = content;
6945
+ let iconName = 'ExternalLink'; // Import remote
6946
+ try {
6947
+ if (content.startsWith('http://') || content.startsWith('https://')) {
6948
+ const url = new URL(content);
6949
+ label = url.hostname.replace(/^www\./, '') + '.../' + url.pathname.split('/').pop();
6950
+ iconName = 'ExternalLink';
6951
+ }
6952
+ else if (content.startsWith('./') || content.startsWith('../') || content.startsWith('/')) {
6953
+ label = content.split('/').pop() || content;
6954
+ iconName = 'Link'; // Import local
6955
+ }
6956
+ }
6957
+ catch (e) {
6958
+ // Invalid URL or path, keep default label
6959
+ }
6960
+ capabilities.push({
6961
+ type: 'import',
6962
+ label,
6963
+ iconName,
6964
+ agentUrl: content,
6965
+ });
6966
+ continue;
6967
+ }
6487
6968
  if (commitment.type === 'KNOWLEDGE') {
6488
6969
  const content = spaceTrim$2(commitment.content).split('\n')[0] || '';
6489
6970
  let label = content;
@@ -6568,6 +7049,7 @@ function parseAgentSource(agentSource) {
6568
7049
  links,
6569
7050
  parameters,
6570
7051
  capabilities,
7052
+ samples,
6571
7053
  };
6572
7054
  }
6573
7055
  /**
@@ -6705,5 +7187,5 @@ async function $induceBookDownload(book) {
6705
7187
  * Note: [🔵] Code in this file should never be published outside of `@promptbook/browser`
6706
7188
  */
6707
7189
 
6708
- export { $induceBookDownload, $induceFileDownload, $provideScrapersForBrowser, BOOK_LANGUAGE_VERSION, ObjectUrl, PROMPTBOOK_ENGINE_VERSION, SimplePromptInterfaceTools, getIndexedDbStorage, getLocalStorage, getSessionStorage };
7190
+ export { $induceBookDownload, $induceFileDownload, $provideScrapersForBrowser, BOOK_LANGUAGE_VERSION, BrowserSpeechRecognition, ObjectUrl, PROMPTBOOK_ENGINE_VERSION, SimplePromptInterfaceTools, getIndexedDbStorage, getLocalStorage, getSessionStorage };
6709
7191
  //# sourceMappingURL=index.es.js.map