@promptbook/browser 0.112.0-57 → 0.112.0-59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/umd/index.umd.js CHANGED
@@ -27,7 +27,7 @@
27
27
  * @generated
28
28
  * @see https://github.com/webgptorg/promptbook
29
29
  */
30
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-57';
30
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-59';
31
31
  /**
32
32
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
33
33
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1446,6 +1446,49 @@
1446
1446
  return this.appendToSystemMessage(requirements, commentSection);
1447
1447
  }
1448
1448
  }
1449
+ /**
1450
+ * Helper method to append a bullet point to an existing `## SectionTitle` section in the system
1451
+ * message, or to create a new section when it does not yet exist.
1452
+ *
1453
+ * Handles the case where the same commitment type appears multiple times in the book source and
1454
+ * all entries should be grouped under one shared heading rather than emitting a duplicate block.
1455
+ *
1456
+ * @param requirements - Current model requirements.
1457
+ * @param sectionTitle - Section title without the `##` prefix.
1458
+ * @param bulletContent - Bullet content without the leading `- ` prefix.
1459
+ * @returns Requirements with the bullet appended to the section.
1460
+ */
1461
+ appendBulletPointToSection(requirements, sectionTitle, bulletContent) {
1462
+ const sectionHeader = `## ${sectionTitle}`;
1463
+ const bullet = `- ${bulletContent}`;
1464
+ if (requirements.systemMessage.includes(sectionHeader)) {
1465
+ // Append bullet to end of existing section, before the next h2 heading or end of message
1466
+ const newSystemMessage = requirements.systemMessage.replace(new RegExp(`(## ${sectionTitle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\n\\n)([\\s\\S]*?)(?=\\n\\n##|$)`), `$1$2\n${bullet}`);
1467
+ return { ...requirements, systemMessage: newSystemMessage };
1468
+ }
1469
+ return this.appendToSystemMessage(requirements, `${sectionHeader}\n\n${bullet}`, '\n\n');
1470
+ }
1471
+ /**
1472
+ * Helper method to replace an existing `## SectionTitle` section in the system message, or to
1473
+ * append a new one when the section does not yet exist.
1474
+ *
1475
+ * Use this when a commitment type can appear multiple times and each subsequent occurrence should
1476
+ * update the single shared section rather than appending a duplicate block.
1477
+ *
1478
+ * @param requirements - Current model requirements.
1479
+ * @param sectionTitle - Section title without the `##` prefix.
1480
+ * @param sectionContent - Full section content including the `## Title` header line.
1481
+ * @returns Requirements with the section replaced or appended.
1482
+ */
1483
+ replaceOrCreateSection(requirements, sectionTitle, sectionContent) {
1484
+ const sectionHeader = `## ${sectionTitle}`;
1485
+ if (requirements.systemMessage.includes(sectionHeader)) {
1486
+ // Replace all text from the heading until the next h2 heading or end of message
1487
+ const newSystemMessage = requirements.systemMessage.replace(new RegExp(`## ${sectionTitle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}[\\s\\S]*?(?=\\n\\n##|$)`), sectionContent);
1488
+ return { ...requirements, systemMessage: newSystemMessage };
1489
+ }
1490
+ return this.appendToSystemMessage(requirements, sectionContent, '\n\n');
1491
+ }
1449
1492
  /**
1450
1493
  * Gets tool function implementations provided by this commitment
1451
1494
  *
@@ -1925,20 +1968,16 @@
1925
1968
  if (!trimmedContent) {
1926
1969
  return requirements;
1927
1970
  }
1928
- // Get existing dictionary entries from metadata
1971
+ // Store the entry in metadata for debugging and inspection
1929
1972
  const existingDictionary = ((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.DICTIONARY) || '';
1930
- // Merge the new dictionary entry with existing entries
1931
1973
  const mergedDictionary = existingDictionary ? `${existingDictionary}\n${trimmedContent}` : trimmedContent;
1932
- // Store the merged dictionary in metadata for debugging and inspection
1933
1974
  const updatedMetadata = {
1934
1975
  ...requirements._metadata,
1935
1976
  DICTIONARY: mergedDictionary,
1936
1977
  };
1937
- // Create the dictionary section for the system message
1938
- // Format: "# DICTIONARY\nTerm: definition\nTerm: definition..."
1939
- const dictionarySection = `# DICTIONARY\n${mergedDictionary}`;
1978
+ // Append each dictionary entry as a bullet point under ## Dictionary
1940
1979
  return {
1941
- ...this.appendToSystemMessage(requirements, dictionarySection),
1980
+ ...this.appendBulletPointToSection(requirements, 'Dictionary', trimmedContent),
1942
1981
  _metadata: updatedMetadata,
1943
1982
  };
1944
1983
  }
@@ -6613,10 +6652,10 @@
6613
6652
  if (!trimmedContent) {
6614
6653
  return requirements;
6615
6654
  }
6616
- // Add goal to the system message
6617
- const goalSection = `Goal: ${trimmedContent}`;
6655
+ // Add goal as a proper h2 section to the system message
6656
+ const goalSection = `## Goal\n\n${trimmedContent}`;
6618
6657
  const requirementsWithGoal = this.appendToSystemMessage(requirements, goalSection, '\n\n');
6619
- return this.appendToPromptSuffix(requirementsWithGoal, goalSection);
6658
+ return this.appendToPromptSuffix(requirementsWithGoal, trimmedContent);
6620
6659
  }
6621
6660
  }
6622
6661
  // Note: [💞] Ignore a discrepancy between file name and entity name
@@ -7136,11 +7175,8 @@
7136
7175
  if (!trimmedContent) {
7137
7176
  return requirements;
7138
7177
  }
7139
- // Add language rule to the system message
7140
- const languageSection = this.createSystemMessageSection('Language:', spacetrim.spaceTrim((block) => `
7141
- ${block(trimmedContent)}
7142
- <- You are speaking these languages in your responses to the user.
7143
- `));
7178
+ // Add language as a bullet under a ## Language section
7179
+ const languageSection = `## Language\n\n- Your language is ${trimmedContent}`;
7144
7180
  return this.appendToSystemMessage(requirements, languageSection, '\n\n');
7145
7181
  }
7146
7182
  }
@@ -7184,15 +7220,16 @@
7184
7220
  */
7185
7221
  function createMemorySystemMessage(extraInstructions) {
7186
7222
  return spacetrim.spaceTrim((block) => `
7187
- Memory:
7188
- - Prefer storing agent-scoped memories; only make them global when the fact should apply across all your agents.
7189
- - You can use persistent user memory tools.
7190
- - Use "${MemoryToolNames.retrieve}" to load relevant memory before answering.
7191
- - Use "${MemoryToolNames.store}" to save stable user-specific facts that improve future help.
7192
- - Use "${MemoryToolNames.update}" to refresh an existing memory when the content changes.
7193
- - Use "${MemoryToolNames.delete}" to delete memories that are no longer accurate (deletions are soft and hidden from future queries).
7194
- - Store concise memory items and avoid duplicates.
7195
- - Never claim memory was saved or loaded unless the tool confirms it.
7223
+ ## Memory
7224
+
7225
+ - Prefer storing agent-scoped memories; only make them global when the fact should apply across all your agents.
7226
+ - You can use persistent user memory tools.
7227
+ - Use \`${MemoryToolNames.retrieve}\` to load relevant memory before answering.
7228
+ - Use \`${MemoryToolNames.store}\` to save stable user-specific facts that improve future help.
7229
+ - Use \`${MemoryToolNames.update}\` to refresh an existing memory when the content changes.
7230
+ - Use \`${MemoryToolNames.delete}\` to delete memories that are no longer accurate (deletions are soft and hidden from future queries).
7231
+ - Store concise memory items and avoid duplicates.
7232
+ - Never claim memory was saved or loaded unless the tool confirms it.
7196
7233
  ${block(extraInstructions)}
7197
7234
  `);
7198
7235
  }
@@ -8114,10 +8151,8 @@
8114
8151
  if (!trimmedContent) {
8115
8152
  return requirements;
8116
8153
  }
8117
- // Create message section for system message
8118
- const messageSection = `Previous Message: ${trimmedContent}`;
8119
8154
  // Messages represent conversation history and should be included for context
8120
- return this.appendToSystemMessage(requirements, messageSection, '\n\n');
8155
+ return this.appendBulletPointToSection(requirements, 'Previous messages', trimmedContent);
8121
8156
  }
8122
8157
  }
8123
8158
  // Note: [💞] Ignore a discrepancy between file name and entity name
@@ -12911,10 +12946,9 @@
12911
12946
  if (!trimmedContent) {
12912
12947
  return requirements;
12913
12948
  }
12914
- // Add rule to the system message
12915
- const ruleSection = `Rule: ${trimmedContent}`;
12916
- const requirementsWithRule = this.appendToSystemMessage(requirements, ruleSection, '\n\n');
12917
- return this.appendToPromptSuffix(requirementsWithRule, ruleSection);
12949
+ // Group all rules under a single ## Rules section as bullet points
12950
+ const requirementsWithRule = this.appendBulletPointToSection(requirements, 'Rules', trimmedContent);
12951
+ return this.appendToPromptSuffix(requirementsWithRule, `- ${trimmedContent}`);
12918
12952
  }
12919
12953
  }
12920
12954
  // Note: [💞] Ignore a discrepancy between file name and entity name
@@ -13150,10 +13184,8 @@
13150
13184
  if (!trimmedContent) {
13151
13185
  return requirements;
13152
13186
  }
13153
- // Create scenario section for system message
13154
- const scenarioSection = `Scenario: ${trimmedContent}`;
13155
13187
  // Scenarios provide important contextual information that affects behavior
13156
- return this.appendToSystemMessage(requirements, scenarioSection, '\n\n');
13188
+ return this.appendBulletPointToSection(requirements, 'Scenarios', trimmedContent);
13157
13189
  }
13158
13190
  }
13159
13191
  // Note: [💞] Ignore a discrepancy between file name and entity name
@@ -13536,8 +13568,8 @@
13536
13568
  * @private
13537
13569
  */
13538
13570
  const TEAM_SYSTEM_MESSAGE_GUIDANCE_LINES = [
13539
- '- If a teammate is relevant to the request, consult that teammate using the matching tool.',
13540
- '- Do not ask the user for information that a listed teammate can provide directly.',
13571
+ '- If a teammate is relevant to the request, consult that teammate using the matching tool.',
13572
+ '- Do not ask the user for information that a listed teammate can provide directly.',
13541
13573
  ];
13542
13574
  /**
13543
13575
  * Constant for remote agents by Url.
@@ -13665,7 +13697,7 @@
13665
13697
  toolName: entry.toolName,
13666
13698
  });
13667
13699
  }
13668
- const teamSystemMessage = this.createSystemMessageSection('Teammates:', buildTeamSystemMessageBody(teamEntries));
13700
+ const teamSystemMessage = this.createSystemMessageSection('Teammates', buildTeamSystemMessageBody(teamEntries));
13669
13701
  return this.appendToSystemMessage({
13670
13702
  ...requirements,
13671
13703
  tools: updatedTools,
@@ -14155,36 +14187,38 @@
14155
14187
  switch (type) {
14156
14188
  case 'USE TIME':
14157
14189
  return spacetrim.spaceTrim((block) => `
14158
- Time and date context:
14159
- - It is ${moment__default["default"]().format('MMMM YYYY')} now.
14160
- - If you need more precise current time information, use the tool "get_current_time".
14190
+ ## Time and date context
14191
+
14192
+ - It is ${moment__default["default"]().format('MMMM YYYY')} now.
14193
+ - If you need more precise current time information, use the tool \`get_current_time\`.
14161
14194
  ${block(formatOptionalInstructionBlock('Time instructions', combinedAdditionalInstructions))}
14162
14195
  `);
14163
14196
  case 'USE BROWSER':
14164
14197
  return spacetrim.spaceTrim((block) => `
14165
- You have access to browser tools to fetch and access content from the internet.
14166
- - Use "fetch_url_content" to retrieve content from specific URLs (webpages or documents) using scrapers.
14167
- - Use "run_browser" for real interactive browser automation (navigation, clicks, typing, waiting, scrolling).
14168
- When you need to know information from a specific website or document, use the fetch_url_content tool.
14198
+ ## Browser
14199
+
14200
+ - Use \`fetch_url_content\` to retrieve content from specific URLs (webpages or documents) using scrapers.
14201
+ - Use \`run_browser\` for real interactive browser automation (navigation, clicks, typing, waiting, scrolling).
14202
+ - When you need to know information from a specific website or document, use the tools provided.
14169
14203
  ${block(formatOptionalInstructionBlock('Browser instructions', combinedAdditionalInstructions))}
14170
14204
  `);
14171
14205
  case 'USE SEARCH ENGINE':
14172
14206
  return spacetrim.spaceTrim((block) => `
14173
- Tool:
14174
- - You have access to the web search engine via the tool "web_search".
14175
- - Use it to find up-to-date information or facts that you don't know.
14176
- - When you need to know some information from the internet, use the tool provided to you.
14177
- - Do not make up information when you can search for it.
14178
- - Do not tell the user you cannot search for information, YOU CAN.
14207
+ ## Web Search
14208
+
14209
+ - Use \`web_search\` to find up-to-date information or facts.
14210
+ - When you need to know some information from the internet, use the search tool provided.
14211
+ - Do not make up information when you can search for it.
14212
+ - Do not tell the user you cannot search for information, YOU CAN.
14179
14213
  ${block(formatOptionalInstructionBlock('Search instructions', combinedAdditionalInstructions))}
14180
14214
  `);
14181
14215
  case 'USE DEEPSEARCH':
14182
14216
  return spacetrim.spaceTrim((block) => `
14183
- Tool:
14184
- - You have access to DeepSearch via the tool "deep_search".
14185
- - Use it for broader research tasks that need multi-step investigation, comparison, or synthesis across multiple sources.
14186
- - Prefer it over quick search when the user asks for a well-grounded brief, report, or deeper investigation.
14187
- - Do not pretend you cannot research current information when this tool is available.
14217
+ ## Deep Research
14218
+
14219
+ - Use \`deep_search\` for broader research tasks that need multi-step investigation, comparison, or synthesis across multiple sources.
14220
+ - Prefer it over quick search when the user asks for a well-grounded brief, report, or deeper investigation.
14221
+ - Do not pretend you cannot research current information when this tool is available.
14188
14222
  ${block(formatOptionalInstructionBlock('DeepSearch instructions', combinedAdditionalInstructions))}
14189
14223
  `);
14190
14224
  }
@@ -14514,96 +14548,6 @@
14514
14548
  }
14515
14549
  // Note: [💞] Ignore a discrepancy between file name and entity name
14516
14550
 
14517
- /**
14518
- * Base Google Calendar API URL.
14519
- *
14520
- * @private constant of callGoogleCalendarApi
14521
- */
14522
- const GOOGLE_CALENDAR_API_BASE_URL = 'https://www.googleapis.com/calendar/v3';
14523
- /**
14524
- * Runs one Google Calendar API request and parses JSON response payload.
14525
- *
14526
- * @private function of UseCalendarCommitmentDefinition
14527
- */
14528
- async function callGoogleCalendarApi(accessToken, options) {
14529
- const url = new URL(options.path, GOOGLE_CALENDAR_API_BASE_URL);
14530
- if (options.query) {
14531
- for (const [key, value] of Object.entries(options.query)) {
14532
- if (value && value.trim()) {
14533
- url.searchParams.set(key, value);
14534
- }
14535
- }
14536
- }
14537
- const response = await fetch(url.toString(), {
14538
- method: options.method,
14539
- headers: {
14540
- Authorization: `Bearer ${accessToken}`,
14541
- Accept: 'application/json',
14542
- 'Content-Type': 'application/json',
14543
- },
14544
- body: options.body ? JSON.stringify(options.body) : undefined,
14545
- });
14546
- const textPayload = await response.text();
14547
- const parsedPayload = tryParseJson$2(textPayload);
14548
- if (options.allowNotFound && response.status === 404) {
14549
- return null;
14550
- }
14551
- if (!response.ok) {
14552
- throw new Error(spacetrim.spaceTrim(`
14553
- Google Calendar API request failed (${response.status} ${response.statusText}):
14554
- ${extractGoogleCalendarApiErrorMessage(parsedPayload, textPayload)}
14555
- `));
14556
- }
14557
- return parsedPayload;
14558
- }
14559
- /**
14560
- * Parses raw text into JSON when possible.
14561
- *
14562
- * @private function of callGoogleCalendarApi
14563
- */
14564
- function tryParseJson$2(rawText) {
14565
- if (!rawText.trim()) {
14566
- return {};
14567
- }
14568
- try {
14569
- return JSON.parse(rawText);
14570
- }
14571
- catch (_a) {
14572
- return rawText;
14573
- }
14574
- }
14575
- /**
14576
- * Extracts a user-friendly Google Calendar API error message.
14577
- *
14578
- * @private function of callGoogleCalendarApi
14579
- */
14580
- function extractGoogleCalendarApiErrorMessage(parsedPayload, fallbackText) {
14581
- if (parsedPayload && typeof parsedPayload === 'object') {
14582
- const payload = parsedPayload;
14583
- const errorPayload = payload.error;
14584
- if (errorPayload && typeof errorPayload === 'object') {
14585
- const normalizedErrorPayload = errorPayload;
14586
- const message = typeof normalizedErrorPayload.message === 'string' ? normalizedErrorPayload.message : '';
14587
- const errors = Array.isArray(normalizedErrorPayload.errors) ? normalizedErrorPayload.errors : [];
14588
- const flattenedErrors = errors
14589
- .map((errorEntry) => {
14590
- if (!errorEntry || typeof errorEntry !== 'object') {
14591
- return '';
14592
- }
14593
- const normalizedErrorEntry = errorEntry;
14594
- const detailMessage = typeof normalizedErrorEntry.message === 'string' ? normalizedErrorEntry.message : '';
14595
- const reason = typeof normalizedErrorEntry.reason === 'string' ? normalizedErrorEntry.reason : '';
14596
- return [detailMessage, reason].filter(Boolean).join(' | ');
14597
- })
14598
- .filter(Boolean);
14599
- if (message || flattenedErrors.length > 0) {
14600
- return [message, ...flattenedErrors].filter(Boolean).join(' | ');
14601
- }
14602
- }
14603
- }
14604
- return fallbackText || 'Unknown Google Calendar API error';
14605
- }
14606
-
14607
14551
  /**
14608
14552
  * Hostnames accepted for Google Calendar references.
14609
14553
  *
@@ -14785,6 +14729,96 @@
14785
14729
  }
14786
14730
  // Note: [💞] Ignore a discrepancy between file name and entity name
14787
14731
 
14732
+ /**
14733
+ * Base Google Calendar API URL.
14734
+ *
14735
+ * @private constant of callGoogleCalendarApi
14736
+ */
14737
+ const GOOGLE_CALENDAR_API_BASE_URL = 'https://www.googleapis.com/calendar/v3';
14738
+ /**
14739
+ * Runs one Google Calendar API request and parses JSON response payload.
14740
+ *
14741
+ * @private function of UseCalendarCommitmentDefinition
14742
+ */
14743
+ async function callGoogleCalendarApi(accessToken, options) {
14744
+ const url = new URL(options.path, GOOGLE_CALENDAR_API_BASE_URL);
14745
+ if (options.query) {
14746
+ for (const [key, value] of Object.entries(options.query)) {
14747
+ if (value && value.trim()) {
14748
+ url.searchParams.set(key, value);
14749
+ }
14750
+ }
14751
+ }
14752
+ const response = await fetch(url.toString(), {
14753
+ method: options.method,
14754
+ headers: {
14755
+ Authorization: `Bearer ${accessToken}`,
14756
+ Accept: 'application/json',
14757
+ 'Content-Type': 'application/json',
14758
+ },
14759
+ body: options.body ? JSON.stringify(options.body) : undefined,
14760
+ });
14761
+ const textPayload = await response.text();
14762
+ const parsedPayload = tryParseJson$2(textPayload);
14763
+ if (options.allowNotFound && response.status === 404) {
14764
+ return null;
14765
+ }
14766
+ if (!response.ok) {
14767
+ throw new Error(spacetrim.spaceTrim(`
14768
+ Google Calendar API request failed (${response.status} ${response.statusText}):
14769
+ ${extractGoogleCalendarApiErrorMessage(parsedPayload, textPayload)}
14770
+ `));
14771
+ }
14772
+ return parsedPayload;
14773
+ }
14774
+ /**
14775
+ * Parses raw text into JSON when possible.
14776
+ *
14777
+ * @private function of callGoogleCalendarApi
14778
+ */
14779
+ function tryParseJson$2(rawText) {
14780
+ if (!rawText.trim()) {
14781
+ return {};
14782
+ }
14783
+ try {
14784
+ return JSON.parse(rawText);
14785
+ }
14786
+ catch (_a) {
14787
+ return rawText;
14788
+ }
14789
+ }
14790
+ /**
14791
+ * Extracts a user-friendly Google Calendar API error message.
14792
+ *
14793
+ * @private function of callGoogleCalendarApi
14794
+ */
14795
+ function extractGoogleCalendarApiErrorMessage(parsedPayload, fallbackText) {
14796
+ if (parsedPayload && typeof parsedPayload === 'object') {
14797
+ const payload = parsedPayload;
14798
+ const errorPayload = payload.error;
14799
+ if (errorPayload && typeof errorPayload === 'object') {
14800
+ const normalizedErrorPayload = errorPayload;
14801
+ const message = typeof normalizedErrorPayload.message === 'string' ? normalizedErrorPayload.message : '';
14802
+ const errors = Array.isArray(normalizedErrorPayload.errors) ? normalizedErrorPayload.errors : [];
14803
+ const flattenedErrors = errors
14804
+ .map((errorEntry) => {
14805
+ if (!errorEntry || typeof errorEntry !== 'object') {
14806
+ return '';
14807
+ }
14808
+ const normalizedErrorEntry = errorEntry;
14809
+ const detailMessage = typeof normalizedErrorEntry.message === 'string' ? normalizedErrorEntry.message : '';
14810
+ const reason = typeof normalizedErrorEntry.reason === 'string' ? normalizedErrorEntry.reason : '';
14811
+ return [detailMessage, reason].filter(Boolean).join(' | ');
14812
+ })
14813
+ .filter(Boolean);
14814
+ if (message || flattenedErrors.length > 0) {
14815
+ return [message, ...flattenedErrors].filter(Boolean).join(' | ');
14816
+ }
14817
+ }
14818
+ }
14819
+ return fallbackText || 'Unknown Google Calendar API error';
14820
+ }
14821
+
14788
14822
  /**
14789
14823
  * Wallet metadata used by USE CALENDAR when resolving Google Calendar credentials.
14790
14824
  *
@@ -15685,18 +15719,20 @@
15685
15719
  if (parsedCommitment.calendar) {
15686
15720
  addConfiguredCalendarIfMissing(existingConfiguredCalendars, parsedCommitment.calendar);
15687
15721
  }
15688
- const calendarsList = existingConfiguredCalendars.length > 0
15689
- ? existingConfiguredCalendars
15690
- .map((calendar) => [
15691
- `- ${calendar.provider}: ${calendar.url}`,
15692
- calendar.scopes.length > 0 ? ` scopes: ${calendar.scopes.join(', ')}` : '',
15693
- ]
15694
- .filter(Boolean)
15695
- .join('\n'))
15696
- .join('\n')
15697
- : '- Calendar is resolved from runtime context';
15722
+ const calendarBullets = existingConfiguredCalendars.length > 0
15723
+ ? existingConfiguredCalendars.map((calendar) => `- ${calendar.provider}: ${calendar.url}`).join('\n')
15724
+ : '- Calendar is resolved from runtime context';
15698
15725
  const extraInstructions = formatOptionalInstructionBlock('Calendar instructions', parsedCommitment.instructions);
15699
- return this.appendToSystemMessage({
15726
+ const calendarSectionContent = spacetrim.spaceTrim((block) => `
15727
+ ## Calendar
15728
+
15729
+ - Use \`calendar_list_events\`, \`calendar_get_event\`, \`calendar_create_event\`, \`calendar_update_event\`, \`calendar_delete_event\`, and \`calendar_invite_guests\` to manage events in configured calendars.
15730
+ - Supported operations include read, create, update, delete, invite guests, and reminders.
15731
+ - Configured calendars:
15732
+ ${block(calendarBullets)}
15733
+ ${block(extraInstructions)}
15734
+ `);
15735
+ return this.replaceOrCreateSection({
15700
15736
  ...requirements,
15701
15737
  tools: createUseCalendarTools(requirements.tools || []),
15702
15738
  _metadata: {
@@ -15704,16 +15740,7 @@
15704
15740
  useCalendar: true,
15705
15741
  useCalendars: existingConfiguredCalendars,
15706
15742
  },
15707
- }, spacetrim.spaceTrim((block) => `
15708
- Calendar tools:
15709
- - You can inspect and manage events in configured calendars.
15710
- - Supported operations include read, create, update, delete, invite guests, and reminders.
15711
- - Configured calendars:
15712
- ${block(calendarsList)}
15713
- - USE CALENDAR credentials are read from wallet records (ACCESS_TOKEN, service "${UseCalendarWallet.service}", key "${UseCalendarWallet.key}").
15714
- - If credentials are missing, ask user to connect calendar credentials in host UI and/or add them to wallet.
15715
- ${block(extraInstructions)}
15716
- `));
15743
+ }, 'Calendar', calendarSectionContent);
15717
15744
  }
15718
15745
  /**
15719
15746
  * Gets human-readable titles for tool functions provided by this commitment.
@@ -16050,18 +16077,6 @@
16050
16077
  * @private internal USE EMAIL constant
16051
16078
  */
16052
16079
  const SEND_EMAIL_TOOL_NAME = 'send_email';
16053
- /**
16054
- * Wallet service used for SMTP credentials required by USE EMAIL.
16055
- *
16056
- * @private internal USE EMAIL constant
16057
- */
16058
- const USE_EMAIL_SMTP_WALLET_SERVICE = 'smtp';
16059
- /**
16060
- * Wallet key used for SMTP credentials required by USE EMAIL.
16061
- *
16062
- * @private internal USE EMAIL constant
16063
- */
16064
- const USE_EMAIL_SMTP_WALLET_KEY = 'use-email-smtp-credentials';
16065
16080
  /**
16066
16081
  * USE EMAIL commitment definition.
16067
16082
  *
@@ -16120,31 +16135,41 @@
16120
16135
  `);
16121
16136
  }
16122
16137
  applyToAgentModelRequirements(requirements, content) {
16138
+ var _a;
16123
16139
  const parsedCommitment = parseUseEmailCommitmentContent(content);
16124
- const extraInstructions = formatOptionalInstructionBlock('Email instructions', parsedCommitment.instructions);
16125
- const senderInstruction = parsedCommitment.senderEmail
16126
- ? `- Default sender address from commitment: "${parsedCommitment.senderEmail}".`
16127
- : '';
16128
16140
  const updatedTools = addUseEmailTools(requirements.tools || []);
16129
- return this.appendToSystemMessage({
16141
+ // Collect all configured sender emails across multiple USE EMAIL commitments
16142
+ const existingSenders = Array.isArray((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.useEmailSenders)
16143
+ ? [...requirements._metadata.useEmailSenders]
16144
+ : [];
16145
+ if (parsedCommitment.senderEmail && !existingSenders.includes(parsedCommitment.senderEmail)) {
16146
+ existingSenders.push(parsedCommitment.senderEmail);
16147
+ }
16148
+ const senderBullets = existingSenders.length > 0
16149
+ ? existingSenders
16150
+ .map((email, index) => index === 0
16151
+ ? `- Default sender address: "${email}".`
16152
+ : `- Additional sender address: "${email}".`)
16153
+ .join('\n')
16154
+ : '';
16155
+ const extraInstructions = formatOptionalInstructionBlock('Email instructions', parsedCommitment.instructions);
16156
+ const emailSectionContent = spacetrim.spaceTrim((block) => `
16157
+ ## Emails
16158
+
16159
+ - Use \`${SEND_EMAIL_TOOL_NAME}\` to send outbound emails.
16160
+ ${block(senderBullets)}
16161
+ ${block(extraInstructions)}
16162
+ `);
16163
+ return this.replaceOrCreateSection({
16130
16164
  ...requirements,
16131
16165
  tools: updatedTools,
16132
16166
  _metadata: {
16133
16167
  ...requirements._metadata,
16134
16168
  useEmail: true,
16135
16169
  ...(parsedCommitment.senderEmail ? { useEmailSender: parsedCommitment.senderEmail } : {}),
16170
+ useEmailSenders: existingSenders,
16136
16171
  },
16137
- }, spacetrim.spaceTrim((block) => `
16138
- Email tool:
16139
- - Use "${SEND_EMAIL_TOOL_NAME}" to send outbound emails.
16140
- - Prefer \`message\` argument compatible with Promptbook \`Message\` type.
16141
- - Include subject in \`message.metadata.subject\` (or use legacy \`subject\` argument).
16142
- - USE EMAIL credentials are read from wallet records (ACCESS_TOKEN, service "${USE_EMAIL_SMTP_WALLET_SERVICE}", key "${USE_EMAIL_SMTP_WALLET_KEY}").
16143
- - Wallet secret must contain SMTP credentials in JSON format with fields \`host\`, \`port\`, \`secure\`, \`username\`, \`password\`.
16144
- - If credentials are missing, ask user to add wallet credentials.
16145
- ${block(senderInstruction)}
16146
- ${block(extraInstructions)}
16147
- `));
16172
+ }, 'Emails', emailSectionContent);
16148
16173
  }
16149
16174
  /**
16150
16175
  * Gets human-readable titles for tool functions provided by this commitment.
@@ -16180,13 +16205,13 @@
16180
16205
  ...existingTools,
16181
16206
  {
16182
16207
  name: SEND_EMAIL_TOOL_NAME,
16183
- description: 'Send an outbound email through configured SMTP credentials. Prefer providing Message-like payload in `message`.',
16208
+ description: 'Send an outbound email.',
16184
16209
  parameters: {
16185
16210
  type: 'object',
16186
16211
  properties: {
16187
16212
  message: {
16188
16213
  type: 'object',
16189
- description: 'Preferred input payload compatible with Promptbook Message type. Use metadata.subject for subject line.',
16214
+ description: 'Email payload. Use metadata.subject for the subject line.',
16190
16215
  },
16191
16216
  to: {
16192
16217
  type: 'string',
@@ -16290,13 +16315,14 @@
16290
16315
  useImageGenerator: content || true,
16291
16316
  },
16292
16317
  }, spacetrim.spaceTrim((block) => `
16293
- Image generation:
16294
- - You do not generate images directly and you do not call any image tool.
16295
- - When the user asks for an image, include markdown notation in your message:
16296
- \`![<alt text>](?image-prompt=<prompt>)\`
16297
- - Keep \`<alt text>\` short and descriptive.
16298
- - Keep \`<prompt>\` detailed so the generated image matches the request.
16299
- - You can include normal explanatory text before and after the notation.
16318
+ ## Image generation
16319
+
16320
+ - You do not generate images directly and you do not call any image tool.
16321
+ - When the user asks for an image, include markdown notation in your message:
16322
+ \`![<alt text>](?image-prompt=<prompt>)\`
16323
+ - Keep \`<alt text>\` short and descriptive.
16324
+ - Keep \`<prompt>\` detailed so the generated image matches the request.
16325
+ - You can include normal explanatory text before and after the notation.
16300
16326
  ${block(extraInstructions)}
16301
16327
  `));
16302
16328
  }
@@ -16476,11 +16502,12 @@
16476
16502
  usePopup: content || true,
16477
16503
  },
16478
16504
  }, spacetrim.spaceTrim((block) => `
16479
- Tool:
16480
- - You can open a popup window with a specific URL using the tool "open_popup".
16481
- - Use this when you want the user to see or interact with a specific website.
16505
+ ## Popup
16506
+
16507
+ - You can open a popup window with a specific URL using the tool \`open_popup\`.
16508
+ - Use this when you want the user to see or interact with a specific website.
16482
16509
  ${block(extraInstructions)}
16483
- `));
16510
+ `));
16484
16511
  }
16485
16512
  /**
16486
16513
  * Gets human-readable titles for tool functions provided by this commitment.
@@ -16654,11 +16681,12 @@
16654
16681
  usePrivacy: content || true,
16655
16682
  },
16656
16683
  }, spacetrim.spaceTrim((block) => `
16657
- Privacy mode:
16658
- - Use "${TURN_PRIVACY_ON_TOOL_NAME}" when the user asks for a private/sensitive conversation.
16659
- - This tool requests a UI confirmation dialog. Private mode is enabled only after user confirms.
16660
- - Current implementation uses the existing chat private mode (no chat persistence, memory persistence, or self-learning while active).
16661
- - Do not claim that end-to-end encryption is implemented yet.
16684
+ ## Privacy
16685
+
16686
+ - Use \`${TURN_PRIVACY_ON_TOOL_NAME}\` when the user asks for a private/sensitive conversation.
16687
+ - This tool requests a UI confirmation dialog. Private mode is enabled only after user confirms.
16688
+ - Current implementation uses the existing chat private mode (no chat persistence, memory persistence, or self-learning while active).
16689
+ - Do not claim that end-to-end encryption is implemented yet.
16662
16690
  ${block(extraInstructions)}
16663
16691
  `));
16664
16692
  }
@@ -18301,9 +18329,16 @@
18301
18329
  }
18302
18330
  const existingConfiguredProjects = normalizeConfiguredProjects((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.useProjects);
18303
18331
  addConfiguredProjectIfMissing(existingConfiguredProjects, parsedCommitment.repository);
18304
- const repositoriesList = existingConfiguredProjects.map((project) => `- ${project.url}`).join('\n');
18305
18332
  const extraInstructions = formatOptionalInstructionBlock('Project instructions', parsedCommitment.instructions);
18306
- return this.appendToSystemMessage({
18333
+ const sectionContent = spacetrim.spaceTrim((block) => `
18334
+ - You can inspect and edit configured GitHub repositories using project tools.
18335
+ - Configured repositories:
18336
+ ${block(existingConfiguredProjects.map((project) => `- ${project.url}`).join('\n'))}
18337
+ - When a repository is not obvious from context, pass \`repository\` in tool arguments explicitly.
18338
+ - If credentials are missing, ask the user to connect their GitHub account in the host UI.
18339
+ ${block(extraInstructions)}
18340
+ `);
18341
+ return this.replaceOrCreateSection({
18307
18342
  ...requirements,
18308
18343
  tools: createUseProjectTools(requirements.tools || []),
18309
18344
  _metadata: {
@@ -18311,16 +18346,7 @@
18311
18346
  useProject: true,
18312
18347
  useProjects: existingConfiguredProjects,
18313
18348
  },
18314
- }, spacetrim.spaceTrim((block) => `
18315
- Project tools:
18316
- - You can inspect and edit configured GitHub repositories using project tools.
18317
- - Configured repositories:
18318
- ${block(repositoriesList)}
18319
- - When a repository is not obvious from context, pass "repository" in tool arguments explicitly.
18320
- - USE PROJECT credentials are read from wallet records (ACCESS_TOKEN, service "${UseProjectWallet.service}", key "${UseProjectWallet.key}").
18321
- - If credentials are missing, ask the user to connect credentials in host UI and/or add them to wallet.
18322
- ${block(extraInstructions)}
18323
- `));
18349
+ }, 'GitHub repositories', sectionContent);
18324
18350
  }
18325
18351
  /**
18326
18352
  * Gets human-readable titles for tool functions provided by this commitment.
@@ -18667,11 +18693,12 @@
18667
18693
  useSpawn: content || true,
18668
18694
  },
18669
18695
  }, spacetrim.spaceTrim((block) => `
18670
- Spawning agents:
18671
- - Use "${SPAWN_AGENT_TOOL_NAME}" only when user asks to create a persistent new agent.
18672
- - Pass full agent source in \`source\`.
18673
- - Keep \`source\` concise; the maximum accepted length is ${CREATE_AGENT_INPUT_SOURCE_MAX_LENGTH} characters.
18674
- - Do not add unknown fields in tool arguments.
18696
+ ## Spawning agents
18697
+
18698
+ - Use \`${SPAWN_AGENT_TOOL_NAME}\` only when user asks to create a persistent new agent.
18699
+ - Pass full agent source in \`source\`.
18700
+ - Keep \`source\` concise; the maximum accepted length is ${CREATE_AGENT_INPUT_SOURCE_MAX_LENGTH} characters.
18701
+ - Do not add unknown fields in tool arguments.
18675
18702
  ${block(extraInstructions)}
18676
18703
  `));
18677
18704
  }
@@ -18705,13 +18732,14 @@
18705
18732
  */
18706
18733
  function createTimeoutSystemMessage(extraInstructions) {
18707
18734
  return spacetrim.spaceTrim((block) => `
18708
- Timeout scheduling:
18709
- - Use "set_timeout" to wake this same chat thread in the future.
18710
- - Use "list_timeouts" to review timeout ids/details across all chats for the same user+agent scope.
18711
- - "cancel_timeout" accepts either one timeout id or \`allActive: true\` to cancel all active timeouts in this same user+agent scope.
18712
- - Use "update_timeout" to pause/resume, edit next run, edit recurrence, or update timeout payload details.
18713
- - 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\`.
18714
- - Do not claim a timer was set or cancelled unless the tool confirms it.
18735
+ ## Timeout scheduling
18736
+
18737
+ - Use \`set_timeout\` to wake this same chat thread in the future.
18738
+ - Use \`list_timeouts\` to review timeout ids/details across all chats for the same user+agent scope.
18739
+ - \`cancel_timeout\` accepts either one timeout id or \`allActive: true\` to cancel all active timeouts in this same user+agent scope.
18740
+ - Use \`update_timeout\` to pause/resume, edit next run, edit recurrence, or update timeout payload details.
18741
+ - 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\`.
18742
+ - Do not claim a timer was set or cancelled unless the tool confirms it.
18715
18743
  ${block(extraInstructions)}
18716
18744
  `);
18717
18745
  }
@@ -19811,10 +19839,11 @@
19811
19839
  useUserLocation: content || true,
19812
19840
  },
19813
19841
  }, spacetrim.spaceTrim((block) => `
19814
- User location:
19815
- - Use "${GET_USER_LOCATION_TOOL_NAME}" only when location is needed for a better answer.
19816
- - If the tool returns "unavailable" or "permission-denied", ask user to share location or provide city manually.
19817
- - Do not invent coordinates or local facts when location is unavailable.
19842
+ ## User location
19843
+
19844
+ - Use \`${GET_USER_LOCATION_TOOL_NAME}\` only when location is needed for a better answer.
19845
+ - If the tool returns "unavailable" or "permission-denied", ask user to share location or provide city manually.
19846
+ - Do not invent coordinates or local facts when location is unavailable.
19818
19847
  ${block(extraInstructions)}
19819
19848
  `));
19820
19849
  }
@@ -26977,7 +27006,7 @@
26977
27006
  if (examples.length === 0) {
26978
27007
  return null;
26979
27008
  }
26980
- return `Example interaction:\n\n${examples.join('\n\n')}`;
27009
+ return `## Sample of communication with the agent:\n\n${examples.join('\n\n')}`;
26981
27010
  }
26982
27011
  /**
26983
27012
  * Collects the individual lines used in the example interaction section.
@@ -26993,11 +27022,11 @@
26993
27022
  const examples = [];
26994
27023
  const initialMessage = (_a = parseResult.commitments.find((commitment) => commitment.type === 'INITIAL MESSAGE')) === null || _a === void 0 ? void 0 : _a.content;
26995
27024
  if (initialMessage) {
26996
- examples.push(`Agent: ${initialMessage}`);
27025
+ examples.push(`**Agent:**\n${initialMessage}`);
26997
27026
  }
26998
27027
  if (samples && samples.length > 0) {
26999
27028
  for (const sample of samples) {
27000
- examples.push(`User: ${sample.question}\nAgent: ${sample.answer}`);
27029
+ examples.push(`**User:** ${sample.question}\n\n**Agent:**\n${sample.answer}`);
27001
27030
  }
27002
27031
  }
27003
27032
  return examples;