@promptbook/cli 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
@@ -60,7 +60,7 @@
60
60
  * @generated
61
61
  * @see https://github.com/webgptorg/promptbook
62
62
  */
63
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-57';
63
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-59';
64
64
  /**
65
65
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
66
66
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -18139,6 +18139,49 @@
18139
18139
  return this.appendToSystemMessage(requirements, commentSection);
18140
18140
  }
18141
18141
  }
18142
+ /**
18143
+ * Helper method to append a bullet point to an existing `## SectionTitle` section in the system
18144
+ * message, or to create a new section when it does not yet exist.
18145
+ *
18146
+ * Handles the case where the same commitment type appears multiple times in the book source and
18147
+ * all entries should be grouped under one shared heading rather than emitting a duplicate block.
18148
+ *
18149
+ * @param requirements - Current model requirements.
18150
+ * @param sectionTitle - Section title without the `##` prefix.
18151
+ * @param bulletContent - Bullet content without the leading `- ` prefix.
18152
+ * @returns Requirements with the bullet appended to the section.
18153
+ */
18154
+ appendBulletPointToSection(requirements, sectionTitle, bulletContent) {
18155
+ const sectionHeader = `## ${sectionTitle}`;
18156
+ const bullet = `- ${bulletContent}`;
18157
+ if (requirements.systemMessage.includes(sectionHeader)) {
18158
+ // Append bullet to end of existing section, before the next h2 heading or end of message
18159
+ const newSystemMessage = requirements.systemMessage.replace(new RegExp(`(## ${sectionTitle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\n\\n)([\\s\\S]*?)(?=\\n\\n##|$)`), `$1$2\n${bullet}`);
18160
+ return { ...requirements, systemMessage: newSystemMessage };
18161
+ }
18162
+ return this.appendToSystemMessage(requirements, `${sectionHeader}\n\n${bullet}`, '\n\n');
18163
+ }
18164
+ /**
18165
+ * Helper method to replace an existing `## SectionTitle` section in the system message, or to
18166
+ * append a new one when the section does not yet exist.
18167
+ *
18168
+ * Use this when a commitment type can appear multiple times and each subsequent occurrence should
18169
+ * update the single shared section rather than appending a duplicate block.
18170
+ *
18171
+ * @param requirements - Current model requirements.
18172
+ * @param sectionTitle - Section title without the `##` prefix.
18173
+ * @param sectionContent - Full section content including the `## Title` header line.
18174
+ * @returns Requirements with the section replaced or appended.
18175
+ */
18176
+ replaceOrCreateSection(requirements, sectionTitle, sectionContent) {
18177
+ const sectionHeader = `## ${sectionTitle}`;
18178
+ if (requirements.systemMessage.includes(sectionHeader)) {
18179
+ // Replace all text from the heading until the next h2 heading or end of message
18180
+ const newSystemMessage = requirements.systemMessage.replace(new RegExp(`## ${sectionTitle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}[\\s\\S]*?(?=\\n\\n##|$)`), sectionContent);
18181
+ return { ...requirements, systemMessage: newSystemMessage };
18182
+ }
18183
+ return this.appendToSystemMessage(requirements, sectionContent, '\n\n');
18184
+ }
18142
18185
  /**
18143
18186
  * Gets tool function implementations provided by this commitment
18144
18187
  *
@@ -18600,20 +18643,16 @@
18600
18643
  if (!trimmedContent) {
18601
18644
  return requirements;
18602
18645
  }
18603
- // Get existing dictionary entries from metadata
18646
+ // Store the entry in metadata for debugging and inspection
18604
18647
  const existingDictionary = ((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.DICTIONARY) || '';
18605
- // Merge the new dictionary entry with existing entries
18606
18648
  const mergedDictionary = existingDictionary ? `${existingDictionary}\n${trimmedContent}` : trimmedContent;
18607
- // Store the merged dictionary in metadata for debugging and inspection
18608
18649
  const updatedMetadata = {
18609
18650
  ...requirements._metadata,
18610
18651
  DICTIONARY: mergedDictionary,
18611
18652
  };
18612
- // Create the dictionary section for the system message
18613
- // Format: "# DICTIONARY\nTerm: definition\nTerm: definition..."
18614
- const dictionarySection = `# DICTIONARY\n${mergedDictionary}`;
18653
+ // Append each dictionary entry as a bullet point under ## Dictionary
18615
18654
  return {
18616
- ...this.appendToSystemMessage(requirements, dictionarySection),
18655
+ ...this.appendBulletPointToSection(requirements, 'Dictionary', trimmedContent),
18617
18656
  _metadata: updatedMetadata,
18618
18657
  };
18619
18658
  }
@@ -19116,10 +19155,10 @@
19116
19155
  if (!trimmedContent) {
19117
19156
  return requirements;
19118
19157
  }
19119
- // Add goal to the system message
19120
- const goalSection = `Goal: ${trimmedContent}`;
19158
+ // Add goal as a proper h2 section to the system message
19159
+ const goalSection = `## Goal\n\n${trimmedContent}`;
19121
19160
  const requirementsWithGoal = this.appendToSystemMessage(requirements, goalSection, '\n\n');
19122
- return this.appendToPromptSuffix(requirementsWithGoal, goalSection);
19161
+ return this.appendToPromptSuffix(requirementsWithGoal, trimmedContent);
19123
19162
  }
19124
19163
  }
19125
19164
  // Note: [💞] Ignore a discrepancy between file name and entity name
@@ -19639,11 +19678,8 @@
19639
19678
  if (!trimmedContent) {
19640
19679
  return requirements;
19641
19680
  }
19642
- // Add language rule to the system message
19643
- const languageSection = this.createSystemMessageSection('Language:', _spaceTrim.spaceTrim((block) => `
19644
- ${block(trimmedContent)}
19645
- <- You are speaking these languages in your responses to the user.
19646
- `));
19681
+ // Add language as a bullet under a ## Language section
19682
+ const languageSection = `## Language\n\n- Your language is ${trimmedContent}`;
19647
19683
  return this.appendToSystemMessage(requirements, languageSection, '\n\n');
19648
19684
  }
19649
19685
  }
@@ -19687,15 +19723,16 @@
19687
19723
  */
19688
19724
  function createMemorySystemMessage(extraInstructions) {
19689
19725
  return _spaceTrim.spaceTrim((block) => `
19690
- Memory:
19691
- - Prefer storing agent-scoped memories; only make them global when the fact should apply across all your agents.
19692
- - You can use persistent user memory tools.
19693
- - Use "${MemoryToolNames.retrieve}" to load relevant memory before answering.
19694
- - Use "${MemoryToolNames.store}" to save stable user-specific facts that improve future help.
19695
- - Use "${MemoryToolNames.update}" to refresh an existing memory when the content changes.
19696
- - Use "${MemoryToolNames.delete}" to delete memories that are no longer accurate (deletions are soft and hidden from future queries).
19697
- - Store concise memory items and avoid duplicates.
19698
- - Never claim memory was saved or loaded unless the tool confirms it.
19726
+ ## Memory
19727
+
19728
+ - Prefer storing agent-scoped memories; only make them global when the fact should apply across all your agents.
19729
+ - You can use persistent user memory tools.
19730
+ - Use \`${MemoryToolNames.retrieve}\` to load relevant memory before answering.
19731
+ - Use \`${MemoryToolNames.store}\` to save stable user-specific facts that improve future help.
19732
+ - Use \`${MemoryToolNames.update}\` to refresh an existing memory when the content changes.
19733
+ - Use \`${MemoryToolNames.delete}\` to delete memories that are no longer accurate (deletions are soft and hidden from future queries).
19734
+ - Store concise memory items and avoid duplicates.
19735
+ - Never claim memory was saved or loaded unless the tool confirms it.
19699
19736
  ${block(extraInstructions)}
19700
19737
  `);
19701
19738
  }
@@ -20617,10 +20654,8 @@
20617
20654
  if (!trimmedContent) {
20618
20655
  return requirements;
20619
20656
  }
20620
- // Create message section for system message
20621
- const messageSection = `Previous Message: ${trimmedContent}`;
20622
20657
  // Messages represent conversation history and should be included for context
20623
- return this.appendToSystemMessage(requirements, messageSection, '\n\n');
20658
+ return this.appendBulletPointToSection(requirements, 'Previous messages', trimmedContent);
20624
20659
  }
20625
20660
  }
20626
20661
  // Note: [💞] Ignore a discrepancy between file name and entity name
@@ -25414,10 +25449,9 @@
25414
25449
  if (!trimmedContent) {
25415
25450
  return requirements;
25416
25451
  }
25417
- // Add rule to the system message
25418
- const ruleSection = `Rule: ${trimmedContent}`;
25419
- const requirementsWithRule = this.appendToSystemMessage(requirements, ruleSection, '\n\n');
25420
- return this.appendToPromptSuffix(requirementsWithRule, ruleSection);
25452
+ // Group all rules under a single ## Rules section as bullet points
25453
+ const requirementsWithRule = this.appendBulletPointToSection(requirements, 'Rules', trimmedContent);
25454
+ return this.appendToPromptSuffix(requirementsWithRule, `- ${trimmedContent}`);
25421
25455
  }
25422
25456
  }
25423
25457
  // Note: [💞] Ignore a discrepancy between file name and entity name
@@ -25653,10 +25687,8 @@
25653
25687
  if (!trimmedContent) {
25654
25688
  return requirements;
25655
25689
  }
25656
- // Create scenario section for system message
25657
- const scenarioSection = `Scenario: ${trimmedContent}`;
25658
25690
  // Scenarios provide important contextual information that affects behavior
25659
- return this.appendToSystemMessage(requirements, scenarioSection, '\n\n');
25691
+ return this.appendBulletPointToSection(requirements, 'Scenarios', trimmedContent);
25660
25692
  }
25661
25693
  }
25662
25694
  // Note: [💞] Ignore a discrepancy between file name and entity name
@@ -26039,8 +26071,8 @@
26039
26071
  * @private
26040
26072
  */
26041
26073
  const TEAM_SYSTEM_MESSAGE_GUIDANCE_LINES = [
26042
- '- If a teammate is relevant to the request, consult that teammate using the matching tool.',
26043
- '- Do not ask the user for information that a listed teammate can provide directly.',
26074
+ '- If a teammate is relevant to the request, consult that teammate using the matching tool.',
26075
+ '- Do not ask the user for information that a listed teammate can provide directly.',
26044
26076
  ];
26045
26077
  /**
26046
26078
  * Constant for remote agents by Url.
@@ -26168,7 +26200,7 @@
26168
26200
  toolName: entry.toolName,
26169
26201
  });
26170
26202
  }
26171
- const teamSystemMessage = this.createSystemMessageSection('Teammates:', buildTeamSystemMessageBody(teamEntries));
26203
+ const teamSystemMessage = this.createSystemMessageSection('Teammates', buildTeamSystemMessageBody(teamEntries));
26172
26204
  return this.appendToSystemMessage({
26173
26205
  ...requirements,
26174
26206
  tools: updatedTools,
@@ -26658,36 +26690,38 @@
26658
26690
  switch (type) {
26659
26691
  case 'USE TIME':
26660
26692
  return _spaceTrim.spaceTrim((block) => `
26661
- Time and date context:
26662
- - It is ${moment__default["default"]().format('MMMM YYYY')} now.
26663
- - If you need more precise current time information, use the tool "get_current_time".
26693
+ ## Time and date context
26694
+
26695
+ - It is ${moment__default["default"]().format('MMMM YYYY')} now.
26696
+ - If you need more precise current time information, use the tool \`get_current_time\`.
26664
26697
  ${block(formatOptionalInstructionBlock('Time instructions', combinedAdditionalInstructions))}
26665
26698
  `);
26666
26699
  case 'USE BROWSER':
26667
26700
  return _spaceTrim.spaceTrim((block) => `
26668
- You have access to browser tools to fetch and access content from the internet.
26669
- - Use "fetch_url_content" to retrieve content from specific URLs (webpages or documents) using scrapers.
26670
- - Use "run_browser" for real interactive browser automation (navigation, clicks, typing, waiting, scrolling).
26671
- When you need to know information from a specific website or document, use the fetch_url_content tool.
26701
+ ## Browser
26702
+
26703
+ - Use \`fetch_url_content\` to retrieve content from specific URLs (webpages or documents) using scrapers.
26704
+ - Use \`run_browser\` for real interactive browser automation (navigation, clicks, typing, waiting, scrolling).
26705
+ - When you need to know information from a specific website or document, use the tools provided.
26672
26706
  ${block(formatOptionalInstructionBlock('Browser instructions', combinedAdditionalInstructions))}
26673
26707
  `);
26674
26708
  case 'USE SEARCH ENGINE':
26675
26709
  return _spaceTrim.spaceTrim((block) => `
26676
- Tool:
26677
- - You have access to the web search engine via the tool "web_search".
26678
- - Use it to find up-to-date information or facts that you don't know.
26679
- - When you need to know some information from the internet, use the tool provided to you.
26680
- - Do not make up information when you can search for it.
26681
- - Do not tell the user you cannot search for information, YOU CAN.
26710
+ ## Web Search
26711
+
26712
+ - Use \`web_search\` to find up-to-date information or facts.
26713
+ - When you need to know some information from the internet, use the search tool provided.
26714
+ - Do not make up information when you can search for it.
26715
+ - Do not tell the user you cannot search for information, YOU CAN.
26682
26716
  ${block(formatOptionalInstructionBlock('Search instructions', combinedAdditionalInstructions))}
26683
26717
  `);
26684
26718
  case 'USE DEEPSEARCH':
26685
26719
  return _spaceTrim.spaceTrim((block) => `
26686
- Tool:
26687
- - You have access to DeepSearch via the tool "deep_search".
26688
- - Use it for broader research tasks that need multi-step investigation, comparison, or synthesis across multiple sources.
26689
- - Prefer it over quick search when the user asks for a well-grounded brief, report, or deeper investigation.
26690
- - Do not pretend you cannot research current information when this tool is available.
26720
+ ## Deep Research
26721
+
26722
+ - Use \`deep_search\` for broader research tasks that need multi-step investigation, comparison, or synthesis across multiple sources.
26723
+ - Prefer it over quick search when the user asks for a well-grounded brief, report, or deeper investigation.
26724
+ - Do not pretend you cannot research current information when this tool is available.
26691
26725
  ${block(formatOptionalInstructionBlock('DeepSearch instructions', combinedAdditionalInstructions))}
26692
26726
  `);
26693
26727
  }
@@ -27017,96 +27051,6 @@
27017
27051
  }
27018
27052
  // Note: [💞] Ignore a discrepancy between file name and entity name
27019
27053
 
27020
- /**
27021
- * Base Google Calendar API URL.
27022
- *
27023
- * @private constant of callGoogleCalendarApi
27024
- */
27025
- const GOOGLE_CALENDAR_API_BASE_URL = 'https://www.googleapis.com/calendar/v3';
27026
- /**
27027
- * Runs one Google Calendar API request and parses JSON response payload.
27028
- *
27029
- * @private function of UseCalendarCommitmentDefinition
27030
- */
27031
- async function callGoogleCalendarApi(accessToken, options) {
27032
- const url = new URL(options.path, GOOGLE_CALENDAR_API_BASE_URL);
27033
- if (options.query) {
27034
- for (const [key, value] of Object.entries(options.query)) {
27035
- if (value && value.trim()) {
27036
- url.searchParams.set(key, value);
27037
- }
27038
- }
27039
- }
27040
- const response = await fetch(url.toString(), {
27041
- method: options.method,
27042
- headers: {
27043
- Authorization: `Bearer ${accessToken}`,
27044
- Accept: 'application/json',
27045
- 'Content-Type': 'application/json',
27046
- },
27047
- body: options.body ? JSON.stringify(options.body) : undefined,
27048
- });
27049
- const textPayload = await response.text();
27050
- const parsedPayload = tryParseJson$2(textPayload);
27051
- if (options.allowNotFound && response.status === 404) {
27052
- return null;
27053
- }
27054
- if (!response.ok) {
27055
- throw new Error(_spaceTrim.spaceTrim(`
27056
- Google Calendar API request failed (${response.status} ${response.statusText}):
27057
- ${extractGoogleCalendarApiErrorMessage(parsedPayload, textPayload)}
27058
- `));
27059
- }
27060
- return parsedPayload;
27061
- }
27062
- /**
27063
- * Parses raw text into JSON when possible.
27064
- *
27065
- * @private function of callGoogleCalendarApi
27066
- */
27067
- function tryParseJson$2(rawText) {
27068
- if (!rawText.trim()) {
27069
- return {};
27070
- }
27071
- try {
27072
- return JSON.parse(rawText);
27073
- }
27074
- catch (_a) {
27075
- return rawText;
27076
- }
27077
- }
27078
- /**
27079
- * Extracts a user-friendly Google Calendar API error message.
27080
- *
27081
- * @private function of callGoogleCalendarApi
27082
- */
27083
- function extractGoogleCalendarApiErrorMessage(parsedPayload, fallbackText) {
27084
- if (parsedPayload && typeof parsedPayload === 'object') {
27085
- const payload = parsedPayload;
27086
- const errorPayload = payload.error;
27087
- if (errorPayload && typeof errorPayload === 'object') {
27088
- const normalizedErrorPayload = errorPayload;
27089
- const message = typeof normalizedErrorPayload.message === 'string' ? normalizedErrorPayload.message : '';
27090
- const errors = Array.isArray(normalizedErrorPayload.errors) ? normalizedErrorPayload.errors : [];
27091
- const flattenedErrors = errors
27092
- .map((errorEntry) => {
27093
- if (!errorEntry || typeof errorEntry !== 'object') {
27094
- return '';
27095
- }
27096
- const normalizedErrorEntry = errorEntry;
27097
- const detailMessage = typeof normalizedErrorEntry.message === 'string' ? normalizedErrorEntry.message : '';
27098
- const reason = typeof normalizedErrorEntry.reason === 'string' ? normalizedErrorEntry.reason : '';
27099
- return [detailMessage, reason].filter(Boolean).join(' | ');
27100
- })
27101
- .filter(Boolean);
27102
- if (message || flattenedErrors.length > 0) {
27103
- return [message, ...flattenedErrors].filter(Boolean).join(' | ');
27104
- }
27105
- }
27106
- }
27107
- return fallbackText || 'Unknown Google Calendar API error';
27108
- }
27109
-
27110
27054
  /**
27111
27055
  * Hostnames accepted for Google Calendar references.
27112
27056
  *
@@ -27288,6 +27232,96 @@
27288
27232
  }
27289
27233
  // Note: [💞] Ignore a discrepancy between file name and entity name
27290
27234
 
27235
+ /**
27236
+ * Base Google Calendar API URL.
27237
+ *
27238
+ * @private constant of callGoogleCalendarApi
27239
+ */
27240
+ const GOOGLE_CALENDAR_API_BASE_URL = 'https://www.googleapis.com/calendar/v3';
27241
+ /**
27242
+ * Runs one Google Calendar API request and parses JSON response payload.
27243
+ *
27244
+ * @private function of UseCalendarCommitmentDefinition
27245
+ */
27246
+ async function callGoogleCalendarApi(accessToken, options) {
27247
+ const url = new URL(options.path, GOOGLE_CALENDAR_API_BASE_URL);
27248
+ if (options.query) {
27249
+ for (const [key, value] of Object.entries(options.query)) {
27250
+ if (value && value.trim()) {
27251
+ url.searchParams.set(key, value);
27252
+ }
27253
+ }
27254
+ }
27255
+ const response = await fetch(url.toString(), {
27256
+ method: options.method,
27257
+ headers: {
27258
+ Authorization: `Bearer ${accessToken}`,
27259
+ Accept: 'application/json',
27260
+ 'Content-Type': 'application/json',
27261
+ },
27262
+ body: options.body ? JSON.stringify(options.body) : undefined,
27263
+ });
27264
+ const textPayload = await response.text();
27265
+ const parsedPayload = tryParseJson$2(textPayload);
27266
+ if (options.allowNotFound && response.status === 404) {
27267
+ return null;
27268
+ }
27269
+ if (!response.ok) {
27270
+ throw new Error(_spaceTrim.spaceTrim(`
27271
+ Google Calendar API request failed (${response.status} ${response.statusText}):
27272
+ ${extractGoogleCalendarApiErrorMessage(parsedPayload, textPayload)}
27273
+ `));
27274
+ }
27275
+ return parsedPayload;
27276
+ }
27277
+ /**
27278
+ * Parses raw text into JSON when possible.
27279
+ *
27280
+ * @private function of callGoogleCalendarApi
27281
+ */
27282
+ function tryParseJson$2(rawText) {
27283
+ if (!rawText.trim()) {
27284
+ return {};
27285
+ }
27286
+ try {
27287
+ return JSON.parse(rawText);
27288
+ }
27289
+ catch (_a) {
27290
+ return rawText;
27291
+ }
27292
+ }
27293
+ /**
27294
+ * Extracts a user-friendly Google Calendar API error message.
27295
+ *
27296
+ * @private function of callGoogleCalendarApi
27297
+ */
27298
+ function extractGoogleCalendarApiErrorMessage(parsedPayload, fallbackText) {
27299
+ if (parsedPayload && typeof parsedPayload === 'object') {
27300
+ const payload = parsedPayload;
27301
+ const errorPayload = payload.error;
27302
+ if (errorPayload && typeof errorPayload === 'object') {
27303
+ const normalizedErrorPayload = errorPayload;
27304
+ const message = typeof normalizedErrorPayload.message === 'string' ? normalizedErrorPayload.message : '';
27305
+ const errors = Array.isArray(normalizedErrorPayload.errors) ? normalizedErrorPayload.errors : [];
27306
+ const flattenedErrors = errors
27307
+ .map((errorEntry) => {
27308
+ if (!errorEntry || typeof errorEntry !== 'object') {
27309
+ return '';
27310
+ }
27311
+ const normalizedErrorEntry = errorEntry;
27312
+ const detailMessage = typeof normalizedErrorEntry.message === 'string' ? normalizedErrorEntry.message : '';
27313
+ const reason = typeof normalizedErrorEntry.reason === 'string' ? normalizedErrorEntry.reason : '';
27314
+ return [detailMessage, reason].filter(Boolean).join(' | ');
27315
+ })
27316
+ .filter(Boolean);
27317
+ if (message || flattenedErrors.length > 0) {
27318
+ return [message, ...flattenedErrors].filter(Boolean).join(' | ');
27319
+ }
27320
+ }
27321
+ }
27322
+ return fallbackText || 'Unknown Google Calendar API error';
27323
+ }
27324
+
27291
27325
  /**
27292
27326
  * Wallet metadata used by USE CALENDAR when resolving Google Calendar credentials.
27293
27327
  *
@@ -28188,18 +28222,20 @@
28188
28222
  if (parsedCommitment.calendar) {
28189
28223
  addConfiguredCalendarIfMissing(existingConfiguredCalendars, parsedCommitment.calendar);
28190
28224
  }
28191
- const calendarsList = existingConfiguredCalendars.length > 0
28192
- ? existingConfiguredCalendars
28193
- .map((calendar) => [
28194
- `- ${calendar.provider}: ${calendar.url}`,
28195
- calendar.scopes.length > 0 ? ` scopes: ${calendar.scopes.join(', ')}` : '',
28196
- ]
28197
- .filter(Boolean)
28198
- .join('\n'))
28199
- .join('\n')
28200
- : '- Calendar is resolved from runtime context';
28225
+ const calendarBullets = existingConfiguredCalendars.length > 0
28226
+ ? existingConfiguredCalendars.map((calendar) => `- ${calendar.provider}: ${calendar.url}`).join('\n')
28227
+ : '- Calendar is resolved from runtime context';
28201
28228
  const extraInstructions = formatOptionalInstructionBlock('Calendar instructions', parsedCommitment.instructions);
28202
- return this.appendToSystemMessage({
28229
+ const calendarSectionContent = _spaceTrim.spaceTrim((block) => `
28230
+ ## Calendar
28231
+
28232
+ - 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.
28233
+ - Supported operations include read, create, update, delete, invite guests, and reminders.
28234
+ - Configured calendars:
28235
+ ${block(calendarBullets)}
28236
+ ${block(extraInstructions)}
28237
+ `);
28238
+ return this.replaceOrCreateSection({
28203
28239
  ...requirements,
28204
28240
  tools: createUseCalendarTools(requirements.tools || []),
28205
28241
  _metadata: {
@@ -28207,16 +28243,7 @@
28207
28243
  useCalendar: true,
28208
28244
  useCalendars: existingConfiguredCalendars,
28209
28245
  },
28210
- }, _spaceTrim.spaceTrim((block) => `
28211
- Calendar tools:
28212
- - You can inspect and manage events in configured calendars.
28213
- - Supported operations include read, create, update, delete, invite guests, and reminders.
28214
- - Configured calendars:
28215
- ${block(calendarsList)}
28216
- - USE CALENDAR credentials are read from wallet records (ACCESS_TOKEN, service "${UseCalendarWallet.service}", key "${UseCalendarWallet.key}").
28217
- - If credentials are missing, ask user to connect calendar credentials in host UI and/or add them to wallet.
28218
- ${block(extraInstructions)}
28219
- `));
28246
+ }, 'Calendar', calendarSectionContent);
28220
28247
  }
28221
28248
  /**
28222
28249
  * Gets human-readable titles for tool functions provided by this commitment.
@@ -28553,18 +28580,6 @@
28553
28580
  * @private internal USE EMAIL constant
28554
28581
  */
28555
28582
  const SEND_EMAIL_TOOL_NAME = 'send_email';
28556
- /**
28557
- * Wallet service used for SMTP credentials required by USE EMAIL.
28558
- *
28559
- * @private internal USE EMAIL constant
28560
- */
28561
- const USE_EMAIL_SMTP_WALLET_SERVICE = 'smtp';
28562
- /**
28563
- * Wallet key used for SMTP credentials required by USE EMAIL.
28564
- *
28565
- * @private internal USE EMAIL constant
28566
- */
28567
- const USE_EMAIL_SMTP_WALLET_KEY = 'use-email-smtp-credentials';
28568
28583
  /**
28569
28584
  * USE EMAIL commitment definition.
28570
28585
  *
@@ -28623,31 +28638,41 @@
28623
28638
  `);
28624
28639
  }
28625
28640
  applyToAgentModelRequirements(requirements, content) {
28641
+ var _a;
28626
28642
  const parsedCommitment = parseUseEmailCommitmentContent(content);
28627
- const extraInstructions = formatOptionalInstructionBlock('Email instructions', parsedCommitment.instructions);
28628
- const senderInstruction = parsedCommitment.senderEmail
28629
- ? `- Default sender address from commitment: "${parsedCommitment.senderEmail}".`
28630
- : '';
28631
28643
  const updatedTools = addUseEmailTools(requirements.tools || []);
28632
- return this.appendToSystemMessage({
28644
+ // Collect all configured sender emails across multiple USE EMAIL commitments
28645
+ const existingSenders = Array.isArray((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.useEmailSenders)
28646
+ ? [...requirements._metadata.useEmailSenders]
28647
+ : [];
28648
+ if (parsedCommitment.senderEmail && !existingSenders.includes(parsedCommitment.senderEmail)) {
28649
+ existingSenders.push(parsedCommitment.senderEmail);
28650
+ }
28651
+ const senderBullets = existingSenders.length > 0
28652
+ ? existingSenders
28653
+ .map((email, index) => index === 0
28654
+ ? `- Default sender address: "${email}".`
28655
+ : `- Additional sender address: "${email}".`)
28656
+ .join('\n')
28657
+ : '';
28658
+ const extraInstructions = formatOptionalInstructionBlock('Email instructions', parsedCommitment.instructions);
28659
+ const emailSectionContent = _spaceTrim.spaceTrim((block) => `
28660
+ ## Emails
28661
+
28662
+ - Use \`${SEND_EMAIL_TOOL_NAME}\` to send outbound emails.
28663
+ ${block(senderBullets)}
28664
+ ${block(extraInstructions)}
28665
+ `);
28666
+ return this.replaceOrCreateSection({
28633
28667
  ...requirements,
28634
28668
  tools: updatedTools,
28635
28669
  _metadata: {
28636
28670
  ...requirements._metadata,
28637
28671
  useEmail: true,
28638
28672
  ...(parsedCommitment.senderEmail ? { useEmailSender: parsedCommitment.senderEmail } : {}),
28673
+ useEmailSenders: existingSenders,
28639
28674
  },
28640
- }, _spaceTrim.spaceTrim((block) => `
28641
- Email tool:
28642
- - Use "${SEND_EMAIL_TOOL_NAME}" to send outbound emails.
28643
- - Prefer \`message\` argument compatible with Promptbook \`Message\` type.
28644
- - Include subject in \`message.metadata.subject\` (or use legacy \`subject\` argument).
28645
- - USE EMAIL credentials are read from wallet records (ACCESS_TOKEN, service "${USE_EMAIL_SMTP_WALLET_SERVICE}", key "${USE_EMAIL_SMTP_WALLET_KEY}").
28646
- - Wallet secret must contain SMTP credentials in JSON format with fields \`host\`, \`port\`, \`secure\`, \`username\`, \`password\`.
28647
- - If credentials are missing, ask user to add wallet credentials.
28648
- ${block(senderInstruction)}
28649
- ${block(extraInstructions)}
28650
- `));
28675
+ }, 'Emails', emailSectionContent);
28651
28676
  }
28652
28677
  /**
28653
28678
  * Gets human-readable titles for tool functions provided by this commitment.
@@ -28683,13 +28708,13 @@
28683
28708
  ...existingTools,
28684
28709
  {
28685
28710
  name: SEND_EMAIL_TOOL_NAME,
28686
- description: 'Send an outbound email through configured SMTP credentials. Prefer providing Message-like payload in `message`.',
28711
+ description: 'Send an outbound email.',
28687
28712
  parameters: {
28688
28713
  type: 'object',
28689
28714
  properties: {
28690
28715
  message: {
28691
28716
  type: 'object',
28692
- description: 'Preferred input payload compatible with Promptbook Message type. Use metadata.subject for subject line.',
28717
+ description: 'Email payload. Use metadata.subject for the subject line.',
28693
28718
  },
28694
28719
  to: {
28695
28720
  type: 'string',
@@ -28793,13 +28818,14 @@
28793
28818
  useImageGenerator: content || true,
28794
28819
  },
28795
28820
  }, _spaceTrim.spaceTrim((block) => `
28796
- Image generation:
28797
- - You do not generate images directly and you do not call any image tool.
28798
- - When the user asks for an image, include markdown notation in your message:
28799
- \`![<alt text>](?image-prompt=<prompt>)\`
28800
- - Keep \`<alt text>\` short and descriptive.
28801
- - Keep \`<prompt>\` detailed so the generated image matches the request.
28802
- - You can include normal explanatory text before and after the notation.
28821
+ ## Image generation
28822
+
28823
+ - You do not generate images directly and you do not call any image tool.
28824
+ - When the user asks for an image, include markdown notation in your message:
28825
+ \`![<alt text>](?image-prompt=<prompt>)\`
28826
+ - Keep \`<alt text>\` short and descriptive.
28827
+ - Keep \`<prompt>\` detailed so the generated image matches the request.
28828
+ - You can include normal explanatory text before and after the notation.
28803
28829
  ${block(extraInstructions)}
28804
28830
  `));
28805
28831
  }
@@ -28979,11 +29005,12 @@
28979
29005
  usePopup: content || true,
28980
29006
  },
28981
29007
  }, _spaceTrim.spaceTrim((block) => `
28982
- Tool:
28983
- - You can open a popup window with a specific URL using the tool "open_popup".
28984
- - Use this when you want the user to see or interact with a specific website.
29008
+ ## Popup
29009
+
29010
+ - You can open a popup window with a specific URL using the tool \`open_popup\`.
29011
+ - Use this when you want the user to see or interact with a specific website.
28985
29012
  ${block(extraInstructions)}
28986
- `));
29013
+ `));
28987
29014
  }
28988
29015
  /**
28989
29016
  * Gets human-readable titles for tool functions provided by this commitment.
@@ -29157,11 +29184,12 @@
29157
29184
  usePrivacy: content || true,
29158
29185
  },
29159
29186
  }, _spaceTrim.spaceTrim((block) => `
29160
- Privacy mode:
29161
- - Use "${TURN_PRIVACY_ON_TOOL_NAME}" when the user asks for a private/sensitive conversation.
29162
- - This tool requests a UI confirmation dialog. Private mode is enabled only after user confirms.
29163
- - Current implementation uses the existing chat private mode (no chat persistence, memory persistence, or self-learning while active).
29164
- - Do not claim that end-to-end encryption is implemented yet.
29187
+ ## Privacy
29188
+
29189
+ - Use \`${TURN_PRIVACY_ON_TOOL_NAME}\` when the user asks for a private/sensitive conversation.
29190
+ - This tool requests a UI confirmation dialog. Private mode is enabled only after user confirms.
29191
+ - Current implementation uses the existing chat private mode (no chat persistence, memory persistence, or self-learning while active).
29192
+ - Do not claim that end-to-end encryption is implemented yet.
29165
29193
  ${block(extraInstructions)}
29166
29194
  `));
29167
29195
  }
@@ -30785,9 +30813,16 @@
30785
30813
  }
30786
30814
  const existingConfiguredProjects = normalizeConfiguredProjects((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.useProjects);
30787
30815
  addConfiguredProjectIfMissing(existingConfiguredProjects, parsedCommitment.repository);
30788
- const repositoriesList = existingConfiguredProjects.map((project) => `- ${project.url}`).join('\n');
30789
30816
  const extraInstructions = formatOptionalInstructionBlock('Project instructions', parsedCommitment.instructions);
30790
- return this.appendToSystemMessage({
30817
+ const sectionContent = _spaceTrim.spaceTrim((block) => `
30818
+ - You can inspect and edit configured GitHub repositories using project tools.
30819
+ - Configured repositories:
30820
+ ${block(existingConfiguredProjects.map((project) => `- ${project.url}`).join('\n'))}
30821
+ - When a repository is not obvious from context, pass \`repository\` in tool arguments explicitly.
30822
+ - If credentials are missing, ask the user to connect their GitHub account in the host UI.
30823
+ ${block(extraInstructions)}
30824
+ `);
30825
+ return this.replaceOrCreateSection({
30791
30826
  ...requirements,
30792
30827
  tools: createUseProjectTools(requirements.tools || []),
30793
30828
  _metadata: {
@@ -30795,16 +30830,7 @@
30795
30830
  useProject: true,
30796
30831
  useProjects: existingConfiguredProjects,
30797
30832
  },
30798
- }, _spaceTrim.spaceTrim((block) => `
30799
- Project tools:
30800
- - You can inspect and edit configured GitHub repositories using project tools.
30801
- - Configured repositories:
30802
- ${block(repositoriesList)}
30803
- - When a repository is not obvious from context, pass "repository" in tool arguments explicitly.
30804
- - USE PROJECT credentials are read from wallet records (ACCESS_TOKEN, service "${UseProjectWallet.service}", key "${UseProjectWallet.key}").
30805
- - If credentials are missing, ask the user to connect credentials in host UI and/or add them to wallet.
30806
- ${block(extraInstructions)}
30807
- `));
30833
+ }, 'GitHub repositories', sectionContent);
30808
30834
  }
30809
30835
  /**
30810
30836
  * Gets human-readable titles for tool functions provided by this commitment.
@@ -31151,11 +31177,12 @@
31151
31177
  useSpawn: content || true,
31152
31178
  },
31153
31179
  }, _spaceTrim.spaceTrim((block) => `
31154
- Spawning agents:
31155
- - Use "${SPAWN_AGENT_TOOL_NAME}" only when user asks to create a persistent new agent.
31156
- - Pass full agent source in \`source\`.
31157
- - Keep \`source\` concise; the maximum accepted length is ${CREATE_AGENT_INPUT_SOURCE_MAX_LENGTH} characters.
31158
- - Do not add unknown fields in tool arguments.
31180
+ ## Spawning agents
31181
+
31182
+ - Use \`${SPAWN_AGENT_TOOL_NAME}\` only when user asks to create a persistent new agent.
31183
+ - Pass full agent source in \`source\`.
31184
+ - Keep \`source\` concise; the maximum accepted length is ${CREATE_AGENT_INPUT_SOURCE_MAX_LENGTH} characters.
31185
+ - Do not add unknown fields in tool arguments.
31159
31186
  ${block(extraInstructions)}
31160
31187
  `));
31161
31188
  }
@@ -31189,13 +31216,14 @@
31189
31216
  */
31190
31217
  function createTimeoutSystemMessage(extraInstructions) {
31191
31218
  return _spaceTrim.spaceTrim((block) => `
31192
- Timeout scheduling:
31193
- - Use "set_timeout" to wake this same chat thread in the future.
31194
- - Use "list_timeouts" to review timeout ids/details across all chats for the same user+agent scope.
31195
- - "cancel_timeout" accepts either one timeout id or \`allActive: true\` to cancel all active timeouts in this same user+agent scope.
31196
- - Use "update_timeout" to pause/resume, edit next run, edit recurrence, or update timeout payload details.
31197
- - 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\`.
31198
- - Do not claim a timer was set or cancelled unless the tool confirms it.
31219
+ ## Timeout scheduling
31220
+
31221
+ - Use \`set_timeout\` to wake this same chat thread in the future.
31222
+ - Use \`list_timeouts\` to review timeout ids/details across all chats for the same user+agent scope.
31223
+ - \`cancel_timeout\` accepts either one timeout id or \`allActive: true\` to cancel all active timeouts in this same user+agent scope.
31224
+ - Use \`update_timeout\` to pause/resume, edit next run, edit recurrence, or update timeout payload details.
31225
+ - 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\`.
31226
+ - Do not claim a timer was set or cancelled unless the tool confirms it.
31199
31227
  ${block(extraInstructions)}
31200
31228
  `);
31201
31229
  }
@@ -32295,10 +32323,11 @@
32295
32323
  useUserLocation: content || true,
32296
32324
  },
32297
32325
  }, _spaceTrim.spaceTrim((block) => `
32298
- User location:
32299
- - Use "${GET_USER_LOCATION_TOOL_NAME}" only when location is needed for a better answer.
32300
- - If the tool returns "unavailable" or "permission-denied", ask user to share location or provide city manually.
32301
- - Do not invent coordinates or local facts when location is unavailable.
32326
+ ## User location
32327
+
32328
+ - Use \`${GET_USER_LOCATION_TOOL_NAME}\` only when location is needed for a better answer.
32329
+ - If the tool returns "unavailable" or "permission-denied", ask user to share location or provide city manually.
32330
+ - Do not invent coordinates or local facts when location is unavailable.
32302
32331
  ${block(extraInstructions)}
32303
32332
  `));
32304
32333
  }
@@ -45641,7 +45670,7 @@
45641
45670
  if (examples.length === 0) {
45642
45671
  return null;
45643
45672
  }
45644
- return `Example interaction:\n\n${examples.join('\n\n')}`;
45673
+ return `## Sample of communication with the agent:\n\n${examples.join('\n\n')}`;
45645
45674
  }
45646
45675
  /**
45647
45676
  * Collects the individual lines used in the example interaction section.
@@ -45657,11 +45686,11 @@
45657
45686
  const examples = [];
45658
45687
  const initialMessage = (_a = parseResult.commitments.find((commitment) => commitment.type === 'INITIAL MESSAGE')) === null || _a === void 0 ? void 0 : _a.content;
45659
45688
  if (initialMessage) {
45660
- examples.push(`Agent: ${initialMessage}`);
45689
+ examples.push(`**Agent:**\n${initialMessage}`);
45661
45690
  }
45662
45691
  if (samples && samples.length > 0) {
45663
45692
  for (const sample of samples) {
45664
- examples.push(`User: ${sample.question}\nAgent: ${sample.answer}`);
45693
+ examples.push(`**User:** ${sample.question}\n\n**Agent:**\n${sample.answer}`);
45665
45694
  }
45666
45695
  }
45667
45696
  return examples;