@rubytech/create-maxy 1.0.762 → 1.0.764

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 (84) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/neo4j/schema.cypher +50 -0
  3. package/payload/platform/package-lock.json +56 -1
  4. package/payload/platform/package.json +1 -0
  5. package/payload/platform/plugins/docs/references/outlook-guide.md +69 -0
  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-S3M2NZMA.js +3136 -0
  79. package/payload/server/chunk-SGBNY4NP.js +9540 -0
  80. package/payload/server/client-pool-5V5GX3UT.js +28 -0
  81. package/payload/server/maxy-edge.js +2 -2
  82. package/payload/server/public/assets/{admin-7vGwd7wu.js → admin-V6NDkEoR.js} +2 -2
  83. package/payload/server/public/index.html +1 -1
  84. package/payload/server/server.js +104 -6
@@ -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"}
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@maxy/outlook",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "start": "node dist/index.js"
10
+ },
11
+ "dependencies": {
12
+ "@microsoft/microsoft-graph-client": "^3.0.7",
13
+ "@modelcontextprotocol/sdk": "^1.12.1",
14
+ "zod": "^3.24.0"
15
+ },
16
+ "devDependencies": {
17
+ "@types/node": "^22.0.0",
18
+ "typescript": "^5.7.0"
19
+ }
20
+ }
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env bash
2
+ # verify-doc-impl.sh
3
+ #
4
+ # Doc-impl alignment grep, promoted from Task 811's manual verification step
5
+ # to a permanent gate. Run from anywhere; resolves to the plugin tree itself.
6
+ #
7
+ # Verifies:
8
+ # 1. Every `outlook-*` tool name in `platform/plugins/docs/references/outlook-guide.md`
9
+ # resolves to a `server.tool("outlook-...", ...)` registration in mcp/src/index.ts.
10
+ # 2. Every `[outlook-mcp]` log-line shape in outlook-guide.md matches a
11
+ # log({event:"..."}) literal in mcp/src/.
12
+ # 3. Every tool name in `PLUGIN.md` frontmatter matches a registration in mcp/src/index.ts.
13
+ # 4. Public-agent isolation: `outlook` does not appear in public-agent assembly files.
14
+ # 5. Bearer-token redaction: log.ts contains the redaction regex pair.
15
+ #
16
+ # Exit non-zero on any mismatch. Print the first diverging item.
17
+
18
+ set -euo pipefail
19
+
20
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
21
+ PLUGIN_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
22
+ REPO_ROOT="$(cd "$PLUGIN_DIR/../../../.." && pwd)"
23
+ GUIDE="$REPO_ROOT/platform/plugins/docs/references/outlook-guide.md"
24
+ PLUGIN_MD="$REPO_ROOT/platform/plugins/outlook/PLUGIN.md"
25
+ INDEX_TS="$PLUGIN_DIR/src/index.ts"
26
+ SRC_DIR="$PLUGIN_DIR/src"
27
+
28
+ fail() {
29
+ echo "[verify-doc-impl] FAIL: $1" >&2
30
+ exit 1
31
+ }
32
+
33
+ [ -f "$GUIDE" ] || fail "operator guide missing: $GUIDE"
34
+ [ -f "$PLUGIN_MD" ] || fail "PLUGIN.md missing: $PLUGIN_MD"
35
+ [ -f "$INDEX_TS" ] || fail "index.ts missing: $INDEX_TS"
36
+
37
+ # Tool names registered in src/index.ts. The MCP-SDK call shape is:
38
+ # server.tool(
39
+ # "outlook-XYZ",
40
+ # ...
41
+ # so the tool name appears on its own line as ` "outlook-XYZ",`.
42
+ TOOLS_REGISTERED=$(grep -oE '"outlook-[a-z\-]+",' "$INDEX_TS" \
43
+ | sed -E 's/^"|",$//g' | sort -u)
44
+
45
+ # Tool names referenced in outlook-guide.md (backtick-wrapped)
46
+ TOOLS_IN_GUIDE=$(grep -oE '`outlook-[a-z\-]+`' "$GUIDE" | tr -d '`' | sort -u)
47
+
48
+ # Tool names in PLUGIN.md frontmatter (lines starting with " - outlook-")
49
+ TOOLS_IN_PLUGIN_MD=$(grep -E '^\s+- outlook-' "$PLUGIN_MD" | sed -E 's/^[[:space:]]*-[[:space:]]+//' | sort -u)
50
+
51
+ # Set 1: every tool in guide must be registered
52
+ while IFS= read -r tool; do
53
+ [ -z "$tool" ] && continue
54
+ if ! echo "$TOOLS_REGISTERED" | grep -qx "$tool"; then
55
+ fail "tool '$tool' referenced in outlook-guide.md but not registered in mcp/src/index.ts"
56
+ fi
57
+ done <<< "$TOOLS_IN_GUIDE"
58
+
59
+ # Set 2: every tool in PLUGIN.md frontmatter must be registered
60
+ while IFS= read -r tool; do
61
+ [ -z "$tool" ] && continue
62
+ if ! echo "$TOOLS_REGISTERED" | grep -qx "$tool"; then
63
+ fail "tool '$tool' declared in PLUGIN.md frontmatter but not registered in mcp/src/index.ts"
64
+ fi
65
+ done <<< "$TOOLS_IN_PLUGIN_MD"
66
+
67
+ # Set 3: every registered tool must appear in PLUGIN.md frontmatter
68
+ while IFS= read -r tool; do
69
+ [ -z "$tool" ] && continue
70
+ if ! echo "$TOOLS_IN_PLUGIN_MD" | grep -qx "$tool"; then
71
+ fail "tool '$tool' registered in mcp/src/index.ts but missing from PLUGIN.md frontmatter"
72
+ fi
73
+ done <<< "$TOOLS_REGISTERED"
74
+
75
+ # Log-shape alignment: every event tag in outlook-guide.md must have a matching
76
+ # log({ event: "..." }) literal in mcp/src/. Event tags appear in the table as:
77
+ # | Auth init | `auth-init account=<id> codeChallenge=...` |
78
+ # We pull the first word inside backticks on each table row that contains "account=".
79
+ EVENTS_IN_GUIDE=$(grep -E '`[a-z\-]+ account=' "$GUIDE" \
80
+ | sed -E 's/.*`([a-z\-]+) account=.*/\1/' | sort -u)
81
+ EVENTS_IN_SRC=$(grep -rh -oE 'event:[[:space:]]*"[a-z\-]+"' "$SRC_DIR" \
82
+ | sed -E 's/^event:[[:space:]]*"|"$//g' | sort -u)
83
+
84
+ while IFS= read -r ev; do
85
+ [ -z "$ev" ] && continue
86
+ if ! echo "$EVENTS_IN_SRC" | grep -qx "$ev"; then
87
+ fail "log event '$ev' documented in outlook-guide.md but no log({event:\"$ev\"}) literal in mcp/src/"
88
+ fi
89
+ done <<< "$EVENTS_IN_GUIDE"
90
+
91
+ # Public-agent isolation: outlook must not appear in public-agent assembly files.
92
+ ISOLATION_HITS=$( (cd "$REPO_ROOT" && grep -rE 'outlook' \
93
+ platform/ui/app/lib/claude-agent/public-agent.ts \
94
+ platform/ui/app/lib/claude-agent/system-prompt-assembly.ts \
95
+ platform/templates/agents/public/ 2>/dev/null) || true)
96
+ if [ -n "$ISOLATION_HITS" ]; then
97
+ echo "$ISOLATION_HITS" >&2
98
+ fail "isolation breach: 'outlook' string appears in public-agent assembly path"
99
+ fi
100
+
101
+ # Bearer redaction guard: lib/log.ts must contain both regex literals.
102
+ if ! grep -q 'Bearer\\s+\[A-Za-z0-9' "$SRC_DIR/lib/log.ts"; then
103
+ fail "Bearer redaction regex missing in lib/log.ts"
104
+ fi
105
+ if ! grep -q 'access_token=\[A-Za-z0-9' "$SRC_DIR/lib/log.ts"; then
106
+ fail "access_token redaction regex missing in lib/log.ts"
107
+ fi
108
+
109
+ echo "[verify-doc-impl] OK — $(echo "$TOOLS_REGISTERED" | wc -l | tr -d ' ') tools, $(echo "$EVENTS_IN_GUIDE" | wc -l | tr -d ' ') events, isolation, redaction all aligned"