@promptbook/browser 0.112.0-11 → 0.112.0-12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/esm/index.es.js +1236 -1
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/src/book-2.0/agent-source/AgentBasicInformation.d.ts +1 -1
  4. package/esm/src/book-components/Chat/Chat/ChatToolCallModal.test.d.ts +2 -0
  5. package/esm/src/book-components/Chat/Chat/renderToolCallDetails.d.ts +4 -0
  6. package/esm/src/book-components/Chat/utils/getToolCallChipletInfo.timeout.test.d.ts +1 -0
  7. package/esm/src/book-components/Chat/utils/timeoutToolCallPresentation.d.ts +123 -0
  8. package/esm/src/book-components/Chat/utils/timeoutToolCallPresentation.test.d.ts +1 -0
  9. package/esm/src/commitments/USE_CALENDAR/USE_CALENDAR.d.ts +42 -0
  10. package/esm/src/commitments/USE_CALENDAR/USE_CALENDAR.test.d.ts +1 -0
  11. package/esm/src/commitments/USE_CALENDAR/UseCalendarToolNames.d.ts +13 -0
  12. package/esm/src/commitments/USE_CALENDAR/UseCalendarWallet.d.ts +9 -0
  13. package/esm/src/commitments/USE_CALENDAR/calendarReference.d.ts +68 -0
  14. package/esm/src/commitments/USE_CALENDAR/callGoogleCalendarApi.d.ts +19 -0
  15. package/esm/src/commitments/USE_CALENDAR/createUseCalendarToolFunctions.d.ts +8 -0
  16. package/esm/src/commitments/USE_CALENDAR/createUseCalendarTools.d.ts +7 -0
  17. package/esm/src/commitments/USE_CALENDAR/getUseCalendarToolTitles.d.ts +7 -0
  18. package/esm/src/commitments/USE_CALENDAR/normalizeConfiguredCalendars.d.ts +19 -0
  19. package/esm/src/commitments/USE_CALENDAR/resolveUseCalendarToolRuntimeOrWalletCredentialResult.d.ts +34 -0
  20. package/esm/src/commitments/_common/toolRuntimeContext.d.ts +9 -0
  21. package/esm/src/commitments/index.d.ts +2 -1
  22. package/esm/src/executables/apps/locateVscode.d.ts +7 -0
  23. package/esm/src/executables/apps/locateVscode.test.d.ts +1 -0
  24. package/esm/src/executables/browsers/locateBrowser.d.ts +10 -0
  25. package/esm/src/executables/browsers/locateBrowser.test.d.ts +1 -0
  26. package/esm/src/executables/browsers/locateChrome.d.ts +7 -0
  27. package/esm/src/executables/browsers/locateChrome.test.d.ts +1 -0
  28. package/esm/src/executables/browsers/locateDefaultSystemBrowser.d.ts +10 -0
  29. package/esm/src/executables/browsers/locateDefaultSystemBrowser.test.d.ts +1 -0
  30. package/esm/src/executables/browsers/locateEdge.d.ts +7 -0
  31. package/esm/src/executables/browsers/locateEdge.test.d.ts +1 -0
  32. package/esm/src/executables/browsers/locateFirefox.d.ts +7 -0
  33. package/esm/src/executables/browsers/locateFirefox.test.d.ts +1 -0
  34. package/esm/src/executables/browsers/locateInternetExplorer.d.ts +7 -0
  35. package/esm/src/executables/browsers/locateInternetExplorer.test.d.ts +1 -0
  36. package/esm/src/executables/browsers/locateSafari.d.ts +7 -0
  37. package/esm/src/version.d.ts +1 -1
  38. package/package.json +2 -2
  39. package/umd/index.umd.js +1236 -1
  40. package/umd/index.umd.js.map +1 -1
  41. package/umd/src/book-2.0/agent-source/AgentBasicInformation.d.ts +1 -1
  42. package/umd/src/book-components/Chat/Chat/ChatToolCallModal.test.d.ts +2 -0
  43. package/umd/src/book-components/Chat/Chat/renderToolCallDetails.d.ts +4 -0
  44. package/umd/src/book-components/Chat/utils/getToolCallChipletInfo.timeout.test.d.ts +1 -0
  45. package/umd/src/book-components/Chat/utils/timeoutToolCallPresentation.d.ts +123 -0
  46. package/umd/src/book-components/Chat/utils/timeoutToolCallPresentation.test.d.ts +1 -0
  47. package/umd/src/commitments/USE_CALENDAR/USE_CALENDAR.d.ts +42 -0
  48. package/umd/src/commitments/USE_CALENDAR/USE_CALENDAR.test.d.ts +1 -0
  49. package/umd/src/commitments/USE_CALENDAR/UseCalendarToolNames.d.ts +13 -0
  50. package/umd/src/commitments/USE_CALENDAR/UseCalendarWallet.d.ts +9 -0
  51. package/umd/src/commitments/USE_CALENDAR/calendarReference.d.ts +68 -0
  52. package/umd/src/commitments/USE_CALENDAR/callGoogleCalendarApi.d.ts +19 -0
  53. package/umd/src/commitments/USE_CALENDAR/createUseCalendarToolFunctions.d.ts +8 -0
  54. package/umd/src/commitments/USE_CALENDAR/createUseCalendarTools.d.ts +7 -0
  55. package/umd/src/commitments/USE_CALENDAR/getUseCalendarToolTitles.d.ts +7 -0
  56. package/umd/src/commitments/USE_CALENDAR/normalizeConfiguredCalendars.d.ts +19 -0
  57. package/umd/src/commitments/USE_CALENDAR/resolveUseCalendarToolRuntimeOrWalletCredentialResult.d.ts +34 -0
  58. package/umd/src/commitments/_common/toolRuntimeContext.d.ts +9 -0
  59. package/umd/src/commitments/index.d.ts +2 -1
  60. package/umd/src/executables/apps/locateVscode.d.ts +7 -0
  61. package/umd/src/executables/apps/locateVscode.test.d.ts +1 -0
  62. package/umd/src/executables/browsers/locateBrowser.d.ts +10 -0
  63. package/umd/src/executables/browsers/locateBrowser.test.d.ts +1 -0
  64. package/umd/src/executables/browsers/locateChrome.d.ts +7 -0
  65. package/umd/src/executables/browsers/locateChrome.test.d.ts +1 -0
  66. package/umd/src/executables/browsers/locateDefaultSystemBrowser.d.ts +10 -0
  67. package/umd/src/executables/browsers/locateDefaultSystemBrowser.test.d.ts +1 -0
  68. package/umd/src/executables/browsers/locateEdge.d.ts +7 -0
  69. package/umd/src/executables/browsers/locateEdge.test.d.ts +1 -0
  70. package/umd/src/executables/browsers/locateFirefox.d.ts +7 -0
  71. package/umd/src/executables/browsers/locateFirefox.test.d.ts +1 -0
  72. package/umd/src/executables/browsers/locateInternetExplorer.d.ts +7 -0
  73. package/umd/src/executables/browsers/locateInternetExplorer.test.d.ts +1 -0
  74. package/umd/src/executables/browsers/locateSafari.d.ts +7 -0
  75. package/umd/src/version.d.ts +1 -1
package/esm/index.es.js CHANGED
@@ -29,7 +29,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
29
29
  * @generated
30
30
  * @see https://github.com/webgptorg/promptbook
31
31
  */
32
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-11';
32
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-12';
33
33
  /**
34
34
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
35
35
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -10963,6 +10963,1232 @@ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
10963
10963
  * Note: [💞] Ignore a discrepancy between file name and entity name
10964
10964
  */
10965
10965
 
10966
+ /**
10967
+ * Base Google Calendar API URL.
10968
+ *
10969
+ * @private constant of callGoogleCalendarApi
10970
+ */
10971
+ const GOOGLE_CALENDAR_API_BASE_URL = 'https://www.googleapis.com/calendar/v3';
10972
+ /**
10973
+ * Runs one Google Calendar API request and parses JSON response payload.
10974
+ *
10975
+ * @private function of UseCalendarCommitmentDefinition
10976
+ */
10977
+ async function callGoogleCalendarApi(accessToken, options) {
10978
+ const url = new URL(options.path, GOOGLE_CALENDAR_API_BASE_URL);
10979
+ if (options.query) {
10980
+ for (const [key, value] of Object.entries(options.query)) {
10981
+ if (value && value.trim()) {
10982
+ url.searchParams.set(key, value);
10983
+ }
10984
+ }
10985
+ }
10986
+ const response = await fetch(url.toString(), {
10987
+ method: options.method,
10988
+ headers: {
10989
+ Authorization: `Bearer ${accessToken}`,
10990
+ Accept: 'application/json',
10991
+ 'Content-Type': 'application/json',
10992
+ },
10993
+ body: options.body ? JSON.stringify(options.body) : undefined,
10994
+ });
10995
+ const textPayload = await response.text();
10996
+ const parsedPayload = tryParseJson$2(textPayload);
10997
+ if (options.allowNotFound && response.status === 404) {
10998
+ return null;
10999
+ }
11000
+ if (!response.ok) {
11001
+ throw new Error(spaceTrim$1(`
11002
+ Google Calendar API request failed (${response.status} ${response.statusText}):
11003
+ ${extractGoogleCalendarApiErrorMessage(parsedPayload, textPayload)}
11004
+ `));
11005
+ }
11006
+ return parsedPayload;
11007
+ }
11008
+ /**
11009
+ * Parses raw text into JSON when possible.
11010
+ *
11011
+ * @private function of callGoogleCalendarApi
11012
+ */
11013
+ function tryParseJson$2(rawText) {
11014
+ if (!rawText.trim()) {
11015
+ return {};
11016
+ }
11017
+ try {
11018
+ return JSON.parse(rawText);
11019
+ }
11020
+ catch (_a) {
11021
+ return rawText;
11022
+ }
11023
+ }
11024
+ /**
11025
+ * Extracts a user-friendly Google Calendar API error message.
11026
+ *
11027
+ * @private function of callGoogleCalendarApi
11028
+ */
11029
+ function extractGoogleCalendarApiErrorMessage(parsedPayload, fallbackText) {
11030
+ if (parsedPayload && typeof parsedPayload === 'object') {
11031
+ const payload = parsedPayload;
11032
+ const errorPayload = payload.error;
11033
+ if (errorPayload && typeof errorPayload === 'object') {
11034
+ const normalizedErrorPayload = errorPayload;
11035
+ const message = typeof normalizedErrorPayload.message === 'string' ? normalizedErrorPayload.message : '';
11036
+ const errors = Array.isArray(normalizedErrorPayload.errors) ? normalizedErrorPayload.errors : [];
11037
+ const flattenedErrors = errors
11038
+ .map((errorEntry) => {
11039
+ if (!errorEntry || typeof errorEntry !== 'object') {
11040
+ return '';
11041
+ }
11042
+ const normalizedErrorEntry = errorEntry;
11043
+ const detailMessage = typeof normalizedErrorEntry.message === 'string' ? normalizedErrorEntry.message : '';
11044
+ const reason = typeof normalizedErrorEntry.reason === 'string' ? normalizedErrorEntry.reason : '';
11045
+ return [detailMessage, reason].filter(Boolean).join(' | ');
11046
+ })
11047
+ .filter(Boolean);
11048
+ if (message || flattenedErrors.length > 0) {
11049
+ return [message, ...flattenedErrors].filter(Boolean).join(' | ');
11050
+ }
11051
+ }
11052
+ }
11053
+ return fallbackText || 'Unknown Google Calendar API error';
11054
+ }
11055
+
11056
+ /**
11057
+ * Hostnames accepted for Google Calendar references.
11058
+ *
11059
+ * @private internal USE CALENDAR constant
11060
+ */
11061
+ const GOOGLE_CALENDAR_HOSTNAMES = new Set(['calendar.google.com', 'www.calendar.google.com']);
11062
+ /**
11063
+ * Default Google Calendar OAuth scopes when commitment content does not list any.
11064
+ *
11065
+ * @private internal USE CALENDAR constant
11066
+ */
11067
+ const DEFAULT_GOOGLE_CALENDAR_SCOPES = ['https://www.googleapis.com/auth/calendar'];
11068
+ /**
11069
+ * Parses one Google Calendar URL/reference into canonical details.
11070
+ *
11071
+ * Supported input forms:
11072
+ * - `https://calendar.google.com/...`
11073
+ * - `calendar.google.com/...`
11074
+ *
11075
+ * @private internal utility of USE CALENDAR commitment
11076
+ */
11077
+ function parseGoogleCalendarReference(rawReference) {
11078
+ const trimmedReference = rawReference.trim();
11079
+ if (!trimmedReference) {
11080
+ return null;
11081
+ }
11082
+ const normalizedReference = trimmedReference.startsWith('calendar.google.com/')
11083
+ ? `https://${trimmedReference}`
11084
+ : trimmedReference;
11085
+ let parsedUrl;
11086
+ try {
11087
+ parsedUrl = new URL(normalizedReference);
11088
+ }
11089
+ catch (_a) {
11090
+ return null;
11091
+ }
11092
+ if (!GOOGLE_CALENDAR_HOSTNAMES.has(parsedUrl.hostname.toLowerCase())) {
11093
+ return null;
11094
+ }
11095
+ parsedUrl.protocol = 'https:';
11096
+ parsedUrl.hash = '';
11097
+ return {
11098
+ provider: 'google',
11099
+ url: parsedUrl.toString(),
11100
+ calendarId: parseGoogleCalendarIdFromUrl(parsedUrl) || 'primary',
11101
+ scopes: [...DEFAULT_GOOGLE_CALENDAR_SCOPES],
11102
+ };
11103
+ }
11104
+ /**
11105
+ * Parses `USE CALENDAR` commitment content into calendar reference + optional instructions.
11106
+ *
11107
+ * @private internal utility of USE CALENDAR commitment
11108
+ */
11109
+ function parseUseCalendarCommitmentContent(content) {
11110
+ const trimmedContent = spaceTrim$1(content);
11111
+ if (!trimmedContent) {
11112
+ return {
11113
+ calendar: null,
11114
+ calendarUrlRaw: null,
11115
+ instructions: '',
11116
+ };
11117
+ }
11118
+ const lines = trimmedContent
11119
+ .split(/\r?\n/)
11120
+ .map((line) => line.trim())
11121
+ .filter(Boolean);
11122
+ if (lines.length === 0) {
11123
+ return {
11124
+ calendar: null,
11125
+ calendarUrlRaw: null,
11126
+ instructions: '',
11127
+ };
11128
+ }
11129
+ let calendarReferenceRaw = null;
11130
+ let calendarReference = null;
11131
+ const firstLine = lines[0] || '';
11132
+ const firstLineTokens = firstLine.split(/\s+/).filter(Boolean);
11133
+ for (const token of firstLineTokens) {
11134
+ const cleanedToken = token.replace(/[),.;:!?]+$/g, '');
11135
+ const parsedReference = parseGoogleCalendarReference(cleanedToken);
11136
+ if (!parsedReference) {
11137
+ continue;
11138
+ }
11139
+ calendarReferenceRaw = cleanedToken;
11140
+ calendarReference = parsedReference;
11141
+ break;
11142
+ }
11143
+ if (!calendarReference) {
11144
+ const firstUrl = findFirstUrlToken(trimmedContent);
11145
+ if (firstUrl) {
11146
+ calendarReferenceRaw = firstUrl;
11147
+ calendarReference = parseGoogleCalendarReference(firstUrl);
11148
+ }
11149
+ }
11150
+ const scopes = extractGoogleCalendarScopes(trimmedContent);
11151
+ if (calendarReference) {
11152
+ calendarReference = {
11153
+ ...calendarReference,
11154
+ scopes: scopes.length > 0 ? scopes : [...DEFAULT_GOOGLE_CALENDAR_SCOPES],
11155
+ tokenRef: extractTokenRef(trimmedContent),
11156
+ };
11157
+ }
11158
+ const instructionLines = [...lines];
11159
+ if (instructionLines.length > 0 && calendarReferenceRaw) {
11160
+ instructionLines[0] = removeTokenFromLine(instructionLines[0] || '', calendarReferenceRaw);
11161
+ }
11162
+ const filteredInstructionLines = instructionLines.filter((line) => !/^\s*SCOPES?\s+/i.test(line) && !line.trim().startsWith('https://www.googleapis.com/auth/'));
11163
+ return {
11164
+ calendar: calendarReference,
11165
+ calendarUrlRaw: calendarReferenceRaw,
11166
+ instructions: filteredInstructionLines.join('\n').trim(),
11167
+ };
11168
+ }
11169
+ /**
11170
+ * Attempts to resolve one concrete Google Calendar id from URL.
11171
+ *
11172
+ * @private internal utility of USE CALENDAR commitment
11173
+ */
11174
+ function parseGoogleCalendarIdFromUrl(url) {
11175
+ const rawCalendarId = url.searchParams.get('cid') || url.searchParams.get('src') || url.searchParams.get('calendarId');
11176
+ if (!rawCalendarId) {
11177
+ return null;
11178
+ }
11179
+ const decodedCalendarId = decodeURIComponent(rawCalendarId).trim();
11180
+ return decodedCalendarId || null;
11181
+ }
11182
+ /**
11183
+ * Finds the first URL-looking token in text.
11184
+ *
11185
+ * @private utility of USE CALENDAR commitment
11186
+ */
11187
+ function findFirstUrlToken(text) {
11188
+ const match = text.match(/https?:\/\/[^\s)]+/i);
11189
+ return match ? match[0] || null : null;
11190
+ }
11191
+ /**
11192
+ * Extracts Google Calendar OAuth scopes declared in commitment text.
11193
+ *
11194
+ * @private utility of USE CALENDAR commitment
11195
+ */
11196
+ function extractGoogleCalendarScopes(content) {
11197
+ const scopesFromUrls = content.match(/https:\/\/www\.googleapis\.com\/auth\/[A-Za-z0-9._/-]+/gim) || [];
11198
+ const scopesFromKeywordLines = content
11199
+ .split(/\r?\n/)
11200
+ .map((line) => line.trim())
11201
+ .filter((line) => /^\s*SCOPES?\s+/i.test(line))
11202
+ .flatMap((line) => line
11203
+ .replace(/^\s*SCOPES?\s+/i, '')
11204
+ .split(/[,\s]+/)
11205
+ .map((scope) => scope.trim())
11206
+ .filter(Boolean))
11207
+ .filter((scope) => scope.startsWith('https://www.googleapis.com/auth/'));
11208
+ const uniqueScopes = new Set();
11209
+ for (const scope of [...scopesFromUrls, ...scopesFromKeywordLines]) {
11210
+ uniqueScopes.add(scope);
11211
+ }
11212
+ return [...uniqueScopes];
11213
+ }
11214
+ /**
11215
+ * Extracts optional token reference marker from commitment text.
11216
+ *
11217
+ * @private utility of USE CALENDAR commitment
11218
+ */
11219
+ function extractTokenRef(content) {
11220
+ var _a;
11221
+ const tokenRefMatch = content.match(/@[\w.-]+/);
11222
+ const tokenRef = (_a = tokenRefMatch === null || tokenRefMatch === void 0 ? void 0 : tokenRefMatch[0]) === null || _a === void 0 ? void 0 : _a.trim();
11223
+ return tokenRef || undefined;
11224
+ }
11225
+ /**
11226
+ * Removes one specific token from one instruction line.
11227
+ *
11228
+ * @private utility of USE CALENDAR commitment
11229
+ */
11230
+ function removeTokenFromLine(line, token) {
11231
+ const tokens = line.split(/\s+/).filter(Boolean);
11232
+ const filteredTokens = tokens.filter((lineToken) => lineToken.replace(/[),.;:!?]+$/g, '') !== token);
11233
+ return filteredTokens.join(' ').trim();
11234
+ }
11235
+ /**
11236
+ * Note: [💞] Ignore a discrepancy between file name and entity name
11237
+ */
11238
+
11239
+ /**
11240
+ * Wallet metadata used by USE CALENDAR when resolving Google Calendar credentials.
11241
+ *
11242
+ * @private constant of UseCalendarCommitmentDefinition
11243
+ */
11244
+ const UseCalendarWallet = {
11245
+ service: 'google_calendar',
11246
+ key: 'use-calendar-google-token',
11247
+ };
11248
+
11249
+ /**
11250
+ * Internal error used to signal missing wallet credentials.
11251
+ *
11252
+ * @private class of resolveUseCalendarToolRuntimeOrWalletCredentialResult
11253
+ */
11254
+ class CalendarWalletCredentialRequiredError extends Error {
11255
+ constructor(options) {
11256
+ super('Google Calendar token is missing in wallet. Request it from user and store as ACCESS_TOKEN (service google_calendar, key use-calendar-google-token).');
11257
+ this.name = 'CalendarWalletCredentialRequiredError';
11258
+ this.service = UseCalendarWallet.service;
11259
+ this.key = UseCalendarWallet.key;
11260
+ this.calendarReference = options.calendarReference;
11261
+ }
11262
+ }
11263
+ /**
11264
+ * Resolves calendar runtime or returns a wallet-credential-required payload when missing.
11265
+ *
11266
+ * @private function of UseCalendarCommitmentDefinition
11267
+ */
11268
+ function resolveUseCalendarToolRuntimeOrWalletCredentialResult(args) {
11269
+ try {
11270
+ return resolveUseCalendarToolRuntime(args);
11271
+ }
11272
+ catch (error) {
11273
+ if (error instanceof CalendarWalletCredentialRequiredError) {
11274
+ return {
11275
+ walletResult: JSON.stringify(createCalendarWalletCredentialRequiredResult(error)),
11276
+ };
11277
+ }
11278
+ throw error;
11279
+ }
11280
+ }
11281
+ /**
11282
+ * Resolves runtime calendar + token for a USE CALENDAR tool call.
11283
+ *
11284
+ * @private function of resolveUseCalendarToolRuntimeOrWalletCredentialResult
11285
+ */
11286
+ function resolveUseCalendarToolRuntime(args) {
11287
+ var _a, _b;
11288
+ const runtimeContext = (readToolRuntimeContextFromToolArgs(args) ||
11289
+ {});
11290
+ const configuredCalendars = normalizeConfiguredCalendars$1((_a = runtimeContext.calendars) === null || _a === void 0 ? void 0 : _a.connections);
11291
+ const calendarArgument = normalizeOptionalText$1(args.calendarUrl);
11292
+ let calendarReference = null;
11293
+ if (calendarArgument) {
11294
+ calendarReference = parseGoogleCalendarReference(calendarArgument);
11295
+ if (!calendarReference) {
11296
+ throw new Error(`Calendar URL "${calendarArgument}" is invalid.`);
11297
+ }
11298
+ }
11299
+ else if (configuredCalendars.length === 1) {
11300
+ calendarReference = configuredCalendars[0] || null;
11301
+ }
11302
+ else if (configuredCalendars.length > 1) {
11303
+ throw new Error('Calendar is ambiguous. Provide "calendarUrl" argument with one calendar from USE CALENDAR commitments.');
11304
+ }
11305
+ else {
11306
+ throw new Error('Calendar is required. Provide "calendarUrl" argument in the tool call.');
11307
+ }
11308
+ if (!calendarReference) {
11309
+ throw new Error('Calendar is required but was not resolved.');
11310
+ }
11311
+ const accessToken = normalizeOptionalText$1((_b = runtimeContext.calendars) === null || _b === void 0 ? void 0 : _b.googleAccessToken) || '';
11312
+ if (!accessToken) {
11313
+ throw new CalendarWalletCredentialRequiredError({
11314
+ calendarReference,
11315
+ });
11316
+ }
11317
+ if (configuredCalendars.length > 0) {
11318
+ const allowedCalendarUrls = new Set(configuredCalendars.map((configuredCalendar) => configuredCalendar.url));
11319
+ if (!allowedCalendarUrls.has(calendarReference.url)) {
11320
+ throw new Error(`Calendar "${calendarReference.url}" is not configured by USE CALENDAR for this agent.`);
11321
+ }
11322
+ }
11323
+ return {
11324
+ calendarReference,
11325
+ accessToken,
11326
+ };
11327
+ }
11328
+ /**
11329
+ * Normalizes optional calendar list from runtime context.
11330
+ *
11331
+ * @private function of resolveUseCalendarToolRuntimeOrWalletCredentialResult
11332
+ */
11333
+ function normalizeConfiguredCalendars$1(rawCalendars) {
11334
+ if (!Array.isArray(rawCalendars)) {
11335
+ return [];
11336
+ }
11337
+ const calendars = [];
11338
+ const knownCalendars = new Set();
11339
+ for (const rawCalendar of rawCalendars) {
11340
+ if (!rawCalendar || typeof rawCalendar !== 'object') {
11341
+ continue;
11342
+ }
11343
+ const calendar = rawCalendar;
11344
+ const rawUrl = normalizeOptionalText$1(calendar.url);
11345
+ if (!rawUrl) {
11346
+ continue;
11347
+ }
11348
+ const parsedReference = parseGoogleCalendarReference(rawUrl);
11349
+ if (!parsedReference) {
11350
+ continue;
11351
+ }
11352
+ const key = `${parsedReference.provider}|${parsedReference.url}`;
11353
+ if (knownCalendars.has(key)) {
11354
+ continue;
11355
+ }
11356
+ knownCalendars.add(key);
11357
+ const scopes = Array.isArray(calendar.scopes)
11358
+ ? calendar.scopes
11359
+ .filter((scope) => typeof scope === 'string')
11360
+ .map((scope) => scope.trim())
11361
+ .filter(Boolean)
11362
+ : [];
11363
+ calendars.push({
11364
+ ...parsedReference,
11365
+ scopes: scopes.length > 0 ? scopes : parsedReference.scopes,
11366
+ });
11367
+ }
11368
+ return calendars;
11369
+ }
11370
+ /**
11371
+ * Converts missing-wallet errors into structured tool result payloads.
11372
+ *
11373
+ * @private function of resolveUseCalendarToolRuntimeOrWalletCredentialResult
11374
+ */
11375
+ function createCalendarWalletCredentialRequiredResult(error) {
11376
+ return {
11377
+ action: 'calendar-auth',
11378
+ status: 'wallet-credential-required',
11379
+ recordType: 'ACCESS_TOKEN',
11380
+ service: error.service,
11381
+ key: error.key,
11382
+ isUserScoped: false,
11383
+ isGlobal: false,
11384
+ provider: 'google',
11385
+ calendarUrl: error.calendarReference.url,
11386
+ scopes: error.calendarReference.scopes,
11387
+ message: error.message,
11388
+ };
11389
+ }
11390
+ /**
11391
+ * Normalizes unknown text input to trimmed non-empty string.
11392
+ *
11393
+ * @private function of resolveUseCalendarToolRuntimeOrWalletCredentialResult
11394
+ */
11395
+ function normalizeOptionalText$1(value) {
11396
+ if (typeof value !== 'string') {
11397
+ return undefined;
11398
+ }
11399
+ const trimmedValue = value.trim();
11400
+ return trimmedValue || undefined;
11401
+ }
11402
+
11403
+ /**
11404
+ * Names of tools used by the USE CALENDAR commitment.
11405
+ *
11406
+ * @private constant of UseCalendarCommitmentDefinition
11407
+ */
11408
+ const UseCalendarToolNames = {
11409
+ listEvents: 'calendar_list_events',
11410
+ getEvent: 'calendar_get_event',
11411
+ createEvent: 'calendar_create_event',
11412
+ updateEvent: 'calendar_update_event',
11413
+ deleteEvent: 'calendar_delete_event',
11414
+ inviteGuests: 'calendar_invite_guests',
11415
+ };
11416
+
11417
+ /**
11418
+ * Gets Google Calendar tool function implementations.
11419
+ *
11420
+ * @private function of UseCalendarCommitmentDefinition
11421
+ */
11422
+ function createUseCalendarToolFunctions() {
11423
+ return {
11424
+ async [UseCalendarToolNames.listEvents](args) {
11425
+ return withUseCalendarRuntime(args, async ({ calendarReference, accessToken }) => {
11426
+ const query = {};
11427
+ if (normalizeOptionalText(args.timeMin)) {
11428
+ query.timeMin = args.timeMin.trim();
11429
+ }
11430
+ if (normalizeOptionalText(args.timeMax)) {
11431
+ query.timeMax = args.timeMax.trim();
11432
+ }
11433
+ if (normalizeOptionalText(args.query)) {
11434
+ query.q = args.query.trim();
11435
+ }
11436
+ if (typeof args.maxResults === 'number' && Number.isFinite(args.maxResults) && args.maxResults > 0) {
11437
+ query.maxResults = String(Math.floor(args.maxResults));
11438
+ }
11439
+ if (args.singleEvents !== undefined) {
11440
+ query.singleEvents = args.singleEvents ? 'true' : 'false';
11441
+ }
11442
+ if (args.orderBy === 'startTime' || args.orderBy === 'updated') {
11443
+ query.orderBy = args.orderBy;
11444
+ }
11445
+ if (normalizeOptionalText(args.timeZone)) {
11446
+ query.timeZone = args.timeZone.trim();
11447
+ }
11448
+ const payload = await callGoogleCalendarApi(accessToken, {
11449
+ method: 'GET',
11450
+ path: `/calendars/${encodeGoogleCalendarId(calendarReference.calendarId)}/events`,
11451
+ query,
11452
+ });
11453
+ const events = ((payload === null || payload === void 0 ? void 0 : payload.items) || []).map((event) => mapGoogleCalendarEvent(event));
11454
+ return JSON.stringify({
11455
+ provider: calendarReference.provider,
11456
+ calendarUrl: calendarReference.url,
11457
+ calendarId: calendarReference.calendarId,
11458
+ events,
11459
+ nextPageToken: (payload === null || payload === void 0 ? void 0 : payload.nextPageToken) || null,
11460
+ nextSyncToken: (payload === null || payload === void 0 ? void 0 : payload.nextSyncToken) || null,
11461
+ });
11462
+ });
11463
+ },
11464
+ async [UseCalendarToolNames.getEvent](args) {
11465
+ return withUseCalendarRuntime(args, async ({ calendarReference, accessToken }) => {
11466
+ const eventId = normalizeRequiredText(args.eventId, 'eventId');
11467
+ const payload = await callGoogleCalendarApi(accessToken, {
11468
+ method: 'GET',
11469
+ path: `/calendars/${encodeGoogleCalendarId(calendarReference.calendarId)}/events/${encodeURIComponent(eventId)}`,
11470
+ });
11471
+ return JSON.stringify({
11472
+ provider: calendarReference.provider,
11473
+ calendarUrl: calendarReference.url,
11474
+ calendarId: calendarReference.calendarId,
11475
+ event: mapGoogleCalendarEvent(payload || {}),
11476
+ });
11477
+ });
11478
+ },
11479
+ async [UseCalendarToolNames.createEvent](args) {
11480
+ return withUseCalendarRuntime(args, async ({ calendarReference, accessToken }) => {
11481
+ const requestBody = createGoogleCalendarEventPayload({
11482
+ summary: normalizeRequiredText(args.summary, 'summary'),
11483
+ description: normalizeOptionalText(args.description),
11484
+ location: normalizeOptionalText(args.location),
11485
+ start: normalizeRequiredText(args.start, 'start'),
11486
+ end: normalizeRequiredText(args.end, 'end'),
11487
+ timeZone: normalizeOptionalText(args.timeZone),
11488
+ attendees: normalizeAttendees(args.attendees),
11489
+ reminderMinutes: normalizeReminderMinutes(args.reminderMinutes),
11490
+ });
11491
+ const payload = await callGoogleCalendarApi(accessToken, {
11492
+ method: 'POST',
11493
+ path: `/calendars/${encodeGoogleCalendarId(calendarReference.calendarId)}/events`,
11494
+ query: createSendUpdatesQuery(args.sendUpdates),
11495
+ body: requestBody,
11496
+ });
11497
+ return JSON.stringify({
11498
+ provider: calendarReference.provider,
11499
+ calendarUrl: calendarReference.url,
11500
+ calendarId: calendarReference.calendarId,
11501
+ event: mapGoogleCalendarEvent(payload || {}),
11502
+ });
11503
+ });
11504
+ },
11505
+ async [UseCalendarToolNames.updateEvent](args) {
11506
+ return withUseCalendarRuntime(args, async ({ calendarReference, accessToken }) => {
11507
+ const eventId = normalizeRequiredText(args.eventId, 'eventId');
11508
+ const requestBody = createGoogleCalendarEventPayload({
11509
+ summary: normalizeOptionalText(args.summary),
11510
+ description: normalizeOptionalText(args.description),
11511
+ location: normalizeOptionalText(args.location),
11512
+ start: normalizeOptionalText(args.start),
11513
+ end: normalizeOptionalText(args.end),
11514
+ timeZone: normalizeOptionalText(args.timeZone),
11515
+ attendees: normalizeAttendees(args.attendees),
11516
+ reminderMinutes: normalizeReminderMinutes(args.reminderMinutes),
11517
+ });
11518
+ const payload = await callGoogleCalendarApi(accessToken, {
11519
+ method: 'PATCH',
11520
+ path: `/calendars/${encodeGoogleCalendarId(calendarReference.calendarId)}/events/${encodeURIComponent(eventId)}`,
11521
+ query: createSendUpdatesQuery(args.sendUpdates),
11522
+ body: requestBody,
11523
+ });
11524
+ return JSON.stringify({
11525
+ provider: calendarReference.provider,
11526
+ calendarUrl: calendarReference.url,
11527
+ calendarId: calendarReference.calendarId,
11528
+ event: mapGoogleCalendarEvent(payload || {}),
11529
+ });
11530
+ });
11531
+ },
11532
+ async [UseCalendarToolNames.deleteEvent](args) {
11533
+ return withUseCalendarRuntime(args, async ({ calendarReference, accessToken }) => {
11534
+ const eventId = normalizeRequiredText(args.eventId, 'eventId');
11535
+ await callGoogleCalendarApi(accessToken, {
11536
+ method: 'DELETE',
11537
+ path: `/calendars/${encodeGoogleCalendarId(calendarReference.calendarId)}/events/${encodeURIComponent(eventId)}`,
11538
+ query: createSendUpdatesQuery(args.sendUpdates),
11539
+ });
11540
+ return JSON.stringify({
11541
+ provider: calendarReference.provider,
11542
+ calendarUrl: calendarReference.url,
11543
+ calendarId: calendarReference.calendarId,
11544
+ eventId,
11545
+ status: 'deleted',
11546
+ });
11547
+ });
11548
+ },
11549
+ async [UseCalendarToolNames.inviteGuests](args) {
11550
+ return withUseCalendarRuntime(args, async ({ calendarReference, accessToken }) => {
11551
+ const eventId = normalizeRequiredText(args.eventId, 'eventId');
11552
+ const guests = normalizeAttendees(args.guests);
11553
+ if (guests.length === 0) {
11554
+ throw new Error('Tool "calendar_invite_guests" requires non-empty "guests".');
11555
+ }
11556
+ const existingEvent = await callGoogleCalendarApi(accessToken, {
11557
+ method: 'GET',
11558
+ path: `/calendars/${encodeGoogleCalendarId(calendarReference.calendarId)}/events/${encodeURIComponent(eventId)}`,
11559
+ });
11560
+ const existingAttendees = ((existingEvent === null || existingEvent === void 0 ? void 0 : existingEvent.attendees) || [])
11561
+ .map((attendee) => normalizeOptionalText(attendee.email))
11562
+ .filter((email) => Boolean(email));
11563
+ const mergedAttendees = [...new Set([...existingAttendees, ...guests])];
11564
+ const payload = await callGoogleCalendarApi(accessToken, {
11565
+ method: 'PATCH',
11566
+ path: `/calendars/${encodeGoogleCalendarId(calendarReference.calendarId)}/events/${encodeURIComponent(eventId)}`,
11567
+ query: createSendUpdatesQuery(args.sendUpdates),
11568
+ body: {
11569
+ attendees: mergedAttendees.map((email) => ({ email })),
11570
+ },
11571
+ });
11572
+ return JSON.stringify({
11573
+ provider: calendarReference.provider,
11574
+ calendarUrl: calendarReference.url,
11575
+ calendarId: calendarReference.calendarId,
11576
+ event: mapGoogleCalendarEvent(payload || {}),
11577
+ invitedGuests: guests,
11578
+ });
11579
+ });
11580
+ },
11581
+ };
11582
+ }
11583
+ /**
11584
+ * Executes one tool operation with resolved USE CALENDAR runtime.
11585
+ *
11586
+ * @private function of createUseCalendarToolFunctions
11587
+ */
11588
+ async function withUseCalendarRuntime(args, operation) {
11589
+ const runtime = resolveUseCalendarToolRuntimeOrWalletCredentialResult(args);
11590
+ if ('walletResult' in runtime) {
11591
+ return runtime.walletResult;
11592
+ }
11593
+ return operation(runtime);
11594
+ }
11595
+ /**
11596
+ * Encodes one Google calendar id for URL path usage.
11597
+ *
11598
+ * @private function of createUseCalendarToolFunctions
11599
+ */
11600
+ function encodeGoogleCalendarId(calendarId) {
11601
+ return encodeURIComponent(calendarId);
11602
+ }
11603
+ /**
11604
+ * Normalizes one required textual input.
11605
+ *
11606
+ * @private function of createUseCalendarToolFunctions
11607
+ */
11608
+ function normalizeRequiredText(value, fieldName) {
11609
+ const normalizedValue = normalizeOptionalText(value);
11610
+ if (!normalizedValue) {
11611
+ throw new Error(`Tool "${fieldName}" requires non-empty value.`);
11612
+ }
11613
+ return normalizedValue;
11614
+ }
11615
+ /**
11616
+ * Normalizes unknown text input to trimmed non-empty string.
11617
+ *
11618
+ * @private function of createUseCalendarToolFunctions
11619
+ */
11620
+ function normalizeOptionalText(value) {
11621
+ if (typeof value !== 'string') {
11622
+ return undefined;
11623
+ }
11624
+ const trimmedValue = value.trim();
11625
+ return trimmedValue || undefined;
11626
+ }
11627
+ /**
11628
+ * Normalizes optional attendee list from tool input.
11629
+ *
11630
+ * @private function of createUseCalendarToolFunctions
11631
+ */
11632
+ function normalizeAttendees(value) {
11633
+ if (!Array.isArray(value)) {
11634
+ return [];
11635
+ }
11636
+ const normalizedAttendees = value
11637
+ .filter((attendee) => typeof attendee === 'string')
11638
+ .map((attendee) => attendee.trim())
11639
+ .filter(Boolean);
11640
+ return [...new Set(normalizedAttendees)];
11641
+ }
11642
+ /**
11643
+ * Normalizes optional reminder-minute offsets from tool input.
11644
+ *
11645
+ * @private function of createUseCalendarToolFunctions
11646
+ */
11647
+ function normalizeReminderMinutes(value) {
11648
+ if (!Array.isArray(value)) {
11649
+ return [];
11650
+ }
11651
+ const reminderMinutes = value
11652
+ .filter((minute) => typeof minute === 'number' && Number.isFinite(minute))
11653
+ .map((minute) => Math.max(0, Math.floor(minute)));
11654
+ return [...new Set(reminderMinutes)];
11655
+ }
11656
+ /**
11657
+ * Builds optional `sendUpdates` query for mutating Google Calendar requests.
11658
+ *
11659
+ * @private function of createUseCalendarToolFunctions
11660
+ */
11661
+ function createSendUpdatesQuery(sendUpdates) {
11662
+ if (sendUpdates === 'all' || sendUpdates === 'externalOnly' || sendUpdates === 'none') {
11663
+ return { sendUpdates };
11664
+ }
11665
+ return {};
11666
+ }
11667
+ /**
11668
+ * Creates one Google Calendar event payload from normalized tool arguments.
11669
+ *
11670
+ * @private function of createUseCalendarToolFunctions
11671
+ */
11672
+ function createGoogleCalendarEventPayload(options) {
11673
+ const payload = {};
11674
+ if (options.summary) {
11675
+ payload.summary = options.summary;
11676
+ }
11677
+ if (options.description) {
11678
+ payload.description = options.description;
11679
+ }
11680
+ if (options.location) {
11681
+ payload.location = options.location;
11682
+ }
11683
+ if (options.start) {
11684
+ payload.start = createGoogleCalendarDateValue(options.start, options.timeZone);
11685
+ }
11686
+ if (options.end) {
11687
+ payload.end = createGoogleCalendarDateValue(options.end, options.timeZone);
11688
+ }
11689
+ if (options.attendees && options.attendees.length > 0) {
11690
+ payload.attendees = options.attendees.map((email) => ({ email }));
11691
+ }
11692
+ if (options.reminderMinutes && options.reminderMinutes.length > 0) {
11693
+ payload.reminders = {
11694
+ useDefault: false,
11695
+ overrides: options.reminderMinutes.map((minutes) => ({
11696
+ method: 'popup',
11697
+ minutes,
11698
+ })),
11699
+ };
11700
+ }
11701
+ return payload;
11702
+ }
11703
+ /**
11704
+ * Converts date/dateTime input into a Google Calendar-compatible date object.
11705
+ *
11706
+ * @private function of createUseCalendarToolFunctions
11707
+ */
11708
+ function createGoogleCalendarDateValue(value, timeZone) {
11709
+ const isDateOnly = /^\d{4}-\d{2}-\d{2}$/.test(value);
11710
+ if (isDateOnly) {
11711
+ return {
11712
+ date: value,
11713
+ };
11714
+ }
11715
+ return {
11716
+ dateTime: value,
11717
+ ...(timeZone ? { timeZone } : {}),
11718
+ };
11719
+ }
11720
+ /**
11721
+ * Maps raw Google Calendar event payload to a compact tool result object.
11722
+ *
11723
+ * @private function of createUseCalendarToolFunctions
11724
+ */
11725
+ function mapGoogleCalendarEvent(event) {
11726
+ return {
11727
+ id: event.id || null,
11728
+ summary: event.summary || null,
11729
+ description: event.description || null,
11730
+ location: event.location || null,
11731
+ status: event.status || null,
11732
+ htmlLink: event.htmlLink || null,
11733
+ start: event.start || null,
11734
+ end: event.end || null,
11735
+ organizer: event.organizer || null,
11736
+ attendees: (event.attendees || []).map((attendee) => ({
11737
+ email: attendee.email || null,
11738
+ responseStatus: attendee.responseStatus || null,
11739
+ })),
11740
+ };
11741
+ }
11742
+
11743
+ /**
11744
+ * Shared calendar URL argument description used in USE CALENDAR tool schemas.
11745
+ *
11746
+ * @private constant of createUseCalendarTools
11747
+ */
11748
+ const CALENDAR_URL_PARAMETER_DESCRIPTION = 'Google Calendar URL configured by USE CALENDAR (for example "https://calendar.google.com/...").';
11749
+ /**
11750
+ * Adds USE CALENDAR tool definitions while keeping already registered tools untouched.
11751
+ *
11752
+ * @private function of UseCalendarCommitmentDefinition
11753
+ */
11754
+ function createUseCalendarTools(existingTools) {
11755
+ const updatedTools = [...existingTools];
11756
+ const addToolIfMissing = (tool) => {
11757
+ if (!updatedTools.some((existingTool) => existingTool.name === tool.name)) {
11758
+ updatedTools.push(tool);
11759
+ }
11760
+ };
11761
+ addToolIfMissing({
11762
+ name: UseCalendarToolNames.listEvents,
11763
+ description: 'List events from a configured calendar for a time range.',
11764
+ parameters: {
11765
+ type: 'object',
11766
+ properties: {
11767
+ calendarUrl: {
11768
+ type: 'string',
11769
+ description: CALENDAR_URL_PARAMETER_DESCRIPTION,
11770
+ },
11771
+ timeMin: {
11772
+ type: 'string',
11773
+ description: 'Inclusive event start bound in ISO datetime.',
11774
+ },
11775
+ timeMax: {
11776
+ type: 'string',
11777
+ description: 'Exclusive event end bound in ISO datetime.',
11778
+ },
11779
+ query: {
11780
+ type: 'string',
11781
+ description: 'Optional free-text event search query.',
11782
+ },
11783
+ maxResults: {
11784
+ type: 'integer',
11785
+ description: 'Maximum number of events to return.',
11786
+ },
11787
+ singleEvents: {
11788
+ type: 'boolean',
11789
+ description: 'Expand recurring events into individual instances.',
11790
+ },
11791
+ orderBy: {
11792
+ type: 'string',
11793
+ description: 'Optional ordering ("startTime" or "updated").',
11794
+ },
11795
+ timeZone: {
11796
+ type: 'string',
11797
+ description: 'Optional IANA timezone for response rendering.',
11798
+ },
11799
+ },
11800
+ required: [],
11801
+ },
11802
+ });
11803
+ addToolIfMissing({
11804
+ name: UseCalendarToolNames.getEvent,
11805
+ description: 'Get one event by id from a configured calendar.',
11806
+ parameters: {
11807
+ type: 'object',
11808
+ properties: {
11809
+ calendarUrl: {
11810
+ type: 'string',
11811
+ description: CALENDAR_URL_PARAMETER_DESCRIPTION,
11812
+ },
11813
+ eventId: {
11814
+ type: 'string',
11815
+ description: 'Google Calendar event id.',
11816
+ },
11817
+ },
11818
+ required: ['eventId'],
11819
+ },
11820
+ });
11821
+ addToolIfMissing({
11822
+ name: UseCalendarToolNames.createEvent,
11823
+ description: 'Create one event in a configured calendar.',
11824
+ parameters: {
11825
+ type: 'object',
11826
+ properties: {
11827
+ calendarUrl: {
11828
+ type: 'string',
11829
+ description: CALENDAR_URL_PARAMETER_DESCRIPTION,
11830
+ },
11831
+ summary: {
11832
+ type: 'string',
11833
+ description: 'Event title/summary.',
11834
+ },
11835
+ description: {
11836
+ type: 'string',
11837
+ description: 'Optional event description.',
11838
+ },
11839
+ location: {
11840
+ type: 'string',
11841
+ description: 'Optional event location.',
11842
+ },
11843
+ start: {
11844
+ type: 'string',
11845
+ description: 'Event start as ISO datetime or date.',
11846
+ },
11847
+ end: {
11848
+ type: 'string',
11849
+ description: 'Event end as ISO datetime or date.',
11850
+ },
11851
+ timeZone: {
11852
+ type: 'string',
11853
+ description: 'Optional timezone for datetime values.',
11854
+ },
11855
+ attendees: {
11856
+ type: 'array',
11857
+ description: 'Optional guest email list.',
11858
+ },
11859
+ reminderMinutes: {
11860
+ type: 'array',
11861
+ description: 'Optional popup reminder minute offsets.',
11862
+ },
11863
+ sendUpdates: {
11864
+ type: 'string',
11865
+ description: 'Guest update policy ("all", "externalOnly", "none").',
11866
+ },
11867
+ },
11868
+ required: ['summary', 'start', 'end'],
11869
+ },
11870
+ });
11871
+ addToolIfMissing({
11872
+ name: UseCalendarToolNames.updateEvent,
11873
+ description: 'Update one existing event in a configured calendar.',
11874
+ parameters: {
11875
+ type: 'object',
11876
+ properties: {
11877
+ calendarUrl: {
11878
+ type: 'string',
11879
+ description: CALENDAR_URL_PARAMETER_DESCRIPTION,
11880
+ },
11881
+ eventId: {
11882
+ type: 'string',
11883
+ description: 'Google Calendar event id.',
11884
+ },
11885
+ summary: {
11886
+ type: 'string',
11887
+ description: 'Updated event summary.',
11888
+ },
11889
+ description: {
11890
+ type: 'string',
11891
+ description: 'Updated event description.',
11892
+ },
11893
+ location: {
11894
+ type: 'string',
11895
+ description: 'Updated event location.',
11896
+ },
11897
+ start: {
11898
+ type: 'string',
11899
+ description: 'Updated event start as ISO datetime or date.',
11900
+ },
11901
+ end: {
11902
+ type: 'string',
11903
+ description: 'Updated event end as ISO datetime or date.',
11904
+ },
11905
+ timeZone: {
11906
+ type: 'string',
11907
+ description: 'Optional timezone for datetime values.',
11908
+ },
11909
+ attendees: {
11910
+ type: 'array',
11911
+ description: 'Optional replacement guest email list.',
11912
+ },
11913
+ reminderMinutes: {
11914
+ type: 'array',
11915
+ description: 'Optional replacement popup reminder minute offsets.',
11916
+ },
11917
+ sendUpdates: {
11918
+ type: 'string',
11919
+ description: 'Guest update policy ("all", "externalOnly", "none").',
11920
+ },
11921
+ },
11922
+ required: ['eventId'],
11923
+ },
11924
+ });
11925
+ addToolIfMissing({
11926
+ name: UseCalendarToolNames.deleteEvent,
11927
+ description: 'Delete one event from a configured calendar.',
11928
+ parameters: {
11929
+ type: 'object',
11930
+ properties: {
11931
+ calendarUrl: {
11932
+ type: 'string',
11933
+ description: CALENDAR_URL_PARAMETER_DESCRIPTION,
11934
+ },
11935
+ eventId: {
11936
+ type: 'string',
11937
+ description: 'Google Calendar event id.',
11938
+ },
11939
+ sendUpdates: {
11940
+ type: 'string',
11941
+ description: 'Guest update policy ("all", "externalOnly", "none").',
11942
+ },
11943
+ },
11944
+ required: ['eventId'],
11945
+ },
11946
+ });
11947
+ addToolIfMissing({
11948
+ name: UseCalendarToolNames.inviteGuests,
11949
+ description: 'Add guests to an existing event in a configured calendar.',
11950
+ parameters: {
11951
+ type: 'object',
11952
+ properties: {
11953
+ calendarUrl: {
11954
+ type: 'string',
11955
+ description: CALENDAR_URL_PARAMETER_DESCRIPTION,
11956
+ },
11957
+ eventId: {
11958
+ type: 'string',
11959
+ description: 'Google Calendar event id.',
11960
+ },
11961
+ guests: {
11962
+ type: 'array',
11963
+ description: 'Guest email list to add to the event.',
11964
+ },
11965
+ sendUpdates: {
11966
+ type: 'string',
11967
+ description: 'Guest update policy ("all", "externalOnly", "none").',
11968
+ },
11969
+ },
11970
+ required: ['eventId', 'guests'],
11971
+ },
11972
+ });
11973
+ return updatedTools;
11974
+ }
11975
+
11976
+ /**
11977
+ * Gets human-readable tool labels for USE CALENDAR functions.
11978
+ *
11979
+ * @private function of UseCalendarCommitmentDefinition
11980
+ */
11981
+ function getUseCalendarToolTitles() {
11982
+ return {
11983
+ [UseCalendarToolNames.listEvents]: 'List calendar events',
11984
+ [UseCalendarToolNames.getEvent]: 'Get calendar event',
11985
+ [UseCalendarToolNames.createEvent]: 'Create calendar event',
11986
+ [UseCalendarToolNames.updateEvent]: 'Update calendar event',
11987
+ [UseCalendarToolNames.deleteEvent]: 'Delete calendar event',
11988
+ [UseCalendarToolNames.inviteGuests]: 'Invite calendar guests',
11989
+ };
11990
+ }
11991
+
11992
+ /**
11993
+ * Normalizes unknown metadata payload into a typed list of configured calendars.
11994
+ *
11995
+ * @private internal utility of USE CALENDAR commitment
11996
+ */
11997
+ function normalizeConfiguredCalendars(rawCalendars) {
11998
+ if (!Array.isArray(rawCalendars)) {
11999
+ return [];
12000
+ }
12001
+ const uniqueCalendars = new Set();
12002
+ const calendars = [];
12003
+ for (const rawCalendar of rawCalendars) {
12004
+ if (!rawCalendar || typeof rawCalendar !== 'object') {
12005
+ continue;
12006
+ }
12007
+ const calendar = rawCalendar;
12008
+ const provider = normalizeProvider(calendar.provider);
12009
+ const url = normalizeText(calendar.url);
12010
+ const calendarId = normalizeText(calendar.calendarId);
12011
+ if (!provider || !url || !calendarId) {
12012
+ continue;
12013
+ }
12014
+ const uniqueKey = `${provider}|${url}`;
12015
+ if (uniqueCalendars.has(uniqueKey)) {
12016
+ continue;
12017
+ }
12018
+ uniqueCalendars.add(uniqueKey);
12019
+ const scopes = Array.isArray(calendar.scopes)
12020
+ ? calendar.scopes
12021
+ .filter((scope) => typeof scope === 'string')
12022
+ .map((scope) => scope.trim())
12023
+ .filter(Boolean)
12024
+ : [];
12025
+ calendars.push({
12026
+ provider,
12027
+ url,
12028
+ calendarId,
12029
+ scopes,
12030
+ ...(normalizeText(calendar.tokenRef) ? { tokenRef: normalizeText(calendar.tokenRef) } : {}),
12031
+ });
12032
+ }
12033
+ return calendars;
12034
+ }
12035
+ /**
12036
+ * Normalizes optional provider text to one supported value.
12037
+ *
12038
+ * @private function of normalizeConfiguredCalendars
12039
+ */
12040
+ function normalizeProvider(value) {
12041
+ if (typeof value !== 'string') {
12042
+ return null;
12043
+ }
12044
+ const normalizedProvider = value.trim().toLowerCase();
12045
+ if (normalizedProvider === 'google') {
12046
+ return 'google';
12047
+ }
12048
+ return null;
12049
+ }
12050
+ /**
12051
+ * Normalizes unknown text input to trimmed non-empty string.
12052
+ *
12053
+ * @private function of normalizeConfiguredCalendars
12054
+ */
12055
+ function normalizeText(value) {
12056
+ return typeof value === 'string' ? value.trim() : '';
12057
+ }
12058
+
12059
+ /**
12060
+ * USE CALENDAR commitment definition.
12061
+ *
12062
+ * `USE CALENDAR` enables calendar tooling so the agent can read and manage events
12063
+ * in one configured Google Calendar.
12064
+ *
12065
+ * Authentication is expected through runtime context provided by the host app UI.
12066
+ * Hosts can provide manual wallet tokens or host-managed OAuth tokens.
12067
+ *
12068
+ * @private [🪔] Maybe export the commitments through some package
12069
+ */
12070
+ class UseCalendarCommitmentDefinition extends BaseCommitmentDefinition {
12071
+ constructor() {
12072
+ super('USE CALENDAR', ['CALENDAR']);
12073
+ }
12074
+ /**
12075
+ * Short one-line description of USE CALENDAR.
12076
+ */
12077
+ get description() {
12078
+ return 'Enable calendar tools for reading and managing events through Google Calendar.';
12079
+ }
12080
+ /**
12081
+ * Icon for this commitment.
12082
+ */
12083
+ get icon() {
12084
+ return '📅';
12085
+ }
12086
+ /**
12087
+ * Markdown documentation for USE CALENDAR commitment.
12088
+ */
12089
+ get documentation() {
12090
+ return spaceTrim$1(`
12091
+ # USE CALENDAR
12092
+
12093
+ Enables the agent to access and manage one Google Calendar.
12094
+
12095
+ ## Key aspects
12096
+
12097
+ - The first URL in the commitment should point to a Google Calendar URL.
12098
+ - Optional \`SCOPES\` lines can provide explicit OAuth scopes.
12099
+ - Optional extra instructions can follow calendar reference lines.
12100
+ - Runtime provides Google Calendar OAuth token (manual wallet token or host-managed OAuth token).
12101
+ - Tools support listing events, reading one event, creating events, updating events, deleting events, and inviting guests.
12102
+
12103
+ ## Examples
12104
+
12105
+ \`\`\`book
12106
+ Scheduling Assistant
12107
+
12108
+ PERSONA You coordinate meetings and schedules.
12109
+ USE CALENDAR https://calendar.google.com/calendar/u/0/r
12110
+ \`\`\`
12111
+
12112
+ \`\`\`book
12113
+ Executive Assistant
12114
+
12115
+ USE CALENDAR https://calendar.google.com/calendar/u/0/r
12116
+ SCOPES https://www.googleapis.com/auth/calendar.readonly
12117
+ RULE Ask for confirmation before deleting events.
12118
+ \`\`\`
12119
+ `);
12120
+ }
12121
+ applyToAgentModelRequirements(requirements, content) {
12122
+ var _a;
12123
+ const parsedCommitment = parseUseCalendarCommitmentContent(content);
12124
+ const existingConfiguredCalendars = normalizeConfiguredCalendars((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.useCalendars);
12125
+ if (parsedCommitment.calendar) {
12126
+ addConfiguredCalendarIfMissing(existingConfiguredCalendars, parsedCommitment.calendar);
12127
+ }
12128
+ const calendarsList = existingConfiguredCalendars.length > 0
12129
+ ? existingConfiguredCalendars
12130
+ .map((calendar) => [
12131
+ `- ${calendar.provider}: ${calendar.url}`,
12132
+ calendar.scopes.length > 0 ? ` scopes: ${calendar.scopes.join(', ')}` : '',
12133
+ ]
12134
+ .filter(Boolean)
12135
+ .join('\n'))
12136
+ .join('\n')
12137
+ : '- Calendar is resolved from runtime context';
12138
+ const extraInstructions = formatOptionalInstructionBlock('Calendar instructions', parsedCommitment.instructions);
12139
+ return this.appendToSystemMessage({
12140
+ ...requirements,
12141
+ tools: createUseCalendarTools(requirements.tools || []),
12142
+ _metadata: {
12143
+ ...requirements._metadata,
12144
+ useCalendar: true,
12145
+ useCalendars: existingConfiguredCalendars,
12146
+ },
12147
+ }, spaceTrim$1((block) => `
12148
+ Calendar tools:
12149
+ - You can inspect and manage events in configured calendars.
12150
+ - Supported operations include read, create, update, delete, invite guests, and reminders.
12151
+ - Configured calendars:
12152
+ ${block(calendarsList)}
12153
+ - USE CALENDAR credentials are read from wallet records (ACCESS_TOKEN, service "${UseCalendarWallet.service}", key "${UseCalendarWallet.key}").
12154
+ - If credentials are missing, ask user to connect calendar credentials in host UI and/or add them to wallet.
12155
+ ${block(extraInstructions)}
12156
+ `));
12157
+ }
12158
+ /**
12159
+ * Gets human-readable titles for tool functions provided by this commitment.
12160
+ */
12161
+ getToolTitles() {
12162
+ return getUseCalendarToolTitles();
12163
+ }
12164
+ /**
12165
+ * Gets calendar tool function implementations.
12166
+ */
12167
+ getToolFunctions() {
12168
+ return createUseCalendarToolFunctions();
12169
+ }
12170
+ }
12171
+ /**
12172
+ * Adds calendar into configured calendars list if it is not already present.
12173
+ *
12174
+ * @private function of UseCalendarCommitmentDefinition
12175
+ */
12176
+ function addConfiguredCalendarIfMissing(configuredCalendars, calendarReference) {
12177
+ if (configuredCalendars.some((calendar) => calendar.provider === calendarReference.provider && calendar.url === calendarReference.url)) {
12178
+ return;
12179
+ }
12180
+ configuredCalendars.push({
12181
+ provider: calendarReference.provider,
12182
+ url: calendarReference.url,
12183
+ calendarId: calendarReference.calendarId,
12184
+ scopes: [...calendarReference.scopes],
12185
+ ...(calendarReference.tokenRef ? { tokenRef: calendarReference.tokenRef } : {}),
12186
+ });
12187
+ }
12188
+ /**
12189
+ * Note: [💞] Ignore a discrepancy between file name and entity name
12190
+ */
12191
+
10966
12192
  /**
10967
12193
  * Lightweight email token matcher used for `USE EMAIL` first-line parsing.
10968
12194
  *
@@ -14849,6 +16075,7 @@ const COMMITMENT_REGISTRY = [
14849
16075
  new UseTimeoutCommitmentDefinition(),
14850
16076
  new UseTimeCommitmentDefinition(),
14851
16077
  new UseUserLocationCommitmentDefinition(),
16078
+ new UseCalendarCommitmentDefinition(),
14852
16079
  new UseEmailCommitmentDefinition(),
14853
16080
  new UsePopupCommitmentDefinition(),
14854
16081
  new UseImageGeneratorCommitmentDefinition('USE IMAGE GENERATOR'),
@@ -15845,6 +17072,14 @@ function parseAgentSource(agentSource) {
15845
17072
  });
15846
17073
  continue;
15847
17074
  }
17075
+ if (commitment.type === 'USE CALENDAR') {
17076
+ capabilities.push({
17077
+ type: 'calendar',
17078
+ label: 'Calendar',
17079
+ iconName: 'Calendar',
17080
+ });
17081
+ continue;
17082
+ }
15848
17083
  if (commitment.type === 'FROM') {
15849
17084
  const content = spaceTrim$2(commitment.content).split(/\r?\n/)[0] || '';
15850
17085
  if (content === 'Adam' || content === '' /* <- Note: Adam is implicit */) {