@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.
- package/esm/index.es.js +1332 -16
- package/esm/index.es.js.map +1 -1
- package/esm/src/book-2.0/agent-source/AgentBasicInformation.d.ts +1 -1
- package/esm/src/book-components/Chat/Chat/ChatToolCallModal.test.d.ts +2 -0
- package/esm/src/book-components/Chat/Chat/renderToolCallDetails.d.ts +4 -0
- package/esm/src/book-components/Chat/utils/getToolCallChipletInfo.timeout.test.d.ts +1 -0
- package/esm/src/book-components/Chat/utils/timeoutToolCallPresentation.d.ts +123 -0
- package/esm/src/book-components/Chat/utils/timeoutToolCallPresentation.test.d.ts +1 -0
- package/esm/src/commitments/USE_BROWSER/resolveRunBrowserToolForNode.d.ts +1 -1
- package/esm/src/commitments/USE_CALENDAR/USE_CALENDAR.d.ts +42 -0
- package/esm/src/commitments/USE_CALENDAR/USE_CALENDAR.test.d.ts +1 -0
- package/esm/src/commitments/USE_CALENDAR/UseCalendarToolNames.d.ts +13 -0
- package/esm/src/commitments/USE_CALENDAR/UseCalendarWallet.d.ts +9 -0
- package/esm/src/commitments/USE_CALENDAR/calendarReference.d.ts +68 -0
- package/esm/src/commitments/USE_CALENDAR/callGoogleCalendarApi.d.ts +19 -0
- package/esm/src/commitments/USE_CALENDAR/createUseCalendarToolFunctions.d.ts +8 -0
- package/esm/src/commitments/USE_CALENDAR/createUseCalendarTools.d.ts +7 -0
- package/esm/src/commitments/USE_CALENDAR/getUseCalendarToolTitles.d.ts +7 -0
- package/esm/src/commitments/USE_CALENDAR/normalizeConfiguredCalendars.d.ts +19 -0
- package/esm/src/commitments/USE_CALENDAR/resolveUseCalendarToolRuntimeOrWalletCredentialResult.d.ts +34 -0
- package/esm/src/commitments/USE_TIMEOUT/TimeoutToolNames.d.ts +1 -0
- package/esm/src/commitments/USE_TIMEOUT/TimeoutToolRuntimeAdapter.d.ts +51 -2
- package/esm/src/commitments/USE_TIMEOUT/USE_TIMEOUT.d.ts +2 -2
- package/esm/src/commitments/USE_TIMEOUT/getTimeoutToolRuntimeAdapterOrDisabledResult.d.ts +2 -2
- package/esm/src/commitments/USE_TIMEOUT/parseTimeoutToolArgs.d.ts +14 -1
- package/esm/src/commitments/_common/toolRuntimeContext.d.ts +9 -0
- package/esm/src/commitments/index.d.ts +2 -1
- package/esm/src/executables/apps/locateVscode.d.ts +7 -0
- package/esm/src/executables/apps/locateVscode.test.d.ts +1 -0
- package/esm/src/executables/browsers/locateBrowser.d.ts +10 -0
- package/esm/src/executables/browsers/locateBrowser.test.d.ts +1 -0
- package/esm/src/executables/browsers/locateChrome.d.ts +7 -0
- package/esm/src/executables/browsers/locateChrome.test.d.ts +1 -0
- package/esm/src/executables/browsers/locateDefaultSystemBrowser.d.ts +10 -0
- package/esm/src/executables/browsers/locateDefaultSystemBrowser.test.d.ts +1 -0
- package/esm/src/executables/browsers/locateEdge.d.ts +7 -0
- package/esm/src/executables/browsers/locateEdge.test.d.ts +1 -0
- package/esm/src/executables/browsers/locateFirefox.d.ts +7 -0
- package/esm/src/executables/browsers/locateFirefox.test.d.ts +1 -0
- package/esm/src/executables/browsers/locateInternetExplorer.d.ts +7 -0
- package/esm/src/executables/browsers/locateInternetExplorer.test.d.ts +1 -0
- package/esm/src/executables/browsers/locateSafari.d.ts +7 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +1332 -16
- package/umd/index.umd.js.map +1 -1
- package/umd/src/book-2.0/agent-source/AgentBasicInformation.d.ts +1 -1
- package/umd/src/book-components/Chat/Chat/ChatToolCallModal.test.d.ts +2 -0
- package/umd/src/book-components/Chat/Chat/renderToolCallDetails.d.ts +4 -0
- package/umd/src/book-components/Chat/utils/getToolCallChipletInfo.timeout.test.d.ts +1 -0
- package/umd/src/book-components/Chat/utils/timeoutToolCallPresentation.d.ts +123 -0
- package/umd/src/book-components/Chat/utils/timeoutToolCallPresentation.test.d.ts +1 -0
- package/umd/src/commitments/USE_BROWSER/resolveRunBrowserToolForNode.d.ts +1 -1
- package/umd/src/commitments/USE_CALENDAR/USE_CALENDAR.d.ts +42 -0
- package/umd/src/commitments/USE_CALENDAR/USE_CALENDAR.test.d.ts +1 -0
- package/umd/src/commitments/USE_CALENDAR/UseCalendarToolNames.d.ts +13 -0
- package/umd/src/commitments/USE_CALENDAR/UseCalendarWallet.d.ts +9 -0
- package/umd/src/commitments/USE_CALENDAR/calendarReference.d.ts +68 -0
- package/umd/src/commitments/USE_CALENDAR/callGoogleCalendarApi.d.ts +19 -0
- package/umd/src/commitments/USE_CALENDAR/createUseCalendarToolFunctions.d.ts +8 -0
- package/umd/src/commitments/USE_CALENDAR/createUseCalendarTools.d.ts +7 -0
- package/umd/src/commitments/USE_CALENDAR/getUseCalendarToolTitles.d.ts +7 -0
- package/umd/src/commitments/USE_CALENDAR/normalizeConfiguredCalendars.d.ts +19 -0
- package/umd/src/commitments/USE_CALENDAR/resolveUseCalendarToolRuntimeOrWalletCredentialResult.d.ts +34 -0
- package/umd/src/commitments/USE_TIMEOUT/TimeoutToolNames.d.ts +1 -0
- package/umd/src/commitments/USE_TIMEOUT/TimeoutToolRuntimeAdapter.d.ts +51 -2
- package/umd/src/commitments/USE_TIMEOUT/USE_TIMEOUT.d.ts +2 -2
- package/umd/src/commitments/USE_TIMEOUT/getTimeoutToolRuntimeAdapterOrDisabledResult.d.ts +2 -2
- package/umd/src/commitments/USE_TIMEOUT/parseTimeoutToolArgs.d.ts +14 -1
- package/umd/src/commitments/_common/toolRuntimeContext.d.ts +9 -0
- package/umd/src/commitments/index.d.ts +2 -1
- package/umd/src/executables/apps/locateVscode.d.ts +7 -0
- package/umd/src/executables/apps/locateVscode.test.d.ts +1 -0
- package/umd/src/executables/browsers/locateBrowser.d.ts +10 -0
- package/umd/src/executables/browsers/locateBrowser.test.d.ts +1 -0
- package/umd/src/executables/browsers/locateChrome.d.ts +7 -0
- package/umd/src/executables/browsers/locateChrome.test.d.ts +1 -0
- package/umd/src/executables/browsers/locateDefaultSystemBrowser.d.ts +10 -0
- package/umd/src/executables/browsers/locateDefaultSystemBrowser.test.d.ts +1 -0
- package/umd/src/executables/browsers/locateEdge.d.ts +7 -0
- package/umd/src/executables/browsers/locateEdge.test.d.ts +1 -0
- package/umd/src/executables/browsers/locateFirefox.d.ts +7 -0
- package/umd/src/executables/browsers/locateFirefox.test.d.ts +1 -0
- package/umd/src/executables/browsers/locateInternetExplorer.d.ts +7 -0
- package/umd/src/executables/browsers/locateInternetExplorer.test.d.ts +1 -0
- package/umd/src/executables/browsers/locateSafari.d.ts +7 -0
- 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-
|
|
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
|
-
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 */) {
|