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