@promptbook/wizard 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
@@ -49,7 +49,7 @@
49
49
  * @generated
50
50
  * @see https://github.com/webgptorg/promptbook
51
51
  */
52
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-57';
52
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-59';
53
53
  /**
54
54
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
55
55
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -19499,36 +19499,38 @@
19499
19499
  switch (type) {
19500
19500
  case 'USE TIME':
19501
19501
  return _spaceTrim.spaceTrim((block) => `
19502
- Time and date context:
19503
- - It is ${moment__default["default"]().format('MMMM YYYY')} now.
19504
- - If you need more precise current time information, use the tool "get_current_time".
19502
+ ## Time and date context
19503
+
19504
+ - It is ${moment__default["default"]().format('MMMM YYYY')} now.
19505
+ - If you need more precise current time information, use the tool \`get_current_time\`.
19505
19506
  ${block(formatOptionalInstructionBlock('Time instructions', combinedAdditionalInstructions))}
19506
19507
  `);
19507
19508
  case 'USE BROWSER':
19508
19509
  return _spaceTrim.spaceTrim((block) => `
19509
- You have access to browser tools to fetch and access content from the internet.
19510
- - Use "fetch_url_content" to retrieve content from specific URLs (webpages or documents) using scrapers.
19511
- - Use "run_browser" for real interactive browser automation (navigation, clicks, typing, waiting, scrolling).
19512
- When you need to know information from a specific website or document, use the fetch_url_content tool.
19510
+ ## Browser
19511
+
19512
+ - Use \`fetch_url_content\` to retrieve content from specific URLs (webpages or documents) using scrapers.
19513
+ - Use \`run_browser\` for real interactive browser automation (navigation, clicks, typing, waiting, scrolling).
19514
+ - When you need to know information from a specific website or document, use the tools provided.
19513
19515
  ${block(formatOptionalInstructionBlock('Browser instructions', combinedAdditionalInstructions))}
19514
19516
  `);
19515
19517
  case 'USE SEARCH ENGINE':
19516
19518
  return _spaceTrim.spaceTrim((block) => `
19517
- Tool:
19518
- - You have access to the web search engine via the tool "web_search".
19519
- - Use it to find up-to-date information or facts that you don't know.
19520
- - When you need to know some information from the internet, use the tool provided to you.
19521
- - Do not make up information when you can search for it.
19522
- - Do not tell the user you cannot search for information, YOU CAN.
19519
+ ## Web Search
19520
+
19521
+ - Use \`web_search\` to find up-to-date information or facts.
19522
+ - When you need to know some information from the internet, use the search tool provided.
19523
+ - Do not make up information when you can search for it.
19524
+ - Do not tell the user you cannot search for information, YOU CAN.
19523
19525
  ${block(formatOptionalInstructionBlock('Search instructions', combinedAdditionalInstructions))}
19524
19526
  `);
19525
19527
  case 'USE DEEPSEARCH':
19526
19528
  return _spaceTrim.spaceTrim((block) => `
19527
- Tool:
19528
- - You have access to DeepSearch via the tool "deep_search".
19529
- - Use it for broader research tasks that need multi-step investigation, comparison, or synthesis across multiple sources.
19530
- - Prefer it over quick search when the user asks for a well-grounded brief, report, or deeper investigation.
19531
- - Do not pretend you cannot research current information when this tool is available.
19529
+ ## Deep Research
19530
+
19531
+ - Use \`deep_search\` for broader research tasks that need multi-step investigation, comparison, or synthesis across multiple sources.
19532
+ - Prefer it over quick search when the user asks for a well-grounded brief, report, or deeper investigation.
19533
+ - Do not pretend you cannot research current information when this tool is available.
19532
19534
  ${block(formatOptionalInstructionBlock('DeepSearch instructions', combinedAdditionalInstructions))}
19533
19535
  `);
19534
19536
  }
@@ -19770,6 +19772,49 @@
19770
19772
  return this.appendToSystemMessage(requirements, commentSection);
19771
19773
  }
19772
19774
  }
19775
+ /**
19776
+ * Helper method to append a bullet point to an existing `## SectionTitle` section in the system
19777
+ * message, or to create a new section when it does not yet exist.
19778
+ *
19779
+ * Handles the case where the same commitment type appears multiple times in the book source and
19780
+ * all entries should be grouped under one shared heading rather than emitting a duplicate block.
19781
+ *
19782
+ * @param requirements - Current model requirements.
19783
+ * @param sectionTitle - Section title without the `##` prefix.
19784
+ * @param bulletContent - Bullet content without the leading `- ` prefix.
19785
+ * @returns Requirements with the bullet appended to the section.
19786
+ */
19787
+ appendBulletPointToSection(requirements, sectionTitle, bulletContent) {
19788
+ const sectionHeader = `## ${sectionTitle}`;
19789
+ const bullet = `- ${bulletContent}`;
19790
+ if (requirements.systemMessage.includes(sectionHeader)) {
19791
+ // Append bullet to end of existing section, before the next h2 heading or end of message
19792
+ const newSystemMessage = requirements.systemMessage.replace(new RegExp(`(## ${sectionTitle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\n\\n)([\\s\\S]*?)(?=\\n\\n##|$)`), `$1$2\n${bullet}`);
19793
+ return { ...requirements, systemMessage: newSystemMessage };
19794
+ }
19795
+ return this.appendToSystemMessage(requirements, `${sectionHeader}\n\n${bullet}`, '\n\n');
19796
+ }
19797
+ /**
19798
+ * Helper method to replace an existing `## SectionTitle` section in the system message, or to
19799
+ * append a new one when the section does not yet exist.
19800
+ *
19801
+ * Use this when a commitment type can appear multiple times and each subsequent occurrence should
19802
+ * update the single shared section rather than appending a duplicate block.
19803
+ *
19804
+ * @param requirements - Current model requirements.
19805
+ * @param sectionTitle - Section title without the `##` prefix.
19806
+ * @param sectionContent - Full section content including the `## Title` header line.
19807
+ * @returns Requirements with the section replaced or appended.
19808
+ */
19809
+ replaceOrCreateSection(requirements, sectionTitle, sectionContent) {
19810
+ const sectionHeader = `## ${sectionTitle}`;
19811
+ if (requirements.systemMessage.includes(sectionHeader)) {
19812
+ // Replace all text from the heading until the next h2 heading or end of message
19813
+ const newSystemMessage = requirements.systemMessage.replace(new RegExp(`## ${sectionTitle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}[\\s\\S]*?(?=\\n\\n##|$)`), sectionContent);
19814
+ return { ...requirements, systemMessage: newSystemMessage };
19815
+ }
19816
+ return this.appendToSystemMessage(requirements, sectionContent, '\n\n');
19817
+ }
19773
19818
  /**
19774
19819
  * Gets tool function implementations provided by this commitment
19775
19820
  *
@@ -20231,20 +20276,16 @@
20231
20276
  if (!trimmedContent) {
20232
20277
  return requirements;
20233
20278
  }
20234
- // Get existing dictionary entries from metadata
20279
+ // Store the entry in metadata for debugging and inspection
20235
20280
  const existingDictionary = ((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.DICTIONARY) || '';
20236
- // Merge the new dictionary entry with existing entries
20237
20281
  const mergedDictionary = existingDictionary ? `${existingDictionary}\n${trimmedContent}` : trimmedContent;
20238
- // Store the merged dictionary in metadata for debugging and inspection
20239
20282
  const updatedMetadata = {
20240
20283
  ...requirements._metadata,
20241
20284
  DICTIONARY: mergedDictionary,
20242
20285
  };
20243
- // Create the dictionary section for the system message
20244
- // Format: "# DICTIONARY\nTerm: definition\nTerm: definition..."
20245
- const dictionarySection = `# DICTIONARY\n${mergedDictionary}`;
20286
+ // Append each dictionary entry as a bullet point under ## Dictionary
20246
20287
  return {
20247
- ...this.appendToSystemMessage(requirements, dictionarySection),
20288
+ ...this.appendBulletPointToSection(requirements, 'Dictionary', trimmedContent),
20248
20289
  _metadata: updatedMetadata,
20249
20290
  };
20250
20291
  }
@@ -20517,10 +20558,10 @@
20517
20558
  if (!trimmedContent) {
20518
20559
  return requirements;
20519
20560
  }
20520
- // Add goal to the system message
20521
- const goalSection = `Goal: ${trimmedContent}`;
20561
+ // Add goal as a proper h2 section to the system message
20562
+ const goalSection = `## Goal\n\n${trimmedContent}`;
20522
20563
  const requirementsWithGoal = this.appendToSystemMessage(requirements, goalSection, '\n\n');
20523
- return this.appendToPromptSuffix(requirementsWithGoal, goalSection);
20564
+ return this.appendToPromptSuffix(requirementsWithGoal, trimmedContent);
20524
20565
  }
20525
20566
  }
20526
20567
  // Note: [💞] Ignore a discrepancy between file name and entity name
@@ -20904,11 +20945,8 @@
20904
20945
  if (!trimmedContent) {
20905
20946
  return requirements;
20906
20947
  }
20907
- // Add language rule to the system message
20908
- const languageSection = this.createSystemMessageSection('Language:', _spaceTrim.spaceTrim((block) => `
20909
- ${block(trimmedContent)}
20910
- <- You are speaking these languages in your responses to the user.
20911
- `));
20948
+ // Add language as a bullet under a ## Language section
20949
+ const languageSection = `## Language\n\n- Your language is ${trimmedContent}`;
20912
20950
  return this.appendToSystemMessage(requirements, languageSection, '\n\n');
20913
20951
  }
20914
20952
  }
@@ -20933,15 +20971,16 @@
20933
20971
  */
20934
20972
  function createMemorySystemMessage(extraInstructions) {
20935
20973
  return _spaceTrim.spaceTrim((block) => `
20936
- Memory:
20937
- - Prefer storing agent-scoped memories; only make them global when the fact should apply across all your agents.
20938
- - You can use persistent user memory tools.
20939
- - Use "${MemoryToolNames.retrieve}" to load relevant memory before answering.
20940
- - Use "${MemoryToolNames.store}" to save stable user-specific facts that improve future help.
20941
- - Use "${MemoryToolNames.update}" to refresh an existing memory when the content changes.
20942
- - Use "${MemoryToolNames.delete}" to delete memories that are no longer accurate (deletions are soft and hidden from future queries).
20943
- - Store concise memory items and avoid duplicates.
20944
- - Never claim memory was saved or loaded unless the tool confirms it.
20974
+ ## Memory
20975
+
20976
+ - Prefer storing agent-scoped memories; only make them global when the fact should apply across all your agents.
20977
+ - You can use persistent user memory tools.
20978
+ - Use \`${MemoryToolNames.retrieve}\` to load relevant memory before answering.
20979
+ - Use \`${MemoryToolNames.store}\` to save stable user-specific facts that improve future help.
20980
+ - Use \`${MemoryToolNames.update}\` to refresh an existing memory when the content changes.
20981
+ - Use \`${MemoryToolNames.delete}\` to delete memories that are no longer accurate (deletions are soft and hidden from future queries).
20982
+ - Store concise memory items and avoid duplicates.
20983
+ - Never claim memory was saved or loaded unless the tool confirms it.
20945
20984
  ${block(extraInstructions)}
20946
20985
  `);
20947
20986
  }
@@ -21759,10 +21798,8 @@
21759
21798
  if (!trimmedContent) {
21760
21799
  return requirements;
21761
21800
  }
21762
- // Create message section for system message
21763
- const messageSection = `Previous Message: ${trimmedContent}`;
21764
21801
  // Messages represent conversation history and should be included for context
21765
- return this.appendToSystemMessage(requirements, messageSection, '\n\n');
21802
+ return this.appendBulletPointToSection(requirements, 'Previous messages', trimmedContent);
21766
21803
  }
21767
21804
  }
21768
21805
  // Note: [💞] Ignore a discrepancy between file name and entity name
@@ -26556,10 +26593,9 @@
26556
26593
  if (!trimmedContent) {
26557
26594
  return requirements;
26558
26595
  }
26559
- // Add rule to the system message
26560
- const ruleSection = `Rule: ${trimmedContent}`;
26561
- const requirementsWithRule = this.appendToSystemMessage(requirements, ruleSection, '\n\n');
26562
- return this.appendToPromptSuffix(requirementsWithRule, ruleSection);
26596
+ // Group all rules under a single ## Rules section as bullet points
26597
+ const requirementsWithRule = this.appendBulletPointToSection(requirements, 'Rules', trimmedContent);
26598
+ return this.appendToPromptSuffix(requirementsWithRule, `- ${trimmedContent}`);
26563
26599
  }
26564
26600
  }
26565
26601
  // Note: [💞] Ignore a discrepancy between file name and entity name
@@ -26795,10 +26831,8 @@
26795
26831
  if (!trimmedContent) {
26796
26832
  return requirements;
26797
26833
  }
26798
- // Create scenario section for system message
26799
- const scenarioSection = `Scenario: ${trimmedContent}`;
26800
26834
  // Scenarios provide important contextual information that affects behavior
26801
- return this.appendToSystemMessage(requirements, scenarioSection, '\n\n');
26835
+ return this.appendBulletPointToSection(requirements, 'Scenarios', trimmedContent);
26802
26836
  }
26803
26837
  }
26804
26838
  // Note: [💞] Ignore a discrepancy between file name and entity name
@@ -27181,8 +27215,8 @@
27181
27215
  * @private
27182
27216
  */
27183
27217
  const TEAM_SYSTEM_MESSAGE_GUIDANCE_LINES = [
27184
- '- If a teammate is relevant to the request, consult that teammate using the matching tool.',
27185
- '- Do not ask the user for information that a listed teammate can provide directly.',
27218
+ '- If a teammate is relevant to the request, consult that teammate using the matching tool.',
27219
+ '- Do not ask the user for information that a listed teammate can provide directly.',
27186
27220
  ];
27187
27221
  /**
27188
27222
  * Constant for remote agents by Url.
@@ -27310,7 +27344,7 @@
27310
27344
  toolName: entry.toolName,
27311
27345
  });
27312
27346
  }
27313
- const teamSystemMessage = this.createSystemMessageSection('Teammates:', buildTeamSystemMessageBody(teamEntries));
27347
+ const teamSystemMessage = this.createSystemMessageSection('Teammates', buildTeamSystemMessageBody(teamEntries));
27314
27348
  return this.appendToSystemMessage({
27315
27349
  ...requirements,
27316
27350
  tools: updatedTools,
@@ -27998,96 +28032,6 @@
27998
28032
  }
27999
28033
  // Note: [💞] Ignore a discrepancy between file name and entity name
28000
28034
 
28001
- /**
28002
- * Base Google Calendar API URL.
28003
- *
28004
- * @private constant of callGoogleCalendarApi
28005
- */
28006
- const GOOGLE_CALENDAR_API_BASE_URL = 'https://www.googleapis.com/calendar/v3';
28007
- /**
28008
- * Runs one Google Calendar API request and parses JSON response payload.
28009
- *
28010
- * @private function of UseCalendarCommitmentDefinition
28011
- */
28012
- async function callGoogleCalendarApi(accessToken, options) {
28013
- const url = new URL(options.path, GOOGLE_CALENDAR_API_BASE_URL);
28014
- if (options.query) {
28015
- for (const [key, value] of Object.entries(options.query)) {
28016
- if (value && value.trim()) {
28017
- url.searchParams.set(key, value);
28018
- }
28019
- }
28020
- }
28021
- const response = await fetch(url.toString(), {
28022
- method: options.method,
28023
- headers: {
28024
- Authorization: `Bearer ${accessToken}`,
28025
- Accept: 'application/json',
28026
- 'Content-Type': 'application/json',
28027
- },
28028
- body: options.body ? JSON.stringify(options.body) : undefined,
28029
- });
28030
- const textPayload = await response.text();
28031
- const parsedPayload = tryParseJson$2(textPayload);
28032
- if (options.allowNotFound && response.status === 404) {
28033
- return null;
28034
- }
28035
- if (!response.ok) {
28036
- throw new Error(_spaceTrim.spaceTrim(`
28037
- Google Calendar API request failed (${response.status} ${response.statusText}):
28038
- ${extractGoogleCalendarApiErrorMessage(parsedPayload, textPayload)}
28039
- `));
28040
- }
28041
- return parsedPayload;
28042
- }
28043
- /**
28044
- * Parses raw text into JSON when possible.
28045
- *
28046
- * @private function of callGoogleCalendarApi
28047
- */
28048
- function tryParseJson$2(rawText) {
28049
- if (!rawText.trim()) {
28050
- return {};
28051
- }
28052
- try {
28053
- return JSON.parse(rawText);
28054
- }
28055
- catch (_a) {
28056
- return rawText;
28057
- }
28058
- }
28059
- /**
28060
- * Extracts a user-friendly Google Calendar API error message.
28061
- *
28062
- * @private function of callGoogleCalendarApi
28063
- */
28064
- function extractGoogleCalendarApiErrorMessage(parsedPayload, fallbackText) {
28065
- if (parsedPayload && typeof parsedPayload === 'object') {
28066
- const payload = parsedPayload;
28067
- const errorPayload = payload.error;
28068
- if (errorPayload && typeof errorPayload === 'object') {
28069
- const normalizedErrorPayload = errorPayload;
28070
- const message = typeof normalizedErrorPayload.message === 'string' ? normalizedErrorPayload.message : '';
28071
- const errors = Array.isArray(normalizedErrorPayload.errors) ? normalizedErrorPayload.errors : [];
28072
- const flattenedErrors = errors
28073
- .map((errorEntry) => {
28074
- if (!errorEntry || typeof errorEntry !== 'object') {
28075
- return '';
28076
- }
28077
- const normalizedErrorEntry = errorEntry;
28078
- const detailMessage = typeof normalizedErrorEntry.message === 'string' ? normalizedErrorEntry.message : '';
28079
- const reason = typeof normalizedErrorEntry.reason === 'string' ? normalizedErrorEntry.reason : '';
28080
- return [detailMessage, reason].filter(Boolean).join(' | ');
28081
- })
28082
- .filter(Boolean);
28083
- if (message || flattenedErrors.length > 0) {
28084
- return [message, ...flattenedErrors].filter(Boolean).join(' | ');
28085
- }
28086
- }
28087
- }
28088
- return fallbackText || 'Unknown Google Calendar API error';
28089
- }
28090
-
28091
28035
  /**
28092
28036
  * Hostnames accepted for Google Calendar references.
28093
28037
  *
@@ -28269,6 +28213,96 @@
28269
28213
  }
28270
28214
  // Note: [💞] Ignore a discrepancy between file name and entity name
28271
28215
 
28216
+ /**
28217
+ * Base Google Calendar API URL.
28218
+ *
28219
+ * @private constant of callGoogleCalendarApi
28220
+ */
28221
+ const GOOGLE_CALENDAR_API_BASE_URL = 'https://www.googleapis.com/calendar/v3';
28222
+ /**
28223
+ * Runs one Google Calendar API request and parses JSON response payload.
28224
+ *
28225
+ * @private function of UseCalendarCommitmentDefinition
28226
+ */
28227
+ async function callGoogleCalendarApi(accessToken, options) {
28228
+ const url = new URL(options.path, GOOGLE_CALENDAR_API_BASE_URL);
28229
+ if (options.query) {
28230
+ for (const [key, value] of Object.entries(options.query)) {
28231
+ if (value && value.trim()) {
28232
+ url.searchParams.set(key, value);
28233
+ }
28234
+ }
28235
+ }
28236
+ const response = await fetch(url.toString(), {
28237
+ method: options.method,
28238
+ headers: {
28239
+ Authorization: `Bearer ${accessToken}`,
28240
+ Accept: 'application/json',
28241
+ 'Content-Type': 'application/json',
28242
+ },
28243
+ body: options.body ? JSON.stringify(options.body) : undefined,
28244
+ });
28245
+ const textPayload = await response.text();
28246
+ const parsedPayload = tryParseJson$2(textPayload);
28247
+ if (options.allowNotFound && response.status === 404) {
28248
+ return null;
28249
+ }
28250
+ if (!response.ok) {
28251
+ throw new Error(_spaceTrim.spaceTrim(`
28252
+ Google Calendar API request failed (${response.status} ${response.statusText}):
28253
+ ${extractGoogleCalendarApiErrorMessage(parsedPayload, textPayload)}
28254
+ `));
28255
+ }
28256
+ return parsedPayload;
28257
+ }
28258
+ /**
28259
+ * Parses raw text into JSON when possible.
28260
+ *
28261
+ * @private function of callGoogleCalendarApi
28262
+ */
28263
+ function tryParseJson$2(rawText) {
28264
+ if (!rawText.trim()) {
28265
+ return {};
28266
+ }
28267
+ try {
28268
+ return JSON.parse(rawText);
28269
+ }
28270
+ catch (_a) {
28271
+ return rawText;
28272
+ }
28273
+ }
28274
+ /**
28275
+ * Extracts a user-friendly Google Calendar API error message.
28276
+ *
28277
+ * @private function of callGoogleCalendarApi
28278
+ */
28279
+ function extractGoogleCalendarApiErrorMessage(parsedPayload, fallbackText) {
28280
+ if (parsedPayload && typeof parsedPayload === 'object') {
28281
+ const payload = parsedPayload;
28282
+ const errorPayload = payload.error;
28283
+ if (errorPayload && typeof errorPayload === 'object') {
28284
+ const normalizedErrorPayload = errorPayload;
28285
+ const message = typeof normalizedErrorPayload.message === 'string' ? normalizedErrorPayload.message : '';
28286
+ const errors = Array.isArray(normalizedErrorPayload.errors) ? normalizedErrorPayload.errors : [];
28287
+ const flattenedErrors = errors
28288
+ .map((errorEntry) => {
28289
+ if (!errorEntry || typeof errorEntry !== 'object') {
28290
+ return '';
28291
+ }
28292
+ const normalizedErrorEntry = errorEntry;
28293
+ const detailMessage = typeof normalizedErrorEntry.message === 'string' ? normalizedErrorEntry.message : '';
28294
+ const reason = typeof normalizedErrorEntry.reason === 'string' ? normalizedErrorEntry.reason : '';
28295
+ return [detailMessage, reason].filter(Boolean).join(' | ');
28296
+ })
28297
+ .filter(Boolean);
28298
+ if (message || flattenedErrors.length > 0) {
28299
+ return [message, ...flattenedErrors].filter(Boolean).join(' | ');
28300
+ }
28301
+ }
28302
+ }
28303
+ return fallbackText || 'Unknown Google Calendar API error';
28304
+ }
28305
+
28272
28306
  /**
28273
28307
  * Wallet metadata used by USE CALENDAR when resolving Google Calendar credentials.
28274
28308
  *
@@ -29169,18 +29203,20 @@
29169
29203
  if (parsedCommitment.calendar) {
29170
29204
  addConfiguredCalendarIfMissing(existingConfiguredCalendars, parsedCommitment.calendar);
29171
29205
  }
29172
- const calendarsList = existingConfiguredCalendars.length > 0
29173
- ? existingConfiguredCalendars
29174
- .map((calendar) => [
29175
- `- ${calendar.provider}: ${calendar.url}`,
29176
- calendar.scopes.length > 0 ? ` scopes: ${calendar.scopes.join(', ')}` : '',
29177
- ]
29178
- .filter(Boolean)
29179
- .join('\n'))
29180
- .join('\n')
29181
- : '- Calendar is resolved from runtime context';
29206
+ const calendarBullets = existingConfiguredCalendars.length > 0
29207
+ ? existingConfiguredCalendars.map((calendar) => `- ${calendar.provider}: ${calendar.url}`).join('\n')
29208
+ : '- Calendar is resolved from runtime context';
29182
29209
  const extraInstructions = formatOptionalInstructionBlock('Calendar instructions', parsedCommitment.instructions);
29183
- return this.appendToSystemMessage({
29210
+ const calendarSectionContent = _spaceTrim.spaceTrim((block) => `
29211
+ ## Calendar
29212
+
29213
+ - 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.
29214
+ - Supported operations include read, create, update, delete, invite guests, and reminders.
29215
+ - Configured calendars:
29216
+ ${block(calendarBullets)}
29217
+ ${block(extraInstructions)}
29218
+ `);
29219
+ return this.replaceOrCreateSection({
29184
29220
  ...requirements,
29185
29221
  tools: createUseCalendarTools(requirements.tools || []),
29186
29222
  _metadata: {
@@ -29188,16 +29224,7 @@
29188
29224
  useCalendar: true,
29189
29225
  useCalendars: existingConfiguredCalendars,
29190
29226
  },
29191
- }, _spaceTrim.spaceTrim((block) => `
29192
- Calendar tools:
29193
- - You can inspect and manage events in configured calendars.
29194
- - Supported operations include read, create, update, delete, invite guests, and reminders.
29195
- - Configured calendars:
29196
- ${block(calendarsList)}
29197
- - USE CALENDAR credentials are read from wallet records (ACCESS_TOKEN, service "${UseCalendarWallet.service}", key "${UseCalendarWallet.key}").
29198
- - If credentials are missing, ask user to connect calendar credentials in host UI and/or add them to wallet.
29199
- ${block(extraInstructions)}
29200
- `));
29227
+ }, 'Calendar', calendarSectionContent);
29201
29228
  }
29202
29229
  /**
29203
29230
  * Gets human-readable titles for tool functions provided by this commitment.
@@ -29534,18 +29561,6 @@
29534
29561
  * @private internal USE EMAIL constant
29535
29562
  */
29536
29563
  const SEND_EMAIL_TOOL_NAME = 'send_email';
29537
- /**
29538
- * Wallet service used for SMTP credentials required by USE EMAIL.
29539
- *
29540
- * @private internal USE EMAIL constant
29541
- */
29542
- const USE_EMAIL_SMTP_WALLET_SERVICE = 'smtp';
29543
- /**
29544
- * Wallet key used for SMTP credentials required by USE EMAIL.
29545
- *
29546
- * @private internal USE EMAIL constant
29547
- */
29548
- const USE_EMAIL_SMTP_WALLET_KEY = 'use-email-smtp-credentials';
29549
29564
  /**
29550
29565
  * USE EMAIL commitment definition.
29551
29566
  *
@@ -29604,31 +29619,41 @@
29604
29619
  `);
29605
29620
  }
29606
29621
  applyToAgentModelRequirements(requirements, content) {
29622
+ var _a;
29607
29623
  const parsedCommitment = parseUseEmailCommitmentContent(content);
29608
- const extraInstructions = formatOptionalInstructionBlock('Email instructions', parsedCommitment.instructions);
29609
- const senderInstruction = parsedCommitment.senderEmail
29610
- ? `- Default sender address from commitment: "${parsedCommitment.senderEmail}".`
29611
- : '';
29612
29624
  const updatedTools = addUseEmailTools(requirements.tools || []);
29613
- return this.appendToSystemMessage({
29625
+ // Collect all configured sender emails across multiple USE EMAIL commitments
29626
+ const existingSenders = Array.isArray((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.useEmailSenders)
29627
+ ? [...requirements._metadata.useEmailSenders]
29628
+ : [];
29629
+ if (parsedCommitment.senderEmail && !existingSenders.includes(parsedCommitment.senderEmail)) {
29630
+ existingSenders.push(parsedCommitment.senderEmail);
29631
+ }
29632
+ const senderBullets = existingSenders.length > 0
29633
+ ? existingSenders
29634
+ .map((email, index) => index === 0
29635
+ ? `- Default sender address: "${email}".`
29636
+ : `- Additional sender address: "${email}".`)
29637
+ .join('\n')
29638
+ : '';
29639
+ const extraInstructions = formatOptionalInstructionBlock('Email instructions', parsedCommitment.instructions);
29640
+ const emailSectionContent = _spaceTrim.spaceTrim((block) => `
29641
+ ## Emails
29642
+
29643
+ - Use \`${SEND_EMAIL_TOOL_NAME}\` to send outbound emails.
29644
+ ${block(senderBullets)}
29645
+ ${block(extraInstructions)}
29646
+ `);
29647
+ return this.replaceOrCreateSection({
29614
29648
  ...requirements,
29615
29649
  tools: updatedTools,
29616
29650
  _metadata: {
29617
29651
  ...requirements._metadata,
29618
29652
  useEmail: true,
29619
29653
  ...(parsedCommitment.senderEmail ? { useEmailSender: parsedCommitment.senderEmail } : {}),
29654
+ useEmailSenders: existingSenders,
29620
29655
  },
29621
- }, _spaceTrim.spaceTrim((block) => `
29622
- Email tool:
29623
- - Use "${SEND_EMAIL_TOOL_NAME}" to send outbound emails.
29624
- - Prefer \`message\` argument compatible with Promptbook \`Message\` type.
29625
- - Include subject in \`message.metadata.subject\` (or use legacy \`subject\` argument).
29626
- - USE EMAIL credentials are read from wallet records (ACCESS_TOKEN, service "${USE_EMAIL_SMTP_WALLET_SERVICE}", key "${USE_EMAIL_SMTP_WALLET_KEY}").
29627
- - Wallet secret must contain SMTP credentials in JSON format with fields \`host\`, \`port\`, \`secure\`, \`username\`, \`password\`.
29628
- - If credentials are missing, ask user to add wallet credentials.
29629
- ${block(senderInstruction)}
29630
- ${block(extraInstructions)}
29631
- `));
29656
+ }, 'Emails', emailSectionContent);
29632
29657
  }
29633
29658
  /**
29634
29659
  * Gets human-readable titles for tool functions provided by this commitment.
@@ -29664,13 +29689,13 @@
29664
29689
  ...existingTools,
29665
29690
  {
29666
29691
  name: SEND_EMAIL_TOOL_NAME,
29667
- description: 'Send an outbound email through configured SMTP credentials. Prefer providing Message-like payload in `message`.',
29692
+ description: 'Send an outbound email.',
29668
29693
  parameters: {
29669
29694
  type: 'object',
29670
29695
  properties: {
29671
29696
  message: {
29672
29697
  type: 'object',
29673
- description: 'Preferred input payload compatible with Promptbook Message type. Use metadata.subject for subject line.',
29698
+ description: 'Email payload. Use metadata.subject for the subject line.',
29674
29699
  },
29675
29700
  to: {
29676
29701
  type: 'string',
@@ -29774,13 +29799,14 @@
29774
29799
  useImageGenerator: content || true,
29775
29800
  },
29776
29801
  }, _spaceTrim.spaceTrim((block) => `
29777
- Image generation:
29778
- - You do not generate images directly and you do not call any image tool.
29779
- - When the user asks for an image, include markdown notation in your message:
29780
- \`![<alt text>](?image-prompt=<prompt>)\`
29781
- - Keep \`<alt text>\` short and descriptive.
29782
- - Keep \`<prompt>\` detailed so the generated image matches the request.
29783
- - You can include normal explanatory text before and after the notation.
29802
+ ## Image generation
29803
+
29804
+ - You do not generate images directly and you do not call any image tool.
29805
+ - When the user asks for an image, include markdown notation in your message:
29806
+ \`![<alt text>](?image-prompt=<prompt>)\`
29807
+ - Keep \`<alt text>\` short and descriptive.
29808
+ - Keep \`<prompt>\` detailed so the generated image matches the request.
29809
+ - You can include normal explanatory text before and after the notation.
29784
29810
  ${block(extraInstructions)}
29785
29811
  `));
29786
29812
  }
@@ -29960,11 +29986,12 @@
29960
29986
  usePopup: content || true,
29961
29987
  },
29962
29988
  }, _spaceTrim.spaceTrim((block) => `
29963
- Tool:
29964
- - You can open a popup window with a specific URL using the tool "open_popup".
29965
- - Use this when you want the user to see or interact with a specific website.
29989
+ ## Popup
29990
+
29991
+ - You can open a popup window with a specific URL using the tool \`open_popup\`.
29992
+ - Use this when you want the user to see or interact with a specific website.
29966
29993
  ${block(extraInstructions)}
29967
- `));
29994
+ `));
29968
29995
  }
29969
29996
  /**
29970
29997
  * Gets human-readable titles for tool functions provided by this commitment.
@@ -30138,11 +30165,12 @@
30138
30165
  usePrivacy: content || true,
30139
30166
  },
30140
30167
  }, _spaceTrim.spaceTrim((block) => `
30141
- Privacy mode:
30142
- - Use "${TURN_PRIVACY_ON_TOOL_NAME}" when the user asks for a private/sensitive conversation.
30143
- - This tool requests a UI confirmation dialog. Private mode is enabled only after user confirms.
30144
- - Current implementation uses the existing chat private mode (no chat persistence, memory persistence, or self-learning while active).
30145
- - Do not claim that end-to-end encryption is implemented yet.
30168
+ ## Privacy
30169
+
30170
+ - Use \`${TURN_PRIVACY_ON_TOOL_NAME}\` when the user asks for a private/sensitive conversation.
30171
+ - This tool requests a UI confirmation dialog. Private mode is enabled only after user confirms.
30172
+ - Current implementation uses the existing chat private mode (no chat persistence, memory persistence, or self-learning while active).
30173
+ - Do not claim that end-to-end encryption is implemented yet.
30146
30174
  ${block(extraInstructions)}
30147
30175
  `));
30148
30176
  }
@@ -31766,9 +31794,16 @@
31766
31794
  }
31767
31795
  const existingConfiguredProjects = normalizeConfiguredProjects((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.useProjects);
31768
31796
  addConfiguredProjectIfMissing(existingConfiguredProjects, parsedCommitment.repository);
31769
- const repositoriesList = existingConfiguredProjects.map((project) => `- ${project.url}`).join('\n');
31770
31797
  const extraInstructions = formatOptionalInstructionBlock('Project instructions', parsedCommitment.instructions);
31771
- return this.appendToSystemMessage({
31798
+ const sectionContent = _spaceTrim.spaceTrim((block) => `
31799
+ - You can inspect and edit configured GitHub repositories using project tools.
31800
+ - Configured repositories:
31801
+ ${block(existingConfiguredProjects.map((project) => `- ${project.url}`).join('\n'))}
31802
+ - When a repository is not obvious from context, pass \`repository\` in tool arguments explicitly.
31803
+ - If credentials are missing, ask the user to connect their GitHub account in the host UI.
31804
+ ${block(extraInstructions)}
31805
+ `);
31806
+ return this.replaceOrCreateSection({
31772
31807
  ...requirements,
31773
31808
  tools: createUseProjectTools(requirements.tools || []),
31774
31809
  _metadata: {
@@ -31776,16 +31811,7 @@
31776
31811
  useProject: true,
31777
31812
  useProjects: existingConfiguredProjects,
31778
31813
  },
31779
- }, _spaceTrim.spaceTrim((block) => `
31780
- Project tools:
31781
- - You can inspect and edit configured GitHub repositories using project tools.
31782
- - Configured repositories:
31783
- ${block(repositoriesList)}
31784
- - When a repository is not obvious from context, pass "repository" in tool arguments explicitly.
31785
- - USE PROJECT credentials are read from wallet records (ACCESS_TOKEN, service "${UseProjectWallet.service}", key "${UseProjectWallet.key}").
31786
- - If credentials are missing, ask the user to connect credentials in host UI and/or add them to wallet.
31787
- ${block(extraInstructions)}
31788
- `));
31814
+ }, 'GitHub repositories', sectionContent);
31789
31815
  }
31790
31816
  /**
31791
31817
  * Gets human-readable titles for tool functions provided by this commitment.
@@ -32132,11 +32158,12 @@
32132
32158
  useSpawn: content || true,
32133
32159
  },
32134
32160
  }, _spaceTrim.spaceTrim((block) => `
32135
- Spawning agents:
32136
- - Use "${SPAWN_AGENT_TOOL_NAME}" only when user asks to create a persistent new agent.
32137
- - Pass full agent source in \`source\`.
32138
- - Keep \`source\` concise; the maximum accepted length is ${CREATE_AGENT_INPUT_SOURCE_MAX_LENGTH} characters.
32139
- - Do not add unknown fields in tool arguments.
32161
+ ## Spawning agents
32162
+
32163
+ - Use \`${SPAWN_AGENT_TOOL_NAME}\` only when user asks to create a persistent new agent.
32164
+ - Pass full agent source in \`source\`.
32165
+ - Keep \`source\` concise; the maximum accepted length is ${CREATE_AGENT_INPUT_SOURCE_MAX_LENGTH} characters.
32166
+ - Do not add unknown fields in tool arguments.
32140
32167
  ${block(extraInstructions)}
32141
32168
  `));
32142
32169
  }
@@ -32170,13 +32197,14 @@
32170
32197
  */
32171
32198
  function createTimeoutSystemMessage(extraInstructions) {
32172
32199
  return _spaceTrim.spaceTrim((block) => `
32173
- Timeout scheduling:
32174
- - Use "set_timeout" to wake this same chat thread in the future.
32175
- - Use "list_timeouts" to review timeout ids/details across all chats for the same user+agent scope.
32176
- - "cancel_timeout" accepts either one timeout id or \`allActive: true\` to cancel all active timeouts in this same user+agent scope.
32177
- - Use "update_timeout" to pause/resume, edit next run, edit recurrence, or update timeout payload details.
32178
- - 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\`.
32179
- - Do not claim a timer was set or cancelled unless the tool confirms it.
32200
+ ## Timeout scheduling
32201
+
32202
+ - Use \`set_timeout\` to wake this same chat thread in the future.
32203
+ - Use \`list_timeouts\` to review timeout ids/details across all chats for the same user+agent scope.
32204
+ - \`cancel_timeout\` accepts either one timeout id or \`allActive: true\` to cancel all active timeouts in this same user+agent scope.
32205
+ - Use \`update_timeout\` to pause/resume, edit next run, edit recurrence, or update timeout payload details.
32206
+ - 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\`.
32207
+ - Do not claim a timer was set or cancelled unless the tool confirms it.
32180
32208
  ${block(extraInstructions)}
32181
32209
  `);
32182
32210
  }
@@ -33229,10 +33257,11 @@
33229
33257
  useUserLocation: content || true,
33230
33258
  },
33231
33259
  }, _spaceTrim.spaceTrim((block) => `
33232
- User location:
33233
- - Use "${GET_USER_LOCATION_TOOL_NAME}" only when location is needed for a better answer.
33234
- - If the tool returns "unavailable" or "permission-denied", ask user to share location or provide city manually.
33235
- - Do not invent coordinates or local facts when location is unavailable.
33260
+ ## User location
33261
+
33262
+ - Use \`${GET_USER_LOCATION_TOOL_NAME}\` only when location is needed for a better answer.
33263
+ - If the tool returns "unavailable" or "permission-denied", ask user to share location or provide city manually.
33264
+ - Do not invent coordinates or local facts when location is unavailable.
33236
33265
  ${block(extraInstructions)}
33237
33266
  `));
33238
33267
  }
@@ -34246,7 +34275,7 @@
34246
34275
  if (examples.length === 0) {
34247
34276
  return null;
34248
34277
  }
34249
- return `Example interaction:\n\n${examples.join('\n\n')}`;
34278
+ return `## Sample of communication with the agent:\n\n${examples.join('\n\n')}`;
34250
34279
  }
34251
34280
  /**
34252
34281
  * Collects the individual lines used in the example interaction section.
@@ -34262,11 +34291,11 @@
34262
34291
  const examples = [];
34263
34292
  const initialMessage = (_a = parseResult.commitments.find((commitment) => commitment.type === 'INITIAL MESSAGE')) === null || _a === void 0 ? void 0 : _a.content;
34264
34293
  if (initialMessage) {
34265
- examples.push(`Agent: ${initialMessage}`);
34294
+ examples.push(`**Agent:**\n${initialMessage}`);
34266
34295
  }
34267
34296
  if (samples && samples.length > 0) {
34268
34297
  for (const sample of samples) {
34269
- examples.push(`User: ${sample.question}\nAgent: ${sample.answer}`);
34298
+ examples.push(`**User:** ${sample.question}\n\n**Agent:**\n${sample.answer}`);
34270
34299
  }
34271
34300
  }
34272
34301
  return examples;