@chibitek/chibi 0.1.173 → 0.1.174
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/dist/assets/{abnfDiagram-O67JEVCF-DaA9WpZw.js → abnfDiagram-O67JEVCF-BVDndX1g.js} +1 -1
- package/dist/assets/{arc-DJ4Kdvv6.js → arc-WduS6wYB.js} +1 -1
- package/dist/assets/{architectureDiagram-NJMV4G6O-B975BUTv.js → architectureDiagram-NJMV4G6O-CYK9LkCf.js} +1 -1
- package/dist/assets/{blockDiagram-BEXU5L5S-CXOOfLy7.js → blockDiagram-BEXU5L5S-BMj-aPW9.js} +1 -1
- package/dist/assets/{c4Diagram-YGBWAQC7-CorqQ94E.js → c4Diagram-YGBWAQC7-cXYIStgL.js} +1 -1
- package/dist/assets/channel-TratrwmM.js +1 -0
- package/dist/assets/{chunk-2Q5K7J3B-CPFHpKez.js → chunk-2Q5K7J3B-CZ_nCppA.js} +1 -1
- package/dist/assets/{chunk-3FUC2YCW-CrzBuB3A.js → chunk-3FUC2YCW-C3wRAbtM.js} +2 -2
- package/dist/assets/{chunk-5VM5RSS4-DXJTBdvO.js → chunk-5VM5RSS4-CMvgOXJP.js} +1 -1
- package/dist/assets/{chunk-GTNCS2PH-B0TxALG4.js → chunk-GTNCS2PH-9wBuLQzU.js} +1 -1
- package/dist/assets/{chunk-GWA4HPMP-BL44uVOP.js → chunk-GWA4HPMP-BpJMmfAi.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-CxSklH7P.js → chunk-JWPE2WC7-BnM06ABv.js} +1 -1
- package/dist/assets/{chunk-NETBCI7D-_Lb-D8AY.js → chunk-NETBCI7D-CjjiiXiT.js} +1 -1
- package/dist/assets/{chunk-WEXAMYUT-Dz5jp0xb.js → chunk-WEXAMYUT-D3heHHZs.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-C-cd9N0r.js → chunk-XXDRQBXY-n_P41ZlM.js} +1 -1
- package/dist/assets/{classDiagram-v2-NBCMYWYE-DtQ1781-.js → classDiagram-v2-NBCMYWYE-Dz60Ek-6.js} +1 -1
- package/dist/assets/{cose-bilkent-JH36ORCC-CHzWXNdH.js → cose-bilkent-JH36ORCC-BCt6vBi9.js} +1 -1
- package/dist/assets/{cynefin-OW5HDTMX-lHbKcf1S.js → cynefin-OW5HDTMX-U0uq4EAQ.js} +1 -1
- package/dist/assets/{cynefinDiagram-VND7K2PF-BxY6MCKD.js → cynefinDiagram-VND7K2PF-CaQX0eUJ.js} +1 -1
- package/dist/assets/{dagre-6A5THRUB-C2SBw-Mo.js → dagre-6A5THRUB-DlCMESYH.js} +1 -1
- package/dist/assets/{diagram-22UHCM2B-BwIAlmAU.js → diagram-22UHCM2B-Cl1xmlTD.js} +1 -1
- package/dist/assets/{diagram-3UASUU5V-i6fBkckD.js → diagram-3UASUU5V-Cus3CPg7.js} +1 -1
- package/dist/assets/{diagram-ATOU4E4O-DwedCbB_.js → diagram-ATOU4E4O-i06rMvae.js} +1 -1
- package/dist/assets/{diagram-CDSNMT55-BISF-AQC.js → diagram-CDSNMT55-CUM5_heN.js} +1 -1
- package/dist/assets/{diagram-MLGK6HIB-ImgdRRxp.js → diagram-MLGK6HIB-B5NKRruo.js} +1 -1
- package/dist/assets/{diagram-MPIPVDR6-CxlAwPCS.js → diagram-MPIPVDR6-CAumAcGl.js} +1 -1
- package/dist/assets/{ebnfDiagram-ZINNZB2B-sVJkymKa.js → ebnfDiagram-ZINNZB2B-B19d7d8l.js} +1 -1
- package/dist/assets/{elk-276RUBZZ-DU1vyX4w.js → elk-276RUBZZ-NJEpfRWi.js} +1 -1
- package/dist/assets/{erDiagram-OPXOYQCR-CnCmL1Ve.js → erDiagram-OPXOYQCR-BExk6CHc.js} +1 -1
- package/dist/assets/{flowDiagram-KWPJA3E3-DME2uLJf.js → flowDiagram-KWPJA3E3-ClExQ_p0.js} +1 -1
- package/dist/assets/{ganttDiagram-FUAMR5RP-CJQNW9ts.js → ganttDiagram-FUAMR5RP-1MeM9sSl.js} +1 -1
- package/dist/assets/{gitGraphDiagram-X574FWY7-D88_Y9tg.js → gitGraphDiagram-X574FWY7-Tw9Dudpa.js} +1 -1
- package/dist/assets/{index-U9LN4GhF.js → index-KYHldywn.js} +3 -3
- package/dist/assets/{index-ChmZZe7i.js → index-qsorLr2x.js} +1 -1
- package/dist/assets/{infoDiagram-VRGFBTTK-CxWEf3NI.js → infoDiagram-VRGFBTTK-ChU2tjvl.js} +1 -1
- package/dist/assets/{ishikawaDiagram-OU5B5YK6-B_YoNVjF.js → ishikawaDiagram-OU5B5YK6-BeTbrX2Q.js} +1 -1
- package/dist/assets/{journeyDiagram-ZHPQQLJL-ZYuBE2Bm.js → journeyDiagram-ZHPQQLJL-B7ijaWBD.js} +1 -1
- package/dist/assets/{kanban-definition-PNTS6WVX-jmY_M4Qf.js → kanban-definition-PNTS6WVX-JBmK2F1r.js} +1 -1
- package/dist/assets/{linear-kKUF6ayN.js → linear-B7FXe3Ue.js} +1 -1
- package/dist/assets/{mermaid.core-DC5051S_.js → mermaid.core-BPlfZpqv.js} +5 -5
- package/dist/assets/{mindmap-definition-NLK3R4M7-C5knfygJ.js → mindmap-definition-NLK3R4M7-CmT3S5QR.js} +1 -1
- package/dist/assets/{pegDiagram-GJSIUBJH-Ex6iedL2.js → pegDiagram-GJSIUBJH-CFFHIcdQ.js} +1 -1
- package/dist/assets/{pieDiagram-5QR66LMP-Dv38Ox0D.js → pieDiagram-5QR66LMP-yTiPmXRV.js} +1 -1
- package/dist/assets/{quadrantDiagram-O4NWA36T-CwOEor8N.js → quadrantDiagram-O4NWA36T-Cw8u7esm.js} +1 -1
- package/dist/assets/{railroadDiagram-XR7U4H2S-DVgqz5MR.js → railroadDiagram-XR7U4H2S-BfKggsOW.js} +1 -1
- package/dist/assets/{requirementDiagram-PLB6GJNP-BxiuYo52.js → requirementDiagram-PLB6GJNP-Cf3n79jF.js} +1 -1
- package/dist/assets/{sankeyDiagram-IPEJSGJF--vq_1flP.js → sankeyDiagram-IPEJSGJF-B2NkSZig.js} +1 -1
- package/dist/assets/{sequenceDiagram-PO4LG4MO-9hLpfPA6.js → sequenceDiagram-PO4LG4MO-BfFYiYK3.js} +1 -1
- package/dist/assets/{sizeCapture-INFHLROL-BeGMkj9s.js → sizeCapture-INFHLROL-CZ_2nC3f.js} +1 -1
- package/dist/assets/{stateDiagram-v2-GCMORJYK-BnNOMugb.js → stateDiagram-v2-GCMORJYK-B9jwzMXf.js} +1 -1
- package/dist/assets/{swimlanes-2SLR337P-C1YG6Jq-.js → swimlanes-2SLR337P-Bxhafu77.js} +1 -1
- package/dist/assets/swimlanesDiagram-TC7HE7FX-DWNGCaH3.js +8 -0
- package/dist/assets/{timeline-definition-EJHVYXUP-Co7OtwGA.js → timeline-definition-EJHVYXUP-Dle5SJls.js} +1 -1
- package/dist/assets/{usecaseDiagram-POWQR4AR-BYHFARv3.js → usecaseDiagram-POWQR4AR-CgRTu9EO.js} +1 -1
- package/dist/assets/{vennDiagram-UO4OBE2U-C-sdhL3h.js → vennDiagram-UO4OBE2U-D7m_1z6B.js} +1 -1
- package/dist/assets/{wardleyDiagram-VNRHLVJA-wf8ZNrmQ.js → wardleyDiagram-VNRHLVJA-7-TzmX4L.js} +1 -1
- package/dist/assets/{xychartDiagram-PMCCYNJV-BjRlkVGv.js → xychartDiagram-PMCCYNJV-BVXXdviS.js} +1 -1
- package/dist/index.html +1 -1
- package/dist-server/index.js +645 -327
- package/dist-server/openmausbot.js +2 -2
- package/dist-server/pair-cli.js +2 -2
- package/dist-server/server/dictation.js +8 -0
- package/dist-server/server/drivers/claude.js +4 -4
- package/dist-server/server/oauth-account-core.js +153 -0
- package/dist-server/server/oauth-account-tools.js +7 -348
- package/dist-server/server/oauth-calendar-tools.js +551 -0
- package/dist-server/shared/oauth-providers.js +2 -1
- package/package.json +1 -1
- package/dist/assets/channel-sBYHnjxz.js +0 -1
- package/dist/assets/swimlanesDiagram-TC7HE7FX-9DghUs7S.js +0 -8
package/dist-server/index.js
CHANGED
|
@@ -7780,10 +7780,10 @@ var require_formats = __commonJS({
|
|
|
7780
7780
|
function isLeapYear(year) {
|
|
7781
7781
|
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
7782
7782
|
}
|
|
7783
|
-
var
|
|
7783
|
+
var DATE2 = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
|
|
7784
7784
|
var DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
7785
7785
|
function date5(str5) {
|
|
7786
|
-
const matches2 =
|
|
7786
|
+
const matches2 = DATE2.exec(str5);
|
|
7787
7787
|
if (!matches2)
|
|
7788
7788
|
return false;
|
|
7789
7789
|
const year = +matches2[1];
|
|
@@ -38281,8 +38281,8 @@ function autoCompactWindow(env) {
|
|
|
38281
38281
|
var DEFAULT_AUTOCOMPACT_TOKENS = 2e5;
|
|
38282
38282
|
var CLAUDE_FLAG_FLOORS = {
|
|
38283
38283
|
"--strict-mcp-config": [1, 0, 60],
|
|
38284
|
-
"--setting-sources": [1, 0,
|
|
38285
|
-
"--autocompact": [2, 1,
|
|
38284
|
+
"--setting-sources": [1, 0, 125],
|
|
38285
|
+
"--autocompact": [2, 1, 221],
|
|
38286
38286
|
// 2.1.267 is the first CLI that accepts it; below that the recorded prompt
|
|
38287
38287
|
// simply is not refreshed, which is the pre-existing behaviour.
|
|
38288
38288
|
"--system-prompt-snapshot": [2, 1, 267],
|
|
@@ -54342,8 +54342,8 @@ var McpHealthStore = class {
|
|
|
54342
54342
|
const entry = this.entry(name2, spec);
|
|
54343
54343
|
if (!entry) return void 0;
|
|
54344
54344
|
const what = entry.kind === "crashed" ? "stopped working during a bot's turn" : "would not start";
|
|
54345
|
-
const
|
|
54346
|
-
return `This server ${what}, so bots are working without it for now. ${
|
|
54345
|
+
const when2 = this.now() >= entry.retryAt ? "Atomic tries it again on the next turn." : `Atomic tries it again at ${formatTime(entry.retryAt)}.`;
|
|
54346
|
+
return `This server ${what}, so bots are working without it for now. ${when2} Check its command and settings if this keeps happening.`;
|
|
54347
54347
|
}
|
|
54348
54348
|
/** Why a server is left out of turns right now, or undefined when it mounts. */
|
|
54349
54349
|
unavailableKind(name2, spec) {
|
|
@@ -92669,7 +92669,7 @@ Name: ${name2}`,
|
|
|
92669
92669
|
}
|
|
92670
92670
|
const nextRunAt = nextForOperation(operation, manager, now);
|
|
92671
92671
|
const scheduleTimeZone = definition2.schedule.type === "cron" ? definition2.schedule.timeZone : timeZone;
|
|
92672
|
-
const
|
|
92672
|
+
const when2 = operation.action === "run_now" ? "Now" : scheduleText(definition2.schedule, timeZone);
|
|
92673
92673
|
const destination = definition2.runOn === "cloud" ? "Box-hosted agent" : "Bot\u2019s current model and configured computer";
|
|
92674
92674
|
const current4 = operation.action === "create" ? null : manager.listRoutines().find((routine) => routine.id === operation.routineId) ?? null;
|
|
92675
92675
|
const remainsPaused = operation.action === "update" && current4?.enabled === false;
|
|
@@ -92681,12 +92681,12 @@ Name: ${name2}`,
|
|
|
92681
92681
|
const runLimit = definition2.timeoutMinutes === void 0 ? "no run limit" : `${definition2.timeoutMinutes} min limit`;
|
|
92682
92682
|
return {
|
|
92683
92683
|
title,
|
|
92684
|
-
summary: `${actionLabel} \u201C${name2}\u201D${forSuffix} \xB7 ${
|
|
92684
|
+
summary: `${actionLabel} \u201C${name2}\u201D${forSuffix} \xB7 ${when2} \xB7 ${destination} \xB7 ${runLimit}${status}`,
|
|
92685
92685
|
detail: [
|
|
92686
92686
|
`Action: ${actionCopy.detail}`,
|
|
92687
92687
|
`Name: ${name2}`,
|
|
92688
92688
|
...forBot ? [`For: @${redactSecretsInText(forBot.name)} \u2014 each run uses that bot's engine and permissions`] : [],
|
|
92689
|
-
`Schedule: ${
|
|
92689
|
+
`Schedule: ${when2}`,
|
|
92690
92690
|
`Next run: ${nextDescription}`,
|
|
92691
92691
|
...definition2.schedule.type === "cron" && nextRunAt !== null && operation.action !== "run_now" ? [`Next 3 runs (${scheduleTimeZone}): ${nextCronRuns(definition2.schedule, now, 3).map((at2) => formatInstant(at2, scheduleTimeZone)).join(" \xB7 ")}`] : [],
|
|
92692
92692
|
`Runs on: ${destination}`,
|
|
@@ -93229,12 +93229,12 @@ function taskDescription(routine, bot, timeZone) {
|
|
|
93229
93229
|
].join("\n");
|
|
93230
93230
|
}
|
|
93231
93231
|
function runComment(run7) {
|
|
93232
|
-
const
|
|
93232
|
+
const when2 = new Date(run7.finishedAt ?? run7.scheduledFor).toISOString();
|
|
93233
93233
|
const body = (run7.status === "failed" ? run7.error ?? run7.output : run7.output ?? run7.error)?.trim();
|
|
93234
93234
|
const clipped = body && body.length > MAX_COMMENT_CHARS ? `${body.slice(0, MAX_COMMENT_CHARS)}
|
|
93235
93235
|
|
|
93236
93236
|
(cut short; the full report is in Atomic)` : body;
|
|
93237
|
-
return `Run ${run7.status} \xB7 ${
|
|
93237
|
+
return `Run ${run7.status} \xB7 ${when2}${run7.manual ? " \xB7 started by hand" : ""}${clipped ? `
|
|
93238
93238
|
|
|
93239
93239
|
${clipped}` : ""}`;
|
|
93240
93240
|
}
|
|
@@ -113328,6 +113328,632 @@ function installNativeVault(dataDir2, port, desktopToken, fromBot) {
|
|
|
113328
113328
|
ROUTES.push(createVaultRoutes({ store: () => runtime.store(), owner: (req, auth) => fromBot(req) ? null : runtime.owner(req, auth, desktopToken()) }));
|
|
113329
113329
|
}
|
|
113330
113330
|
|
|
113331
|
+
// server/oauth-account-core.ts
|
|
113332
|
+
var HTTP_TIMEOUT_MS2 = 3e4;
|
|
113333
|
+
var MAX_RESULT_CHARS = 48e3;
|
|
113334
|
+
var MAX_JSON_BYTES = 4 * 1024 * 1024;
|
|
113335
|
+
var MAX_DOWNLOAD_BYTES = 8 * 1024 * 1024;
|
|
113336
|
+
var READS = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true };
|
|
113337
|
+
var CREATES = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true };
|
|
113338
|
+
var SENDS = { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true };
|
|
113339
|
+
var accountArg = { type: "string", description: "Email address of the account to use. Optional only when this bot has exactly one account of this provider." };
|
|
113340
|
+
var EMAIL2 = /^[^\s@<>,;"]+@[^\s@<>,;"]+\.[^\s@<>,;"]+$/;
|
|
113341
|
+
var noNewlines = (value) => !/[\r\n]/.test(value);
|
|
113342
|
+
var base4 = external_exports.object({ account: external_exports.string().max(320).optional() });
|
|
113343
|
+
var ToolInputError = class extends Error {
|
|
113344
|
+
};
|
|
113345
|
+
function bounded2(text17, limit = MAX_RESULT_CHARS) {
|
|
113346
|
+
return text17.length <= limit ? text17 : `${text17.slice(0, limit)}
|
|
113347
|
+
[truncated: ask for less]`;
|
|
113348
|
+
}
|
|
113349
|
+
function addresses(value, field) {
|
|
113350
|
+
if (value === void 0) return [];
|
|
113351
|
+
const list3 = (Array.isArray(value) ? value : value.split(",")).map((item) => item.trim()).filter(Boolean);
|
|
113352
|
+
if (list3.length > 50) throw new ToolInputError(`${field}: at most 50 addresses`);
|
|
113353
|
+
for (const item of list3) {
|
|
113354
|
+
if (!EMAIL2.test(item)) throw new ToolInputError(`${field}: "${item.slice(0, 80)}" is not an email address`);
|
|
113355
|
+
}
|
|
113356
|
+
return list3;
|
|
113357
|
+
}
|
|
113358
|
+
var ProviderApiError = class extends Error {
|
|
113359
|
+
status;
|
|
113360
|
+
constructor(status, message4) {
|
|
113361
|
+
super(message4);
|
|
113362
|
+
this.status = status;
|
|
113363
|
+
}
|
|
113364
|
+
};
|
|
113365
|
+
async function readLimited(response, limit) {
|
|
113366
|
+
const declared = Number(response.headers.get("content-length") ?? "0");
|
|
113367
|
+
if (declared > limit) {
|
|
113368
|
+
await response.body?.cancel().catch(() => {
|
|
113369
|
+
});
|
|
113370
|
+
return null;
|
|
113371
|
+
}
|
|
113372
|
+
if (!response.body) return Buffer.alloc(0);
|
|
113373
|
+
const reader = response.body.getReader();
|
|
113374
|
+
const chunks = [];
|
|
113375
|
+
let size = 0;
|
|
113376
|
+
for (; ; ) {
|
|
113377
|
+
const { done, value } = await reader.read();
|
|
113378
|
+
if (done) break;
|
|
113379
|
+
size += value.byteLength;
|
|
113380
|
+
if (size > limit) {
|
|
113381
|
+
await reader.cancel().catch(() => {
|
|
113382
|
+
});
|
|
113383
|
+
return null;
|
|
113384
|
+
}
|
|
113385
|
+
chunks.push(value);
|
|
113386
|
+
}
|
|
113387
|
+
return Buffer.concat(chunks);
|
|
113388
|
+
}
|
|
113389
|
+
function providerErrorMessage(body, status) {
|
|
113390
|
+
const error51 = body?.error;
|
|
113391
|
+
const message4 = typeof error51 === "string" ? error51 : error51 && typeof error51 === "object" && typeof error51.message === "string" ? error51.message : "";
|
|
113392
|
+
return (message4 || `request failed with HTTP ${status}`).split(/\r?\n/)[0].slice(0, 300);
|
|
113393
|
+
}
|
|
113394
|
+
async function call(ctx, account2, url2, init) {
|
|
113395
|
+
const fetcher = ctx.fetch ?? fetch;
|
|
113396
|
+
const { expect, ...request4 } = init;
|
|
113397
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
113398
|
+
const token = await ctx.accessToken(account2.id);
|
|
113399
|
+
const headers = new Headers(request4.headers);
|
|
113400
|
+
headers.set("authorization", `Bearer ${token}`);
|
|
113401
|
+
if (!headers.has("accept") && expect === "json") headers.set("accept", "application/json");
|
|
113402
|
+
const response = await fetcher(url2, { ...request4, headers, signal: AbortSignal.timeout(HTTP_TIMEOUT_MS2) });
|
|
113403
|
+
if (response.status === 401 && attempt === 0) {
|
|
113404
|
+
await response.body?.cancel().catch(() => {
|
|
113405
|
+
});
|
|
113406
|
+
ctx.invalidate(account2.id);
|
|
113407
|
+
continue;
|
|
113408
|
+
}
|
|
113409
|
+
if (!response.ok) {
|
|
113410
|
+
const raw = await readLimited(response, 64 * 1024);
|
|
113411
|
+
let body = null;
|
|
113412
|
+
try {
|
|
113413
|
+
body = raw ? JSON.parse(raw.toString("utf8")) : null;
|
|
113414
|
+
} catch {
|
|
113415
|
+
body = null;
|
|
113416
|
+
}
|
|
113417
|
+
const message4 = providerErrorMessage(body, response.status);
|
|
113418
|
+
if (response.status === 403) throw new ProviderApiError(403, `${account2.email} does not allow this: ${message4}`);
|
|
113419
|
+
if (response.status === 404) throw new ProviderApiError(404, `Not found in ${account2.email}: ${message4}`);
|
|
113420
|
+
throw new ProviderApiError(response.status, `${OAUTH_PROVIDERS[account2.provider].label} refused the request for ${account2.email}: ${message4}`);
|
|
113421
|
+
}
|
|
113422
|
+
if (expect === "none") {
|
|
113423
|
+
await response.body?.cancel().catch(() => {
|
|
113424
|
+
});
|
|
113425
|
+
return void 0;
|
|
113426
|
+
}
|
|
113427
|
+
const bytes2 = await readLimited(response, expect === "json" ? MAX_JSON_BYTES : MAX_DOWNLOAD_BYTES);
|
|
113428
|
+
if (expect === "bytes") return bytes2;
|
|
113429
|
+
if (!bytes2) throw new ProviderApiError(502, "The response was too large");
|
|
113430
|
+
try {
|
|
113431
|
+
return JSON.parse(bytes2.toString("utf8"));
|
|
113432
|
+
} catch {
|
|
113433
|
+
throw new ProviderApiError(502, "The service returned an unreadable response");
|
|
113434
|
+
}
|
|
113435
|
+
}
|
|
113436
|
+
throw new ProviderApiError(401, `${account2.email} needs to sign in again: open Settings \u2192 Accounts and connect it again.`);
|
|
113437
|
+
}
|
|
113438
|
+
function parse7(schema5, value, what) {
|
|
113439
|
+
const parsed = schema5.safeParse(value);
|
|
113440
|
+
if (!parsed.success) throw new ProviderApiError(502, `Unexpected ${what} response`);
|
|
113441
|
+
return parsed.data;
|
|
113442
|
+
}
|
|
113443
|
+
function json4(value) {
|
|
113444
|
+
return JSON.stringify(value, null, 1);
|
|
113445
|
+
}
|
|
113446
|
+
function htmlToText(html) {
|
|
113447
|
+
return html.replace(/<(script|style)[\s\S]*?<\/\1>/gi, "").replace(/<br\s*\/?>/gi, "\n").replace(/<\/(p|div|tr|li|h\d)>/gi, "\n").replace(/<[^>]+>/g, "").replace(/ /g, " ").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/\n{3,}/g, "\n\n").trim();
|
|
113448
|
+
}
|
|
113449
|
+
var GRAPH = "https://graph.microsoft.com/v1.0";
|
|
113450
|
+
var graphRecipient = external_exports.object({ emailAddress: external_exports.object({ address: external_exports.string().optional(), name: external_exports.string().optional() }).optional() });
|
|
113451
|
+
function recipient(value) {
|
|
113452
|
+
const address2 = value?.emailAddress?.address;
|
|
113453
|
+
const name2 = value?.emailAddress?.name;
|
|
113454
|
+
return address2 ? name2 && name2 !== address2 ? `${name2} <${address2}>` : address2 : void 0;
|
|
113455
|
+
}
|
|
113456
|
+
|
|
113457
|
+
// server/oauth-calendar-tools.ts
|
|
113458
|
+
var CALENDAR = "https://www.googleapis.com/calendar/v3";
|
|
113459
|
+
function isoInstant(value) {
|
|
113460
|
+
return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})$/.test(value) && Number.isFinite(Date.parse(value));
|
|
113461
|
+
}
|
|
113462
|
+
function isoDateOrTime(value) {
|
|
113463
|
+
return /^\d{4}-\d{2}-\d{2}$/.test(value) || /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})?$/.test(value);
|
|
113464
|
+
}
|
|
113465
|
+
var listEventsArgs = base4.extend({
|
|
113466
|
+
timeMin: external_exports.string().refine(isoInstant, "timeMin must be an ISO 8601 date-time with a time zone, e.g. 2026-10-01T00:00:00Z"),
|
|
113467
|
+
timeMax: external_exports.string().refine(isoInstant, "timeMax must be an ISO 8601 date-time with a time zone, e.g. 2026-10-08T00:00:00Z"),
|
|
113468
|
+
calendarId: external_exports.string().min(1).max(320).optional(),
|
|
113469
|
+
max: external_exports.number().int().min(1).max(100).optional()
|
|
113470
|
+
}).strict();
|
|
113471
|
+
var createEventArgs = base4.extend({
|
|
113472
|
+
summary: external_exports.string().min(1).max(1e3).refine(noNewlines, "summary must be one line"),
|
|
113473
|
+
start: external_exports.string().refine(isoDateOrTime, "start must be YYYY-MM-DD or an ISO 8601 date-time"),
|
|
113474
|
+
end: external_exports.string().refine(isoDateOrTime, "end must be YYYY-MM-DD or an ISO 8601 date-time"),
|
|
113475
|
+
timeZone: external_exports.string().min(1).max(64).regex(/^[A-Za-z0-9_+\-/ ]+$/).optional(),
|
|
113476
|
+
description: external_exports.string().max(8e3).optional(),
|
|
113477
|
+
location: external_exports.string().max(1e3).optional(),
|
|
113478
|
+
attendees: external_exports.array(external_exports.string()).max(50).optional(),
|
|
113479
|
+
calendarId: external_exports.string().min(1).max(320).optional()
|
|
113480
|
+
}).strict();
|
|
113481
|
+
var eventArgs = base4.extend({ id: external_exports.string().min(1).max(512).regex(/^[A-Za-z0-9!_.=+\-/~:]+$/, "not a valid id"), calendarId: external_exports.string().min(1).max(320).optional() }).strict();
|
|
113482
|
+
var scopeArg = external_exports.enum(["occurrence", "following", "series"]).optional();
|
|
113483
|
+
var notifyArg = external_exports.enum(["all", "externalOnly", "none"]);
|
|
113484
|
+
var updateEventArgs = eventArgs.extend({
|
|
113485
|
+
scope: scopeArg,
|
|
113486
|
+
notify: notifyArg,
|
|
113487
|
+
summary: createEventArgs.shape.summary.optional(),
|
|
113488
|
+
start: createEventArgs.shape.start.optional(),
|
|
113489
|
+
end: createEventArgs.shape.end.optional(),
|
|
113490
|
+
timeZone: createEventArgs.shape.timeZone,
|
|
113491
|
+
description: createEventArgs.shape.description,
|
|
113492
|
+
location: createEventArgs.shape.location,
|
|
113493
|
+
attendees: external_exports.array(external_exports.string()).max(50).optional(),
|
|
113494
|
+
addAttendees: external_exports.array(external_exports.string()).max(50).optional(),
|
|
113495
|
+
removeAttendees: external_exports.array(external_exports.string()).max(50).optional(),
|
|
113496
|
+
room: external_exports.string().max(320).optional()
|
|
113497
|
+
}).strict();
|
|
113498
|
+
var deleteEventArgs = eventArgs.extend({ scope: scopeArg, notify: notifyArg }).strict();
|
|
113499
|
+
var outlookUpdateEventArgs = updateEventArgs.omit({ calendarId: true }).extend({ notify: external_exports.literal("all") }).strict();
|
|
113500
|
+
var outlookDeleteEventArgs = deleteEventArgs.omit({ calendarId: true }).extend({ notify: external_exports.literal("all") }).strict();
|
|
113501
|
+
var listEventsSchema = (withCalendar) => ({
|
|
113502
|
+
type: "object",
|
|
113503
|
+
properties: {
|
|
113504
|
+
account: accountArg,
|
|
113505
|
+
timeMin: { type: "string", description: "Start of the window, ISO 8601 with a time zone (e.g. 2026-10-01T00:00:00Z)." },
|
|
113506
|
+
timeMax: { type: "string", description: "End of the window, ISO 8601 with a time zone." },
|
|
113507
|
+
...withCalendar ? { calendarId: { type: "string", description: "Calendar id; defaults to the primary calendar." } } : {},
|
|
113508
|
+
max: { type: "integer", minimum: 1, maximum: 100, description: "Most events to return (default 25)." }
|
|
113509
|
+
},
|
|
113510
|
+
required: ["timeMin", "timeMax"],
|
|
113511
|
+
additionalProperties: false
|
|
113512
|
+
});
|
|
113513
|
+
var createEventSchema = (withCalendar) => ({
|
|
113514
|
+
type: "object",
|
|
113515
|
+
properties: {
|
|
113516
|
+
account: accountArg,
|
|
113517
|
+
summary: { type: "string", description: "Event title." },
|
|
113518
|
+
start: { type: "string", description: "YYYY-MM-DD for an all-day event, or an ISO 8601 date-time. Without an offset, pass timeZone." },
|
|
113519
|
+
end: { type: "string", description: "Same format as start. For all-day events this is the day after the last day." },
|
|
113520
|
+
timeZone: { type: "string", description: "IANA time zone such as America/Los_Angeles, used when start/end have no offset." },
|
|
113521
|
+
description: { type: "string" },
|
|
113522
|
+
location: { type: "string" },
|
|
113523
|
+
attendees: { type: "array", items: { type: "string" }, description: "Guest email addresses. They receive an invitation." },
|
|
113524
|
+
...withCalendar ? { calendarId: { type: "string", description: "Calendar id; defaults to the primary calendar." } } : {}
|
|
113525
|
+
},
|
|
113526
|
+
required: ["summary", "start", "end"],
|
|
113527
|
+
additionalProperties: false
|
|
113528
|
+
});
|
|
113529
|
+
var calendarProp = { calendarId: { type: "string", description: "Calendar id; defaults to the primary calendar." } };
|
|
113530
|
+
var eventIdProp = { type: "string", description: "Event id from the list tool: one occurrence of a recurring event, or a single event." };
|
|
113531
|
+
var scopeProp = {
|
|
113532
|
+
type: "string",
|
|
113533
|
+
enum: ["occurrence", "following", "series"],
|
|
113534
|
+
description: "For a recurring event: this occurrence only (default), this and following, or the whole series. Pass the occurrence's id either way; the series is found from it."
|
|
113535
|
+
};
|
|
113536
|
+
var notifyProp = (outlook) => outlook ? { type: "string", enum: ["all"], description: "Outlook always tells the guests about the organizer's changes; pass all to go ahead." } : { type: "string", enum: ["all", "externalOnly", "none"], description: "Who gets an email about the change: all guests, only guests outside your organization, or nobody." };
|
|
113537
|
+
var eventSchema = (withCalendar) => ({
|
|
113538
|
+
type: "object",
|
|
113539
|
+
properties: { account: accountArg, id: eventIdProp, ...withCalendar ? calendarProp : {} },
|
|
113540
|
+
required: ["id"],
|
|
113541
|
+
additionalProperties: false
|
|
113542
|
+
});
|
|
113543
|
+
var updateEventSchema = (withCalendar) => ({
|
|
113544
|
+
type: "object",
|
|
113545
|
+
properties: {
|
|
113546
|
+
account: accountArg,
|
|
113547
|
+
id: eventIdProp,
|
|
113548
|
+
...withCalendar ? calendarProp : {},
|
|
113549
|
+
scope: scopeProp,
|
|
113550
|
+
notify: notifyProp(!withCalendar),
|
|
113551
|
+
summary: { type: "string", description: "New title." },
|
|
113552
|
+
description: { type: "string", description: "New description; replaces the old one." },
|
|
113553
|
+
location: { type: "string" },
|
|
113554
|
+
start: { type: "string", description: "New start, same format as when creating. Pass start and end together. To move a whole series, give a UTC offset." },
|
|
113555
|
+
end: { type: "string", description: "New end, same format as start." },
|
|
113556
|
+
timeZone: { type: "string", description: "IANA time zone for start/end without an offset." },
|
|
113557
|
+
attendees: { type: "array", items: { type: "string" }, description: "Replace the whole guest list with these addresses. Guests who stay keep their reply." },
|
|
113558
|
+
addAttendees: { type: "array", items: { type: "string" }, description: "Guests to add." },
|
|
113559
|
+
removeAttendees: { type: "array", items: { type: "string" }, description: "Guests to remove." },
|
|
113560
|
+
room: { type: "string", description: "Room or resource email address; replaces the room already booked." }
|
|
113561
|
+
},
|
|
113562
|
+
required: ["id", "notify"],
|
|
113563
|
+
additionalProperties: false
|
|
113564
|
+
});
|
|
113565
|
+
var deleteEventSchema = (withCalendar) => ({
|
|
113566
|
+
type: "object",
|
|
113567
|
+
properties: { account: accountArg, id: eventIdProp, ...withCalendar ? calendarProp : {}, scope: scopeProp, notify: notifyProp(!withCalendar) },
|
|
113568
|
+
required: ["id", "notify"],
|
|
113569
|
+
additionalProperties: false
|
|
113570
|
+
});
|
|
113571
|
+
var GOOGLE_CALENDAR_TOOLS = [
|
|
113572
|
+
{ name: "calendar_list_events", provider: "google", family: "calendar", description: "List Google Calendar events between two times.", inputSchema: listEventsSchema(true), annotations: READS, args: listEventsArgs },
|
|
113573
|
+
{ name: "calendar_create_event", provider: "google", family: "calendar", description: "Create a Google Calendar event. Attendees receive an invitation.", inputSchema: createEventSchema(true), annotations: SENDS, args: createEventArgs },
|
|
113574
|
+
{ name: "calendar_get_event", provider: "google", family: "calendar", description: "Read one Google Calendar event by id: details, its series (recurringEventId, recurrence) and each guest's reply.", inputSchema: eventSchema(true), annotations: READS, args: eventArgs },
|
|
113575
|
+
{ name: "calendar_update_event", provider: "google", family: "calendar", description: "Change a Google Calendar event: title, description, location, times, guests or room, for one occurrence, this and following, or the whole series. notify chooses who is emailed.", inputSchema: updateEventSchema(true), annotations: SENDS, args: updateEventArgs },
|
|
113576
|
+
{ name: "calendar_delete_event", provider: "google", family: "calendar", description: "Cancel a Google Calendar event: one occurrence, this and following, or the whole series. notify chooses who is emailed.", inputSchema: deleteEventSchema(true), annotations: SENDS, args: deleteEventArgs }
|
|
113577
|
+
];
|
|
113578
|
+
var OUTLOOK_CALENDAR_TOOLS = [
|
|
113579
|
+
{ name: "outlook_calendar_list_events", provider: "microsoft", family: "outlookCalendar", description: "List Outlook calendar events between two times (times are returned in UTC).", inputSchema: listEventsSchema(false), annotations: READS, args: listEventsArgs.omit({ calendarId: true }) },
|
|
113580
|
+
{ name: "outlook_calendar_create_event", provider: "microsoft", family: "outlookCalendar", description: "Create an Outlook calendar event. Attendees receive an invitation.", inputSchema: createEventSchema(false), annotations: SENDS, args: createEventArgs.omit({ calendarId: true }) },
|
|
113581
|
+
{ name: "outlook_calendar_get_event", provider: "microsoft", family: "outlookCalendar", description: "Read one Outlook calendar event by id: details, its series (seriesMasterId, recurrence) and each guest's reply (times in UTC).", inputSchema: eventSchema(false), annotations: READS, args: eventArgs.omit({ calendarId: true }) },
|
|
113582
|
+
{ name: "outlook_calendar_update_event", provider: "microsoft", family: "outlookCalendar", description: "Change an Outlook calendar event: title, description, location, times, guests or room, for one occurrence, this and following, or the whole series. Guests are told.", inputSchema: updateEventSchema(false), annotations: SENDS, args: outlookUpdateEventArgs },
|
|
113583
|
+
{ name: "outlook_calendar_delete_event", provider: "microsoft", family: "outlookCalendar", description: "Cancel an Outlook calendar event: one occurrence, this and following, or the whole series. Guests are told.", inputSchema: deleteEventSchema(false), annotations: SENDS, args: outlookDeleteEventArgs }
|
|
113584
|
+
];
|
|
113585
|
+
function guestEdit(args) {
|
|
113586
|
+
const replace = args.attendees === void 0 ? void 0 : addresses(args.attendees, "attendees");
|
|
113587
|
+
const add3 = addresses(args.addAttendees, "addAttendees");
|
|
113588
|
+
const remove = addresses(args.removeAttendees, "removeAttendees");
|
|
113589
|
+
const room = args.room === void 0 ? void 0 : addresses(args.room, "room")[0];
|
|
113590
|
+
if (replace && (add3.length || remove.length)) throw new ToolInputError("Pass attendees to replace the guest list, or addAttendees/removeAttendees, not both");
|
|
113591
|
+
return replace || add3.length || remove.length || room ? { replace, add: add3, remove, room } : null;
|
|
113592
|
+
}
|
|
113593
|
+
function editGuests(current4, email3, isRoom, make, edit) {
|
|
113594
|
+
const same = (a, b3) => a.toLowerCase() === b3.toLowerCase();
|
|
113595
|
+
const people = current4.filter((guest) => !isRoom(guest));
|
|
113596
|
+
let next;
|
|
113597
|
+
if (edit.replace) {
|
|
113598
|
+
next = edit.replace.map((address2) => people.find((guest) => same(email3(guest), address2)) ?? make(address2, false));
|
|
113599
|
+
} else {
|
|
113600
|
+
for (const address2 of edit.remove) {
|
|
113601
|
+
if (!people.some((guest) => same(email3(guest), address2))) throw new ToolInputError(`removeAttendees: ${address2} is not a guest of this event`);
|
|
113602
|
+
}
|
|
113603
|
+
next = people.filter((guest) => !edit.remove.some((address2) => same(email3(guest), address2)));
|
|
113604
|
+
for (const address2 of edit.add) if (!next.some((guest) => same(email3(guest), address2))) next.push(make(address2, false));
|
|
113605
|
+
}
|
|
113606
|
+
return [...next, ...edit.room ? [make(edit.room, true)] : current4.filter(isRoom)];
|
|
113607
|
+
}
|
|
113608
|
+
function needsChange(args, fields) {
|
|
113609
|
+
if (!Object.keys(fields).length && args.start === void 0 && args.end === void 0) throw new ToolInputError("Nothing to change: pass at least one field to update");
|
|
113610
|
+
if (args.start === void 0 !== (args.end === void 0)) throw new ToolInputError("Pass start and end together");
|
|
113611
|
+
}
|
|
113612
|
+
var DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
113613
|
+
var millis = (value) => Date.parse(DATE.test(value) ? `${value}T00:00:00Z` : /(?:Z|[+-]\d{2}:\d{2})$/.test(value) ? value : `${value.slice(0, 19)}Z`);
|
|
113614
|
+
function shiftSeries(seriesStart, occurrenceStart, allDay, start, end) {
|
|
113615
|
+
if (DATE.test(start) !== allDay) throw new ToolInputError("A whole series cannot switch between all-day and timed; change one occurrence or this and following");
|
|
113616
|
+
if (!allDay && !/(?:Z|[+-]\d{2}:\d{2})$/.test(start)) throw new ToolInputError("start: to move a whole series, give a UTC offset (e.g. 2026-10-01T15:00:00-07:00)");
|
|
113617
|
+
const moved = millis(seriesStart) + millis(start) - millis(occurrenceStart);
|
|
113618
|
+
return [moved, moved + millis(end) - millis(start)];
|
|
113619
|
+
}
|
|
113620
|
+
function dayBefore(date5) {
|
|
113621
|
+
const day = /* @__PURE__ */ new Date(`${date5}T00:00:00Z`);
|
|
113622
|
+
day.setUTCDate(day.getUTCDate() - 1);
|
|
113623
|
+
return day.toISOString().slice(0, 10);
|
|
113624
|
+
}
|
|
113625
|
+
var googleTime = external_exports.object({ dateTime: external_exports.string().optional(), date: external_exports.string().optional(), timeZone: external_exports.string().optional() });
|
|
113626
|
+
var googleAttendee = external_exports.object({ email: external_exports.string().optional(), responseStatus: external_exports.string().optional(), resource: external_exports.boolean().optional() }).passthrough();
|
|
113627
|
+
var googleEventSchema = external_exports.object({
|
|
113628
|
+
id: external_exports.string(),
|
|
113629
|
+
summary: external_exports.string().optional(),
|
|
113630
|
+
description: external_exports.string().optional(),
|
|
113631
|
+
location: external_exports.string().optional(),
|
|
113632
|
+
status: external_exports.string().optional(),
|
|
113633
|
+
htmlLink: external_exports.string().optional(),
|
|
113634
|
+
start: googleTime.optional(),
|
|
113635
|
+
end: googleTime.optional(),
|
|
113636
|
+
organizer: external_exports.object({ email: external_exports.string().optional() }).optional(),
|
|
113637
|
+
attendees: external_exports.array(googleAttendee).optional(),
|
|
113638
|
+
recurringEventId: external_exports.string().optional(),
|
|
113639
|
+
originalStartTime: googleTime.optional(),
|
|
113640
|
+
recurrence: external_exports.array(external_exports.string()).optional()
|
|
113641
|
+
}).passthrough();
|
|
113642
|
+
function googleEvent(event) {
|
|
113643
|
+
return {
|
|
113644
|
+
id: event.id,
|
|
113645
|
+
summary: event.summary,
|
|
113646
|
+
start: event.start?.dateTime ?? event.start?.date,
|
|
113647
|
+
end: event.end?.dateTime ?? event.end?.date,
|
|
113648
|
+
location: event.location,
|
|
113649
|
+
organizer: event.organizer?.email,
|
|
113650
|
+
attendees: event.attendees?.map((attendee) => `${attendee.email ?? ""}${attendee.resource ? " (room)" : ""}${attendee.responseStatus ? ` (${attendee.responseStatus})` : ""}`),
|
|
113651
|
+
description: event.description ? bounded2(event.description, 2e3) : void 0,
|
|
113652
|
+
recurringEventId: event.recurringEventId,
|
|
113653
|
+
recurrence: event.recurrence,
|
|
113654
|
+
link: event.htmlLink
|
|
113655
|
+
};
|
|
113656
|
+
}
|
|
113657
|
+
async function calendarListEvents(ctx, account2, args) {
|
|
113658
|
+
const calendarId = encodeURIComponent(args.calendarId ?? "primary");
|
|
113659
|
+
const query = new URLSearchParams({ timeMin: args.timeMin, timeMax: args.timeMax, singleEvents: "true", orderBy: "startTime", maxResults: String(args.max ?? 25) });
|
|
113660
|
+
const list3 = parse7(external_exports.object({ items: external_exports.array(googleEventSchema).optional(), timeZone: external_exports.string().optional() }), await call(ctx, account2, `${CALENDAR}/calendars/${calendarId}/events?${query}`, { expect: "json" }), "Calendar");
|
|
113661
|
+
return json4({ account: account2.email, timeZone: list3.timeZone, events: (list3.items ?? []).map(googleEvent) });
|
|
113662
|
+
}
|
|
113663
|
+
function eventTime(value, timeZone, field) {
|
|
113664
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(value)) return { allDay: true, date: value };
|
|
113665
|
+
const hasOffset = /(?:Z|[+-]\d{2}:\d{2})$/.test(value);
|
|
113666
|
+
if (!hasOffset && !timeZone) throw new ToolInputError(`${field}: add a UTC offset (e.g. 2026-10-01T15:00:00-07:00) or pass timeZone`);
|
|
113667
|
+
return { allDay: false, dateTime: value, hasOffset };
|
|
113668
|
+
}
|
|
113669
|
+
function googleTimes(startValue, endValue, timeZone) {
|
|
113670
|
+
const start = eventTime(startValue, timeZone, "start");
|
|
113671
|
+
const end = eventTime(endValue, timeZone, "end");
|
|
113672
|
+
if (start.allDay !== end.allDay) throw new ToolInputError("start and end must both be dates or both be date-times");
|
|
113673
|
+
const time4 = (value) => value.allDay ? { date: value.date } : { dateTime: value.dateTime, ...timeZone ? { timeZone } : {} };
|
|
113674
|
+
return { start: time4(start), end: time4(end) };
|
|
113675
|
+
}
|
|
113676
|
+
async function calendarCreateEvent(ctx, account2, args) {
|
|
113677
|
+
const attendees = addresses(args.attendees, "attendees");
|
|
113678
|
+
const body = {
|
|
113679
|
+
summary: args.summary,
|
|
113680
|
+
...args.description ? { description: args.description } : {},
|
|
113681
|
+
...args.location ? { location: args.location } : {},
|
|
113682
|
+
...googleTimes(args.start, args.end, args.timeZone),
|
|
113683
|
+
...attendees.length ? { attendees: attendees.map((email3) => ({ email: email3 })) } : {}
|
|
113684
|
+
};
|
|
113685
|
+
const calendarId = encodeURIComponent(args.calendarId ?? "primary");
|
|
113686
|
+
const query = new URLSearchParams({ sendUpdates: attendees.length ? "all" : "none" });
|
|
113687
|
+
const created = parse7(googleEventSchema, await call(ctx, account2, `${CALENDAR}/calendars/${calendarId}/events?${query}`, {
|
|
113688
|
+
method: "POST",
|
|
113689
|
+
headers: { "content-type": "application/json" },
|
|
113690
|
+
body: JSON.stringify(body),
|
|
113691
|
+
expect: "json"
|
|
113692
|
+
}), "Calendar");
|
|
113693
|
+
return json4({ account: account2.email, created: googleEvent(created) });
|
|
113694
|
+
}
|
|
113695
|
+
var eventUrl = (calendarId, id, query) => `${CALENDAR}/calendars/${encodeURIComponent(calendarId ?? "primary")}/events${id ? `/${encodeURIComponent(id)}` : ""}${query ? `?${new URLSearchParams(query)}` : ""}`;
|
|
113696
|
+
var when = (time4) => time4?.dateTime ?? time4?.date ?? "";
|
|
113697
|
+
async function googleGet(ctx, account2, calendarId, id) {
|
|
113698
|
+
return parse7(googleEventSchema, await call(ctx, account2, eventUrl(calendarId, id), { expect: "json" }), "Calendar");
|
|
113699
|
+
}
|
|
113700
|
+
async function googleSave(ctx, account2, method, url2, body) {
|
|
113701
|
+
return parse7(googleEventSchema, await call(ctx, account2, url2, { method, headers: { "content-type": "application/json" }, body: JSON.stringify(body), expect: "json" }), "Calendar");
|
|
113702
|
+
}
|
|
113703
|
+
async function googleTarget(ctx, account2, args) {
|
|
113704
|
+
const scope = args.scope ?? "occurrence";
|
|
113705
|
+
const event = await googleGet(ctx, account2, args.calendarId, args.id);
|
|
113706
|
+
if (scope === "occurrence" && event.recurrence) throw new ToolInputError(`${args.id} is a whole series: pass the id of one occurrence (from calendar_list_events), or scope "series"`);
|
|
113707
|
+
if (scope === "occurrence" || !event.recurringEventId && !event.recurrence) return { scope: "occurrence", event, series: event };
|
|
113708
|
+
const series = event.recurringEventId ? await googleGet(ctx, account2, args.calendarId, event.recurringEventId) : event;
|
|
113709
|
+
const first = !event.originalStartTime || millis(when(event.originalStartTime)) === millis(when(series.start));
|
|
113710
|
+
return { scope: first ? "series" : scope, event, series };
|
|
113711
|
+
}
|
|
113712
|
+
function googleFields(args, current4) {
|
|
113713
|
+
const guests = guestEdit(args);
|
|
113714
|
+
return {
|
|
113715
|
+
...args.summary !== void 0 ? { summary: args.summary } : {},
|
|
113716
|
+
...args.description !== void 0 ? { description: args.description } : {},
|
|
113717
|
+
...args.location !== void 0 ? { location: args.location } : {},
|
|
113718
|
+
...guests ? {
|
|
113719
|
+
attendees: editGuests(current4.attendees ?? [], (guest) => guest.email ?? "", (guest) => guest.resource === true, (email3, resource) => resource ? { email: email3, resource } : { email: email3 }, guests)
|
|
113720
|
+
} : {}
|
|
113721
|
+
};
|
|
113722
|
+
}
|
|
113723
|
+
function capRecurrence(rules, from) {
|
|
113724
|
+
const until = from.date ? dayBefore(from.date).replace(/-/g, "") : new Date(millis(from.dateTime ?? "") - 1e3).toISOString().replace(/[-:]|\.\d{3}/g, "");
|
|
113725
|
+
return rules.map((rule) => rule.startsWith("RRULE:") ? `RRULE:${[...rule.slice(6).split(";").filter((part) => !/^(UNTIL|COUNT)=/i.test(part)), `UNTIL=${until}`].join(";")}` : rule);
|
|
113726
|
+
}
|
|
113727
|
+
var SERIES_FIELDS = ["summary", "description", "location", "attendees", "colorId", "reminders", "transparency", "visibility", "guestsCanModify", "guestsCanInviteOthers", "guestsCanSeeOtherGuests"];
|
|
113728
|
+
async function calendarGetEvent(ctx, account2, args) {
|
|
113729
|
+
return json4({ account: account2.email, event: googleEvent(await googleGet(ctx, account2, args.calendarId, args.id)) });
|
|
113730
|
+
}
|
|
113731
|
+
async function calendarUpdateEvent(ctx, account2, args) {
|
|
113732
|
+
const { scope, event, series } = await googleTarget(ctx, account2, args);
|
|
113733
|
+
const fields = googleFields(args, series);
|
|
113734
|
+
needsChange(args, fields);
|
|
113735
|
+
const notify2 = { sendUpdates: args.notify };
|
|
113736
|
+
if (scope === "occurrence") {
|
|
113737
|
+
const times2 = args.start !== void 0 ? googleTimes(args.start, args.end, args.timeZone) : {};
|
|
113738
|
+
const updated = await googleSave(ctx, account2, "PATCH", eventUrl(args.calendarId, event.id, notify2), { ...fields, ...times2 });
|
|
113739
|
+
return json4({ account: account2.email, scope, updated: googleEvent(updated) });
|
|
113740
|
+
}
|
|
113741
|
+
if (scope === "series") {
|
|
113742
|
+
let times2 = {};
|
|
113743
|
+
if (args.start !== void 0) {
|
|
113744
|
+
const allDay = Boolean(event.start?.date);
|
|
113745
|
+
const [start, end] = shiftSeries(when(series.start), when(event.start), allDay, args.start, args.end);
|
|
113746
|
+
const at2 = (ms2) => allDay ? { date: new Date(ms2).toISOString().slice(0, 10) } : { dateTime: new Date(ms2).toISOString(), timeZone: args.timeZone ?? series.start?.timeZone };
|
|
113747
|
+
times2 = { start: at2(start), end: at2(end) };
|
|
113748
|
+
}
|
|
113749
|
+
const updated = await googleSave(ctx, account2, "PATCH", eventUrl(args.calendarId, series.id, notify2), { ...fields, ...times2 });
|
|
113750
|
+
return json4({ account: account2.email, scope, updated: googleEvent(updated) });
|
|
113751
|
+
}
|
|
113752
|
+
if (series.recurrence?.some((rule) => /^RRULE:.*\bCOUNT=/i.test(rule))) {
|
|
113753
|
+
throw new ToolInputError("This series ends after a set number of times, so it cannot be split: change one occurrence or the whole series");
|
|
113754
|
+
}
|
|
113755
|
+
const copied = Object.fromEntries(SERIES_FIELDS.filter((key5) => series[key5] !== void 0).map((key5) => [key5, series[key5]]));
|
|
113756
|
+
const times = args.start !== void 0 ? googleTimes(args.start, args.end, args.timeZone) : { start: event.start, end: event.end };
|
|
113757
|
+
const created = await googleSave(ctx, account2, "POST", eventUrl(args.calendarId, "", notify2), { ...copied, ...fields, ...times, recurrence: series.recurrence });
|
|
113758
|
+
await googleSave(ctx, account2, "PATCH", eventUrl(args.calendarId, series.id, notify2), { recurrence: capRecurrence(series.recurrence ?? [], event.originalStartTime ?? {}) });
|
|
113759
|
+
return json4({ account: account2.email, scope, updated: googleEvent(created), endedSeries: series.id, note: "The old series now ends before this occurrence; a new series with the changes starts here." });
|
|
113760
|
+
}
|
|
113761
|
+
async function calendarDeleteEvent(ctx, account2, args) {
|
|
113762
|
+
const { scope, event, series } = await googleTarget(ctx, account2, args);
|
|
113763
|
+
const notify2 = { sendUpdates: args.notify };
|
|
113764
|
+
if (scope === "following") {
|
|
113765
|
+
await googleSave(ctx, account2, "PATCH", eventUrl(args.calendarId, series.id, notify2), { recurrence: capRecurrence(series.recurrence ?? [], event.originalStartTime ?? {}) });
|
|
113766
|
+
} else {
|
|
113767
|
+
await call(ctx, account2, eventUrl(args.calendarId, (scope === "series" ? series : event).id, notify2), { method: "DELETE", expect: "none" });
|
|
113768
|
+
}
|
|
113769
|
+
return json4({ account: account2.email, cancelled: true, scope, id: scope === "occurrence" ? event.id : series.id });
|
|
113770
|
+
}
|
|
113771
|
+
var graphTime = external_exports.object({ dateTime: external_exports.string().optional(), timeZone: external_exports.string().optional() });
|
|
113772
|
+
var graphEventSchema = external_exports.object({
|
|
113773
|
+
id: external_exports.string(),
|
|
113774
|
+
subject: external_exports.string().nullable().optional(),
|
|
113775
|
+
start: graphTime.optional(),
|
|
113776
|
+
end: graphTime.optional(),
|
|
113777
|
+
isAllDay: external_exports.boolean().optional(),
|
|
113778
|
+
location: external_exports.object({ displayName: external_exports.string().optional() }).nullable().optional(),
|
|
113779
|
+
organizer: graphRecipient.nullable().optional(),
|
|
113780
|
+
attendees: external_exports.array(graphRecipient.extend({ type: external_exports.string().optional(), status: external_exports.object({ response: external_exports.string().optional() }).optional() })).optional(),
|
|
113781
|
+
webLink: external_exports.string().optional(),
|
|
113782
|
+
bodyPreview: external_exports.string().optional(),
|
|
113783
|
+
body: external_exports.object({ contentType: external_exports.string().optional(), content: external_exports.string().optional() }).optional(),
|
|
113784
|
+
type: external_exports.string().optional(),
|
|
113785
|
+
seriesMasterId: external_exports.string().nullable().optional(),
|
|
113786
|
+
originalStartTimeZone: external_exports.string().optional(),
|
|
113787
|
+
recurrence: external_exports.object({
|
|
113788
|
+
pattern: external_exports.record(external_exports.string(), external_exports.unknown()),
|
|
113789
|
+
range: external_exports.object({ type: external_exports.string(), startDate: external_exports.string().optional(), endDate: external_exports.string().optional() }).passthrough()
|
|
113790
|
+
}).nullable().optional()
|
|
113791
|
+
});
|
|
113792
|
+
function graphEvent(event) {
|
|
113793
|
+
return {
|
|
113794
|
+
id: event.id,
|
|
113795
|
+
summary: event.subject,
|
|
113796
|
+
start: event.start?.dateTime ? `${event.start.dateTime}${event.start.timeZone === "UTC" ? "Z" : ` (${event.start.timeZone ?? ""})`}` : void 0,
|
|
113797
|
+
end: event.end?.dateTime ? `${event.end.dateTime}${event.end.timeZone === "UTC" ? "Z" : ` (${event.end.timeZone ?? ""})`}` : void 0,
|
|
113798
|
+
allDay: event.isAllDay,
|
|
113799
|
+
location: event.location?.displayName || void 0,
|
|
113800
|
+
organizer: recipient(event.organizer),
|
|
113801
|
+
attendees: event.attendees?.map((attendee) => `${recipient(attendee) ?? ""}${attendee.type === "resource" ? " (room)" : ""}${attendee.status?.response ? ` (${attendee.status.response})` : ""}`),
|
|
113802
|
+
preview: event.bodyPreview ? bounded2(event.bodyPreview, 1e3) : void 0,
|
|
113803
|
+
type: event.type,
|
|
113804
|
+
seriesMasterId: event.seriesMasterId ?? void 0,
|
|
113805
|
+
recurrence: event.recurrence ?? void 0,
|
|
113806
|
+
link: event.webLink
|
|
113807
|
+
};
|
|
113808
|
+
}
|
|
113809
|
+
async function outlookListEvents(ctx, account2, args) {
|
|
113810
|
+
const query = new URLSearchParams({
|
|
113811
|
+
startDateTime: new Date(args.timeMin).toISOString(),
|
|
113812
|
+
endDateTime: new Date(args.timeMax).toISOString(),
|
|
113813
|
+
$top: String(args.max ?? 25),
|
|
113814
|
+
$orderby: "start/dateTime",
|
|
113815
|
+
$select: "id,subject,start,end,isAllDay,location,organizer,attendees,webLink,bodyPreview"
|
|
113816
|
+
});
|
|
113817
|
+
const list3 = parse7(external_exports.object({ value: external_exports.array(graphEventSchema) }), await call(ctx, account2, `${GRAPH}/me/calendarView?${query}`, {
|
|
113818
|
+
headers: { prefer: 'outlook.timezone="UTC"' },
|
|
113819
|
+
expect: "json"
|
|
113820
|
+
}), "Outlook calendar");
|
|
113821
|
+
return json4({ account: account2.email, timeZone: "UTC", events: list3.value.map(graphEvent) });
|
|
113822
|
+
}
|
|
113823
|
+
function graphDateTime(value, timeZone, field) {
|
|
113824
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(value)) return { dateTime: `${value}T00:00:00`, timeZone: timeZone ?? "UTC", allDay: true };
|
|
113825
|
+
if (/(?:Z|[+-]\d{2}:\d{2})$/.test(value)) {
|
|
113826
|
+
const parsed = Date.parse(value);
|
|
113827
|
+
if (!Number.isFinite(parsed)) throw new ToolInputError(`${field}: not a valid date-time`);
|
|
113828
|
+
return { dateTime: new Date(parsed).toISOString().replace(/\.\d{3}Z$/, ""), timeZone: "UTC", allDay: false };
|
|
113829
|
+
}
|
|
113830
|
+
if (!timeZone) throw new ToolInputError(`${field}: add a UTC offset (e.g. 2026-10-01T15:00:00-07:00) or pass timeZone`);
|
|
113831
|
+
return { dateTime: value, timeZone, allDay: false };
|
|
113832
|
+
}
|
|
113833
|
+
function graphTimes(startValue, endValue, timeZone) {
|
|
113834
|
+
const start = graphDateTime(startValue, timeZone, "start");
|
|
113835
|
+
const end = graphDateTime(endValue, timeZone, "end");
|
|
113836
|
+
if (start.allDay !== end.allDay) throw new ToolInputError("start and end must both be dates or both be date-times");
|
|
113837
|
+
return { start: { dateTime: start.dateTime, timeZone: start.timeZone }, end: { dateTime: end.dateTime, timeZone: end.timeZone }, isAllDay: start.allDay };
|
|
113838
|
+
}
|
|
113839
|
+
async function outlookCreateEvent(ctx, account2, args) {
|
|
113840
|
+
const attendees = addresses(args.attendees, "attendees");
|
|
113841
|
+
const created = await graphSave(ctx, account2, "POST", `${GRAPH}/me/events`, {
|
|
113842
|
+
subject: args.summary,
|
|
113843
|
+
...args.description ? { body: { contentType: "Text", content: args.description } } : {},
|
|
113844
|
+
...graphTimes(args.start, args.end, args.timeZone),
|
|
113845
|
+
...args.location ? { location: { displayName: args.location } } : {},
|
|
113846
|
+
...attendees.length ? { attendees: attendees.map((address2) => ({ emailAddress: { address: address2 }, type: "required" })) } : {}
|
|
113847
|
+
});
|
|
113848
|
+
return json4({ account: account2.email, created: graphEvent(created) });
|
|
113849
|
+
}
|
|
113850
|
+
var GRAPH_EVENT_FIELDS = "id,subject,start,end,isAllDay,location,organizer,attendees,webLink,bodyPreview,body,type,seriesMasterId,recurrence,originalStartTimeZone";
|
|
113851
|
+
var UTC = 'outlook.timezone="UTC"';
|
|
113852
|
+
var graphEventUrl = (id) => `${GRAPH}/me/events/${encodeURIComponent(id)}`;
|
|
113853
|
+
async function graphGet(ctx, account2, id, prefer = UTC) {
|
|
113854
|
+
return parse7(graphEventSchema, await call(ctx, account2, `${graphEventUrl(id)}?${new URLSearchParams({ $select: GRAPH_EVENT_FIELDS })}`, { headers: { prefer }, expect: "json" }), "Outlook calendar");
|
|
113855
|
+
}
|
|
113856
|
+
async function graphSave(ctx, account2, method, url2, body) {
|
|
113857
|
+
return parse7(graphEventSchema, await call(ctx, account2, url2, {
|
|
113858
|
+
method,
|
|
113859
|
+
headers: { "content-type": "application/json", prefer: UTC },
|
|
113860
|
+
body: JSON.stringify(body),
|
|
113861
|
+
expect: "json"
|
|
113862
|
+
}), "Outlook calendar");
|
|
113863
|
+
}
|
|
113864
|
+
async function graphTarget(ctx, account2, args) {
|
|
113865
|
+
const scope = args.scope ?? "occurrence";
|
|
113866
|
+
const event = await graphGet(ctx, account2, args.id);
|
|
113867
|
+
if (scope === "occurrence" && event.type === "seriesMaster") throw new ToolInputError(`${args.id} is a whole series: pass the id of one occurrence (from outlook_calendar_list_events), or scope "series"`);
|
|
113868
|
+
if (scope === "occurrence" || !event.seriesMasterId && event.type !== "seriesMaster") return { scope: "occurrence", event, series: event };
|
|
113869
|
+
const series = event.type === "seriesMaster" ? event : await graphGet(ctx, account2, event.seriesMasterId);
|
|
113870
|
+
const first = event.type === "seriesMaster" || millis(event.start?.dateTime ?? "") === millis(series.start?.dateTime ?? "");
|
|
113871
|
+
return { scope: first ? "series" : scope, event, series };
|
|
113872
|
+
}
|
|
113873
|
+
var graphGuests = (event) => (event.attendees ?? []).map((guest) => ({ emailAddress: { address: guest.emailAddress?.address ?? "" }, type: guest.type ?? "required" }));
|
|
113874
|
+
function graphFields(args, current4) {
|
|
113875
|
+
const guests = guestEdit(args);
|
|
113876
|
+
return {
|
|
113877
|
+
...args.summary !== void 0 ? { subject: args.summary } : {},
|
|
113878
|
+
...args.description !== void 0 ? { body: { contentType: "Text", content: args.description } } : {},
|
|
113879
|
+
...args.location !== void 0 ? { location: { displayName: args.location } } : {},
|
|
113880
|
+
...guests ? {
|
|
113881
|
+
attendees: editGuests(graphGuests(current4), (guest) => guest.emailAddress.address, (guest) => guest.type === "resource", (address2, room) => ({ emailAddress: { address: address2 }, type: room ? "resource" : "required" }), guests)
|
|
113882
|
+
} : {}
|
|
113883
|
+
};
|
|
113884
|
+
}
|
|
113885
|
+
async function seriesDay(ctx, account2, event, series) {
|
|
113886
|
+
const local = await graphGet(ctx, account2, event.id, `outlook.timezone="${series.originalStartTimeZone ?? "UTC"}"`);
|
|
113887
|
+
return { local, day: (local.start?.dateTime ?? "").slice(0, 10) };
|
|
113888
|
+
}
|
|
113889
|
+
function endSeriesBefore(series, day) {
|
|
113890
|
+
const recurrence = series.recurrence;
|
|
113891
|
+
return { recurrence: { pattern: recurrence.pattern, range: { ...recurrence.range, type: "endDate", endDate: dayBefore(day) } } };
|
|
113892
|
+
}
|
|
113893
|
+
async function outlookGetEvent(ctx, account2, args) {
|
|
113894
|
+
const event = await graphGet(ctx, account2, args.id, `${UTC}, outlook.body-content-type="text"`);
|
|
113895
|
+
return json4({ account: account2.email, timeZone: "UTC", event: { ...graphEvent(event), description: event.body?.content ? bounded2(event.body.content, 2e3) : void 0 } });
|
|
113896
|
+
}
|
|
113897
|
+
async function outlookUpdateEvent(ctx, account2, args) {
|
|
113898
|
+
const { scope, event, series } = await graphTarget(ctx, account2, args);
|
|
113899
|
+
const fields = graphFields(args, series);
|
|
113900
|
+
needsChange(args, fields);
|
|
113901
|
+
if (scope === "occurrence") {
|
|
113902
|
+
const updated = await graphSave(ctx, account2, "PATCH", graphEventUrl(event.id), { ...fields, ...args.start !== void 0 ? graphTimes(args.start, args.end, args.timeZone) : {} });
|
|
113903
|
+
return json4({ account: account2.email, scope, updated: graphEvent(updated) });
|
|
113904
|
+
}
|
|
113905
|
+
const zone = series.originalStartTimeZone ?? "UTC";
|
|
113906
|
+
if (scope === "series") {
|
|
113907
|
+
let times2 = {};
|
|
113908
|
+
if (args.start !== void 0) {
|
|
113909
|
+
const local2 = await graphGet(ctx, account2, series.id, `outlook.timezone="${zone}"`);
|
|
113910
|
+
const [start, end] = shiftSeries(local2.start?.dateTime ?? "", event.start?.dateTime ?? "", event.isAllDay === true, args.start, args.end);
|
|
113911
|
+
const at2 = (ms2) => ({ dateTime: new Date(ms2).toISOString().slice(0, 19), timeZone: zone });
|
|
113912
|
+
times2 = { start: at2(start), end: at2(end) };
|
|
113913
|
+
}
|
|
113914
|
+
const updated = await graphSave(ctx, account2, "PATCH", graphEventUrl(series.id), { ...fields, ...times2 });
|
|
113915
|
+
return json4({ account: account2.email, scope, updated: graphEvent(updated) });
|
|
113916
|
+
}
|
|
113917
|
+
if (!series.recurrence || series.recurrence.range.type === "numbered") {
|
|
113918
|
+
throw new ToolInputError("This series ends after a set number of times, so it cannot be split: change one occurrence or the whole series");
|
|
113919
|
+
}
|
|
113920
|
+
const { local, day } = await seriesDay(ctx, account2, event, series);
|
|
113921
|
+
const times = args.start !== void 0 ? graphTimes(args.start, args.end, args.timeZone) : { start: { dateTime: local.start?.dateTime, timeZone: zone }, end: { dateTime: local.end?.dateTime, timeZone: zone }, isAllDay: series.isAllDay === true };
|
|
113922
|
+
const created = await graphSave(ctx, account2, "POST", `${GRAPH}/me/events`, {
|
|
113923
|
+
subject: series.subject,
|
|
113924
|
+
...series.body?.content ? { body: series.body } : {},
|
|
113925
|
+
...series.location?.displayName ? { location: { displayName: series.location.displayName } } : {},
|
|
113926
|
+
attendees: graphGuests(series),
|
|
113927
|
+
...fields,
|
|
113928
|
+
...times,
|
|
113929
|
+
recurrence: { pattern: series.recurrence.pattern, range: { ...series.recurrence.range, startDate: day } }
|
|
113930
|
+
});
|
|
113931
|
+
await graphSave(ctx, account2, "PATCH", graphEventUrl(series.id), endSeriesBefore(series, day));
|
|
113932
|
+
return json4({ account: account2.email, scope, updated: graphEvent(created), endedSeries: series.id, note: "The old series now ends before this occurrence; a new series with the changes starts here." });
|
|
113933
|
+
}
|
|
113934
|
+
async function outlookDeleteEvent(ctx, account2, args) {
|
|
113935
|
+
const { scope, event, series } = await graphTarget(ctx, account2, args);
|
|
113936
|
+
if (scope === "following") {
|
|
113937
|
+
const { day } = await seriesDay(ctx, account2, event, series);
|
|
113938
|
+
await graphSave(ctx, account2, "PATCH", graphEventUrl(series.id), endSeriesBefore(series, day));
|
|
113939
|
+
} else {
|
|
113940
|
+
await call(ctx, account2, graphEventUrl((scope === "series" ? series : event).id), { method: "DELETE", expect: "none" });
|
|
113941
|
+
}
|
|
113942
|
+
return json4({ account: account2.email, cancelled: true, scope, id: scope === "occurrence" ? event.id : series.id });
|
|
113943
|
+
}
|
|
113944
|
+
var CALENDAR_RUNNERS = {
|
|
113945
|
+
calendar_list_events: calendarListEvents,
|
|
113946
|
+
calendar_create_event: calendarCreateEvent,
|
|
113947
|
+
calendar_get_event: calendarGetEvent,
|
|
113948
|
+
calendar_update_event: calendarUpdateEvent,
|
|
113949
|
+
calendar_delete_event: calendarDeleteEvent,
|
|
113950
|
+
outlook_calendar_list_events: outlookListEvents,
|
|
113951
|
+
outlook_calendar_create_event: outlookCreateEvent,
|
|
113952
|
+
outlook_calendar_get_event: outlookGetEvent,
|
|
113953
|
+
outlook_calendar_update_event: outlookUpdateEvent,
|
|
113954
|
+
outlook_calendar_delete_event: outlookDeleteEvent
|
|
113955
|
+
};
|
|
113956
|
+
|
|
113331
113957
|
// server/office-text.ts
|
|
113332
113958
|
import { inflateRawSync } from "node:zlib";
|
|
113333
113959
|
var MAX_ENTRIES4 = 2e3;
|
|
@@ -113439,26 +114065,9 @@ ${paragraphs(files.get(name2).toString("utf8"), "a:p", "a:t")}`);
|
|
|
113439
114065
|
}
|
|
113440
114066
|
|
|
113441
114067
|
// server/oauth-account-tools.ts
|
|
113442
|
-
var HTTP_TIMEOUT_MS2 = 3e4;
|
|
113443
|
-
var MAX_RESULT_CHARS = 48e3;
|
|
113444
114068
|
var MAX_BODY_CHARS = 2e4;
|
|
113445
114069
|
var MAX_FILE_TEXT_CHARS = 4e4;
|
|
113446
|
-
var MAX_JSON_BYTES = 4 * 1024 * 1024;
|
|
113447
|
-
var MAX_DOWNLOAD_BYTES = 8 * 1024 * 1024;
|
|
113448
|
-
var READS = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true };
|
|
113449
|
-
var CREATES = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true };
|
|
113450
|
-
var SENDS = { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true };
|
|
113451
|
-
var accountArg = { type: "string", description: "Email address of the account to use. Optional only when this bot has exactly one account of this provider." };
|
|
113452
114070
|
var emailList = external_exports.union([external_exports.string(), external_exports.array(external_exports.string()).max(50)]);
|
|
113453
|
-
var EMAIL2 = /^[^\s@<>,;"]+@[^\s@<>,;"]+\.[^\s@<>,;"]+$/;
|
|
113454
|
-
var noNewlines = (value) => !/[\r\n]/.test(value);
|
|
113455
|
-
function isoInstant(value) {
|
|
113456
|
-
return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})$/.test(value) && Number.isFinite(Date.parse(value));
|
|
113457
|
-
}
|
|
113458
|
-
function isoDateOrTime(value) {
|
|
113459
|
-
return /^\d{4}-\d{2}-\d{2}$/.test(value) || /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})?$/.test(value);
|
|
113460
|
-
}
|
|
113461
|
-
var base4 = external_exports.object({ account: external_exports.string().max(320).optional() });
|
|
113462
114071
|
var searchArgs = base4.extend({ q: external_exports.string().min(1).max(500), max: external_exports.number().int().min(1).max(25).optional() }).strict();
|
|
113463
114072
|
var idArgs = (key5) => base4.extend({ [key5]: external_exports.string().min(1).max(512).regex(/^[A-Za-z0-9!_.=+\-/~:]+$/, "not a valid id") }).strict();
|
|
113464
114073
|
var draftArgs = base4.extend({
|
|
@@ -113467,22 +114076,6 @@ var draftArgs = base4.extend({
|
|
|
113467
114076
|
body: external_exports.string().max(2e5),
|
|
113468
114077
|
cc: emailList.optional()
|
|
113469
114078
|
}).strict();
|
|
113470
|
-
var listEventsArgs = base4.extend({
|
|
113471
|
-
timeMin: external_exports.string().refine(isoInstant, "timeMin must be an ISO 8601 date-time with a time zone, e.g. 2026-10-01T00:00:00Z"),
|
|
113472
|
-
timeMax: external_exports.string().refine(isoInstant, "timeMax must be an ISO 8601 date-time with a time zone, e.g. 2026-10-08T00:00:00Z"),
|
|
113473
|
-
calendarId: external_exports.string().min(1).max(320).optional(),
|
|
113474
|
-
max: external_exports.number().int().min(1).max(100).optional()
|
|
113475
|
-
}).strict();
|
|
113476
|
-
var createEventArgs = base4.extend({
|
|
113477
|
-
summary: external_exports.string().min(1).max(1e3).refine(noNewlines, "summary must be one line"),
|
|
113478
|
-
start: external_exports.string().refine(isoDateOrTime, "start must be YYYY-MM-DD or an ISO 8601 date-time"),
|
|
113479
|
-
end: external_exports.string().refine(isoDateOrTime, "end must be YYYY-MM-DD or an ISO 8601 date-time"),
|
|
113480
|
-
timeZone: external_exports.string().min(1).max(64).regex(/^[A-Za-z0-9_+\-/ ]+$/).optional(),
|
|
113481
|
-
description: external_exports.string().max(8e3).optional(),
|
|
113482
|
-
location: external_exports.string().max(1e3).optional(),
|
|
113483
|
-
attendees: external_exports.array(external_exports.string()).max(50).optional(),
|
|
113484
|
-
calendarId: external_exports.string().min(1).max(320).optional()
|
|
113485
|
-
}).strict();
|
|
113486
114079
|
var listAccountsArgs = external_exports.object({}).strict();
|
|
113487
114080
|
var searchSchema = (what) => ({
|
|
113488
114081
|
type: "object",
|
|
@@ -113503,50 +114096,20 @@ var draftSchema = {
|
|
|
113503
114096
|
required: ["to", "subject", "body"],
|
|
113504
114097
|
additionalProperties: false
|
|
113505
114098
|
};
|
|
113506
|
-
var listEventsSchema = (withCalendar) => ({
|
|
113507
|
-
type: "object",
|
|
113508
|
-
properties: {
|
|
113509
|
-
account: accountArg,
|
|
113510
|
-
timeMin: { type: "string", description: "Start of the window, ISO 8601 with a time zone (e.g. 2026-10-01T00:00:00Z)." },
|
|
113511
|
-
timeMax: { type: "string", description: "End of the window, ISO 8601 with a time zone." },
|
|
113512
|
-
...withCalendar ? { calendarId: { type: "string", description: "Calendar id; defaults to the primary calendar." } } : {},
|
|
113513
|
-
max: { type: "integer", minimum: 1, maximum: 100, description: "Most events to return (default 25)." }
|
|
113514
|
-
},
|
|
113515
|
-
required: ["timeMin", "timeMax"],
|
|
113516
|
-
additionalProperties: false
|
|
113517
|
-
});
|
|
113518
|
-
var createEventSchema = (withCalendar) => ({
|
|
113519
|
-
type: "object",
|
|
113520
|
-
properties: {
|
|
113521
|
-
account: accountArg,
|
|
113522
|
-
summary: { type: "string", description: "Event title." },
|
|
113523
|
-
start: { type: "string", description: "YYYY-MM-DD for an all-day event, or an ISO 8601 date-time. Without an offset, pass timeZone." },
|
|
113524
|
-
end: { type: "string", description: "Same format as start. For all-day events this is the day after the last day." },
|
|
113525
|
-
timeZone: { type: "string", description: "IANA time zone such as America/Los_Angeles, used when start/end have no offset." },
|
|
113526
|
-
description: { type: "string" },
|
|
113527
|
-
location: { type: "string" },
|
|
113528
|
-
attendees: { type: "array", items: { type: "string" }, description: "Guest email addresses. They receive an invitation." },
|
|
113529
|
-
...withCalendar ? { calendarId: { type: "string", description: "Calendar id; defaults to the primary calendar." } } : {}
|
|
113530
|
-
},
|
|
113531
|
-
required: ["summary", "start", "end"],
|
|
113532
|
-
additionalProperties: false
|
|
113533
|
-
});
|
|
113534
114099
|
var ACCOUNT_TOOLS = [
|
|
113535
114100
|
{ name: "list_accounts", provider: null, description: "List the Google and Microsoft accounts this bot may use, by email.", inputSchema: { type: "object", properties: {}, additionalProperties: false }, annotations: READS, args: listAccountsArgs },
|
|
113536
114101
|
{ name: "gmail_search", provider: "google", family: "gmail", description: "Search Gmail with Gmail search syntax (e.g. from:alex newer_than:7d). Returns message ids, senders, subjects, dates and snippets.", inputSchema: searchSchema("Gmail search query."), annotations: READS, args: searchArgs },
|
|
113537
114102
|
{ name: "gmail_read", provider: "google", family: "gmail", description: "Read one Gmail message by id: headers, plain-text body and attachment names.", inputSchema: idSchema("id", "Message id from gmail_search."), annotations: READS, args: idArgs("id") },
|
|
113538
114103
|
{ name: "gmail_create_draft", provider: "google", family: "gmailSend", description: "Create a plain-text Gmail draft. Nothing is sent until gmail_send_draft.", inputSchema: draftSchema, annotations: CREATES, args: draftArgs },
|
|
113539
114104
|
{ name: "gmail_send_draft", provider: "google", family: "gmailSend", description: "Send an existing Gmail draft by its draft id.", inputSchema: idSchema("draftId", "Draft id from gmail_create_draft."), annotations: SENDS, args: idArgs("draftId") },
|
|
113540
|
-
|
|
113541
|
-
{ name: "calendar_create_event", provider: "google", family: "calendar", description: "Create a Google Calendar event. Attendees receive an invitation.", inputSchema: createEventSchema(true), annotations: SENDS, args: createEventArgs },
|
|
114105
|
+
...GOOGLE_CALENDAR_TOOLS,
|
|
113542
114106
|
{ name: "drive_search", provider: "google", family: "drive", description: "Search Google Drive files by words in their name or content.", inputSchema: searchSchema("Words to look for."), annotations: READS, args: searchArgs },
|
|
113543
114107
|
{ name: "drive_read", provider: "google", family: "drive", description: "Read a Google Drive file by id: text for Docs, Sheets (CSV), Slides, Office and text files; details and a link otherwise.", inputSchema: idSchema("fileId", "File id from drive_search."), annotations: READS, args: idArgs("fileId") },
|
|
113544
114108
|
{ name: "outlook_search", provider: "microsoft", family: "outlook", description: "Search Outlook mail by words (sender, subject, body). Returns message ids, senders, subjects, dates and previews.", inputSchema: searchSchema("Words to search for."), annotations: READS, args: searchArgs },
|
|
113545
114109
|
{ name: "outlook_read", provider: "microsoft", family: "outlook", description: "Read one Outlook message by id: headers and plain-text body.", inputSchema: idSchema("id", "Message id from outlook_search."), annotations: READS, args: idArgs("id") },
|
|
113546
114110
|
{ name: "outlook_create_draft", provider: "microsoft", family: "outlook", description: "Create a plain-text Outlook draft. Nothing is sent until outlook_send_draft.", inputSchema: draftSchema, annotations: CREATES, args: draftArgs },
|
|
113547
114111
|
{ name: "outlook_send_draft", provider: "microsoft", family: "outlook", description: "Send an existing Outlook draft by its id.", inputSchema: idSchema("draftId", "Draft id from outlook_create_draft."), annotations: SENDS, args: idArgs("draftId") },
|
|
113548
|
-
|
|
113549
|
-
{ name: "outlook_calendar_create_event", provider: "microsoft", family: "outlookCalendar", description: "Create an Outlook calendar event. Attendees receive an invitation.", inputSchema: createEventSchema(false), annotations: SENDS, args: createEventArgs.omit({ calendarId: true }) },
|
|
114112
|
+
...OUTLOOK_CALENDAR_TOOLS,
|
|
113550
114113
|
{ name: "onedrive_search", provider: "microsoft", family: "onedrive", description: "Search OneDrive files by words in their name or content.", inputSchema: searchSchema("Words to look for."), annotations: READS, args: searchArgs },
|
|
113551
114114
|
{ name: "onedrive_read", provider: "microsoft", family: "onedrive", description: "Read a OneDrive file by id: text for small text and Office files, details and a link otherwise.", inputSchema: idSchema("fileId", "File id from onedrive_search."), annotations: READS, args: idArgs("fileId") }
|
|
113552
114115
|
];
|
|
@@ -113557,12 +114120,6 @@ function accountToolList(providers) {
|
|
|
113557
114120
|
function isReadOnlyAccountTool(name2) {
|
|
113558
114121
|
return TOOL_BY_NAME.get(name2)?.annotations.readOnlyHint === true;
|
|
113559
114122
|
}
|
|
113560
|
-
var ToolInputError = class extends Error {
|
|
113561
|
-
};
|
|
113562
|
-
function bounded2(text17, limit = MAX_RESULT_CHARS) {
|
|
113563
|
-
return text17.length <= limit ? text17 : `${text17.slice(0, limit)}
|
|
113564
|
-
[truncated: ask for less]`;
|
|
113565
|
-
}
|
|
113566
114123
|
function describeIssues(error51) {
|
|
113567
114124
|
return error51.issues.slice(0, 5).map((issue2) => `${issue2.path.join(".") || "arguments"}: ${issue2.message}`).join("; ");
|
|
113568
114125
|
}
|
|
@@ -113579,109 +114136,9 @@ function resolveAccount(provider, allowed, requested) {
|
|
|
113579
114136
|
if (candidates.length === 1) return candidates[0];
|
|
113580
114137
|
throw new ToolInputError(`Pass account: this bot has more than one ${label} account (${candidates.map((account2) => account2.email).join(", ")}).`);
|
|
113581
114138
|
}
|
|
113582
|
-
function addresses(value, field) {
|
|
113583
|
-
if (value === void 0) return [];
|
|
113584
|
-
const list3 = (Array.isArray(value) ? value : value.split(",")).map((item) => item.trim()).filter(Boolean);
|
|
113585
|
-
if (list3.length > 50) throw new ToolInputError(`${field}: at most 50 addresses`);
|
|
113586
|
-
for (const item of list3) {
|
|
113587
|
-
if (!EMAIL2.test(item)) throw new ToolInputError(`${field}: "${item.slice(0, 80)}" is not an email address`);
|
|
113588
|
-
}
|
|
113589
|
-
return list3;
|
|
113590
|
-
}
|
|
113591
|
-
var ProviderApiError = class extends Error {
|
|
113592
|
-
status;
|
|
113593
|
-
constructor(status, message4) {
|
|
113594
|
-
super(message4);
|
|
113595
|
-
this.status = status;
|
|
113596
|
-
}
|
|
113597
|
-
};
|
|
113598
|
-
async function readLimited(response, limit) {
|
|
113599
|
-
const declared = Number(response.headers.get("content-length") ?? "0");
|
|
113600
|
-
if (declared > limit) {
|
|
113601
|
-
await response.body?.cancel().catch(() => {
|
|
113602
|
-
});
|
|
113603
|
-
return null;
|
|
113604
|
-
}
|
|
113605
|
-
if (!response.body) return Buffer.alloc(0);
|
|
113606
|
-
const reader = response.body.getReader();
|
|
113607
|
-
const chunks = [];
|
|
113608
|
-
let size = 0;
|
|
113609
|
-
for (; ; ) {
|
|
113610
|
-
const { done, value } = await reader.read();
|
|
113611
|
-
if (done) break;
|
|
113612
|
-
size += value.byteLength;
|
|
113613
|
-
if (size > limit) {
|
|
113614
|
-
await reader.cancel().catch(() => {
|
|
113615
|
-
});
|
|
113616
|
-
return null;
|
|
113617
|
-
}
|
|
113618
|
-
chunks.push(value);
|
|
113619
|
-
}
|
|
113620
|
-
return Buffer.concat(chunks);
|
|
113621
|
-
}
|
|
113622
|
-
function providerErrorMessage(body, status) {
|
|
113623
|
-
const error51 = body?.error;
|
|
113624
|
-
const message4 = typeof error51 === "string" ? error51 : error51 && typeof error51 === "object" && typeof error51.message === "string" ? error51.message : "";
|
|
113625
|
-
return (message4 || `request failed with HTTP ${status}`).split(/\r?\n/)[0].slice(0, 300);
|
|
113626
|
-
}
|
|
113627
|
-
async function call(ctx, account2, url2, init) {
|
|
113628
|
-
const fetcher = ctx.fetch ?? fetch;
|
|
113629
|
-
const { expect, ...request4 } = init;
|
|
113630
|
-
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
113631
|
-
const token = await ctx.accessToken(account2.id);
|
|
113632
|
-
const headers = new Headers(request4.headers);
|
|
113633
|
-
headers.set("authorization", `Bearer ${token}`);
|
|
113634
|
-
if (!headers.has("accept") && expect === "json") headers.set("accept", "application/json");
|
|
113635
|
-
const response = await fetcher(url2, { ...request4, headers, signal: AbortSignal.timeout(HTTP_TIMEOUT_MS2) });
|
|
113636
|
-
if (response.status === 401 && attempt === 0) {
|
|
113637
|
-
await response.body?.cancel().catch(() => {
|
|
113638
|
-
});
|
|
113639
|
-
ctx.invalidate(account2.id);
|
|
113640
|
-
continue;
|
|
113641
|
-
}
|
|
113642
|
-
if (!response.ok) {
|
|
113643
|
-
const raw = await readLimited(response, 64 * 1024);
|
|
113644
|
-
let body = null;
|
|
113645
|
-
try {
|
|
113646
|
-
body = raw ? JSON.parse(raw.toString("utf8")) : null;
|
|
113647
|
-
} catch {
|
|
113648
|
-
body = null;
|
|
113649
|
-
}
|
|
113650
|
-
const message4 = providerErrorMessage(body, response.status);
|
|
113651
|
-
if (response.status === 403) throw new ProviderApiError(403, `${account2.email} does not allow this: ${message4}`);
|
|
113652
|
-
if (response.status === 404) throw new ProviderApiError(404, `Not found in ${account2.email}: ${message4}`);
|
|
113653
|
-
throw new ProviderApiError(response.status, `${OAUTH_PROVIDERS[account2.provider].label} refused the request for ${account2.email}: ${message4}`);
|
|
113654
|
-
}
|
|
113655
|
-
if (expect === "none") {
|
|
113656
|
-
await response.body?.cancel().catch(() => {
|
|
113657
|
-
});
|
|
113658
|
-
return void 0;
|
|
113659
|
-
}
|
|
113660
|
-
const bytes2 = await readLimited(response, expect === "json" ? MAX_JSON_BYTES : MAX_DOWNLOAD_BYTES);
|
|
113661
|
-
if (expect === "bytes") return bytes2;
|
|
113662
|
-
if (!bytes2) throw new ProviderApiError(502, "The response was too large");
|
|
113663
|
-
try {
|
|
113664
|
-
return JSON.parse(bytes2.toString("utf8"));
|
|
113665
|
-
} catch {
|
|
113666
|
-
throw new ProviderApiError(502, "The service returned an unreadable response");
|
|
113667
|
-
}
|
|
113668
|
-
}
|
|
113669
|
-
throw new ProviderApiError(401, `${account2.email} needs to sign in again: open Settings \u2192 Accounts and connect it again.`);
|
|
113670
|
-
}
|
|
113671
|
-
function parse7(schema5, value, what) {
|
|
113672
|
-
const parsed = schema5.safeParse(value);
|
|
113673
|
-
if (!parsed.success) throw new ProviderApiError(502, `Unexpected ${what} response`);
|
|
113674
|
-
return parsed.data;
|
|
113675
|
-
}
|
|
113676
|
-
function json4(value) {
|
|
113677
|
-
return JSON.stringify(value, null, 1);
|
|
113678
|
-
}
|
|
113679
114139
|
function decodeBase64Url(data) {
|
|
113680
114140
|
return data ? Buffer.from(data, "base64url").toString("utf8") : "";
|
|
113681
114141
|
}
|
|
113682
|
-
function htmlToText(html) {
|
|
113683
|
-
return html.replace(/<(script|style)[\s\S]*?<\/\1>/gi, "").replace(/<br\s*\/?>/gi, "\n").replace(/<\/(p|div|tr|li|h\d)>/gi, "\n").replace(/<[^>]+>/g, "").replace(/ /g, " ").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/\n{3,}/g, "\n\n").trim();
|
|
113684
|
-
}
|
|
113685
114142
|
function encodeHeader(value) {
|
|
113686
114143
|
return /^[\x20-\x7e]*$/.test(value) ? value : `=?UTF-8?B?${Buffer.from(value, "utf8").toString("base64")}?=`;
|
|
113687
114144
|
}
|
|
@@ -113714,7 +114171,6 @@ function readable(name2, mimeType) {
|
|
|
113714
114171
|
return Boolean(officeKind(name2, mimeType)) || TEXT_MIME.test(mimeType) || TEXT_EXTENSION2.test(name2);
|
|
113715
114172
|
}
|
|
113716
114173
|
var GMAIL = "https://gmail.googleapis.com/gmail/v1/users/me";
|
|
113717
|
-
var CALENDAR = "https://www.googleapis.com/calendar/v3";
|
|
113718
114174
|
var DRIVE2 = "https://www.googleapis.com/drive/v3";
|
|
113719
114175
|
var gmailPartSchema = external_exports.lazy(() => external_exports.object({
|
|
113720
114176
|
mimeType: external_exports.string().optional(),
|
|
@@ -113803,67 +114259,6 @@ async function gmailSendDraft(ctx, account2, args) {
|
|
|
113803
114259
|
);
|
|
113804
114260
|
return json4({ account: account2.email, sent: true, messageId: sent.id, threadId: sent.threadId });
|
|
113805
114261
|
}
|
|
113806
|
-
var googleEventSchema = external_exports.object({
|
|
113807
|
-
id: external_exports.string(),
|
|
113808
|
-
summary: external_exports.string().optional(),
|
|
113809
|
-
description: external_exports.string().optional(),
|
|
113810
|
-
location: external_exports.string().optional(),
|
|
113811
|
-
status: external_exports.string().optional(),
|
|
113812
|
-
htmlLink: external_exports.string().optional(),
|
|
113813
|
-
start: external_exports.object({ dateTime: external_exports.string().optional(), date: external_exports.string().optional(), timeZone: external_exports.string().optional() }).optional(),
|
|
113814
|
-
end: external_exports.object({ dateTime: external_exports.string().optional(), date: external_exports.string().optional(), timeZone: external_exports.string().optional() }).optional(),
|
|
113815
|
-
organizer: external_exports.object({ email: external_exports.string().optional() }).optional(),
|
|
113816
|
-
attendees: external_exports.array(external_exports.object({ email: external_exports.string().optional(), responseStatus: external_exports.string().optional() })).optional()
|
|
113817
|
-
});
|
|
113818
|
-
function googleEvent(event) {
|
|
113819
|
-
return {
|
|
113820
|
-
id: event.id,
|
|
113821
|
-
summary: event.summary,
|
|
113822
|
-
start: event.start?.dateTime ?? event.start?.date,
|
|
113823
|
-
end: event.end?.dateTime ?? event.end?.date,
|
|
113824
|
-
location: event.location,
|
|
113825
|
-
organizer: event.organizer?.email,
|
|
113826
|
-
attendees: event.attendees?.map((attendee) => `${attendee.email ?? ""}${attendee.responseStatus ? ` (${attendee.responseStatus})` : ""}`),
|
|
113827
|
-
description: event.description ? bounded2(event.description, 2e3) : void 0,
|
|
113828
|
-
link: event.htmlLink
|
|
113829
|
-
};
|
|
113830
|
-
}
|
|
113831
|
-
async function calendarListEvents(ctx, account2, args) {
|
|
113832
|
-
const calendarId = encodeURIComponent(args.calendarId ?? "primary");
|
|
113833
|
-
const query = new URLSearchParams({ timeMin: args.timeMin, timeMax: args.timeMax, singleEvents: "true", orderBy: "startTime", maxResults: String(args.max ?? 25) });
|
|
113834
|
-
const list3 = parse7(external_exports.object({ items: external_exports.array(googleEventSchema).optional(), timeZone: external_exports.string().optional() }), await call(ctx, account2, `${CALENDAR}/calendars/${calendarId}/events?${query}`, { expect: "json" }), "Calendar");
|
|
113835
|
-
return json4({ account: account2.email, timeZone: list3.timeZone, events: (list3.items ?? []).map(googleEvent) });
|
|
113836
|
-
}
|
|
113837
|
-
function eventTime(value, timeZone, field) {
|
|
113838
|
-
if (/^\d{4}-\d{2}-\d{2}$/.test(value)) return { allDay: true, date: value };
|
|
113839
|
-
const hasOffset = /(?:Z|[+-]\d{2}:\d{2})$/.test(value);
|
|
113840
|
-
if (!hasOffset && !timeZone) throw new ToolInputError(`${field}: add a UTC offset (e.g. 2026-10-01T15:00:00-07:00) or pass timeZone`);
|
|
113841
|
-
return { allDay: false, dateTime: value, hasOffset };
|
|
113842
|
-
}
|
|
113843
|
-
async function calendarCreateEvent(ctx, account2, args) {
|
|
113844
|
-
const start = eventTime(args.start, args.timeZone, "start");
|
|
113845
|
-
const end = eventTime(args.end, args.timeZone, "end");
|
|
113846
|
-
if (start.allDay !== end.allDay) throw new ToolInputError("start and end must both be dates or both be date-times");
|
|
113847
|
-
const attendees = addresses(args.attendees, "attendees");
|
|
113848
|
-
const time4 = (value) => value.allDay ? { date: value.date } : { dateTime: value.dateTime, ...args.timeZone ? { timeZone: args.timeZone } : {} };
|
|
113849
|
-
const body = {
|
|
113850
|
-
summary: args.summary,
|
|
113851
|
-
...args.description ? { description: args.description } : {},
|
|
113852
|
-
...args.location ? { location: args.location } : {},
|
|
113853
|
-
start: time4(start),
|
|
113854
|
-
end: time4(end),
|
|
113855
|
-
...attendees.length ? { attendees: attendees.map((email3) => ({ email: email3 })) } : {}
|
|
113856
|
-
};
|
|
113857
|
-
const calendarId = encodeURIComponent(args.calendarId ?? "primary");
|
|
113858
|
-
const query = new URLSearchParams({ sendUpdates: attendees.length ? "all" : "none" });
|
|
113859
|
-
const created = parse7(googleEventSchema, await call(ctx, account2, `${CALENDAR}/calendars/${calendarId}/events?${query}`, {
|
|
113860
|
-
method: "POST",
|
|
113861
|
-
headers: { "content-type": "application/json" },
|
|
113862
|
-
body: JSON.stringify(body),
|
|
113863
|
-
expect: "json"
|
|
113864
|
-
}), "Calendar");
|
|
113865
|
-
return json4({ account: account2.email, created: googleEvent(created) });
|
|
113866
|
-
}
|
|
113867
114262
|
var driveFileSchema = external_exports.object({
|
|
113868
114263
|
id: external_exports.string(),
|
|
113869
114264
|
name: external_exports.string().optional(),
|
|
@@ -113908,8 +114303,6 @@ async function driveRead(ctx, account2, args) {
|
|
|
113908
114303
|
const text17 = bytes2 ? exportType ? bytes2.toString("utf8") : fileText(file2.name ?? "", mimeType, bytes2) : null;
|
|
113909
114304
|
return json4(text17 === null ? { ...details, note: "This file's text cannot be read here; share the link instead." } : { ...details, text: bounded2(text17, MAX_FILE_TEXT_CHARS) });
|
|
113910
114305
|
}
|
|
113911
|
-
var GRAPH = "https://graph.microsoft.com/v1.0";
|
|
113912
|
-
var graphRecipient = external_exports.object({ emailAddress: external_exports.object({ address: external_exports.string().optional(), name: external_exports.string().optional() }).optional() });
|
|
113913
114306
|
var graphMessageSchema = external_exports.object({
|
|
113914
114307
|
id: external_exports.string(),
|
|
113915
114308
|
conversationId: external_exports.string().optional(),
|
|
@@ -113923,11 +114316,6 @@ var graphMessageSchema = external_exports.object({
|
|
|
113923
114316
|
hasAttachments: external_exports.boolean().optional(),
|
|
113924
114317
|
body: external_exports.object({ contentType: external_exports.string().optional(), content: external_exports.string().optional() }).optional()
|
|
113925
114318
|
});
|
|
113926
|
-
function recipient(value) {
|
|
113927
|
-
const address2 = value?.emailAddress?.address;
|
|
113928
|
-
const name2 = value?.emailAddress?.name;
|
|
113929
|
-
return address2 ? name2 && name2 !== address2 ? `${name2} <${address2}>` : address2 : void 0;
|
|
113930
|
-
}
|
|
113931
114319
|
async function outlookSearch(ctx, account2, args) {
|
|
113932
114320
|
const query = new URLSearchParams({
|
|
113933
114321
|
$search: `"${args.q.replace(/["\\]/g, " ")}"`,
|
|
@@ -113990,78 +114378,6 @@ async function outlookSendDraft(ctx, account2, args) {
|
|
|
113990
114378
|
await call(ctx, account2, `${GRAPH}/me/messages/${encodeURIComponent(args.draftId)}/send`, { method: "POST", expect: "none" });
|
|
113991
114379
|
return json4({ account: account2.email, sent: true, draftId: args.draftId });
|
|
113992
114380
|
}
|
|
113993
|
-
var graphTime = external_exports.object({ dateTime: external_exports.string().optional(), timeZone: external_exports.string().optional() });
|
|
113994
|
-
var graphEventSchema = external_exports.object({
|
|
113995
|
-
id: external_exports.string(),
|
|
113996
|
-
subject: external_exports.string().nullable().optional(),
|
|
113997
|
-
start: graphTime.optional(),
|
|
113998
|
-
end: graphTime.optional(),
|
|
113999
|
-
isAllDay: external_exports.boolean().optional(),
|
|
114000
|
-
location: external_exports.object({ displayName: external_exports.string().optional() }).nullable().optional(),
|
|
114001
|
-
organizer: graphRecipient.nullable().optional(),
|
|
114002
|
-
attendees: external_exports.array(graphRecipient.extend({ status: external_exports.object({ response: external_exports.string().optional() }).optional() })).optional(),
|
|
114003
|
-
webLink: external_exports.string().optional(),
|
|
114004
|
-
bodyPreview: external_exports.string().optional()
|
|
114005
|
-
});
|
|
114006
|
-
function graphEvent(event) {
|
|
114007
|
-
return {
|
|
114008
|
-
id: event.id,
|
|
114009
|
-
summary: event.subject,
|
|
114010
|
-
start: event.start?.dateTime ? `${event.start.dateTime}${event.start.timeZone === "UTC" ? "Z" : ` (${event.start.timeZone ?? ""})`}` : void 0,
|
|
114011
|
-
end: event.end?.dateTime ? `${event.end.dateTime}${event.end.timeZone === "UTC" ? "Z" : ` (${event.end.timeZone ?? ""})`}` : void 0,
|
|
114012
|
-
allDay: event.isAllDay,
|
|
114013
|
-
location: event.location?.displayName || void 0,
|
|
114014
|
-
organizer: recipient(event.organizer),
|
|
114015
|
-
attendees: event.attendees?.map((attendee) => `${recipient(attendee) ?? ""}${attendee.status?.response ? ` (${attendee.status.response})` : ""}`),
|
|
114016
|
-
preview: event.bodyPreview ? bounded2(event.bodyPreview, 1e3) : void 0,
|
|
114017
|
-
link: event.webLink
|
|
114018
|
-
};
|
|
114019
|
-
}
|
|
114020
|
-
async function outlookListEvents(ctx, account2, args) {
|
|
114021
|
-
const query = new URLSearchParams({
|
|
114022
|
-
startDateTime: new Date(args.timeMin).toISOString(),
|
|
114023
|
-
endDateTime: new Date(args.timeMax).toISOString(),
|
|
114024
|
-
$top: String(args.max ?? 25),
|
|
114025
|
-
$orderby: "start/dateTime",
|
|
114026
|
-
$select: "id,subject,start,end,isAllDay,location,organizer,attendees,webLink,bodyPreview"
|
|
114027
|
-
});
|
|
114028
|
-
const list3 = parse7(external_exports.object({ value: external_exports.array(graphEventSchema) }), await call(ctx, account2, `${GRAPH}/me/calendarView?${query}`, {
|
|
114029
|
-
headers: { prefer: 'outlook.timezone="UTC"' },
|
|
114030
|
-
expect: "json"
|
|
114031
|
-
}), "Outlook calendar");
|
|
114032
|
-
return json4({ account: account2.email, timeZone: "UTC", events: list3.value.map(graphEvent) });
|
|
114033
|
-
}
|
|
114034
|
-
function graphDateTime(value, timeZone, field) {
|
|
114035
|
-
if (/^\d{4}-\d{2}-\d{2}$/.test(value)) return { dateTime: `${value}T00:00:00`, timeZone: timeZone ?? "UTC", allDay: true };
|
|
114036
|
-
if (/(?:Z|[+-]\d{2}:\d{2})$/.test(value)) {
|
|
114037
|
-
const parsed = Date.parse(value);
|
|
114038
|
-
if (!Number.isFinite(parsed)) throw new ToolInputError(`${field}: not a valid date-time`);
|
|
114039
|
-
return { dateTime: new Date(parsed).toISOString().replace(/\.\d{3}Z$/, ""), timeZone: "UTC", allDay: false };
|
|
114040
|
-
}
|
|
114041
|
-
if (!timeZone) throw new ToolInputError(`${field}: add a UTC offset (e.g. 2026-10-01T15:00:00-07:00) or pass timeZone`);
|
|
114042
|
-
return { dateTime: value, timeZone, allDay: false };
|
|
114043
|
-
}
|
|
114044
|
-
async function outlookCreateEvent(ctx, account2, args) {
|
|
114045
|
-
const start = graphDateTime(args.start, args.timeZone, "start");
|
|
114046
|
-
const end = graphDateTime(args.end, args.timeZone, "end");
|
|
114047
|
-
if (start.allDay !== end.allDay) throw new ToolInputError("start and end must both be dates or both be date-times");
|
|
114048
|
-
const attendees = addresses(args.attendees, "attendees");
|
|
114049
|
-
const created = parse7(graphEventSchema, await call(ctx, account2, `${GRAPH}/me/events`, {
|
|
114050
|
-
method: "POST",
|
|
114051
|
-
headers: { "content-type": "application/json", prefer: 'outlook.timezone="UTC"' },
|
|
114052
|
-
body: JSON.stringify({
|
|
114053
|
-
subject: args.summary,
|
|
114054
|
-
...args.description ? { body: { contentType: "Text", content: args.description } } : {},
|
|
114055
|
-
start: { dateTime: start.dateTime, timeZone: start.timeZone },
|
|
114056
|
-
end: { dateTime: end.dateTime, timeZone: end.timeZone },
|
|
114057
|
-
...start.allDay ? { isAllDay: true } : {},
|
|
114058
|
-
...args.location ? { location: { displayName: args.location } } : {},
|
|
114059
|
-
...attendees.length ? { attendees: attendees.map((address2) => ({ emailAddress: { address: address2 }, type: "required" })) } : {}
|
|
114060
|
-
}),
|
|
114061
|
-
expect: "json"
|
|
114062
|
-
}), "Outlook calendar");
|
|
114063
|
-
return json4({ account: account2.email, created: graphEvent(created) });
|
|
114064
|
-
}
|
|
114065
114381
|
var driveItemSchema = external_exports.object({
|
|
114066
114382
|
id: external_exports.string(),
|
|
114067
114383
|
name: external_exports.string().optional(),
|
|
@@ -114098,16 +114414,13 @@ var RUNNERS = {
|
|
|
114098
114414
|
gmail_read: gmailRead,
|
|
114099
114415
|
gmail_create_draft: gmailCreateDraft,
|
|
114100
114416
|
gmail_send_draft: gmailSendDraft,
|
|
114101
|
-
|
|
114102
|
-
calendar_create_event: calendarCreateEvent,
|
|
114417
|
+
...CALENDAR_RUNNERS,
|
|
114103
114418
|
drive_search: driveSearch,
|
|
114104
114419
|
drive_read: driveRead,
|
|
114105
114420
|
outlook_search: outlookSearch,
|
|
114106
114421
|
outlook_read: outlookRead,
|
|
114107
114422
|
outlook_create_draft: outlookCreateDraft,
|
|
114108
114423
|
outlook_send_draft: outlookSendDraft,
|
|
114109
|
-
outlook_calendar_list_events: outlookListEvents,
|
|
114110
|
-
outlook_calendar_create_event: outlookCreateEvent,
|
|
114111
114424
|
onedrive_search: onedriveSearch,
|
|
114112
114425
|
onedrive_read: onedriveRead
|
|
114113
114426
|
};
|
|
@@ -121539,6 +121852,11 @@ function checkCleanup(input, output) {
|
|
|
121539
121852
|
const kept = new Set(contentTokens(cleaned));
|
|
121540
121853
|
if (tokens.filter((t) => kept.has(t)).length / tokens.length < 0.6) return { ok: false, reason: "overlap" };
|
|
121541
121854
|
}
|
|
121855
|
+
const spoken2 = new Set(contentTokens(input));
|
|
121856
|
+
const written = new Set(contentTokens(cleaned));
|
|
121857
|
+
const added = [...written].filter((t) => !spoken2.has(t)).length;
|
|
121858
|
+
const removed = [...spoken2].filter((t) => !written.has(t)).length;
|
|
121859
|
+
if (added > removed + 1) return { ok: false, reason: "added" };
|
|
121542
121860
|
return { ok: true, text: cleaned };
|
|
121543
121861
|
}
|
|
121544
121862
|
async function ask(provider, prompt, timeoutMs) {
|