@promptbook/core 0.112.0-11 → 0.112.0-13

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 (87) hide show
  1. package/esm/index.es.js +1332 -16
  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_BROWSER/resolveRunBrowserToolForNode.d.ts +1 -1
  10. package/esm/src/commitments/USE_CALENDAR/USE_CALENDAR.d.ts +42 -0
  11. package/esm/src/commitments/USE_CALENDAR/USE_CALENDAR.test.d.ts +1 -0
  12. package/esm/src/commitments/USE_CALENDAR/UseCalendarToolNames.d.ts +13 -0
  13. package/esm/src/commitments/USE_CALENDAR/UseCalendarWallet.d.ts +9 -0
  14. package/esm/src/commitments/USE_CALENDAR/calendarReference.d.ts +68 -0
  15. package/esm/src/commitments/USE_CALENDAR/callGoogleCalendarApi.d.ts +19 -0
  16. package/esm/src/commitments/USE_CALENDAR/createUseCalendarToolFunctions.d.ts +8 -0
  17. package/esm/src/commitments/USE_CALENDAR/createUseCalendarTools.d.ts +7 -0
  18. package/esm/src/commitments/USE_CALENDAR/getUseCalendarToolTitles.d.ts +7 -0
  19. package/esm/src/commitments/USE_CALENDAR/normalizeConfiguredCalendars.d.ts +19 -0
  20. package/esm/src/commitments/USE_CALENDAR/resolveUseCalendarToolRuntimeOrWalletCredentialResult.d.ts +34 -0
  21. package/esm/src/commitments/USE_TIMEOUT/TimeoutToolNames.d.ts +1 -0
  22. package/esm/src/commitments/USE_TIMEOUT/TimeoutToolRuntimeAdapter.d.ts +51 -2
  23. package/esm/src/commitments/USE_TIMEOUT/USE_TIMEOUT.d.ts +2 -2
  24. package/esm/src/commitments/USE_TIMEOUT/getTimeoutToolRuntimeAdapterOrDisabledResult.d.ts +2 -2
  25. package/esm/src/commitments/USE_TIMEOUT/parseTimeoutToolArgs.d.ts +14 -1
  26. package/esm/src/commitments/_common/toolRuntimeContext.d.ts +9 -0
  27. package/esm/src/commitments/index.d.ts +2 -1
  28. package/esm/src/executables/apps/locateVscode.d.ts +7 -0
  29. package/esm/src/executables/apps/locateVscode.test.d.ts +1 -0
  30. package/esm/src/executables/browsers/locateBrowser.d.ts +10 -0
  31. package/esm/src/executables/browsers/locateBrowser.test.d.ts +1 -0
  32. package/esm/src/executables/browsers/locateChrome.d.ts +7 -0
  33. package/esm/src/executables/browsers/locateChrome.test.d.ts +1 -0
  34. package/esm/src/executables/browsers/locateDefaultSystemBrowser.d.ts +10 -0
  35. package/esm/src/executables/browsers/locateDefaultSystemBrowser.test.d.ts +1 -0
  36. package/esm/src/executables/browsers/locateEdge.d.ts +7 -0
  37. package/esm/src/executables/browsers/locateEdge.test.d.ts +1 -0
  38. package/esm/src/executables/browsers/locateFirefox.d.ts +7 -0
  39. package/esm/src/executables/browsers/locateFirefox.test.d.ts +1 -0
  40. package/esm/src/executables/browsers/locateInternetExplorer.d.ts +7 -0
  41. package/esm/src/executables/browsers/locateInternetExplorer.test.d.ts +1 -0
  42. package/esm/src/executables/browsers/locateSafari.d.ts +7 -0
  43. package/esm/src/version.d.ts +1 -1
  44. package/package.json +1 -1
  45. package/umd/index.umd.js +1332 -16
  46. package/umd/index.umd.js.map +1 -1
  47. package/umd/src/book-2.0/agent-source/AgentBasicInformation.d.ts +1 -1
  48. package/umd/src/book-components/Chat/Chat/ChatToolCallModal.test.d.ts +2 -0
  49. package/umd/src/book-components/Chat/Chat/renderToolCallDetails.d.ts +4 -0
  50. package/umd/src/book-components/Chat/utils/getToolCallChipletInfo.timeout.test.d.ts +1 -0
  51. package/umd/src/book-components/Chat/utils/timeoutToolCallPresentation.d.ts +123 -0
  52. package/umd/src/book-components/Chat/utils/timeoutToolCallPresentation.test.d.ts +1 -0
  53. package/umd/src/commitments/USE_BROWSER/resolveRunBrowserToolForNode.d.ts +1 -1
  54. package/umd/src/commitments/USE_CALENDAR/USE_CALENDAR.d.ts +42 -0
  55. package/umd/src/commitments/USE_CALENDAR/USE_CALENDAR.test.d.ts +1 -0
  56. package/umd/src/commitments/USE_CALENDAR/UseCalendarToolNames.d.ts +13 -0
  57. package/umd/src/commitments/USE_CALENDAR/UseCalendarWallet.d.ts +9 -0
  58. package/umd/src/commitments/USE_CALENDAR/calendarReference.d.ts +68 -0
  59. package/umd/src/commitments/USE_CALENDAR/callGoogleCalendarApi.d.ts +19 -0
  60. package/umd/src/commitments/USE_CALENDAR/createUseCalendarToolFunctions.d.ts +8 -0
  61. package/umd/src/commitments/USE_CALENDAR/createUseCalendarTools.d.ts +7 -0
  62. package/umd/src/commitments/USE_CALENDAR/getUseCalendarToolTitles.d.ts +7 -0
  63. package/umd/src/commitments/USE_CALENDAR/normalizeConfiguredCalendars.d.ts +19 -0
  64. package/umd/src/commitments/USE_CALENDAR/resolveUseCalendarToolRuntimeOrWalletCredentialResult.d.ts +34 -0
  65. package/umd/src/commitments/USE_TIMEOUT/TimeoutToolNames.d.ts +1 -0
  66. package/umd/src/commitments/USE_TIMEOUT/TimeoutToolRuntimeAdapter.d.ts +51 -2
  67. package/umd/src/commitments/USE_TIMEOUT/USE_TIMEOUT.d.ts +2 -2
  68. package/umd/src/commitments/USE_TIMEOUT/getTimeoutToolRuntimeAdapterOrDisabledResult.d.ts +2 -2
  69. package/umd/src/commitments/USE_TIMEOUT/parseTimeoutToolArgs.d.ts +14 -1
  70. package/umd/src/commitments/_common/toolRuntimeContext.d.ts +9 -0
  71. package/umd/src/commitments/index.d.ts +2 -1
  72. package/umd/src/executables/apps/locateVscode.d.ts +7 -0
  73. package/umd/src/executables/apps/locateVscode.test.d.ts +1 -0
  74. package/umd/src/executables/browsers/locateBrowser.d.ts +10 -0
  75. package/umd/src/executables/browsers/locateBrowser.test.d.ts +1 -0
  76. package/umd/src/executables/browsers/locateChrome.d.ts +7 -0
  77. package/umd/src/executables/browsers/locateChrome.test.d.ts +1 -0
  78. package/umd/src/executables/browsers/locateDefaultSystemBrowser.d.ts +10 -0
  79. package/umd/src/executables/browsers/locateDefaultSystemBrowser.test.d.ts +1 -0
  80. package/umd/src/executables/browsers/locateEdge.d.ts +7 -0
  81. package/umd/src/executables/browsers/locateEdge.test.d.ts +1 -0
  82. package/umd/src/executables/browsers/locateFirefox.d.ts +7 -0
  83. package/umd/src/executables/browsers/locateFirefox.test.d.ts +1 -0
  84. package/umd/src/executables/browsers/locateInternetExplorer.d.ts +7 -0
  85. package/umd/src/executables/browsers/locateInternetExplorer.test.d.ts +1 -0
  86. package/umd/src/executables/browsers/locateSafari.d.ts +7 -0
  87. package/umd/src/version.d.ts +1 -1
package/esm/index.es.js CHANGED
@@ -28,7 +28,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
28
28
  * @generated
29
29
  * @see https://github.com/webgptorg/promptbook
30
30
  */
31
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-11';
31
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-13';
32
32
  /**
33
33
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
34
34
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -15736,6 +15736,1232 @@ class UseBrowserCommitmentDefinition extends BaseCommitmentDefinition {
15736
15736
  * Note: [💞] Ignore a discrepancy between file name and entity name
15737
15737
  */
15738
15738
 
15739
+ /**
15740
+ * Base Google Calendar API URL.
15741
+ *
15742
+ * @private constant of callGoogleCalendarApi
15743
+ */
15744
+ const GOOGLE_CALENDAR_API_BASE_URL = 'https://www.googleapis.com/calendar/v3';
15745
+ /**
15746
+ * Runs one Google Calendar API request and parses JSON response payload.
15747
+ *
15748
+ * @private function of UseCalendarCommitmentDefinition
15749
+ */
15750
+ async function callGoogleCalendarApi(accessToken, options) {
15751
+ const url = new URL(options.path, GOOGLE_CALENDAR_API_BASE_URL);
15752
+ if (options.query) {
15753
+ for (const [key, value] of Object.entries(options.query)) {
15754
+ if (value && value.trim()) {
15755
+ url.searchParams.set(key, value);
15756
+ }
15757
+ }
15758
+ }
15759
+ const response = await fetch(url.toString(), {
15760
+ method: options.method,
15761
+ headers: {
15762
+ Authorization: `Bearer ${accessToken}`,
15763
+ Accept: 'application/json',
15764
+ 'Content-Type': 'application/json',
15765
+ },
15766
+ body: options.body ? JSON.stringify(options.body) : undefined,
15767
+ });
15768
+ const textPayload = await response.text();
15769
+ const parsedPayload = tryParseJson$2(textPayload);
15770
+ if (options.allowNotFound && response.status === 404) {
15771
+ return null;
15772
+ }
15773
+ if (!response.ok) {
15774
+ throw new Error(spaceTrim$1(`
15775
+ Google Calendar API request failed (${response.status} ${response.statusText}):
15776
+ ${extractGoogleCalendarApiErrorMessage(parsedPayload, textPayload)}
15777
+ `));
15778
+ }
15779
+ return parsedPayload;
15780
+ }
15781
+ /**
15782
+ * Parses raw text into JSON when possible.
15783
+ *
15784
+ * @private function of callGoogleCalendarApi
15785
+ */
15786
+ function tryParseJson$2(rawText) {
15787
+ if (!rawText.trim()) {
15788
+ return {};
15789
+ }
15790
+ try {
15791
+ return JSON.parse(rawText);
15792
+ }
15793
+ catch (_a) {
15794
+ return rawText;
15795
+ }
15796
+ }
15797
+ /**
15798
+ * Extracts a user-friendly Google Calendar API error message.
15799
+ *
15800
+ * @private function of callGoogleCalendarApi
15801
+ */
15802
+ function extractGoogleCalendarApiErrorMessage(parsedPayload, fallbackText) {
15803
+ if (parsedPayload && typeof parsedPayload === 'object') {
15804
+ const payload = parsedPayload;
15805
+ const errorPayload = payload.error;
15806
+ if (errorPayload && typeof errorPayload === 'object') {
15807
+ const normalizedErrorPayload = errorPayload;
15808
+ const message = typeof normalizedErrorPayload.message === 'string' ? normalizedErrorPayload.message : '';
15809
+ const errors = Array.isArray(normalizedErrorPayload.errors) ? normalizedErrorPayload.errors : [];
15810
+ const flattenedErrors = errors
15811
+ .map((errorEntry) => {
15812
+ if (!errorEntry || typeof errorEntry !== 'object') {
15813
+ return '';
15814
+ }
15815
+ const normalizedErrorEntry = errorEntry;
15816
+ const detailMessage = typeof normalizedErrorEntry.message === 'string' ? normalizedErrorEntry.message : '';
15817
+ const reason = typeof normalizedErrorEntry.reason === 'string' ? normalizedErrorEntry.reason : '';
15818
+ return [detailMessage, reason].filter(Boolean).join(' | ');
15819
+ })
15820
+ .filter(Boolean);
15821
+ if (message || flattenedErrors.length > 0) {
15822
+ return [message, ...flattenedErrors].filter(Boolean).join(' | ');
15823
+ }
15824
+ }
15825
+ }
15826
+ return fallbackText || 'Unknown Google Calendar API error';
15827
+ }
15828
+
15829
+ /**
15830
+ * Hostnames accepted for Google Calendar references.
15831
+ *
15832
+ * @private internal USE CALENDAR constant
15833
+ */
15834
+ const GOOGLE_CALENDAR_HOSTNAMES = new Set(['calendar.google.com', 'www.calendar.google.com']);
15835
+ /**
15836
+ * Default Google Calendar OAuth scopes when commitment content does not list any.
15837
+ *
15838
+ * @private internal USE CALENDAR constant
15839
+ */
15840
+ const DEFAULT_GOOGLE_CALENDAR_SCOPES = ['https://www.googleapis.com/auth/calendar'];
15841
+ /**
15842
+ * Parses one Google Calendar URL/reference into canonical details.
15843
+ *
15844
+ * Supported input forms:
15845
+ * - `https://calendar.google.com/...`
15846
+ * - `calendar.google.com/...`
15847
+ *
15848
+ * @private internal utility of USE CALENDAR commitment
15849
+ */
15850
+ function parseGoogleCalendarReference(rawReference) {
15851
+ const trimmedReference = rawReference.trim();
15852
+ if (!trimmedReference) {
15853
+ return null;
15854
+ }
15855
+ const normalizedReference = trimmedReference.startsWith('calendar.google.com/')
15856
+ ? `https://${trimmedReference}`
15857
+ : trimmedReference;
15858
+ let parsedUrl;
15859
+ try {
15860
+ parsedUrl = new URL(normalizedReference);
15861
+ }
15862
+ catch (_a) {
15863
+ return null;
15864
+ }
15865
+ if (!GOOGLE_CALENDAR_HOSTNAMES.has(parsedUrl.hostname.toLowerCase())) {
15866
+ return null;
15867
+ }
15868
+ parsedUrl.protocol = 'https:';
15869
+ parsedUrl.hash = '';
15870
+ return {
15871
+ provider: 'google',
15872
+ url: parsedUrl.toString(),
15873
+ calendarId: parseGoogleCalendarIdFromUrl(parsedUrl) || 'primary',
15874
+ scopes: [...DEFAULT_GOOGLE_CALENDAR_SCOPES],
15875
+ };
15876
+ }
15877
+ /**
15878
+ * Parses `USE CALENDAR` commitment content into calendar reference + optional instructions.
15879
+ *
15880
+ * @private internal utility of USE CALENDAR commitment
15881
+ */
15882
+ function parseUseCalendarCommitmentContent(content) {
15883
+ const trimmedContent = spaceTrim$1(content);
15884
+ if (!trimmedContent) {
15885
+ return {
15886
+ calendar: null,
15887
+ calendarUrlRaw: null,
15888
+ instructions: '',
15889
+ };
15890
+ }
15891
+ const lines = trimmedContent
15892
+ .split(/\r?\n/)
15893
+ .map((line) => line.trim())
15894
+ .filter(Boolean);
15895
+ if (lines.length === 0) {
15896
+ return {
15897
+ calendar: null,
15898
+ calendarUrlRaw: null,
15899
+ instructions: '',
15900
+ };
15901
+ }
15902
+ let calendarReferenceRaw = null;
15903
+ let calendarReference = null;
15904
+ const firstLine = lines[0] || '';
15905
+ const firstLineTokens = firstLine.split(/\s+/).filter(Boolean);
15906
+ for (const token of firstLineTokens) {
15907
+ const cleanedToken = token.replace(/[),.;:!?]+$/g, '');
15908
+ const parsedReference = parseGoogleCalendarReference(cleanedToken);
15909
+ if (!parsedReference) {
15910
+ continue;
15911
+ }
15912
+ calendarReferenceRaw = cleanedToken;
15913
+ calendarReference = parsedReference;
15914
+ break;
15915
+ }
15916
+ if (!calendarReference) {
15917
+ const firstUrl = findFirstUrlToken(trimmedContent);
15918
+ if (firstUrl) {
15919
+ calendarReferenceRaw = firstUrl;
15920
+ calendarReference = parseGoogleCalendarReference(firstUrl);
15921
+ }
15922
+ }
15923
+ const scopes = extractGoogleCalendarScopes(trimmedContent);
15924
+ if (calendarReference) {
15925
+ calendarReference = {
15926
+ ...calendarReference,
15927
+ scopes: scopes.length > 0 ? scopes : [...DEFAULT_GOOGLE_CALENDAR_SCOPES],
15928
+ tokenRef: extractTokenRef(trimmedContent),
15929
+ };
15930
+ }
15931
+ const instructionLines = [...lines];
15932
+ if (instructionLines.length > 0 && calendarReferenceRaw) {
15933
+ instructionLines[0] = removeTokenFromLine(instructionLines[0] || '', calendarReferenceRaw);
15934
+ }
15935
+ const filteredInstructionLines = instructionLines.filter((line) => !/^\s*SCOPES?\s+/i.test(line) && !line.trim().startsWith('https://www.googleapis.com/auth/'));
15936
+ return {
15937
+ calendar: calendarReference,
15938
+ calendarUrlRaw: calendarReferenceRaw,
15939
+ instructions: filteredInstructionLines.join('\n').trim(),
15940
+ };
15941
+ }
15942
+ /**
15943
+ * Attempts to resolve one concrete Google Calendar id from URL.
15944
+ *
15945
+ * @private internal utility of USE CALENDAR commitment
15946
+ */
15947
+ function parseGoogleCalendarIdFromUrl(url) {
15948
+ const rawCalendarId = url.searchParams.get('cid') || url.searchParams.get('src') || url.searchParams.get('calendarId');
15949
+ if (!rawCalendarId) {
15950
+ return null;
15951
+ }
15952
+ const decodedCalendarId = decodeURIComponent(rawCalendarId).trim();
15953
+ return decodedCalendarId || null;
15954
+ }
15955
+ /**
15956
+ * Finds the first URL-looking token in text.
15957
+ *
15958
+ * @private utility of USE CALENDAR commitment
15959
+ */
15960
+ function findFirstUrlToken(text) {
15961
+ const match = text.match(/https?:\/\/[^\s)]+/i);
15962
+ return match ? match[0] || null : null;
15963
+ }
15964
+ /**
15965
+ * Extracts Google Calendar OAuth scopes declared in commitment text.
15966
+ *
15967
+ * @private utility of USE CALENDAR commitment
15968
+ */
15969
+ function extractGoogleCalendarScopes(content) {
15970
+ const scopesFromUrls = content.match(/https:\/\/www\.googleapis\.com\/auth\/[A-Za-z0-9._/-]+/gim) || [];
15971
+ const scopesFromKeywordLines = content
15972
+ .split(/\r?\n/)
15973
+ .map((line) => line.trim())
15974
+ .filter((line) => /^\s*SCOPES?\s+/i.test(line))
15975
+ .flatMap((line) => line
15976
+ .replace(/^\s*SCOPES?\s+/i, '')
15977
+ .split(/[,\s]+/)
15978
+ .map((scope) => scope.trim())
15979
+ .filter(Boolean))
15980
+ .filter((scope) => scope.startsWith('https://www.googleapis.com/auth/'));
15981
+ const uniqueScopes = new Set();
15982
+ for (const scope of [...scopesFromUrls, ...scopesFromKeywordLines]) {
15983
+ uniqueScopes.add(scope);
15984
+ }
15985
+ return [...uniqueScopes];
15986
+ }
15987
+ /**
15988
+ * Extracts optional token reference marker from commitment text.
15989
+ *
15990
+ * @private utility of USE CALENDAR commitment
15991
+ */
15992
+ function extractTokenRef(content) {
15993
+ var _a;
15994
+ const tokenRefMatch = content.match(/@[\w.-]+/);
15995
+ const tokenRef = (_a = tokenRefMatch === null || tokenRefMatch === void 0 ? void 0 : tokenRefMatch[0]) === null || _a === void 0 ? void 0 : _a.trim();
15996
+ return tokenRef || undefined;
15997
+ }
15998
+ /**
15999
+ * Removes one specific token from one instruction line.
16000
+ *
16001
+ * @private utility of USE CALENDAR commitment
16002
+ */
16003
+ function removeTokenFromLine(line, token) {
16004
+ const tokens = line.split(/\s+/).filter(Boolean);
16005
+ const filteredTokens = tokens.filter((lineToken) => lineToken.replace(/[),.;:!?]+$/g, '') !== token);
16006
+ return filteredTokens.join(' ').trim();
16007
+ }
16008
+ /**
16009
+ * Note: [💞] Ignore a discrepancy between file name and entity name
16010
+ */
16011
+
16012
+ /**
16013
+ * Wallet metadata used by USE CALENDAR when resolving Google Calendar credentials.
16014
+ *
16015
+ * @private constant of UseCalendarCommitmentDefinition
16016
+ */
16017
+ const UseCalendarWallet = {
16018
+ service: 'google_calendar',
16019
+ key: 'use-calendar-google-token',
16020
+ };
16021
+
16022
+ /**
16023
+ * Internal error used to signal missing wallet credentials.
16024
+ *
16025
+ * @private class of resolveUseCalendarToolRuntimeOrWalletCredentialResult
16026
+ */
16027
+ class CalendarWalletCredentialRequiredError extends Error {
16028
+ constructor(options) {
16029
+ 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).');
16030
+ this.name = 'CalendarWalletCredentialRequiredError';
16031
+ this.service = UseCalendarWallet.service;
16032
+ this.key = UseCalendarWallet.key;
16033
+ this.calendarReference = options.calendarReference;
16034
+ }
16035
+ }
16036
+ /**
16037
+ * Resolves calendar runtime or returns a wallet-credential-required payload when missing.
16038
+ *
16039
+ * @private function of UseCalendarCommitmentDefinition
16040
+ */
16041
+ function resolveUseCalendarToolRuntimeOrWalletCredentialResult(args) {
16042
+ try {
16043
+ return resolveUseCalendarToolRuntime(args);
16044
+ }
16045
+ catch (error) {
16046
+ if (error instanceof CalendarWalletCredentialRequiredError) {
16047
+ return {
16048
+ walletResult: JSON.stringify(createCalendarWalletCredentialRequiredResult(error)),
16049
+ };
16050
+ }
16051
+ throw error;
16052
+ }
16053
+ }
16054
+ /**
16055
+ * Resolves runtime calendar + token for a USE CALENDAR tool call.
16056
+ *
16057
+ * @private function of resolveUseCalendarToolRuntimeOrWalletCredentialResult
16058
+ */
16059
+ function resolveUseCalendarToolRuntime(args) {
16060
+ var _a, _b;
16061
+ const runtimeContext = (readToolRuntimeContextFromToolArgs(args) ||
16062
+ {});
16063
+ const configuredCalendars = normalizeConfiguredCalendars$1((_a = runtimeContext.calendars) === null || _a === void 0 ? void 0 : _a.connections);
16064
+ const calendarArgument = normalizeOptionalText$1(args.calendarUrl);
16065
+ let calendarReference = null;
16066
+ if (calendarArgument) {
16067
+ calendarReference = parseGoogleCalendarReference(calendarArgument);
16068
+ if (!calendarReference) {
16069
+ throw new Error(`Calendar URL "${calendarArgument}" is invalid.`);
16070
+ }
16071
+ }
16072
+ else if (configuredCalendars.length === 1) {
16073
+ calendarReference = configuredCalendars[0] || null;
16074
+ }
16075
+ else if (configuredCalendars.length > 1) {
16076
+ throw new Error('Calendar is ambiguous. Provide "calendarUrl" argument with one calendar from USE CALENDAR commitments.');
16077
+ }
16078
+ else {
16079
+ throw new Error('Calendar is required. Provide "calendarUrl" argument in the tool call.');
16080
+ }
16081
+ if (!calendarReference) {
16082
+ throw new Error('Calendar is required but was not resolved.');
16083
+ }
16084
+ const accessToken = normalizeOptionalText$1((_b = runtimeContext.calendars) === null || _b === void 0 ? void 0 : _b.googleAccessToken) || '';
16085
+ if (!accessToken) {
16086
+ throw new CalendarWalletCredentialRequiredError({
16087
+ calendarReference,
16088
+ });
16089
+ }
16090
+ if (configuredCalendars.length > 0) {
16091
+ const allowedCalendarUrls = new Set(configuredCalendars.map((configuredCalendar) => configuredCalendar.url));
16092
+ if (!allowedCalendarUrls.has(calendarReference.url)) {
16093
+ throw new Error(`Calendar "${calendarReference.url}" is not configured by USE CALENDAR for this agent.`);
16094
+ }
16095
+ }
16096
+ return {
16097
+ calendarReference,
16098
+ accessToken,
16099
+ };
16100
+ }
16101
+ /**
16102
+ * Normalizes optional calendar list from runtime context.
16103
+ *
16104
+ * @private function of resolveUseCalendarToolRuntimeOrWalletCredentialResult
16105
+ */
16106
+ function normalizeConfiguredCalendars$1(rawCalendars) {
16107
+ if (!Array.isArray(rawCalendars)) {
16108
+ return [];
16109
+ }
16110
+ const calendars = [];
16111
+ const knownCalendars = new Set();
16112
+ for (const rawCalendar of rawCalendars) {
16113
+ if (!rawCalendar || typeof rawCalendar !== 'object') {
16114
+ continue;
16115
+ }
16116
+ const calendar = rawCalendar;
16117
+ const rawUrl = normalizeOptionalText$1(calendar.url);
16118
+ if (!rawUrl) {
16119
+ continue;
16120
+ }
16121
+ const parsedReference = parseGoogleCalendarReference(rawUrl);
16122
+ if (!parsedReference) {
16123
+ continue;
16124
+ }
16125
+ const key = `${parsedReference.provider}|${parsedReference.url}`;
16126
+ if (knownCalendars.has(key)) {
16127
+ continue;
16128
+ }
16129
+ knownCalendars.add(key);
16130
+ const scopes = Array.isArray(calendar.scopes)
16131
+ ? calendar.scopes
16132
+ .filter((scope) => typeof scope === 'string')
16133
+ .map((scope) => scope.trim())
16134
+ .filter(Boolean)
16135
+ : [];
16136
+ calendars.push({
16137
+ ...parsedReference,
16138
+ scopes: scopes.length > 0 ? scopes : parsedReference.scopes,
16139
+ });
16140
+ }
16141
+ return calendars;
16142
+ }
16143
+ /**
16144
+ * Converts missing-wallet errors into structured tool result payloads.
16145
+ *
16146
+ * @private function of resolveUseCalendarToolRuntimeOrWalletCredentialResult
16147
+ */
16148
+ function createCalendarWalletCredentialRequiredResult(error) {
16149
+ return {
16150
+ action: 'calendar-auth',
16151
+ status: 'wallet-credential-required',
16152
+ recordType: 'ACCESS_TOKEN',
16153
+ service: error.service,
16154
+ key: error.key,
16155
+ isUserScoped: false,
16156
+ isGlobal: false,
16157
+ provider: 'google',
16158
+ calendarUrl: error.calendarReference.url,
16159
+ scopes: error.calendarReference.scopes,
16160
+ message: error.message,
16161
+ };
16162
+ }
16163
+ /**
16164
+ * Normalizes unknown text input to trimmed non-empty string.
16165
+ *
16166
+ * @private function of resolveUseCalendarToolRuntimeOrWalletCredentialResult
16167
+ */
16168
+ function normalizeOptionalText$1(value) {
16169
+ if (typeof value !== 'string') {
16170
+ return undefined;
16171
+ }
16172
+ const trimmedValue = value.trim();
16173
+ return trimmedValue || undefined;
16174
+ }
16175
+
16176
+ /**
16177
+ * Names of tools used by the USE CALENDAR commitment.
16178
+ *
16179
+ * @private constant of UseCalendarCommitmentDefinition
16180
+ */
16181
+ const UseCalendarToolNames = {
16182
+ listEvents: 'calendar_list_events',
16183
+ getEvent: 'calendar_get_event',
16184
+ createEvent: 'calendar_create_event',
16185
+ updateEvent: 'calendar_update_event',
16186
+ deleteEvent: 'calendar_delete_event',
16187
+ inviteGuests: 'calendar_invite_guests',
16188
+ };
16189
+
16190
+ /**
16191
+ * Gets Google Calendar tool function implementations.
16192
+ *
16193
+ * @private function of UseCalendarCommitmentDefinition
16194
+ */
16195
+ function createUseCalendarToolFunctions() {
16196
+ return {
16197
+ async [UseCalendarToolNames.listEvents](args) {
16198
+ return withUseCalendarRuntime(args, async ({ calendarReference, accessToken }) => {
16199
+ const query = {};
16200
+ if (normalizeOptionalText(args.timeMin)) {
16201
+ query.timeMin = args.timeMin.trim();
16202
+ }
16203
+ if (normalizeOptionalText(args.timeMax)) {
16204
+ query.timeMax = args.timeMax.trim();
16205
+ }
16206
+ if (normalizeOptionalText(args.query)) {
16207
+ query.q = args.query.trim();
16208
+ }
16209
+ if (typeof args.maxResults === 'number' && Number.isFinite(args.maxResults) && args.maxResults > 0) {
16210
+ query.maxResults = String(Math.floor(args.maxResults));
16211
+ }
16212
+ if (args.singleEvents !== undefined) {
16213
+ query.singleEvents = args.singleEvents ? 'true' : 'false';
16214
+ }
16215
+ if (args.orderBy === 'startTime' || args.orderBy === 'updated') {
16216
+ query.orderBy = args.orderBy;
16217
+ }
16218
+ if (normalizeOptionalText(args.timeZone)) {
16219
+ query.timeZone = args.timeZone.trim();
16220
+ }
16221
+ const payload = await callGoogleCalendarApi(accessToken, {
16222
+ method: 'GET',
16223
+ path: `/calendars/${encodeGoogleCalendarId(calendarReference.calendarId)}/events`,
16224
+ query,
16225
+ });
16226
+ const events = ((payload === null || payload === void 0 ? void 0 : payload.items) || []).map((event) => mapGoogleCalendarEvent(event));
16227
+ return JSON.stringify({
16228
+ provider: calendarReference.provider,
16229
+ calendarUrl: calendarReference.url,
16230
+ calendarId: calendarReference.calendarId,
16231
+ events,
16232
+ nextPageToken: (payload === null || payload === void 0 ? void 0 : payload.nextPageToken) || null,
16233
+ nextSyncToken: (payload === null || payload === void 0 ? void 0 : payload.nextSyncToken) || null,
16234
+ });
16235
+ });
16236
+ },
16237
+ async [UseCalendarToolNames.getEvent](args) {
16238
+ return withUseCalendarRuntime(args, async ({ calendarReference, accessToken }) => {
16239
+ const eventId = normalizeRequiredText(args.eventId, 'eventId');
16240
+ const payload = await callGoogleCalendarApi(accessToken, {
16241
+ method: 'GET',
16242
+ path: `/calendars/${encodeGoogleCalendarId(calendarReference.calendarId)}/events/${encodeURIComponent(eventId)}`,
16243
+ });
16244
+ return JSON.stringify({
16245
+ provider: calendarReference.provider,
16246
+ calendarUrl: calendarReference.url,
16247
+ calendarId: calendarReference.calendarId,
16248
+ event: mapGoogleCalendarEvent(payload || {}),
16249
+ });
16250
+ });
16251
+ },
16252
+ async [UseCalendarToolNames.createEvent](args) {
16253
+ return withUseCalendarRuntime(args, async ({ calendarReference, accessToken }) => {
16254
+ const requestBody = createGoogleCalendarEventPayload({
16255
+ summary: normalizeRequiredText(args.summary, 'summary'),
16256
+ description: normalizeOptionalText(args.description),
16257
+ location: normalizeOptionalText(args.location),
16258
+ start: normalizeRequiredText(args.start, 'start'),
16259
+ end: normalizeRequiredText(args.end, 'end'),
16260
+ timeZone: normalizeOptionalText(args.timeZone),
16261
+ attendees: normalizeAttendees(args.attendees),
16262
+ reminderMinutes: normalizeReminderMinutes(args.reminderMinutes),
16263
+ });
16264
+ const payload = await callGoogleCalendarApi(accessToken, {
16265
+ method: 'POST',
16266
+ path: `/calendars/${encodeGoogleCalendarId(calendarReference.calendarId)}/events`,
16267
+ query: createSendUpdatesQuery(args.sendUpdates),
16268
+ body: requestBody,
16269
+ });
16270
+ return JSON.stringify({
16271
+ provider: calendarReference.provider,
16272
+ calendarUrl: calendarReference.url,
16273
+ calendarId: calendarReference.calendarId,
16274
+ event: mapGoogleCalendarEvent(payload || {}),
16275
+ });
16276
+ });
16277
+ },
16278
+ async [UseCalendarToolNames.updateEvent](args) {
16279
+ return withUseCalendarRuntime(args, async ({ calendarReference, accessToken }) => {
16280
+ const eventId = normalizeRequiredText(args.eventId, 'eventId');
16281
+ const requestBody = createGoogleCalendarEventPayload({
16282
+ summary: normalizeOptionalText(args.summary),
16283
+ description: normalizeOptionalText(args.description),
16284
+ location: normalizeOptionalText(args.location),
16285
+ start: normalizeOptionalText(args.start),
16286
+ end: normalizeOptionalText(args.end),
16287
+ timeZone: normalizeOptionalText(args.timeZone),
16288
+ attendees: normalizeAttendees(args.attendees),
16289
+ reminderMinutes: normalizeReminderMinutes(args.reminderMinutes),
16290
+ });
16291
+ const payload = await callGoogleCalendarApi(accessToken, {
16292
+ method: 'PATCH',
16293
+ path: `/calendars/${encodeGoogleCalendarId(calendarReference.calendarId)}/events/${encodeURIComponent(eventId)}`,
16294
+ query: createSendUpdatesQuery(args.sendUpdates),
16295
+ body: requestBody,
16296
+ });
16297
+ return JSON.stringify({
16298
+ provider: calendarReference.provider,
16299
+ calendarUrl: calendarReference.url,
16300
+ calendarId: calendarReference.calendarId,
16301
+ event: mapGoogleCalendarEvent(payload || {}),
16302
+ });
16303
+ });
16304
+ },
16305
+ async [UseCalendarToolNames.deleteEvent](args) {
16306
+ return withUseCalendarRuntime(args, async ({ calendarReference, accessToken }) => {
16307
+ const eventId = normalizeRequiredText(args.eventId, 'eventId');
16308
+ await callGoogleCalendarApi(accessToken, {
16309
+ method: 'DELETE',
16310
+ path: `/calendars/${encodeGoogleCalendarId(calendarReference.calendarId)}/events/${encodeURIComponent(eventId)}`,
16311
+ query: createSendUpdatesQuery(args.sendUpdates),
16312
+ });
16313
+ return JSON.stringify({
16314
+ provider: calendarReference.provider,
16315
+ calendarUrl: calendarReference.url,
16316
+ calendarId: calendarReference.calendarId,
16317
+ eventId,
16318
+ status: 'deleted',
16319
+ });
16320
+ });
16321
+ },
16322
+ async [UseCalendarToolNames.inviteGuests](args) {
16323
+ return withUseCalendarRuntime(args, async ({ calendarReference, accessToken }) => {
16324
+ const eventId = normalizeRequiredText(args.eventId, 'eventId');
16325
+ const guests = normalizeAttendees(args.guests);
16326
+ if (guests.length === 0) {
16327
+ throw new Error('Tool "calendar_invite_guests" requires non-empty "guests".');
16328
+ }
16329
+ const existingEvent = await callGoogleCalendarApi(accessToken, {
16330
+ method: 'GET',
16331
+ path: `/calendars/${encodeGoogleCalendarId(calendarReference.calendarId)}/events/${encodeURIComponent(eventId)}`,
16332
+ });
16333
+ const existingAttendees = ((existingEvent === null || existingEvent === void 0 ? void 0 : existingEvent.attendees) || [])
16334
+ .map((attendee) => normalizeOptionalText(attendee.email))
16335
+ .filter((email) => Boolean(email));
16336
+ const mergedAttendees = [...new Set([...existingAttendees, ...guests])];
16337
+ const payload = await callGoogleCalendarApi(accessToken, {
16338
+ method: 'PATCH',
16339
+ path: `/calendars/${encodeGoogleCalendarId(calendarReference.calendarId)}/events/${encodeURIComponent(eventId)}`,
16340
+ query: createSendUpdatesQuery(args.sendUpdates),
16341
+ body: {
16342
+ attendees: mergedAttendees.map((email) => ({ email })),
16343
+ },
16344
+ });
16345
+ return JSON.stringify({
16346
+ provider: calendarReference.provider,
16347
+ calendarUrl: calendarReference.url,
16348
+ calendarId: calendarReference.calendarId,
16349
+ event: mapGoogleCalendarEvent(payload || {}),
16350
+ invitedGuests: guests,
16351
+ });
16352
+ });
16353
+ },
16354
+ };
16355
+ }
16356
+ /**
16357
+ * Executes one tool operation with resolved USE CALENDAR runtime.
16358
+ *
16359
+ * @private function of createUseCalendarToolFunctions
16360
+ */
16361
+ async function withUseCalendarRuntime(args, operation) {
16362
+ const runtime = resolveUseCalendarToolRuntimeOrWalletCredentialResult(args);
16363
+ if ('walletResult' in runtime) {
16364
+ return runtime.walletResult;
16365
+ }
16366
+ return operation(runtime);
16367
+ }
16368
+ /**
16369
+ * Encodes one Google calendar id for URL path usage.
16370
+ *
16371
+ * @private function of createUseCalendarToolFunctions
16372
+ */
16373
+ function encodeGoogleCalendarId(calendarId) {
16374
+ return encodeURIComponent(calendarId);
16375
+ }
16376
+ /**
16377
+ * Normalizes one required textual input.
16378
+ *
16379
+ * @private function of createUseCalendarToolFunctions
16380
+ */
16381
+ function normalizeRequiredText(value, fieldName) {
16382
+ const normalizedValue = normalizeOptionalText(value);
16383
+ if (!normalizedValue) {
16384
+ throw new Error(`Tool "${fieldName}" requires non-empty value.`);
16385
+ }
16386
+ return normalizedValue;
16387
+ }
16388
+ /**
16389
+ * Normalizes unknown text input to trimmed non-empty string.
16390
+ *
16391
+ * @private function of createUseCalendarToolFunctions
16392
+ */
16393
+ function normalizeOptionalText(value) {
16394
+ if (typeof value !== 'string') {
16395
+ return undefined;
16396
+ }
16397
+ const trimmedValue = value.trim();
16398
+ return trimmedValue || undefined;
16399
+ }
16400
+ /**
16401
+ * Normalizes optional attendee list from tool input.
16402
+ *
16403
+ * @private function of createUseCalendarToolFunctions
16404
+ */
16405
+ function normalizeAttendees(value) {
16406
+ if (!Array.isArray(value)) {
16407
+ return [];
16408
+ }
16409
+ const normalizedAttendees = value
16410
+ .filter((attendee) => typeof attendee === 'string')
16411
+ .map((attendee) => attendee.trim())
16412
+ .filter(Boolean);
16413
+ return [...new Set(normalizedAttendees)];
16414
+ }
16415
+ /**
16416
+ * Normalizes optional reminder-minute offsets from tool input.
16417
+ *
16418
+ * @private function of createUseCalendarToolFunctions
16419
+ */
16420
+ function normalizeReminderMinutes(value) {
16421
+ if (!Array.isArray(value)) {
16422
+ return [];
16423
+ }
16424
+ const reminderMinutes = value
16425
+ .filter((minute) => typeof minute === 'number' && Number.isFinite(minute))
16426
+ .map((minute) => Math.max(0, Math.floor(minute)));
16427
+ return [...new Set(reminderMinutes)];
16428
+ }
16429
+ /**
16430
+ * Builds optional `sendUpdates` query for mutating Google Calendar requests.
16431
+ *
16432
+ * @private function of createUseCalendarToolFunctions
16433
+ */
16434
+ function createSendUpdatesQuery(sendUpdates) {
16435
+ if (sendUpdates === 'all' || sendUpdates === 'externalOnly' || sendUpdates === 'none') {
16436
+ return { sendUpdates };
16437
+ }
16438
+ return {};
16439
+ }
16440
+ /**
16441
+ * Creates one Google Calendar event payload from normalized tool arguments.
16442
+ *
16443
+ * @private function of createUseCalendarToolFunctions
16444
+ */
16445
+ function createGoogleCalendarEventPayload(options) {
16446
+ const payload = {};
16447
+ if (options.summary) {
16448
+ payload.summary = options.summary;
16449
+ }
16450
+ if (options.description) {
16451
+ payload.description = options.description;
16452
+ }
16453
+ if (options.location) {
16454
+ payload.location = options.location;
16455
+ }
16456
+ if (options.start) {
16457
+ payload.start = createGoogleCalendarDateValue(options.start, options.timeZone);
16458
+ }
16459
+ if (options.end) {
16460
+ payload.end = createGoogleCalendarDateValue(options.end, options.timeZone);
16461
+ }
16462
+ if (options.attendees && options.attendees.length > 0) {
16463
+ payload.attendees = options.attendees.map((email) => ({ email }));
16464
+ }
16465
+ if (options.reminderMinutes && options.reminderMinutes.length > 0) {
16466
+ payload.reminders = {
16467
+ useDefault: false,
16468
+ overrides: options.reminderMinutes.map((minutes) => ({
16469
+ method: 'popup',
16470
+ minutes,
16471
+ })),
16472
+ };
16473
+ }
16474
+ return payload;
16475
+ }
16476
+ /**
16477
+ * Converts date/dateTime input into a Google Calendar-compatible date object.
16478
+ *
16479
+ * @private function of createUseCalendarToolFunctions
16480
+ */
16481
+ function createGoogleCalendarDateValue(value, timeZone) {
16482
+ const isDateOnly = /^\d{4}-\d{2}-\d{2}$/.test(value);
16483
+ if (isDateOnly) {
16484
+ return {
16485
+ date: value,
16486
+ };
16487
+ }
16488
+ return {
16489
+ dateTime: value,
16490
+ ...(timeZone ? { timeZone } : {}),
16491
+ };
16492
+ }
16493
+ /**
16494
+ * Maps raw Google Calendar event payload to a compact tool result object.
16495
+ *
16496
+ * @private function of createUseCalendarToolFunctions
16497
+ */
16498
+ function mapGoogleCalendarEvent(event) {
16499
+ return {
16500
+ id: event.id || null,
16501
+ summary: event.summary || null,
16502
+ description: event.description || null,
16503
+ location: event.location || null,
16504
+ status: event.status || null,
16505
+ htmlLink: event.htmlLink || null,
16506
+ start: event.start || null,
16507
+ end: event.end || null,
16508
+ organizer: event.organizer || null,
16509
+ attendees: (event.attendees || []).map((attendee) => ({
16510
+ email: attendee.email || null,
16511
+ responseStatus: attendee.responseStatus || null,
16512
+ })),
16513
+ };
16514
+ }
16515
+
16516
+ /**
16517
+ * Shared calendar URL argument description used in USE CALENDAR tool schemas.
16518
+ *
16519
+ * @private constant of createUseCalendarTools
16520
+ */
16521
+ const CALENDAR_URL_PARAMETER_DESCRIPTION = 'Google Calendar URL configured by USE CALENDAR (for example "https://calendar.google.com/...").';
16522
+ /**
16523
+ * Adds USE CALENDAR tool definitions while keeping already registered tools untouched.
16524
+ *
16525
+ * @private function of UseCalendarCommitmentDefinition
16526
+ */
16527
+ function createUseCalendarTools(existingTools) {
16528
+ const updatedTools = [...existingTools];
16529
+ const addToolIfMissing = (tool) => {
16530
+ if (!updatedTools.some((existingTool) => existingTool.name === tool.name)) {
16531
+ updatedTools.push(tool);
16532
+ }
16533
+ };
16534
+ addToolIfMissing({
16535
+ name: UseCalendarToolNames.listEvents,
16536
+ description: 'List events from a configured calendar for a time range.',
16537
+ parameters: {
16538
+ type: 'object',
16539
+ properties: {
16540
+ calendarUrl: {
16541
+ type: 'string',
16542
+ description: CALENDAR_URL_PARAMETER_DESCRIPTION,
16543
+ },
16544
+ timeMin: {
16545
+ type: 'string',
16546
+ description: 'Inclusive event start bound in ISO datetime.',
16547
+ },
16548
+ timeMax: {
16549
+ type: 'string',
16550
+ description: 'Exclusive event end bound in ISO datetime.',
16551
+ },
16552
+ query: {
16553
+ type: 'string',
16554
+ description: 'Optional free-text event search query.',
16555
+ },
16556
+ maxResults: {
16557
+ type: 'integer',
16558
+ description: 'Maximum number of events to return.',
16559
+ },
16560
+ singleEvents: {
16561
+ type: 'boolean',
16562
+ description: 'Expand recurring events into individual instances.',
16563
+ },
16564
+ orderBy: {
16565
+ type: 'string',
16566
+ description: 'Optional ordering ("startTime" or "updated").',
16567
+ },
16568
+ timeZone: {
16569
+ type: 'string',
16570
+ description: 'Optional IANA timezone for response rendering.',
16571
+ },
16572
+ },
16573
+ required: [],
16574
+ },
16575
+ });
16576
+ addToolIfMissing({
16577
+ name: UseCalendarToolNames.getEvent,
16578
+ description: 'Get one event by id from a configured calendar.',
16579
+ parameters: {
16580
+ type: 'object',
16581
+ properties: {
16582
+ calendarUrl: {
16583
+ type: 'string',
16584
+ description: CALENDAR_URL_PARAMETER_DESCRIPTION,
16585
+ },
16586
+ eventId: {
16587
+ type: 'string',
16588
+ description: 'Google Calendar event id.',
16589
+ },
16590
+ },
16591
+ required: ['eventId'],
16592
+ },
16593
+ });
16594
+ addToolIfMissing({
16595
+ name: UseCalendarToolNames.createEvent,
16596
+ description: 'Create one event in a configured calendar.',
16597
+ parameters: {
16598
+ type: 'object',
16599
+ properties: {
16600
+ calendarUrl: {
16601
+ type: 'string',
16602
+ description: CALENDAR_URL_PARAMETER_DESCRIPTION,
16603
+ },
16604
+ summary: {
16605
+ type: 'string',
16606
+ description: 'Event title/summary.',
16607
+ },
16608
+ description: {
16609
+ type: 'string',
16610
+ description: 'Optional event description.',
16611
+ },
16612
+ location: {
16613
+ type: 'string',
16614
+ description: 'Optional event location.',
16615
+ },
16616
+ start: {
16617
+ type: 'string',
16618
+ description: 'Event start as ISO datetime or date.',
16619
+ },
16620
+ end: {
16621
+ type: 'string',
16622
+ description: 'Event end as ISO datetime or date.',
16623
+ },
16624
+ timeZone: {
16625
+ type: 'string',
16626
+ description: 'Optional timezone for datetime values.',
16627
+ },
16628
+ attendees: {
16629
+ type: 'array',
16630
+ description: 'Optional guest email list.',
16631
+ },
16632
+ reminderMinutes: {
16633
+ type: 'array',
16634
+ description: 'Optional popup reminder minute offsets.',
16635
+ },
16636
+ sendUpdates: {
16637
+ type: 'string',
16638
+ description: 'Guest update policy ("all", "externalOnly", "none").',
16639
+ },
16640
+ },
16641
+ required: ['summary', 'start', 'end'],
16642
+ },
16643
+ });
16644
+ addToolIfMissing({
16645
+ name: UseCalendarToolNames.updateEvent,
16646
+ description: 'Update one existing event in a configured calendar.',
16647
+ parameters: {
16648
+ type: 'object',
16649
+ properties: {
16650
+ calendarUrl: {
16651
+ type: 'string',
16652
+ description: CALENDAR_URL_PARAMETER_DESCRIPTION,
16653
+ },
16654
+ eventId: {
16655
+ type: 'string',
16656
+ description: 'Google Calendar event id.',
16657
+ },
16658
+ summary: {
16659
+ type: 'string',
16660
+ description: 'Updated event summary.',
16661
+ },
16662
+ description: {
16663
+ type: 'string',
16664
+ description: 'Updated event description.',
16665
+ },
16666
+ location: {
16667
+ type: 'string',
16668
+ description: 'Updated event location.',
16669
+ },
16670
+ start: {
16671
+ type: 'string',
16672
+ description: 'Updated event start as ISO datetime or date.',
16673
+ },
16674
+ end: {
16675
+ type: 'string',
16676
+ description: 'Updated event end as ISO datetime or date.',
16677
+ },
16678
+ timeZone: {
16679
+ type: 'string',
16680
+ description: 'Optional timezone for datetime values.',
16681
+ },
16682
+ attendees: {
16683
+ type: 'array',
16684
+ description: 'Optional replacement guest email list.',
16685
+ },
16686
+ reminderMinutes: {
16687
+ type: 'array',
16688
+ description: 'Optional replacement popup reminder minute offsets.',
16689
+ },
16690
+ sendUpdates: {
16691
+ type: 'string',
16692
+ description: 'Guest update policy ("all", "externalOnly", "none").',
16693
+ },
16694
+ },
16695
+ required: ['eventId'],
16696
+ },
16697
+ });
16698
+ addToolIfMissing({
16699
+ name: UseCalendarToolNames.deleteEvent,
16700
+ description: 'Delete one event from a configured calendar.',
16701
+ parameters: {
16702
+ type: 'object',
16703
+ properties: {
16704
+ calendarUrl: {
16705
+ type: 'string',
16706
+ description: CALENDAR_URL_PARAMETER_DESCRIPTION,
16707
+ },
16708
+ eventId: {
16709
+ type: 'string',
16710
+ description: 'Google Calendar event id.',
16711
+ },
16712
+ sendUpdates: {
16713
+ type: 'string',
16714
+ description: 'Guest update policy ("all", "externalOnly", "none").',
16715
+ },
16716
+ },
16717
+ required: ['eventId'],
16718
+ },
16719
+ });
16720
+ addToolIfMissing({
16721
+ name: UseCalendarToolNames.inviteGuests,
16722
+ description: 'Add guests to an existing event in a configured calendar.',
16723
+ parameters: {
16724
+ type: 'object',
16725
+ properties: {
16726
+ calendarUrl: {
16727
+ type: 'string',
16728
+ description: CALENDAR_URL_PARAMETER_DESCRIPTION,
16729
+ },
16730
+ eventId: {
16731
+ type: 'string',
16732
+ description: 'Google Calendar event id.',
16733
+ },
16734
+ guests: {
16735
+ type: 'array',
16736
+ description: 'Guest email list to add to the event.',
16737
+ },
16738
+ sendUpdates: {
16739
+ type: 'string',
16740
+ description: 'Guest update policy ("all", "externalOnly", "none").',
16741
+ },
16742
+ },
16743
+ required: ['eventId', 'guests'],
16744
+ },
16745
+ });
16746
+ return updatedTools;
16747
+ }
16748
+
16749
+ /**
16750
+ * Gets human-readable tool labels for USE CALENDAR functions.
16751
+ *
16752
+ * @private function of UseCalendarCommitmentDefinition
16753
+ */
16754
+ function getUseCalendarToolTitles() {
16755
+ return {
16756
+ [UseCalendarToolNames.listEvents]: 'List calendar events',
16757
+ [UseCalendarToolNames.getEvent]: 'Get calendar event',
16758
+ [UseCalendarToolNames.createEvent]: 'Create calendar event',
16759
+ [UseCalendarToolNames.updateEvent]: 'Update calendar event',
16760
+ [UseCalendarToolNames.deleteEvent]: 'Delete calendar event',
16761
+ [UseCalendarToolNames.inviteGuests]: 'Invite calendar guests',
16762
+ };
16763
+ }
16764
+
16765
+ /**
16766
+ * Normalizes unknown metadata payload into a typed list of configured calendars.
16767
+ *
16768
+ * @private internal utility of USE CALENDAR commitment
16769
+ */
16770
+ function normalizeConfiguredCalendars(rawCalendars) {
16771
+ if (!Array.isArray(rawCalendars)) {
16772
+ return [];
16773
+ }
16774
+ const uniqueCalendars = new Set();
16775
+ const calendars = [];
16776
+ for (const rawCalendar of rawCalendars) {
16777
+ if (!rawCalendar || typeof rawCalendar !== 'object') {
16778
+ continue;
16779
+ }
16780
+ const calendar = rawCalendar;
16781
+ const provider = normalizeProvider(calendar.provider);
16782
+ const url = normalizeText(calendar.url);
16783
+ const calendarId = normalizeText(calendar.calendarId);
16784
+ if (!provider || !url || !calendarId) {
16785
+ continue;
16786
+ }
16787
+ const uniqueKey = `${provider}|${url}`;
16788
+ if (uniqueCalendars.has(uniqueKey)) {
16789
+ continue;
16790
+ }
16791
+ uniqueCalendars.add(uniqueKey);
16792
+ const scopes = Array.isArray(calendar.scopes)
16793
+ ? calendar.scopes
16794
+ .filter((scope) => typeof scope === 'string')
16795
+ .map((scope) => scope.trim())
16796
+ .filter(Boolean)
16797
+ : [];
16798
+ calendars.push({
16799
+ provider,
16800
+ url,
16801
+ calendarId,
16802
+ scopes,
16803
+ ...(normalizeText(calendar.tokenRef) ? { tokenRef: normalizeText(calendar.tokenRef) } : {}),
16804
+ });
16805
+ }
16806
+ return calendars;
16807
+ }
16808
+ /**
16809
+ * Normalizes optional provider text to one supported value.
16810
+ *
16811
+ * @private function of normalizeConfiguredCalendars
16812
+ */
16813
+ function normalizeProvider(value) {
16814
+ if (typeof value !== 'string') {
16815
+ return null;
16816
+ }
16817
+ const normalizedProvider = value.trim().toLowerCase();
16818
+ if (normalizedProvider === 'google') {
16819
+ return 'google';
16820
+ }
16821
+ return null;
16822
+ }
16823
+ /**
16824
+ * Normalizes unknown text input to trimmed non-empty string.
16825
+ *
16826
+ * @private function of normalizeConfiguredCalendars
16827
+ */
16828
+ function normalizeText(value) {
16829
+ return typeof value === 'string' ? value.trim() : '';
16830
+ }
16831
+
16832
+ /**
16833
+ * USE CALENDAR commitment definition.
16834
+ *
16835
+ * `USE CALENDAR` enables calendar tooling so the agent can read and manage events
16836
+ * in one configured Google Calendar.
16837
+ *
16838
+ * Authentication is expected through runtime context provided by the host app UI.
16839
+ * Hosts can provide manual wallet tokens or host-managed OAuth tokens.
16840
+ *
16841
+ * @private [🪔] Maybe export the commitments through some package
16842
+ */
16843
+ class UseCalendarCommitmentDefinition extends BaseCommitmentDefinition {
16844
+ constructor() {
16845
+ super('USE CALENDAR', ['CALENDAR']);
16846
+ }
16847
+ /**
16848
+ * Short one-line description of USE CALENDAR.
16849
+ */
16850
+ get description() {
16851
+ return 'Enable calendar tools for reading and managing events through Google Calendar.';
16852
+ }
16853
+ /**
16854
+ * Icon for this commitment.
16855
+ */
16856
+ get icon() {
16857
+ return '📅';
16858
+ }
16859
+ /**
16860
+ * Markdown documentation for USE CALENDAR commitment.
16861
+ */
16862
+ get documentation() {
16863
+ return spaceTrim$1(`
16864
+ # USE CALENDAR
16865
+
16866
+ Enables the agent to access and manage one Google Calendar.
16867
+
16868
+ ## Key aspects
16869
+
16870
+ - The first URL in the commitment should point to a Google Calendar URL.
16871
+ - Optional \`SCOPES\` lines can provide explicit OAuth scopes.
16872
+ - Optional extra instructions can follow calendar reference lines.
16873
+ - Runtime provides Google Calendar OAuth token (manual wallet token or host-managed OAuth token).
16874
+ - Tools support listing events, reading one event, creating events, updating events, deleting events, and inviting guests.
16875
+
16876
+ ## Examples
16877
+
16878
+ \`\`\`book
16879
+ Scheduling Assistant
16880
+
16881
+ PERSONA You coordinate meetings and schedules.
16882
+ USE CALENDAR https://calendar.google.com/calendar/u/0/r
16883
+ \`\`\`
16884
+
16885
+ \`\`\`book
16886
+ Executive Assistant
16887
+
16888
+ USE CALENDAR https://calendar.google.com/calendar/u/0/r
16889
+ SCOPES https://www.googleapis.com/auth/calendar.readonly
16890
+ RULE Ask for confirmation before deleting events.
16891
+ \`\`\`
16892
+ `);
16893
+ }
16894
+ applyToAgentModelRequirements(requirements, content) {
16895
+ var _a;
16896
+ const parsedCommitment = parseUseCalendarCommitmentContent(content);
16897
+ const existingConfiguredCalendars = normalizeConfiguredCalendars((_a = requirements._metadata) === null || _a === void 0 ? void 0 : _a.useCalendars);
16898
+ if (parsedCommitment.calendar) {
16899
+ addConfiguredCalendarIfMissing(existingConfiguredCalendars, parsedCommitment.calendar);
16900
+ }
16901
+ const calendarsList = existingConfiguredCalendars.length > 0
16902
+ ? existingConfiguredCalendars
16903
+ .map((calendar) => [
16904
+ `- ${calendar.provider}: ${calendar.url}`,
16905
+ calendar.scopes.length > 0 ? ` scopes: ${calendar.scopes.join(', ')}` : '',
16906
+ ]
16907
+ .filter(Boolean)
16908
+ .join('\n'))
16909
+ .join('\n')
16910
+ : '- Calendar is resolved from runtime context';
16911
+ const extraInstructions = formatOptionalInstructionBlock('Calendar instructions', parsedCommitment.instructions);
16912
+ return this.appendToSystemMessage({
16913
+ ...requirements,
16914
+ tools: createUseCalendarTools(requirements.tools || []),
16915
+ _metadata: {
16916
+ ...requirements._metadata,
16917
+ useCalendar: true,
16918
+ useCalendars: existingConfiguredCalendars,
16919
+ },
16920
+ }, spaceTrim$1((block) => `
16921
+ Calendar tools:
16922
+ - You can inspect and manage events in configured calendars.
16923
+ - Supported operations include read, create, update, delete, invite guests, and reminders.
16924
+ - Configured calendars:
16925
+ ${block(calendarsList)}
16926
+ - USE CALENDAR credentials are read from wallet records (ACCESS_TOKEN, service "${UseCalendarWallet.service}", key "${UseCalendarWallet.key}").
16927
+ - If credentials are missing, ask user to connect calendar credentials in host UI and/or add them to wallet.
16928
+ ${block(extraInstructions)}
16929
+ `));
16930
+ }
16931
+ /**
16932
+ * Gets human-readable titles for tool functions provided by this commitment.
16933
+ */
16934
+ getToolTitles() {
16935
+ return getUseCalendarToolTitles();
16936
+ }
16937
+ /**
16938
+ * Gets calendar tool function implementations.
16939
+ */
16940
+ getToolFunctions() {
16941
+ return createUseCalendarToolFunctions();
16942
+ }
16943
+ }
16944
+ /**
16945
+ * Adds calendar into configured calendars list if it is not already present.
16946
+ *
16947
+ * @private function of UseCalendarCommitmentDefinition
16948
+ */
16949
+ function addConfiguredCalendarIfMissing(configuredCalendars, calendarReference) {
16950
+ if (configuredCalendars.some((calendar) => calendar.provider === calendarReference.provider && calendar.url === calendarReference.url)) {
16951
+ return;
16952
+ }
16953
+ configuredCalendars.push({
16954
+ provider: calendarReference.provider,
16955
+ url: calendarReference.url,
16956
+ calendarId: calendarReference.calendarId,
16957
+ scopes: [...calendarReference.scopes],
16958
+ ...(calendarReference.tokenRef ? { tokenRef: calendarReference.tokenRef } : {}),
16959
+ });
16960
+ }
16961
+ /**
16962
+ * Note: [💞] Ignore a discrepancy between file name and entity name
16963
+ */
16964
+
15739
16965
  /**
15740
16966
  * Lightweight email token matcher used for `USE EMAIL` first-line parsing.
15741
16967
  *
@@ -18569,9 +19795,9 @@ function createTimeoutSystemMessage(extraInstructions) {
18569
19795
  return spaceTrim$1((block) => `
18570
19796
  Timeout scheduling:
18571
19797
  - Use "set_timeout" to wake this same chat thread in the future.
18572
- - Timers are thread-scoped, not global for the whole agent.
19798
+ - Use "list_timeouts" to review timeouts across all chats for the same user+agent scope.
19799
+ - "cancel_timeout" accepts a timeout id from any chat in this same user+agent scope.
18573
19800
  - 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\`.
18574
- - Use "cancel_timeout" when a previously scheduled timeout is no longer relevant.
18575
19801
  - Do not claim a timer was set or cancelled unless the tool confirms it.
18576
19802
  ${block(extraInstructions)}
18577
19803
  `);
@@ -18632,13 +19858,6 @@ function parseToolExecutionEnvelope(rawValue) {
18632
19858
  * @private internal utility of USE TIMEOUT
18633
19859
  */
18634
19860
  function createDisabledTimeoutResult(action, message) {
18635
- if (action === 'set') {
18636
- return {
18637
- action,
18638
- status: 'disabled',
18639
- message,
18640
- };
18641
- }
18642
19861
  return {
18643
19862
  action,
18644
19863
  status: 'disabled',
@@ -18665,6 +19884,18 @@ function getTimeoutToolRuntimeAdapterOrDisabledResult(action, runtimeContext) {
18665
19884
  }
18666
19885
  }
18667
19886
 
19887
+ /**
19888
+ * Default number of rows returned by `list_timeouts`.
19889
+ *
19890
+ * @private internal USE TIMEOUT constant
19891
+ */
19892
+ const DEFAULT_LIST_TIMEOUTS_LIMIT = 20;
19893
+ /**
19894
+ * Hard cap for `list_timeouts` page size.
19895
+ *
19896
+ * @private internal USE TIMEOUT constant
19897
+ */
19898
+ const MAX_LIST_TIMEOUTS_LIMIT = 100;
18668
19899
  /**
18669
19900
  * Parses and validates `USE TIMEOUT` tool arguments.
18670
19901
  *
@@ -18699,6 +19930,31 @@ const parseTimeoutToolArgs = {
18699
19930
  }
18700
19931
  return { timeoutId };
18701
19932
  },
19933
+ /**
19934
+ * Parses `list_timeouts` input.
19935
+ */
19936
+ list(args) {
19937
+ if (args.includeFinished !== undefined && typeof args.includeFinished !== 'boolean') {
19938
+ throw new PipelineExecutionError(spaceTrim$1(`
19939
+ Timeout \`includeFinished\` must be a boolean when provided.
19940
+ `));
19941
+ }
19942
+ const parsedLimit = args.limit === undefined ? DEFAULT_LIST_TIMEOUTS_LIMIT : Math.floor(Number(args.limit));
19943
+ if (!Number.isFinite(parsedLimit) || parsedLimit <= 0) {
19944
+ throw new PipelineExecutionError(spaceTrim$1(`
19945
+ Timeout \`limit\` must be a positive number.
19946
+ `));
19947
+ }
19948
+ if (parsedLimit > MAX_LIST_TIMEOUTS_LIMIT) {
19949
+ throw new PipelineExecutionError(spaceTrim$1(`
19950
+ Timeout \`limit\` must be at most \`${MAX_LIST_TIMEOUTS_LIMIT}\`.
19951
+ `));
19952
+ }
19953
+ return {
19954
+ includeFinished: args.includeFinished === true,
19955
+ limit: parsedLimit,
19956
+ };
19957
+ },
18702
19958
  };
18703
19959
 
18704
19960
  /**
@@ -18709,6 +19965,7 @@ const parseTimeoutToolArgs = {
18709
19965
  const TimeoutToolNames = {
18710
19966
  set: 'set_timeout',
18711
19967
  cancel: 'cancel_timeout',
19968
+ list: 'list_timeouts',
18712
19969
  };
18713
19970
 
18714
19971
  /**
@@ -18808,6 +20065,35 @@ function createTimeoutToolFunctions() {
18808
20065
  return JSON.stringify(result);
18809
20066
  }
18810
20067
  },
20068
+ async [TimeoutToolNames.list](args) {
20069
+ const runtimeContext = resolveTimeoutRuntimeContext(args);
20070
+ const { adapter, disabledResult } = getTimeoutToolRuntimeAdapterOrDisabledResult('list', runtimeContext);
20071
+ if (!adapter || disabledResult) {
20072
+ return JSON.stringify(disabledResult);
20073
+ }
20074
+ try {
20075
+ const parsedArgs = parseTimeoutToolArgs.list(args);
20076
+ const listedTimeouts = await adapter.listTimeouts(parsedArgs, runtimeContext);
20077
+ const result = {
20078
+ action: 'list',
20079
+ status: 'listed',
20080
+ items: listedTimeouts.items,
20081
+ total: listedTimeouts.total,
20082
+ };
20083
+ return createToolExecutionEnvelope({
20084
+ assistantMessage: listedTimeouts.total === 1 ? 'Found 1 timeout.' : `Found ${listedTimeouts.total} timeouts.`,
20085
+ toolResult: result,
20086
+ });
20087
+ }
20088
+ catch (error) {
20089
+ const result = {
20090
+ action: 'list',
20091
+ status: 'error',
20092
+ message: error instanceof Error ? error.message : String(error),
20093
+ };
20094
+ return JSON.stringify(result);
20095
+ }
20096
+ },
18811
20097
  };
18812
20098
  }
18813
20099
 
@@ -18841,26 +20127,45 @@ function createTimeoutTools(existingTools = []) {
18841
20127
  if (!tools.some((tool) => tool.name === TimeoutToolNames.cancel)) {
18842
20128
  tools.push({
18843
20129
  name: TimeoutToolNames.cancel,
18844
- description: 'Cancel one previously scheduled timeout in the current chat thread.',
20130
+ description: 'Cancel one previously scheduled timeout within the same user+agent scope, even if it was set in another chat.',
18845
20131
  parameters: {
18846
20132
  type: 'object',
18847
20133
  properties: {
18848
20134
  timeoutId: {
18849
20135
  type: 'string',
18850
- description: 'Identifier returned earlier by `set_timeout`.',
20136
+ description: 'Identifier returned earlier by `set_timeout` or `list_timeouts`.',
18851
20137
  },
18852
20138
  },
18853
20139
  required: ['timeoutId'],
18854
20140
  },
18855
20141
  });
18856
20142
  }
20143
+ if (!tools.some((tool) => tool.name === TimeoutToolNames.list)) {
20144
+ tools.push({
20145
+ name: TimeoutToolNames.list,
20146
+ description: 'List scheduled timeouts across all chats for this same user+agent scope so they can be reviewed or cancelled.',
20147
+ parameters: {
20148
+ type: 'object',
20149
+ properties: {
20150
+ includeFinished: {
20151
+ type: 'boolean',
20152
+ description: 'When true, include completed, failed, and cancelled rows in addition to active timeouts.',
20153
+ },
20154
+ limit: {
20155
+ type: 'number',
20156
+ description: 'Maximum number of rows to return (default 20, max 100).',
20157
+ },
20158
+ },
20159
+ },
20160
+ });
20161
+ }
18857
20162
  return tools;
18858
20163
  }
18859
20164
 
18860
20165
  /**
18861
20166
  * `USE TIMEOUT` commitment definition.
18862
20167
  *
18863
- * The `USE TIMEOUT` commitment enables thread-scoped timers that wake the same chat later.
20168
+ * The `USE TIMEOUT` commitment enables timeout wake-ups and scoped timeout management.
18864
20169
  *
18865
20170
  * @private [🪔] Maybe export the commitments through some package
18866
20171
  */
@@ -18875,7 +20180,7 @@ class UseTimeoutCommitmentDefinition extends BaseCommitmentDefinition {
18875
20180
  * Short one-line description of `USE TIMEOUT`.
18876
20181
  */
18877
20182
  get description() {
18878
- return 'Enable thread-scoped timers that can wake the same chat in the future.';
20183
+ return 'Enable timeout wake-ups plus scoped timeout listing/cancellation across chats.';
18879
20184
  }
18880
20185
  /**
18881
20186
  * Icon for this commitment.
@@ -18890,14 +20195,15 @@ class UseTimeoutCommitmentDefinition extends BaseCommitmentDefinition {
18890
20195
  return spaceTrim$1(`
18891
20196
  # USE TIMEOUT
18892
20197
 
18893
- Enables the agent to schedule thread-scoped timeout wake-ups.
20198
+ Enables timeout wake-ups and timeout management for the same user+agent scope.
18894
20199
 
18895
20200
  ## Key aspects
18896
20201
 
18897
20202
  - The agent uses \`set_timeout\` to schedule a future wake-up in the same chat thread.
18898
20203
  - The tool returns immediately while the timeout is stored and executed by the runtime later.
18899
20204
  - The wake-up arrives as a new user-like timeout message in the same conversation.
18900
- - The agent can cancel an existing timeout by \`timeoutId\` via \`cancel_timeout\`.
20205
+ - The agent can inspect known timeouts via \`list_timeouts\`.
20206
+ - The agent can cancel an existing timeout by \`timeoutId\` via \`cancel_timeout\`, including timeouts created in another chat.
18901
20207
  - Commitment content is treated as optional timeout policy instructions.
18902
20208
 
18903
20209
  ## Examples
@@ -18926,6 +20232,7 @@ class UseTimeoutCommitmentDefinition extends BaseCommitmentDefinition {
18926
20232
  return {
18927
20233
  [TimeoutToolNames.set]: 'Set timer',
18928
20234
  [TimeoutToolNames.cancel]: 'Cancel timer',
20235
+ [TimeoutToolNames.list]: 'List timers',
18929
20236
  };
18930
20237
  }
18931
20238
  /**
@@ -19603,6 +20910,7 @@ const COMMITMENT_REGISTRY = [
19603
20910
  new UseTimeoutCommitmentDefinition(),
19604
20911
  new UseTimeCommitmentDefinition(),
19605
20912
  new UseUserLocationCommitmentDefinition(),
20913
+ new UseCalendarCommitmentDefinition(),
19606
20914
  new UseEmailCommitmentDefinition(),
19607
20915
  new UsePopupCommitmentDefinition(),
19608
20916
  new UseImageGeneratorCommitmentDefinition('USE IMAGE GENERATOR'),
@@ -20494,6 +21802,14 @@ function parseAgentSource(agentSource) {
20494
21802
  });
20495
21803
  continue;
20496
21804
  }
21805
+ if (commitment.type === 'USE CALENDAR') {
21806
+ capabilities.push({
21807
+ type: 'calendar',
21808
+ label: 'Calendar',
21809
+ iconName: 'Calendar',
21810
+ });
21811
+ continue;
21812
+ }
20497
21813
  if (commitment.type === 'FROM') {
20498
21814
  const content = spaceTrim$2(commitment.content).split(/\r?\n/)[0] || '';
20499
21815
  if (content === 'Adam' || content === '' /* <- Note: Adam is implicit */) {