@rubytech/create-maxy 1.0.763 → 1.0.765

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/package-lock.json +56 -1
  3. package/payload/platform/package.json +1 -0
  4. package/payload/platform/plugins/docs/references/outlook-guide.md +69 -0
  5. package/payload/platform/plugins/docs/references/platform.md +1 -1
  6. package/payload/platform/plugins/outlook/PLUGIN.md +48 -0
  7. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.d.ts +2 -0
  8. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.d.ts.map +1 -0
  9. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.js +94 -0
  10. package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.js.map +1 -0
  11. package/payload/platform/plugins/outlook/mcp/dist/__tests__/log.test.d.ts +2 -0
  12. package/payload/platform/plugins/outlook/mcp/dist/__tests__/log.test.d.ts.map +1 -0
  13. package/payload/platform/plugins/outlook/mcp/dist/__tests__/log.test.js +31 -0
  14. package/payload/platform/plugins/outlook/mcp/dist/__tests__/log.test.js.map +1 -0
  15. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.d.ts +2 -0
  16. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.d.ts.map +1 -0
  17. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.js +213 -0
  18. package/payload/platform/plugins/outlook/mcp/dist/__tests__/pkce-flow.test.js.map +1 -0
  19. package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.d.ts +2 -0
  20. package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.d.ts.map +1 -0
  21. package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.js +130 -0
  22. package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.js.map +1 -0
  23. package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.d.ts +65 -0
  24. package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.d.ts.map +1 -0
  25. package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.js +261 -0
  26. package/payload/platform/plugins/outlook/mcp/dist/auth/pkce-flow.js.map +1 -0
  27. package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.d.ts +61 -0
  28. package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.d.ts.map +1 -0
  29. package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.js +170 -0
  30. package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.js.map +1 -0
  31. package/payload/platform/plugins/outlook/mcp/dist/index.d.ts +18 -0
  32. package/payload/platform/plugins/outlook/mcp/dist/index.d.ts.map +1 -0
  33. package/payload/platform/plugins/outlook/mcp/dist/index.js +152 -0
  34. package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -0
  35. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts +60 -0
  36. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts.map +1 -0
  37. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js +189 -0
  38. package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js.map +1 -0
  39. package/payload/platform/plugins/outlook/mcp/dist/lib/log.d.ts +23 -0
  40. package/payload/platform/plugins/outlook/mcp/dist/lib/log.d.ts.map +1 -0
  41. package/payload/platform/plugins/outlook/mcp/dist/lib/log.js +53 -0
  42. package/payload/platform/plugins/outlook/mcp/dist/lib/log.js.map +1 -0
  43. package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.d.ts +26 -0
  44. package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.d.ts.map +1 -0
  45. package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.js +50 -0
  46. package/payload/platform/plugins/outlook/mcp/dist/tools/account-register.js.map +1 -0
  47. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-event.d.ts +12 -0
  48. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-event.d.ts.map +1 -0
  49. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-event.js +32 -0
  50. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-event.js.map +1 -0
  51. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-list.d.ts +59 -0
  52. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-list.d.ts.map +1 -0
  53. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-list.js +54 -0
  54. package/payload/platform/plugins/outlook/mcp/dist/tools/calendar-list.js.map +1 -0
  55. package/payload/platform/plugins/outlook/mcp/dist/tools/contacts-list.d.ts +14 -0
  56. package/payload/platform/plugins/outlook/mcp/dist/tools/contacts-list.d.ts.map +1 -0
  57. package/payload/platform/plugins/outlook/mcp/dist/tools/contacts-list.js +45 -0
  58. package/payload/platform/plugins/outlook/mcp/dist/tools/contacts-list.js.map +1 -0
  59. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.d.ts +15 -0
  60. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.d.ts.map +1 -0
  61. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.js +48 -0
  62. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-list.js.map +1 -0
  63. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.d.ts +8 -0
  64. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.d.ts.map +1 -0
  65. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.js +49 -0
  66. package/payload/platform/plugins/outlook/mcp/dist/tools/mail-search.js.map +1 -0
  67. package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.d.ts +19 -0
  68. package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.d.ts.map +1 -0
  69. package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.js +58 -0
  70. package/payload/platform/plugins/outlook/mcp/dist/tools/mailbox-info.js.map +1 -0
  71. package/payload/platform/plugins/outlook/mcp/package.json +20 -0
  72. package/payload/platform/plugins/outlook/mcp/scripts/verify-doc-impl.sh +109 -0
  73. package/payload/platform/plugins/outlook/references/auth.md +118 -0
  74. package/payload/platform/plugins/outlook/references/graph-surfaces.md +114 -0
  75. package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +65 -0
  76. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  77. package/payload/server/chunk-EIQT6QDH.js +9562 -0
  78. package/payload/server/chunk-IO2WQEY4.js +9562 -0
  79. package/payload/server/chunk-TKYZ7AEB.js +3142 -0
  80. package/payload/server/client-pool-CX2MFW75.js +28 -0
  81. package/payload/server/maxy-edge.js +2 -2
  82. package/payload/server/public/assets/{admin-V6NDkEoR.js → admin-g-Fjko8R.js} +5 -5
  83. package/payload/server/public/assets/{graph-BHcUKzXh.js → graph-DHBGJFDX.js} +1 -1
  84. package/payload/server/public/assets/page-BscgOyqp.js +50 -0
  85. package/payload/server/public/graph.html +2 -2
  86. package/payload/server/public/index.html +2 -2
  87. package/payload/server/server.js +146 -39
  88. package/payload/server/public/assets/page-DxH_Opxt.js +0 -50
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/lib/log.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI5C;AAcD;;;;;;GAMG;AACH,wBAAgB,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAO7E;AAED,kFAAkF;AAClF,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEzD"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * [outlook-mcp] structured logger.
3
+ *
4
+ * Every log line is prefixed `[outlook-mcp]` and rendered as `key=value` pairs
5
+ * (Pino-compatible shape). Bearer tokens and `access_token=` query strings are
6
+ * redacted before writing — defense in depth even though tools never log them.
7
+ */
8
+ const REDACT_BEARER = /Bearer\s+[A-Za-z0-9._\-+/=]+/g;
9
+ const REDACT_ACCESS_TOKEN = /access_token=[A-Za-z0-9._\-+/=]+/g;
10
+ export function redact(value) {
11
+ return value
12
+ .replace(REDACT_BEARER, "Bearer <REDACTED>")
13
+ .replace(REDACT_ACCESS_TOKEN, "access_token=<REDACTED>");
14
+ }
15
+ function fmt(value) {
16
+ if (value === null || value === undefined)
17
+ return "null";
18
+ if (typeof value === "string") {
19
+ if (/[\s"=]/.test(value)) {
20
+ return `"${redact(value).replace(/"/g, '\\"')}"`;
21
+ }
22
+ return redact(value);
23
+ }
24
+ if (typeof value === "number" || typeof value === "boolean")
25
+ return String(value);
26
+ return `"${redact(JSON.stringify(value)).replace(/"/g, '\\"')}"`;
27
+ }
28
+ /**
29
+ * Log an event line. The first key in `fields` (typically `event`) becomes the
30
+ * top-level event tag; remaining keys are rendered as `k=v` pairs.
31
+ *
32
+ * log({ event: "mail-list", account: "abc", count: 25, elapsedMs: 320 })
33
+ * → [outlook-mcp] mail-list account=abc count=25 elapsedMs=320
34
+ */
35
+ export function log(fields) {
36
+ const { event, ...rest } = fields;
37
+ const parts = [event];
38
+ for (const [key, value] of Object.entries(rest)) {
39
+ parts.push(`${key}=${fmt(value)}`);
40
+ }
41
+ process.stderr.write(`[outlook-mcp] ${parts.join(" ")}\n`);
42
+ }
43
+ /** Truncate a string to N chars, replacing the tail with `…` if it overflowed. */
44
+ export function trunc(value, max) {
45
+ if (value.length <= max)
46
+ return value;
47
+ return value.slice(0, max - 1) + "…";
48
+ }
49
+ /** Hex-prefix of a SHA-256 challenge for log identification (8 chars). */
50
+ export function challengePrefix(challenge) {
51
+ return challenge.slice(0, 8);
52
+ }
53
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/lib/log.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,aAAa,GAAG,+BAA+B,CAAC;AACtD,MAAM,mBAAmB,GAAG,mCAAmC,CAAC;AAEhE,MAAM,UAAU,MAAM,CAAC,KAAa;IAClC,OAAO,KAAK;SACT,OAAO,CAAC,aAAa,EAAE,mBAAmB,CAAC;SAC3C,OAAO,CAAC,mBAAmB,EAAE,yBAAyB,CAAC,CAAC;AAC7D,CAAC;AAED,SAAS,GAAG,CAAC,KAAc;IACzB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACzD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;QACnD,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IAClF,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;AACnE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,CAAC,MAAmD;IACrE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;IAClC,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC;IACtB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC7D,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,KAAK,CAAC,KAAa,EAAE,GAAW;IAC9C,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,KAAK,CAAC;IACtC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;AACvC,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { TokenStore } from "../auth/token-store.js";
2
+ export interface AccountRegisterArgs {
3
+ accountId: string;
4
+ clientId: string;
5
+ tenantId: string;
6
+ tokenStore: TokenStore;
7
+ }
8
+ export interface AccountRegisterResult {
9
+ status: "registered";
10
+ authUrl: string;
11
+ graphUserId: string;
12
+ scopes: string[];
13
+ tokenExpSec: number;
14
+ }
15
+ /**
16
+ * Run the PKCE register flow end-to-end:
17
+ * 1. Bind a loopback callback server, build the auth URL, return URL to operator.
18
+ * 2. Wait for the callback (5-min timeout).
19
+ * 3. Exchange code → tokens; persist encrypted to per-account store.
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.
24
+ */
25
+ export declare function runAccountRegister(args: AccountRegisterArgs): Promise<AccountRegisterResult>;
26
+ //# sourceMappingURL=account-register.d.ts.map
@@ -0,0 +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;AAGzD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAQD;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAiDlG"}
@@ -0,0 +1,50 @@
1
+ import { startPkceFlow } from "../auth/pkce-flow.js";
2
+ import { log } from "../lib/log.js";
3
+ /**
4
+ * Run the PKCE register flow end-to-end:
5
+ * 1. Bind a loopback callback server, build the auth URL, return URL to operator.
6
+ * 2. Wait for the callback (5-min timeout).
7
+ * 3. Exchange code → tokens; persist encrypted to per-account store.
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.
12
+ */
13
+ export async function runAccountRegister(args) {
14
+ const flow = await startPkceFlow({
15
+ clientId: args.clientId,
16
+ tenantId: args.tenantId,
17
+ accountId: args.accountId,
18
+ });
19
+ process.stderr.write(`[outlook-mcp] OPERATOR ACTION: open this URL in the VNC browser to authorize Outlook for account=${args.accountId}:\n${flow.authUrl}\n`);
20
+ const { tokenResponse, scopes } = await flow.result;
21
+ // Fetch /me with the raw access token directly — bypasses TokenStore so we
22
+ // can persist a single, complete blob (with graphUserId) in one write. If
23
+ // /me fails, no tokens hit disk and the operator simply re-runs register.
24
+ const meResp = await fetch("https://graph.microsoft.com/v1.0/me?$select=id,mail,userPrincipalName", {
25
+ headers: { Authorization: `Bearer ${tokenResponse.access_token}` },
26
+ });
27
+ if (!meResp.ok) {
28
+ const text = await meResp.text();
29
+ throw new Error(`Failed to fetch /me after token exchange (status=${meResp.status}): ${text}`);
30
+ }
31
+ const me = (await meResp.json());
32
+ const graphUserId = me.id ?? me.mail ?? me.userPrincipalName ?? "unknown";
33
+ args.tokenStore.store(tokenResponse.access_token, tokenResponse.refresh_token ?? null, tokenResponse.expires_in, { graphUserId, scopes });
34
+ const tokenExpSec = Math.floor((args.tokenStore.read()?.accessTokenExpiry ?? 0) / 1000);
35
+ log({
36
+ event: "auth-ok",
37
+ account: args.accountId,
38
+ graphUserId,
39
+ scopes: scopes.join(","),
40
+ tokenExpSec,
41
+ });
42
+ return {
43
+ status: "registered",
44
+ authUrl: flow.authUrl,
45
+ graphUserId,
46
+ scopes,
47
+ tokenExpSec,
48
+ };
49
+ }
50
+ //# sourceMappingURL=account-register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-register.js","sourceRoot":"","sources":["../../src/tools/account-register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAuBpC;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAyB;IAChE,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC;QAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC,CAAC;IAEH,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oGAAoG,IAAI,CAAC,SAAS,MAAM,IAAI,CAAC,OAAO,IAAI,CACzI,CAAC;IAEF,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC;IAEpD,2EAA2E;IAC3E,0EAA0E;IAC1E,0EAA0E;IAC1E,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,uEAAuE,EAAE;QAClG,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,aAAa,CAAC,YAAY,EAAE,EAAE;KACnE,CAAC,CAAC;IACH,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,oDAAoD,MAAM,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;IACjG,CAAC;IACD,MAAM,EAAE,GAAG,CAAC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAoB,CAAC;IACpD,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,iBAAiB,IAAI,SAAS,CAAC;IAE1E,IAAI,CAAC,UAAU,CAAC,KAAK,CACnB,aAAa,CAAC,YAAY,EAC1B,aAAa,CAAC,aAAa,IAAI,IAAI,EACnC,aAAa,CAAC,UAAU,EACxB,EAAE,WAAW,EAAE,MAAM,EAAE,CACxB,CAAC;IAEF,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,iBAAiB,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACxF,GAAG,CAAC;QACF,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,IAAI,CAAC,SAAS;QACvB,WAAW;QACX,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QACxB,WAAW;KACZ,CAAC,CAAC;IAEH,OAAO;QACL,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,WAAW;QACX,MAAM;QACN,WAAW;KACZ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { GraphClientConfig } from "../lib/graph-client.js";
2
+ import { type CalendarEventItem } from "./calendar-list.js";
3
+ export interface CalendarEventArgs {
4
+ eventId: string;
5
+ }
6
+ export interface CalendarEventDetail extends CalendarEventItem {
7
+ bodyPreview: string;
8
+ body: string;
9
+ webLink: string | null;
10
+ }
11
+ export declare function runCalendarEvent(config: GraphClientConfig, args: CalendarEventArgs): Promise<CalendarEventDetail>;
12
+ //# sourceMappingURL=calendar-event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-event.d.ts","sourceRoot":"","sources":["../../src/tools/calendar-event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,OAAO,EAAc,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAoB,SAAQ,iBAAiB;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAqBD,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,mBAAmB,CAAC,CAiC9B"}
@@ -0,0 +1,32 @@
1
+ import { callGraph } from "../lib/graph-client.js";
2
+ import { log, trunc } from "../lib/log.js";
3
+ import { shapeEvent } from "./calendar-list.js";
4
+ const FIELDS = "id,subject,start,end,location,attendees,isAllDay,organizer,bodyPreview,body,webLink";
5
+ export async function runCalendarEvent(config, args) {
6
+ const eventId = args.eventId.trim();
7
+ if (!eventId) {
8
+ throw new Error("calendar-event: eventId is required.");
9
+ }
10
+ const startMs = Date.now();
11
+ const raw = await callGraph(config, async (client) => {
12
+ return (await client
13
+ .api(`/me/events/${encodeURIComponent(eventId)}`)
14
+ .select(FIELDS)
15
+ .get());
16
+ }, { tool: "calendar-event" });
17
+ const base = shapeEvent(raw);
18
+ const detail = {
19
+ ...base,
20
+ bodyPreview: (raw.bodyPreview ?? "").slice(0, 1024),
21
+ body: (raw.body?.content ?? "").slice(0, 16384),
22
+ webLink: raw.webLink ?? null,
23
+ };
24
+ log({
25
+ event: "calendar-event",
26
+ account: config.accountId,
27
+ eventId: trunc(eventId, 12),
28
+ elapsedMs: Date.now() - startMs,
29
+ });
30
+ return detail;
31
+ }
32
+ //# sourceMappingURL=calendar-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-event.js","sourceRoot":"","sources":["../../src/tools/calendar-event.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,UAAU,EAA0B,MAAM,oBAAoB,CAAC;AA6BxE,MAAM,MAAM,GAAG,qFAAqF,CAAC;AAErG,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAyB,EACzB,IAAuB;IAEvB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IACpC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE3B,MAAM,GAAG,GAAG,MAAM,SAAS,CACzB,MAAM,EACN,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,OAAO,CAAC,MAAM,MAAM;aACjB,GAAG,CAAC,cAAc,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;aAChD,MAAM,CAAC,MAAM,CAAC;aACd,GAAG,EAAE,CAAmB,CAAC;IAC9B,CAAC,EACD,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAC3B,CAAC;IAEF,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAwB;QAClC,GAAG,IAAI;QACP,WAAW,EAAE,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;QACnD,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;QAC/C,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,IAAI;KAC7B,CAAC;IAEF,GAAG,CAAC;QACF,KAAK,EAAE,gBAAgB;QACvB,OAAO,EAAE,MAAM,CAAC,SAAS;QACzB,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC3B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO;KAChC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,59 @@
1
+ import type { GraphClientConfig } from "../lib/graph-client.js";
2
+ export interface CalendarListArgs {
3
+ rangeDays?: number;
4
+ top?: number;
5
+ }
6
+ export interface CalendarEventItem {
7
+ id: string;
8
+ subject: string | null;
9
+ start: {
10
+ dateTime: string;
11
+ timeZone: string;
12
+ };
13
+ end: {
14
+ dateTime: string;
15
+ timeZone: string;
16
+ };
17
+ location: string | null;
18
+ attendees: Array<{
19
+ email: string;
20
+ name: string | null;
21
+ response: string;
22
+ }>;
23
+ isAllDay: boolean;
24
+ organizer: string | null;
25
+ }
26
+ interface RawEvent {
27
+ id: string;
28
+ subject?: string | null;
29
+ start: {
30
+ dateTime: string;
31
+ timeZone: string;
32
+ };
33
+ end: {
34
+ dateTime: string;
35
+ timeZone: string;
36
+ };
37
+ location?: {
38
+ displayName?: string;
39
+ } | null;
40
+ attendees?: Array<{
41
+ emailAddress: {
42
+ address: string;
43
+ name?: string;
44
+ };
45
+ status?: {
46
+ response?: string;
47
+ };
48
+ }>;
49
+ isAllDay?: boolean;
50
+ organizer?: {
51
+ emailAddress?: {
52
+ address?: string;
53
+ };
54
+ };
55
+ }
56
+ export declare function runCalendarList(config: GraphClientConfig, args: CalendarListArgs): Promise<CalendarEventItem[]>;
57
+ export declare function shapeEvent(ev: RawEvent): CalendarEventItem;
58
+ export {};
59
+ //# sourceMappingURL=calendar-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-list.d.ts","sourceRoot":"","sources":["../../src/tools/calendar-list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3E,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,UAAU,QAAQ;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,GAAG,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,QAAQ,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC3C,SAAS,CAAC,EAAE,KAAK,CAAC;QAChB,YAAY,EAAE;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACjD,MAAM,CAAC,EAAE;YAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAChC,CAAC,CAAC;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;CACrD;AAQD,wBAAsB,eAAe,CACnC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,iBAAiB,EAAE,CAAC,CA+B9B;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,GAAG,iBAAiB,CAgB1D"}
@@ -0,0 +1,54 @@
1
+ import { callGraph } from "../lib/graph-client.js";
2
+ import { log } from "../lib/log.js";
3
+ const FIELDS = "id,subject,start,end,location,attendees,isAllDay,organizer";
4
+ export async function runCalendarList(config, args) {
5
+ const rangeDays = clamp(args.rangeDays ?? 7, 1, 365);
6
+ const top = clamp(args.top ?? 100, 1, 500);
7
+ const startMs = Date.now();
8
+ const startISO = new Date().toISOString();
9
+ const endISO = new Date(Date.now() + rangeDays * 24 * 60 * 60 * 1000).toISOString();
10
+ const result = await callGraph(config, async (client) => {
11
+ return (await client
12
+ .api("/me/calendarView")
13
+ .query({ startDateTime: startISO, endDateTime: endISO })
14
+ .top(top)
15
+ .orderby("start/dateTime ASC")
16
+ .select(FIELDS)
17
+ .get());
18
+ }, { tool: "calendar-list" });
19
+ const events = result.value.map(shapeEvent);
20
+ log({
21
+ event: "calendar-list",
22
+ account: config.accountId,
23
+ rangeDays,
24
+ count: events.length,
25
+ elapsedMs: Date.now() - startMs,
26
+ });
27
+ return events;
28
+ }
29
+ export function shapeEvent(ev) {
30
+ return {
31
+ id: ev.id,
32
+ subject: ev.subject ?? null,
33
+ start: ev.start,
34
+ end: ev.end,
35
+ location: ev.location?.displayName ?? null,
36
+ attendees: ev.attendees?.map((a) => ({
37
+ email: a.emailAddress.address,
38
+ name: a.emailAddress.name ?? null,
39
+ response: a.status?.response ?? "none",
40
+ })) ?? [],
41
+ isAllDay: ev.isAllDay ?? false,
42
+ organizer: ev.organizer?.emailAddress?.address ?? null,
43
+ };
44
+ }
45
+ function clamp(input, lo, hi) {
46
+ if (!Number.isFinite(input))
47
+ return lo;
48
+ if (input < lo)
49
+ return lo;
50
+ if (input > hi)
51
+ return hi;
52
+ return Math.floor(input);
53
+ }
54
+ //# sourceMappingURL=calendar-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-list.js","sourceRoot":"","sources":["../../src/tools/calendar-list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { GraphClientConfig } from "../lib/graph-client.js";
2
+ export interface ContactsListArgs {
3
+ top?: number;
4
+ }
5
+ export interface ContactItem {
6
+ id: string;
7
+ displayName: string | null;
8
+ emailAddresses: string[];
9
+ phones: string[];
10
+ jobTitle: string | null;
11
+ companyName: string | null;
12
+ }
13
+ export declare function runContactsList(config: GraphClientConfig, args: ContactsListArgs): Promise<ContactItem[]>;
14
+ //# sourceMappingURL=contacts-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contacts-list.d.ts","sourceRoot":"","sources":["../../src/tools/contacts-list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAmBD,wBAAsB,eAAe,CACnC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,WAAW,EAAE,CAAC,CAsCxB"}
@@ -0,0 +1,45 @@
1
+ import { callGraph } from "../lib/graph-client.js";
2
+ import { log } from "../lib/log.js";
3
+ const FIELDS = "id,displayName,emailAddresses,businessPhones,homePhones,mobilePhone,jobTitle,companyName";
4
+ export async function runContactsList(config, args) {
5
+ const top = clamp(args.top ?? 50, 1, 250);
6
+ const startMs = Date.now();
7
+ const result = await callGraph(config, async (client) => {
8
+ return (await client
9
+ .api("/me/contacts")
10
+ .top(top)
11
+ .select(FIELDS)
12
+ .get());
13
+ }, { tool: "contacts-list" });
14
+ const items = result.value.map((c) => ({
15
+ id: c.id,
16
+ displayName: c.displayName ?? null,
17
+ emailAddresses: (c.emailAddresses ?? [])
18
+ .map((e) => e.address)
19
+ .filter((a) => typeof a === "string"),
20
+ phones: [
21
+ ...(c.businessPhones ?? []),
22
+ ...(c.homePhones ?? []),
23
+ ...(c.mobilePhone ? [c.mobilePhone] : []),
24
+ ],
25
+ jobTitle: c.jobTitle ?? null,
26
+ companyName: c.companyName ?? null,
27
+ }));
28
+ log({
29
+ event: "contacts-list",
30
+ account: config.accountId,
31
+ count: items.length,
32
+ elapsedMs: Date.now() - startMs,
33
+ });
34
+ return items;
35
+ }
36
+ function clamp(input, lo, hi) {
37
+ if (!Number.isFinite(input))
38
+ return lo;
39
+ if (input < lo)
40
+ return lo;
41
+ if (input > hi)
42
+ return hi;
43
+ return Math.floor(input);
44
+ }
45
+ //# sourceMappingURL=contacts-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contacts-list.js","sourceRoot":"","sources":["../../src/tools/contacts-list.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AA8BpC,MAAM,MAAM,GAAG,0FAA0F,CAAC;AAE1G,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAyB,EACzB,IAAsB;IAEtB,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE3B,MAAM,MAAM,GAAG,MAAM,SAAS,CAC5B,MAAM,EACN,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,OAAO,CAAC,MAAM,MAAM;aACjB,GAAG,CAAC,cAAc,CAAC;aACnB,GAAG,CAAC,GAAG,CAAC;aACR,MAAM,CAAC,MAAM,CAAC;aACd,GAAG,EAAE,CAA8B,CAAC;IACzC,CAAC,EACD,EAAE,IAAI,EAAE,eAAe,EAAE,CAC1B,CAAC;IAEF,MAAM,KAAK,GAAkB,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpD,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,WAAW,EAAE,CAAC,CAAC,WAAW,IAAI,IAAI;QAClC,cAAc,EAAE,CAAC,CAAC,CAAC,cAAc,IAAI,EAAE,CAAC;aACrC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;aACrB,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;QACpD,MAAM,EAAE;YACN,GAAG,CAAC,CAAC,CAAC,cAAc,IAAI,EAAE,CAAC;YAC3B,GAAG,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC;YACvB,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1C;QACD,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,IAAI;QAC5B,WAAW,EAAE,CAAC,CAAC,WAAW,IAAI,IAAI;KACnC,CAAC,CAAC,CAAC;IAEJ,GAAG,CAAC;QACF,KAAK,EAAE,eAAe;QACtB,OAAO,EAAE,MAAM,CAAC,SAAS;QACzB,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO;KAChC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,KAAK,CAAC,KAAa,EAAE,EAAU,EAAE,EAAU;IAClD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,EAAE,CAAC;IAC1B,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,EAAE,CAAC;IAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { GraphClientConfig } from "../lib/graph-client.js";
2
+ export interface MailListArgs {
3
+ top?: number;
4
+ folder?: string;
5
+ }
6
+ export interface MailListItem {
7
+ id: string;
8
+ subject: string | null;
9
+ from: string | null;
10
+ receivedDateTime: string;
11
+ bodyPreview: string;
12
+ isRead: boolean;
13
+ }
14
+ export declare function runMailList(config: GraphClientConfig, args: MailListArgs): Promise<MailListItem[]>;
15
+ //# sourceMappingURL=mail-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mail-list.d.ts","sourceRoot":"","sources":["../../src/tools/mail-list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;CACjB;AAiBD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,YAAY,EAAE,CAAC,CA+BzB"}
@@ -0,0 +1,48 @@
1
+ import { callGraph } from "../lib/graph-client.js";
2
+ import { log } from "../lib/log.js";
3
+ const FIELDS = "id,subject,from,receivedDateTime,bodyPreview,isRead";
4
+ export async function runMailList(config, args) {
5
+ const top = clampTop(args.top, 25);
6
+ const folder = args.folder ?? "Inbox";
7
+ const startMs = Date.now();
8
+ const result = await callGraph(config, async (client) => {
9
+ const path = folder.toLowerCase() === "inbox" || folder === ""
10
+ ? "/me/mailFolders/Inbox/messages"
11
+ : `/me/mailFolders/${encodeURIComponent(folder)}/messages`;
12
+ return (await client
13
+ .api(path)
14
+ .top(top)
15
+ .orderby("receivedDateTime DESC")
16
+ .select(FIELDS)
17
+ .get());
18
+ }, { tool: "mail-list" });
19
+ const items = result.value.map(shapeMessage);
20
+ log({
21
+ event: "mail-list",
22
+ account: config.accountId,
23
+ folder,
24
+ count: items.length,
25
+ elapsedMs: Date.now() - startMs,
26
+ });
27
+ return items;
28
+ }
29
+ function shapeMessage(msg) {
30
+ return {
31
+ id: msg.id,
32
+ subject: msg.subject ?? null,
33
+ from: msg.from?.emailAddress?.address ?? null,
34
+ receivedDateTime: msg.receivedDateTime,
35
+ bodyPreview: (msg.bodyPreview ?? "").slice(0, 1024),
36
+ isRead: msg.isRead ?? false,
37
+ };
38
+ }
39
+ function clampTop(input, fallback) {
40
+ if (typeof input !== "number" || !Number.isFinite(input))
41
+ return fallback;
42
+ if (input < 1)
43
+ return 1;
44
+ if (input > 250)
45
+ return 250;
46
+ return Math.floor(input);
47
+ }
48
+ //# sourceMappingURL=mail-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mail-list.js","sourceRoot":"","sources":["../../src/tools/mail-list.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AA6BpC,MAAM,MAAM,GAAG,qDAAqD,CAAC;AAErE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAyB,EACzB,IAAkB;IAElB,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE3B,MAAM,MAAM,GAAG,MAAM,SAAS,CAC5B,MAAM,EACN,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,MAAM,IAAI,GACR,MAAM,CAAC,WAAW,EAAE,KAAK,OAAO,IAAI,MAAM,KAAK,EAAE;YAC/C,CAAC,CAAC,gCAAgC;YAClC,CAAC,CAAC,mBAAmB,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC;QAC/D,OAAO,CAAC,MAAM,MAAM;aACjB,GAAG,CAAC,IAAI,CAAC;aACT,GAAG,CAAC,GAAG,CAAC;aACR,OAAO,CAAC,uBAAuB,CAAC;aAChC,MAAM,CAAC,MAAM,CAAC;aACd,GAAG,EAAE,CAA8B,CAAC;IACzC,CAAC,EACD,EAAE,IAAI,EAAE,WAAW,EAAE,CACtB,CAAC;IAEF,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC7C,GAAG,CAAC;QACF,KAAK,EAAE,WAAW;QAClB,OAAO,EAAE,MAAM,CAAC,SAAS;QACzB,MAAM;QACN,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO;KAChC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CAAC,GAAe;IACnC,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,IAAI;QAC5B,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,IAAI,IAAI;QAC7C,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;QACtC,WAAW,EAAE,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;QACnD,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,KAAK;KAC5B,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,KAAyB,EAAE,QAAgB;IAC3D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC1E,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IACxB,IAAI,KAAK,GAAG,GAAG;QAAE,OAAO,GAAG,CAAC;IAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { GraphClientConfig } from "../lib/graph-client.js";
2
+ import type { MailListItem } from "./mail-list.js";
3
+ export interface MailSearchArgs {
4
+ query: string;
5
+ top?: number;
6
+ }
7
+ export declare function runMailSearch(config: GraphClientConfig, args: MailSearchArgs): Promise<MailListItem[]>;
8
+ //# sourceMappingURL=mail-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mail-search.d.ts","sourceRoot":"","sources":["../../src/tools/mail-search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAiBD,wBAAsB,aAAa,CACjC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,YAAY,EAAE,CAAC,CA0CzB"}
@@ -0,0 +1,49 @@
1
+ import { callGraph } from "../lib/graph-client.js";
2
+ import { log, trunc } from "../lib/log.js";
3
+ const FIELDS = "id,subject,from,receivedDateTime,bodyPreview,isRead";
4
+ export async function runMailSearch(config, args) {
5
+ const top = clampTop(args.top, 25);
6
+ const query = args.query.trim();
7
+ if (!query) {
8
+ throw new Error("mail-search: query is required and must be non-empty.");
9
+ }
10
+ const startMs = Date.now();
11
+ const result = await callGraph(config, async (client) => {
12
+ // Graph requires the $search value to be enclosed in quotes.
13
+ return (await client
14
+ .api("/me/messages")
15
+ .search(`"${query.replace(/"/g, '\\"')}"`)
16
+ .top(top)
17
+ .select(FIELDS)
18
+ // ConsistencyLevel header is required for $search. Older SDK shapes
19
+ // accept .header; newer shapes expose it via .request().
20
+ .header("ConsistencyLevel", "eventual")
21
+ .get());
22
+ }, { tool: "mail-search" });
23
+ const items = result.value.map((msg) => ({
24
+ id: msg.id,
25
+ subject: msg.subject ?? null,
26
+ from: msg.from?.emailAddress?.address ?? null,
27
+ receivedDateTime: msg.receivedDateTime,
28
+ bodyPreview: (msg.bodyPreview ?? "").slice(0, 1024),
29
+ isRead: msg.isRead ?? false,
30
+ }));
31
+ log({
32
+ event: "mail-search",
33
+ account: config.accountId,
34
+ query: trunc(query, 32),
35
+ count: items.length,
36
+ elapsedMs: Date.now() - startMs,
37
+ });
38
+ return items;
39
+ }
40
+ function clampTop(input, fallback) {
41
+ if (typeof input !== "number" || !Number.isFinite(input))
42
+ return fallback;
43
+ if (input < 1)
44
+ return 1;
45
+ if (input > 250)
46
+ return 250;
47
+ return Math.floor(input);
48
+ }
49
+ //# sourceMappingURL=mail-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mail-search.js","sourceRoot":"","sources":["../../src/tools/mail-search.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAqB3C,MAAM,MAAM,GAAG,qDAAqD,CAAC;AAErE,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAyB,EACzB,IAAoB;IAEpB,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE3B,MAAM,MAAM,GAAG,MAAM,SAAS,CAC5B,MAAM,EACN,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,6DAA6D;QAC7D,OAAO,CAAC,MAAM,MAAM;aACjB,GAAG,CAAC,cAAc,CAAC;aACnB,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;aACzC,GAAG,CAAC,GAAG,CAAC;aACR,MAAM,CAAC,MAAM,CAAC;YACf,oEAAoE;YACpE,yDAAyD;aACxD,MAAM,CAAC,kBAAkB,EAAE,UAAU,CAAC;aACtC,GAAG,EAAE,CAA8B,CAAC;IACzC,CAAC,EACD,EAAE,IAAI,EAAE,aAAa,EAAE,CACxB,CAAC;IAEF,MAAM,KAAK,GAAmB,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACvD,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,IAAI;QAC5B,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,IAAI,IAAI;QAC7C,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;QACtC,WAAW,EAAE,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;QACnD,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,KAAK;KAC5B,CAAC,CAAC,CAAC;IAEJ,GAAG,CAAC;QACF,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE,MAAM,CAAC,SAAS;QACzB,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QACvB,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO;KAChC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,KAAyB,EAAE,QAAgB;IAC3D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC1E,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IACxB,IAAI,KAAK,GAAG,GAAG;QAAE,OAAO,GAAG,CAAC;IAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { GraphClientConfig } from "../lib/graph-client.js";
2
+ export interface MailboxInfoArgs {
3
+ }
4
+ export interface MailboxInfo {
5
+ registered: boolean;
6
+ graphUserId: string | null;
7
+ scopes: string[];
8
+ tokenExpSec: number | null;
9
+ refreshTokenExpSec: number | null;
10
+ tokenWithinRefreshWindow: boolean;
11
+ folderCount: number | null;
12
+ }
13
+ /**
14
+ * Health probe: answers "did account X auth?" + "is the token in the
15
+ * refresh window?" without grepping logs. If the account isn't registered,
16
+ * returns `registered: false` rather than throwing.
17
+ */
18
+ export declare function runMailboxInfo(config: GraphClientConfig): Promise<MailboxInfo>;
19
+ //# sourceMappingURL=mailbox-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mailbox-info.d.ts","sourceRoot":"","sources":["../../src/tools/mailbox-info.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAIhE,MAAM,WAAW,eAAe;CAE/B;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,wBAAwB,EAAE,OAAO,CAAC;IAClC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAWD;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAwDpF"}
@@ -0,0 +1,58 @@
1
+ import { callGraph } from "../lib/graph-client.js";
2
+ import { log } from "../lib/log.js";
3
+ /**
4
+ * Health probe: answers "did account X auth?" + "is the token in the
5
+ * refresh window?" without grepping logs. If the account isn't registered,
6
+ * returns `registered: false` rather than throwing.
7
+ */
8
+ export async function runMailboxInfo(config) {
9
+ const blob = config.tokenStore.read();
10
+ const startMs = Date.now();
11
+ if (!blob) {
12
+ log({
13
+ event: "mailbox-info",
14
+ account: config.accountId,
15
+ tokenWithinRefreshWindow: false,
16
+ folderCount: 0,
17
+ });
18
+ return {
19
+ registered: false,
20
+ graphUserId: null,
21
+ scopes: [],
22
+ tokenExpSec: null,
23
+ refreshTokenExpSec: null,
24
+ tokenWithinRefreshWindow: false,
25
+ folderCount: null,
26
+ };
27
+ }
28
+ let folderCount = null;
29
+ try {
30
+ const result = await callGraph(config, async (client) => {
31
+ return (await client.api("/me/mailFolders").top(50).select("id").get());
32
+ }, { tool: "mailbox-info" });
33
+ folderCount = result.value.length;
34
+ }
35
+ catch {
36
+ // Don't throw — operator should still see the auth state even if Graph
37
+ // is unreachable. folderCount stays null.
38
+ folderCount = null;
39
+ }
40
+ const tokenWithinRefreshWindow = config.tokenStore.needsRefresh();
41
+ log({
42
+ event: "mailbox-info",
43
+ account: config.accountId,
44
+ tokenWithinRefreshWindow,
45
+ folderCount: folderCount ?? -1,
46
+ elapsedMs: Date.now() - startMs,
47
+ });
48
+ return {
49
+ registered: true,
50
+ graphUserId: blob.graphUserId,
51
+ scopes: blob.scopes,
52
+ tokenExpSec: Math.floor(blob.accessTokenExpiry / 1000),
53
+ refreshTokenExpSec: Math.floor(blob.refreshTokenExpiry / 1000),
54
+ tokenWithinRefreshWindow,
55
+ folderCount,
56
+ };
57
+ }
58
+ //# sourceMappingURL=mailbox-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mailbox-info.js","sourceRoot":"","sources":["../../src/tools/mailbox-info.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAyBpC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAyB;IAC5D,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE3B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,GAAG,CAAC;YACF,KAAK,EAAE,cAAc;YACrB,OAAO,EAAE,MAAM,CAAC,SAAS;YACzB,wBAAwB,EAAE,KAAK;YAC/B,WAAW,EAAE,CAAC;SACf,CAAC,CAAC;QACH,OAAO;YACL,UAAU,EAAE,KAAK;YACjB,WAAW,EAAE,IAAI;YACjB,MAAM,EAAE,EAAE;YACV,WAAW,EAAE,IAAI;YACjB,kBAAkB,EAAE,IAAI;YACxB,wBAAwB,EAAE,KAAK;YAC/B,WAAW,EAAE,IAAI;SAClB,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,GAAkB,IAAI,CAAC;IACtC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAC5B,MAAM,EACN,KAAK,EAAE,MAAM,EAAE,EAAE;YACf,OAAO,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,CAAiC,CAAC;QAC1G,CAAC,EACD,EAAE,IAAI,EAAE,cAAc,EAAE,CACzB,CAAC;QACF,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,0CAA0C;QAC1C,WAAW,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,MAAM,wBAAwB,GAAG,MAAM,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC;IAClE,GAAG,CAAC;QACF,KAAK,EAAE,cAAc;QACrB,OAAO,EAAE,MAAM,CAAC,SAAS;QACzB,wBAAwB;QACxB,WAAW,EAAE,WAAW,IAAI,CAAC,CAAC;QAC9B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO;KAChC,CAAC,CAAC;IAEH,OAAO;QACL,UAAU,EAAE,IAAI;QAChB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QACtD,kBAAkB,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC9D,wBAAwB;QACxB,WAAW;KACZ,CAAC;AACJ,CAAC"}