@rubytech/create-maxy-code 0.1.414 → 0.1.417
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/__tests__/outlook-client-id-env.test.js +46 -0
- package/dist/index.js +31 -0
- package/dist/port-resolution.js +8 -1
- package/package.json +1 -1
- package/payload/platform/config/brand.json +1 -0
- package/payload/platform/lib/account-enumeration/dist/__tests__/is-provisioned.test.d.ts +2 -0
- package/payload/platform/lib/account-enumeration/dist/__tests__/is-provisioned.test.d.ts.map +1 -0
- package/payload/platform/lib/account-enumeration/dist/__tests__/is-provisioned.test.js +81 -0
- package/payload/platform/lib/account-enumeration/dist/__tests__/is-provisioned.test.js.map +1 -0
- package/payload/platform/lib/account-enumeration/dist/index.d.ts +17 -0
- package/payload/platform/lib/account-enumeration/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/account-enumeration/dist/index.js +46 -9
- package/payload/platform/lib/account-enumeration/dist/index.js.map +1 -1
- package/payload/platform/lib/account-enumeration/src/__tests__/is-provisioned.test.ts +86 -0
- package/payload/platform/lib/account-enumeration/src/index.ts +45 -9
- package/payload/platform/lib/account-scope/dist/index.d.ts +14 -5
- package/payload/platform/lib/account-scope/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/account-scope/dist/index.js +14 -5
- package/payload/platform/lib/account-scope/dist/index.js.map +1 -1
- package/payload/platform/lib/account-scope/src/index.ts +22 -5
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +43 -10
- package/payload/platform/plugins/docs/references/outlook-guide.md +42 -9
- package/payload/platform/plugins/email/references/email-reference.md +1 -1
- package/payload/platform/plugins/filesystem/PLUGIN.md +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.js +16 -2
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js +8 -3
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.js +2 -2
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.js.map +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +2 -2
- package/payload/platform/plugins/memory/mcp/dist/index-testable.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index-testable.js +14 -5
- package/payload/platform/plugins/memory/mcp/dist/index-testable.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +6 -2
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/neo4j-constraint.d.ts +29 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/neo4j-constraint.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/neo4j-constraint.js +44 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/neo4j-constraint.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/owner-person-embed-text.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/owner-person-embed-text.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/owner-person-embed-text.test.js +22 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/owner-person-embed-text.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-bootstrap.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-bootstrap.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-bootstrap.test.js +204 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-bootstrap.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-embed.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-embed.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-embed.test.js +78 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-embed.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/resolve-tool-account.test.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/resolve-tool-account.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts +0 -5
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +2 -12
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts +17 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +137 -6
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
- package/payload/platform/plugins/outlook/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/outlook/PLUGIN.md +40 -7
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/account-register.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/account-register.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/account-register.test.js +137 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/account-register.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/calendar-write.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/calendar-write.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/calendar-write.test.js +186 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/calendar-write.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/device-flow.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/device-flow.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/device-flow.test.js +110 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/device-flow.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client-retry.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client-retry.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client-retry.test.js +108 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client-retry.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.js +13 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/message.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/message.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/message.test.js +32 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/message.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/pending-store.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/pending-store.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/pending-store.test.js +67 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/pending-store.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.js +7 -5
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/write-tools.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/write-tools.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/write-tools.test.js +141 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/write-tools.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.d.ts +69 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.js +129 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/pending-store.d.ts +39 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/pending-store.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/pending-store.js +101 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/pending-store.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.js +3 -2
- package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/index.js +187 -5
- package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts +34 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js +96 -7
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/message.d.ts +31 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/message.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/message.js +30 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/message.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.d.ts +41 -17
- package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.js +87 -28
- package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-cancel.d.ts +17 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-cancel.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-cancel.js +38 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-cancel.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-create.d.ts +29 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-create.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-create.js +50 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-create.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-freebusy.d.ts +34 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-freebusy.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-freebusy.js +46 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-freebusy.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-respond.d.ts +15 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-respond.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-respond.js +27 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-respond.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-update.d.ts +11 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-update.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-update.js +20 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-update.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft-send.d.ts +17 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft-send.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft-send.js +26 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft-send.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.d.ts +11 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.js +26 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.d.ts +14 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.js +26 -0
- package/payload/platform/plugins/outlook/mcp/dist/tools/mail-send.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/scripts/verify-doc-impl.sh +2 -2
- package/payload/platform/plugins/outlook/references/auth.md +51 -54
- package/payload/platform/plugins/outlook/references/graph-surfaces.md +97 -4
- package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +34 -9
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +9 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.d.ts +18 -0
- package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.js +16 -0
- package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +34 -10
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +7 -2
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +9 -0
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +9 -0
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +5 -5
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.js +6 -5
- package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.js +11 -11
- package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
- package/payload/server/public/assets/{AdminLoginScreens-CYPTMmTk.js → AdminLoginScreens-CBTx7ZPK.js} +1 -1
- package/payload/server/public/assets/AdminShell-DPHUeXea.js +2 -0
- package/payload/server/public/assets/{Checkbox-B0pbYJDQ.js → Checkbox-BHTxekRB.js} +1 -1
- package/payload/server/public/assets/{Transcript-CYaAPBFX.js → Transcript-5kLbBInN.js} +1 -1
- package/payload/server/public/assets/{admin-BKDMSRto.js → admin-BWCLE32N.js} +1 -1
- package/payload/server/public/assets/{browser-CxeMDDZA.js → browser-CRvCPsvV.js} +1 -1
- package/payload/server/public/assets/{calendar-DiIiTY9-.js → calendar-BI-kd-QP.js} +1 -1
- package/payload/server/public/assets/chat-DFy8hb1y.js +1 -0
- package/payload/server/public/assets/chevron-left-Bggm5B5U.js +1 -0
- package/payload/server/public/assets/data-HvZ69Ya1.js +1 -0
- package/payload/server/public/assets/{graph-DC3dwnMZ.js → graph-BFSyW_5i.js} +1 -1
- package/payload/server/public/assets/{graph-labels-Csnovm_c.js → graph-labels-DEjD_qJh.js} +1 -1
- package/payload/server/public/assets/{maximize-2-WRUJsg5n.js → maximize-2-BcMJNeCB.js} +1 -1
- package/payload/server/public/assets/{operator-BpzeHTAw.js → operator-Dtvm9ero.js} +1 -1
- package/payload/server/public/assets/{page-8jJOxx6y.js → page-C_pm3hl3.js} +1 -1
- package/payload/server/public/assets/{page-IQDLdebG.js → page-TXi9dmaB.js} +1 -1
- package/payload/server/public/assets/{public-Dqg7jwjq.js → public-DBx3U0r8.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-BayMWwfc.js → rotate-ccw-8ti3QkeY.js} +1 -1
- package/payload/server/public/assets/useSubAccountSwitcher-BUvlETHN.css +1 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-C9aLg8yI.js → useSubAccountSwitcher-Bc5dOBdI.js} +1 -1
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +5 -5
- package/payload/server/public/chat.html +9 -9
- package/payload/server/public/data.html +8 -8
- package/payload/server/public/graph.html +9 -9
- package/payload/server/public/index.html +11 -11
- package/payload/server/public/operator.html +11 -11
- package/payload/server/public/public.html +9 -9
- package/payload/server/server.js +13 -31
- package/payload/server/public/assets/AdminShell-CZH_EZIy.js +0 -2
- package/payload/server/public/assets/chat-C56Oqvt1.js +0 -1
- package/payload/server/public/assets/chevron-left-Da-iZGi_.js +0 -1
- package/payload/server/public/assets/data-ZUdT44Ba.js +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-CRZfyJXR.css +0 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a Microsoft Graph message resource from the tool input shape shared by
|
|
3
|
+
* outlook-mail-send and outlook-draft. Graph stores one body with a single
|
|
4
|
+
* contentType, so `isHtml` chooses HTML vs Text for the whole message.
|
|
5
|
+
*/
|
|
6
|
+
function toRecipients(addrs) {
|
|
7
|
+
return (addrs ?? [])
|
|
8
|
+
.map((a) => a.trim())
|
|
9
|
+
.filter((a) => a.length > 0)
|
|
10
|
+
.map((address) => ({ emailAddress: { address } }));
|
|
11
|
+
}
|
|
12
|
+
export function buildMessage(input) {
|
|
13
|
+
const to = toRecipients(input.to);
|
|
14
|
+
if (to.length === 0) {
|
|
15
|
+
throw new Error("outlook: at least one 'to' recipient is required.");
|
|
16
|
+
}
|
|
17
|
+
const cc = toRecipients(input.cc);
|
|
18
|
+
const bcc = toRecipients(input.bcc);
|
|
19
|
+
const message = {
|
|
20
|
+
subject: input.subject,
|
|
21
|
+
body: { contentType: input.isHtml ? "HTML" : "Text", content: input.body },
|
|
22
|
+
toRecipients: to,
|
|
23
|
+
};
|
|
24
|
+
if (cc.length > 0)
|
|
25
|
+
message.ccRecipients = cc;
|
|
26
|
+
if (bcc.length > 0)
|
|
27
|
+
message.bccRecipients = bcc;
|
|
28
|
+
return message;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../src/lib/message.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAuBH,SAAS,YAAY,CAAC,KAA2B;IAC/C,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;SACjB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;SAC3B,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAmB;IAC9C,MAAM,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IACD,MAAM,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,OAAO,GAAiB;QAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE;QAC1E,YAAY,EAAE,EAAE;KACjB,CAAC;IACF,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,YAAY,GAAG,EAAE,CAAC;IAC7C,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,aAAa,GAAG,GAAG,CAAC;IAChD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -1,26 +1,50 @@
|
|
|
1
|
+
import type { PendingStore } from "../auth/pending-store.js";
|
|
1
2
|
import type { TokenStore } from "../auth/token-store.js";
|
|
2
|
-
export interface
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
export interface StartResult {
|
|
4
|
+
status: "pending";
|
|
5
|
+
userCode: string;
|
|
6
|
+
verificationUri: string;
|
|
7
|
+
verificationUriComplete: string;
|
|
8
|
+
expiresInSec: number;
|
|
9
|
+
intervalSec: number;
|
|
7
10
|
}
|
|
8
|
-
export
|
|
11
|
+
export type PollResult = {
|
|
9
12
|
status: "registered";
|
|
10
|
-
authUrl: string;
|
|
11
13
|
graphUserId: string;
|
|
12
14
|
scopes: string[];
|
|
13
15
|
tokenExpSec: number;
|
|
14
|
-
}
|
|
16
|
+
} | {
|
|
17
|
+
status: "pending";
|
|
18
|
+
intervalSec: number;
|
|
19
|
+
} | {
|
|
20
|
+
status: "expired";
|
|
21
|
+
message?: string;
|
|
22
|
+
} | {
|
|
23
|
+
status: "denied";
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Start the device-code flow: request a code, persist a pending entry, and
|
|
27
|
+
* surface the user code + verification URL. The `devicecode-issued` line is
|
|
28
|
+
* logged BEFORE returning so the code is observable even if the caller drops
|
|
29
|
+
* the result. Returns immediately — no blocking wait.
|
|
30
|
+
*/
|
|
31
|
+
export declare function runAccountRegisterStart(args: {
|
|
32
|
+
accountId: string;
|
|
33
|
+
clientId: string;
|
|
34
|
+
tenantId: string;
|
|
35
|
+
pendingStore: PendingStore;
|
|
36
|
+
}): Promise<StartResult>;
|
|
15
37
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* 4. Fetch /me to record graphUserId for log lines.
|
|
21
|
-
*
|
|
22
|
-
* The MCP tool layer prints the auth URL prominently in the tool response so
|
|
23
|
-
* the operator can paste it into the VNC browser.
|
|
38
|
+
* One poll of the device-code flow. On success, the unchanged path runs: fetch
|
|
39
|
+
* /me, persist tokens, and clear the pending entry (verified by re-stat). The
|
|
40
|
+
* TTL is checked before hitting the network so an elapsed code names its own
|
|
41
|
+
* expiry rather than surfacing an opaque error.
|
|
24
42
|
*/
|
|
25
|
-
export declare function
|
|
43
|
+
export declare function runAccountRegisterPoll(args: {
|
|
44
|
+
accountId: string;
|
|
45
|
+
clientId: string;
|
|
46
|
+
tenantId: string;
|
|
47
|
+
tokenStore: TokenStore;
|
|
48
|
+
pendingStore: PendingStore;
|
|
49
|
+
}): Promise<PollResult>;
|
|
26
50
|
//# sourceMappingURL=account-register.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-register.d.ts","sourceRoot":"","sources":["../../src/tools/account-register.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"account-register.d.ts","sourceRoot":"","sources":["../../src/tools/account-register.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AASzD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,uBAAuB,EAAE,MAAM,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACpF;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEzB;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,YAAY,CAAC;CAC5B,GAAG,OAAO,CAAC,WAAW,CAAC,CA2BvB;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,YAAY,CAAC;CAC5B,GAAG,OAAO,CAAC,UAAU,CAAC,CA2EtB"}
|
|
@@ -1,31 +1,89 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { startDeviceCode, pollDeviceToken } from "../auth/device-flow.js";
|
|
2
2
|
import { log } from "../lib/log.js";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* 4. Fetch /me to record graphUserId for log lines.
|
|
9
|
-
*
|
|
10
|
-
* The MCP tool layer prints the auth URL prominently in the tool response so
|
|
11
|
-
* the operator can paste it into the VNC browser.
|
|
4
|
+
* Start the device-code flow: request a code, persist a pending entry, and
|
|
5
|
+
* surface the user code + verification URL. The `devicecode-issued` line is
|
|
6
|
+
* logged BEFORE returning so the code is observable even if the caller drops
|
|
7
|
+
* the result. Returns immediately — no blocking wait.
|
|
12
8
|
*/
|
|
13
|
-
export async function
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
export async function runAccountRegisterStart(args) {
|
|
10
|
+
const start = await startDeviceCode({ clientId: args.clientId, tenantId: args.tenantId });
|
|
11
|
+
const now = Date.now();
|
|
12
|
+
args.pendingStore.write({
|
|
13
|
+
deviceCode: start.deviceCode,
|
|
14
|
+
scopes: start.scopes,
|
|
15
|
+
intervalSec: start.intervalSec,
|
|
16
|
+
expiresAtMs: now + start.expiresInSec * 1000,
|
|
17
|
+
issuedAtMs: now,
|
|
18
18
|
});
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
log({
|
|
20
|
+
event: "devicecode-issued",
|
|
21
|
+
account: args.accountId,
|
|
22
|
+
userCode: start.userCode,
|
|
23
|
+
verificationUri: start.verificationUri,
|
|
24
|
+
expiresSec: start.expiresInSec,
|
|
25
|
+
intervalSec: start.intervalSec,
|
|
26
26
|
});
|
|
27
|
+
log({ event: "pending-store-census", account: args.accountId, live: args.pendingStore.census() });
|
|
28
|
+
return {
|
|
29
|
+
status: "pending",
|
|
30
|
+
userCode: start.userCode,
|
|
31
|
+
verificationUri: start.verificationUri,
|
|
32
|
+
verificationUriComplete: start.verificationUriComplete,
|
|
33
|
+
expiresInSec: start.expiresInSec,
|
|
34
|
+
intervalSec: start.intervalSec,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* One poll of the device-code flow. On success, the unchanged path runs: fetch
|
|
39
|
+
* /me, persist tokens, and clear the pending entry (verified by re-stat). The
|
|
40
|
+
* TTL is checked before hitting the network so an elapsed code names its own
|
|
41
|
+
* expiry rather than surfacing an opaque error.
|
|
42
|
+
*/
|
|
43
|
+
export async function runAccountRegisterPoll(args) {
|
|
44
|
+
const pending = args.pendingStore.read();
|
|
45
|
+
if (!pending) {
|
|
46
|
+
return {
|
|
47
|
+
status: "expired",
|
|
48
|
+
message: "No pending registration for this account. Run outlook-account-register to start.",
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const now = Date.now();
|
|
52
|
+
const elapsedSec = Math.floor((now - pending.issuedAtMs) / 1000);
|
|
53
|
+
if (now > pending.expiresAtMs) {
|
|
54
|
+
log({ event: "devicecode-expired", account: args.accountId, elapsedSec });
|
|
55
|
+
clearPending(args);
|
|
56
|
+
return { status: "expired" };
|
|
57
|
+
}
|
|
58
|
+
const outcome = await pollDeviceToken({ clientId: args.clientId, tenantId: args.tenantId }, pending.deviceCode);
|
|
59
|
+
if (outcome.kind === "pending") {
|
|
60
|
+
log({ event: "devicecode-poll", account: args.accountId, status: "pending", elapsedSec });
|
|
61
|
+
return { status: "pending", intervalSec: pending.intervalSec };
|
|
62
|
+
}
|
|
63
|
+
if (outcome.kind === "slow_down") {
|
|
64
|
+
const bumped = pending.intervalSec + 5;
|
|
65
|
+
args.pendingStore.write({ ...pending, intervalSec: bumped });
|
|
66
|
+
log({ event: "devicecode-poll", account: args.accountId, status: "pending", elapsedSec, slowDown: true });
|
|
67
|
+
return { status: "pending", intervalSec: bumped };
|
|
68
|
+
}
|
|
69
|
+
if (outcome.kind === "expired") {
|
|
70
|
+
log({ event: "devicecode-expired", account: args.accountId, elapsedSec });
|
|
71
|
+
clearPending(args);
|
|
72
|
+
return { status: "expired" };
|
|
73
|
+
}
|
|
74
|
+
if (outcome.kind === "denied") {
|
|
75
|
+
log({ event: "devicecode-denied", account: args.accountId, elapsedSec });
|
|
76
|
+
clearPending(args);
|
|
77
|
+
return { status: "denied" };
|
|
78
|
+
}
|
|
79
|
+
// success — unchanged /me + persist path
|
|
80
|
+
const { tokenResponse, scopes } = outcome;
|
|
81
|
+
const meResp = await fetch("https://graph.microsoft.com/v1.0/me?$select=id,mail,userPrincipalName", { headers: { Authorization: `Bearer ${tokenResponse.access_token}` } });
|
|
27
82
|
if (!meResp.ok) {
|
|
28
83
|
const text = await meResp.text();
|
|
84
|
+
log({ event: "me-failed", account: args.accountId, status: meResp.status });
|
|
85
|
+
// The device_code is spent; drop the pending entry so it cannot leak.
|
|
86
|
+
clearPending(args);
|
|
29
87
|
throw new Error(`Failed to fetch /me after token exchange (status=${meResp.status}): ${text}`);
|
|
30
88
|
}
|
|
31
89
|
const me = (await meResp.json());
|
|
@@ -39,12 +97,13 @@ export async function runAccountRegister(args) {
|
|
|
39
97
|
scopes: scopes.join(","),
|
|
40
98
|
tokenExpSec,
|
|
41
99
|
});
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
};
|
|
100
|
+
clearPending(args);
|
|
101
|
+
return { status: "registered", graphUserId, scopes, tokenExpSec };
|
|
102
|
+
}
|
|
103
|
+
/** Verified clear + census on every terminal poll outcome. */
|
|
104
|
+
function clearPending(args) {
|
|
105
|
+
const verified = args.pendingStore.clearVerified();
|
|
106
|
+
log({ event: "pending-cleared", account: args.accountId, verified });
|
|
107
|
+
log({ event: "pending-store-census", account: args.accountId, live: args.pendingStore.census() });
|
|
49
108
|
}
|
|
50
109
|
//# sourceMappingURL=account-register.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-register.js","sourceRoot":"","sources":["../../src/tools/account-register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"account-register.js","sourceRoot":"","sources":["../../src/tools/account-register.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { GraphClientConfig } from "../lib/graph-client.js";
|
|
2
|
+
export interface CalendarCancelArgs {
|
|
3
|
+
eventId: string;
|
|
4
|
+
comment?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface CalendarCancelResult {
|
|
7
|
+
eventId: string;
|
|
8
|
+
mode: "cancel" | "delete";
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Cancel an event. The mode is auto-determined from a lightweight pre-GET: an
|
|
12
|
+
* organiser of a meeting (has attendees) POSTs `/cancel` so attendees are
|
|
13
|
+
* notified; anything else (a personal appointment, or a meeting the account
|
|
14
|
+
* only attends) is a DELETE. The determined mode is logged and returned.
|
|
15
|
+
*/
|
|
16
|
+
export declare function runCalendarCancel(config: GraphClientConfig, args: CalendarCancelArgs): Promise<CalendarCancelResult>;
|
|
17
|
+
//# sourceMappingURL=calendar-cancel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-cancel.d.ts","sourceRoot":"","sources":["../../src/tools/calendar-cancel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC3B;AAOD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,oBAAoB,CAAC,CA8C/B"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { callGraph, postGraph, deleteGraph } from "../lib/graph-client.js";
|
|
2
|
+
import { log, trunc } from "../lib/log.js";
|
|
3
|
+
/**
|
|
4
|
+
* Cancel an event. The mode is auto-determined from a lightweight pre-GET: an
|
|
5
|
+
* organiser of a meeting (has attendees) POSTs `/cancel` so attendees are
|
|
6
|
+
* notified; anything else (a personal appointment, or a meeting the account
|
|
7
|
+
* only attends) is a DELETE. The determined mode is logged and returned.
|
|
8
|
+
*/
|
|
9
|
+
export async function runCalendarCancel(config, args) {
|
|
10
|
+
const eventId = args.eventId?.trim();
|
|
11
|
+
if (!eventId) {
|
|
12
|
+
throw new Error("calendar-cancel: eventId is required.");
|
|
13
|
+
}
|
|
14
|
+
const probe = await callGraph(config, (client) => client
|
|
15
|
+
.api(`/me/events/${encodeURIComponent(eventId)}`)
|
|
16
|
+
.select("isOrganizer,attendees")
|
|
17
|
+
.get(), { tool: "calendar-cancel" });
|
|
18
|
+
const isMeeting = probe.isOrganizer === true && (probe.attendees?.length ?? 0) > 0;
|
|
19
|
+
const mode = isMeeting ? "cancel" : "delete";
|
|
20
|
+
log({ event: "cal-cancel-request", account: config.accountId, eventId: trunc(eventId, 16), mode });
|
|
21
|
+
if (mode === "cancel") {
|
|
22
|
+
const { status } = await postGraph(config, `/me/events/${encodeURIComponent(eventId)}/cancel`, { Comment: args.comment ?? "" }, { tool: "calendar-cancel" });
|
|
23
|
+
if (status !== 202) {
|
|
24
|
+
log({ event: "event-cancel-failed", account: config.accountId, eventId: trunc(eventId, 16), mode, status });
|
|
25
|
+
throw new Error(`calendar-cancel: expected HTTP 202 from /cancel, got status=${status}.`);
|
|
26
|
+
}
|
|
27
|
+
log({ event: "event-cancelled", account: config.accountId, eventId: trunc(eventId, 16), mode, status });
|
|
28
|
+
return { eventId, mode };
|
|
29
|
+
}
|
|
30
|
+
const { status } = await deleteGraph(config, `/me/events/${encodeURIComponent(eventId)}`, { tool: "calendar-cancel" });
|
|
31
|
+
if (status !== 204) {
|
|
32
|
+
log({ event: "event-cancel-failed", account: config.accountId, eventId: trunc(eventId, 16), mode, status });
|
|
33
|
+
throw new Error(`calendar-cancel: expected HTTP 204 from delete, got status=${status}.`);
|
|
34
|
+
}
|
|
35
|
+
log({ event: "event-cancelled", account: config.accountId, eventId: trunc(eventId, 16), mode, status });
|
|
36
|
+
return { eventId, mode };
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=calendar-cancel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-cancel.js","sourceRoot":"","sources":["../../src/tools/calendar-cancel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { GraphClientConfig } from "../lib/graph-client.js";
|
|
2
|
+
export interface EventTime {
|
|
3
|
+
dateTime: string;
|
|
4
|
+
timeZone: string;
|
|
5
|
+
}
|
|
6
|
+
export interface EventAttendee {
|
|
7
|
+
email: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
type?: "required" | "optional" | "resource";
|
|
10
|
+
}
|
|
11
|
+
/** Fields shared by create (subject/start/end required) and update (all optional). */
|
|
12
|
+
export interface EventInput {
|
|
13
|
+
subject?: string;
|
|
14
|
+
start?: EventTime;
|
|
15
|
+
end?: EventTime;
|
|
16
|
+
body?: string;
|
|
17
|
+
attendees?: EventAttendee[];
|
|
18
|
+
location?: string;
|
|
19
|
+
isOnlineMeeting?: boolean;
|
|
20
|
+
recurrence?: unknown;
|
|
21
|
+
}
|
|
22
|
+
export interface CalendarCreateResult {
|
|
23
|
+
eventId: string;
|
|
24
|
+
webLink: string | null;
|
|
25
|
+
}
|
|
26
|
+
/** Build a Graph event body from the supplied fields only. Unset keys are omitted. */
|
|
27
|
+
export declare function buildEventBody(input: EventInput): Record<string, unknown>;
|
|
28
|
+
export declare function runCalendarCreate(config: GraphClientConfig, args: EventInput): Promise<CalendarCreateResult>;
|
|
29
|
+
//# sourceMappingURL=calendar-create.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-create.d.ts","sourceRoot":"","sources":["../../src/tools/calendar-create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;CAC7C;AAED,sFAAsF;AACtF,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgBzE;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,oBAAoB,CAAC,CA0B/B"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { postGraph } from "../lib/graph-client.js";
|
|
2
|
+
import { log, trunc } from "../lib/log.js";
|
|
3
|
+
/** Build a Graph event body from the supplied fields only. Unset keys are omitted. */
|
|
4
|
+
export function buildEventBody(input) {
|
|
5
|
+
const body = {};
|
|
6
|
+
if (input.subject !== undefined)
|
|
7
|
+
body.subject = input.subject;
|
|
8
|
+
if (input.start !== undefined)
|
|
9
|
+
body.start = input.start;
|
|
10
|
+
if (input.end !== undefined)
|
|
11
|
+
body.end = input.end;
|
|
12
|
+
if (input.body !== undefined)
|
|
13
|
+
body.body = { contentType: "HTML", content: input.body };
|
|
14
|
+
if (input.location !== undefined)
|
|
15
|
+
body.location = { displayName: input.location };
|
|
16
|
+
if (input.attendees !== undefined) {
|
|
17
|
+
body.attendees = input.attendees.map((a) => ({
|
|
18
|
+
emailAddress: { address: a.email, name: a.name },
|
|
19
|
+
type: a.type ?? "required",
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
if (input.isOnlineMeeting !== undefined)
|
|
23
|
+
body.isOnlineMeeting = input.isOnlineMeeting;
|
|
24
|
+
if (input.recurrence !== undefined)
|
|
25
|
+
body.recurrence = input.recurrence;
|
|
26
|
+
return body;
|
|
27
|
+
}
|
|
28
|
+
export async function runCalendarCreate(config, args) {
|
|
29
|
+
if (!args.subject || !args.start || !args.end) {
|
|
30
|
+
throw new Error("calendar-create: subject, start, and end are required.");
|
|
31
|
+
}
|
|
32
|
+
const graphBody = buildEventBody(args);
|
|
33
|
+
log({ event: "cal-create-request", account: config.accountId, subj: trunc(args.subject, 64) });
|
|
34
|
+
const { status, json } = await postGraph(config, "/me/events", graphBody, {
|
|
35
|
+
tool: "calendar-create",
|
|
36
|
+
});
|
|
37
|
+
const body = json;
|
|
38
|
+
if (status !== 201 || !body?.id) {
|
|
39
|
+
log({
|
|
40
|
+
event: "event-create-failed",
|
|
41
|
+
account: config.accountId,
|
|
42
|
+
status,
|
|
43
|
+
graphError: body ? "no-event-id" : "empty-body",
|
|
44
|
+
});
|
|
45
|
+
throw new Error(`calendar-create: expected HTTP 201 with an event id, got status=${status}.`);
|
|
46
|
+
}
|
|
47
|
+
log({ event: "event-created", account: config.accountId, eventId: trunc(body.id, 16), status });
|
|
48
|
+
return { eventId: body.id, webLink: body.webLink ?? null };
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=calendar-create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-create.js","sourceRoot":"","sources":["../../src/tools/calendar-create.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { GraphClientConfig } from "../lib/graph-client.js";
|
|
2
|
+
import type { EventTime } from "./calendar-create.js";
|
|
3
|
+
export interface FreebusyArgs {
|
|
4
|
+
schedules: string[];
|
|
5
|
+
start: EventTime;
|
|
6
|
+
end: EventTime;
|
|
7
|
+
intervalMinutes?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface FreebusyBusyBlock {
|
|
10
|
+
start: string;
|
|
11
|
+
end: string;
|
|
12
|
+
status: string;
|
|
13
|
+
}
|
|
14
|
+
export interface FreebusyEntry {
|
|
15
|
+
address: string;
|
|
16
|
+
availabilityView: string;
|
|
17
|
+
busy: FreebusyBusyBlock[];
|
|
18
|
+
error: string | null;
|
|
19
|
+
}
|
|
20
|
+
export interface FreebusyResult {
|
|
21
|
+
requested: number;
|
|
22
|
+
resolved: number;
|
|
23
|
+
availability: FreebusyEntry[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Query free/busy for one or more addresses (POST /me/calendar/getSchedule).
|
|
27
|
+
* Graph returns one entry per requested address; an address it cannot resolve
|
|
28
|
+
* (bad address, no permission) comes back with an `error` and an empty
|
|
29
|
+
* availabilityView rather than being omitted. `resolved` counts only the
|
|
30
|
+
* error-free entries, so `resolved < requested` is the partial-result signal
|
|
31
|
+
* and each failed address carries its Graph error rather than reading as free.
|
|
32
|
+
*/
|
|
33
|
+
export declare function runCalendarFreebusy(config: GraphClientConfig, args: FreebusyArgs): Promise<FreebusyResult>;
|
|
34
|
+
//# sourceMappingURL=calendar-freebusy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-freebusy.d.ts","sourceRoot":"","sources":["../../src/tools/calendar-freebusy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,GAAG,EAAE,SAAS,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,iBAAiB,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,aAAa,EAAE,CAAC;CAC/B;AAaD;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,cAAc,CAAC,CAuCzB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { postGraph } from "../lib/graph-client.js";
|
|
2
|
+
import { log } from "../lib/log.js";
|
|
3
|
+
/**
|
|
4
|
+
* Query free/busy for one or more addresses (POST /me/calendar/getSchedule).
|
|
5
|
+
* Graph returns one entry per requested address; an address it cannot resolve
|
|
6
|
+
* (bad address, no permission) comes back with an `error` and an empty
|
|
7
|
+
* availabilityView rather than being omitted. `resolved` counts only the
|
|
8
|
+
* error-free entries, so `resolved < requested` is the partial-result signal
|
|
9
|
+
* and each failed address carries its Graph error rather than reading as free.
|
|
10
|
+
*/
|
|
11
|
+
export async function runCalendarFreebusy(config, args) {
|
|
12
|
+
const schedules = args.schedules?.filter((s) => s && s.trim().length > 0) ?? [];
|
|
13
|
+
if (schedules.length === 0) {
|
|
14
|
+
throw new Error("calendar-freebusy: at least one schedule address is required.");
|
|
15
|
+
}
|
|
16
|
+
const requested = schedules.length;
|
|
17
|
+
log({ event: "freebusy-request", account: config.accountId, requested });
|
|
18
|
+
const graphBody = {
|
|
19
|
+
schedules,
|
|
20
|
+
startTime: args.start,
|
|
21
|
+
endTime: args.end,
|
|
22
|
+
availabilityViewInterval: args.intervalMinutes ?? 60,
|
|
23
|
+
};
|
|
24
|
+
const { status, json } = await postGraph(config, "/me/calendar/getSchedule", graphBody, {
|
|
25
|
+
tool: "calendar-freebusy",
|
|
26
|
+
});
|
|
27
|
+
if (status !== 200) {
|
|
28
|
+
log({ event: "freebusy-failed", account: config.accountId, requested, status });
|
|
29
|
+
throw new Error(`calendar-freebusy: expected HTTP 200, got status=${status}.`);
|
|
30
|
+
}
|
|
31
|
+
const rows = json?.value ?? [];
|
|
32
|
+
const availability = rows.map((row) => ({
|
|
33
|
+
address: row.scheduleId ?? "",
|
|
34
|
+
availabilityView: row.availabilityView ?? "",
|
|
35
|
+
busy: (row.scheduleItems ?? []).map((item) => ({
|
|
36
|
+
start: item.start?.dateTime ?? "",
|
|
37
|
+
end: item.end?.dateTime ?? "",
|
|
38
|
+
status: item.status ?? "unknown",
|
|
39
|
+
})),
|
|
40
|
+
error: row.error ? (row.error.message ?? row.error.responseCode ?? "unresolved") : null,
|
|
41
|
+
}));
|
|
42
|
+
const resolved = availability.filter((entry) => entry.error === null).length;
|
|
43
|
+
log({ event: "freebusy-result", account: config.accountId, requested, resolved });
|
|
44
|
+
return { requested, resolved, availability };
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=calendar-freebusy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-freebusy.js","sourceRoot":"","sources":["../../src/tools/calendar-freebusy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAwCpC;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAyB,EACzB,IAAkB;IAElB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAChF,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IACD,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC;IACnC,GAAG,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;IAEzE,MAAM,SAAS,GAAG;QAChB,SAAS;QACT,SAAS,EAAE,IAAI,CAAC,KAAK;QACrB,OAAO,EAAE,IAAI,CAAC,GAAG;QACjB,wBAAwB,EAAE,IAAI,CAAC,eAAe,IAAI,EAAE;KACrD,CAAC;IAEF,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,0BAA0B,EAAE,SAAS,EAAE;QACtF,IAAI,EAAE,mBAAmB;KAC1B,CAAC,CAAC;IAEH,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QACnB,GAAG,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAChF,MAAM,IAAI,KAAK,CAAC,oDAAoD,MAAM,GAAG,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,IAAI,GAAI,IAAoD,EAAE,KAAK,IAAI,EAAE,CAAC;IAChF,MAAM,YAAY,GAAoB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACvD,OAAO,EAAE,GAAG,CAAC,UAAU,IAAI,EAAE;QAC7B,gBAAgB,EAAE,GAAG,CAAC,gBAAgB,IAAI,EAAE;QAC5C,IAAI,EAAE,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC7C,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,IAAI,EAAE;YACjC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,IAAI,EAAE;YAC7B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,SAAS;SACjC,CAAC,CAAC;QACH,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI;KACxF,CAAC,CAAC,CAAC;IACJ,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,MAAM,CAAC;IAE7E,GAAG,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClF,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { GraphClientConfig } from "../lib/graph-client.js";
|
|
2
|
+
export type RespondAction = "accept" | "decline" | "tentative";
|
|
3
|
+
export interface CalendarRespondArgs {
|
|
4
|
+
eventId: string;
|
|
5
|
+
action: RespondAction;
|
|
6
|
+
comment?: string;
|
|
7
|
+
sendResponse?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface CalendarRespondResult {
|
|
10
|
+
eventId: string;
|
|
11
|
+
action: RespondAction;
|
|
12
|
+
}
|
|
13
|
+
/** Respond to a meeting invite: accept, decline, or tentatively accept. */
|
|
14
|
+
export declare function runCalendarRespond(config: GraphClientConfig, args: CalendarRespondArgs): Promise<CalendarRespondResult>;
|
|
15
|
+
//# sourceMappingURL=calendar-respond.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-respond.d.ts","sourceRoot":"","sources":["../../src/tools/calendar-respond.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;AAQ/D,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,2EAA2E;AAC3E,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,qBAAqB,CAAC,CA0BhC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { postGraph } from "../lib/graph-client.js";
|
|
2
|
+
import { log, trunc } from "../lib/log.js";
|
|
3
|
+
const ENDPOINT = {
|
|
4
|
+
accept: "accept",
|
|
5
|
+
decline: "decline",
|
|
6
|
+
tentative: "tentativelyAccept",
|
|
7
|
+
};
|
|
8
|
+
/** Respond to a meeting invite: accept, decline, or tentatively accept. */
|
|
9
|
+
export async function runCalendarRespond(config, args) {
|
|
10
|
+
const eventId = args.eventId?.trim();
|
|
11
|
+
if (!eventId) {
|
|
12
|
+
throw new Error("calendar-respond: eventId is required.");
|
|
13
|
+
}
|
|
14
|
+
const endpoint = ENDPOINT[args.action];
|
|
15
|
+
if (!endpoint) {
|
|
16
|
+
throw new Error(`calendar-respond: unknown action "${args.action}".`);
|
|
17
|
+
}
|
|
18
|
+
log({ event: "cal-respond-request", account: config.accountId, eventId: trunc(eventId, 16), action: args.action });
|
|
19
|
+
const { status } = await postGraph(config, `/me/events/${encodeURIComponent(eventId)}/${endpoint}`, { Comment: args.comment ?? "", SendResponse: args.sendResponse ?? true }, { tool: "calendar-respond" });
|
|
20
|
+
if (status !== 202) {
|
|
21
|
+
log({ event: "event-respond-failed", account: config.accountId, eventId: trunc(eventId, 16), action: args.action, status });
|
|
22
|
+
throw new Error(`calendar-respond: expected HTTP 202, got status=${status}.`);
|
|
23
|
+
}
|
|
24
|
+
log({ event: "event-responded", account: config.accountId, eventId: trunc(eventId, 16), action: args.action, status });
|
|
25
|
+
return { eventId, action: args.action };
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=calendar-respond.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-respond.js","sourceRoot":"","sources":["../../src/tools/calendar-respond.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAI3C,MAAM,QAAQ,GAAkC;IAC9C,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,mBAAmB;CAC/B,CAAC;AAcF,2EAA2E;AAC3E,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAAyB,EACzB,IAAyB;IAEzB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;IACxE,CAAC;IAED,GAAG,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAEnH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAChC,MAAM,EACN,cAAc,kBAAkB,CAAC,OAAO,CAAC,IAAI,QAAQ,EAAE,EACvD,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI,EAAE,EACxE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAC7B,CAAC;IAEF,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QACnB,GAAG,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5H,MAAM,IAAI,KAAK,CAAC,mDAAmD,MAAM,GAAG,CAAC,CAAC;IAChF,CAAC;IAED,GAAG,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACvH,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { GraphClientConfig } from "../lib/graph-client.js";
|
|
2
|
+
import { type EventInput } from "./calendar-create.js";
|
|
3
|
+
export interface CalendarUpdateArgs extends EventInput {
|
|
4
|
+
eventId: string;
|
|
5
|
+
}
|
|
6
|
+
export interface CalendarUpdateResult {
|
|
7
|
+
eventId: string;
|
|
8
|
+
updated: true;
|
|
9
|
+
}
|
|
10
|
+
export declare function runCalendarUpdate(config: GraphClientConfig, args: CalendarUpdateArgs): Promise<CalendarUpdateResult>;
|
|
11
|
+
//# sourceMappingURL=calendar-update.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-update.d.ts","sourceRoot":"","sources":["../../src/tools/calendar-update.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvE,MAAM,WAAW,kBAAmB,SAAQ,UAAU;IACpD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,IAAI,CAAC;CACf;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,oBAAoB,CAAC,CAuB/B"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { patchGraph } from "../lib/graph-client.js";
|
|
2
|
+
import { log, trunc } from "../lib/log.js";
|
|
3
|
+
import { buildEventBody } from "./calendar-create.js";
|
|
4
|
+
export async function runCalendarUpdate(config, args) {
|
|
5
|
+
const eventId = args.eventId?.trim();
|
|
6
|
+
if (!eventId) {
|
|
7
|
+
throw new Error("calendar-update: eventId is required.");
|
|
8
|
+
}
|
|
9
|
+
const { eventId: _drop, ...fields } = args;
|
|
10
|
+
const graphBody = buildEventBody(fields);
|
|
11
|
+
log({ event: "cal-update-request", account: config.accountId, eventId: trunc(eventId, 16) });
|
|
12
|
+
const { status } = await patchGraph(config, `/me/events/${encodeURIComponent(eventId)}`, graphBody, { tool: "calendar-update" });
|
|
13
|
+
if (status !== 200) {
|
|
14
|
+
log({ event: "event-update-failed", account: config.accountId, eventId: trunc(eventId, 16), status });
|
|
15
|
+
throw new Error(`calendar-update: expected HTTP 200, got status=${status}.`);
|
|
16
|
+
}
|
|
17
|
+
log({ event: "event-updated", account: config.accountId, eventId: trunc(eventId, 16), status });
|
|
18
|
+
return { eventId, updated: true };
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=calendar-update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-update.js","sourceRoot":"","sources":["../../src/tools/calendar-update.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAmB,MAAM,sBAAsB,CAAC;AAWvE,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAyB,EACzB,IAAwB;IAExB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IAC3C,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACzC,GAAG,CAAC,EAAE,KAAK,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;IAE7F,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CACjC,MAAM,EACN,cAAc,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAC3C,SAAS,EACT,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAC5B,CAAC;IAEF,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QACnB,GAAG,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACtG,MAAM,IAAI,KAAK,CAAC,kDAAkD,MAAM,GAAG,CAAC,CAAC;IAC/E,CAAC;IAED,GAAG,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAChG,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACpC,CAAC"}
|