@aaronsb/google-workspace-mcp 2.3.0 → 2.5.0

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 (63) hide show
  1. package/build/__tests__/server/handlers/drive.test.js +2 -15
  2. package/build/__tests__/server/handlers/drive.test.js.map +1 -1
  3. package/build/__tests__/server/session/context.test.d.ts +1 -0
  4. package/build/__tests__/server/session/context.test.js +101 -0
  5. package/build/__tests__/server/session/context.test.js.map +1 -0
  6. package/build/__tests__/server/session/tracker.test.d.ts +1 -0
  7. package/build/__tests__/server/session/tracker.test.js +146 -0
  8. package/build/__tests__/server/session/tracker.test.js.map +1 -0
  9. package/build/accounts/oauth.js +17 -8
  10. package/build/accounts/oauth.js.map +1 -1
  11. package/build/coverage/analyze.d.ts +13 -0
  12. package/build/coverage/analyze.js +49 -0
  13. package/build/coverage/analyze.js.map +1 -0
  14. package/build/coverage/baseline.d.ts +8 -0
  15. package/build/coverage/baseline.js +91 -0
  16. package/build/coverage/baseline.js.map +1 -0
  17. package/build/coverage/compare.d.ts +6 -0
  18. package/build/coverage/compare.js +129 -0
  19. package/build/coverage/compare.js.map +1 -0
  20. package/build/coverage/discover.d.ts +7 -0
  21. package/build/coverage/discover.js +168 -0
  22. package/build/coverage/discover.js.map +1 -0
  23. package/build/coverage/report.d.ts +6 -0
  24. package/build/coverage/report.js +93 -0
  25. package/build/coverage/report.js.map +1 -0
  26. package/build/coverage/types.d.ts +70 -0
  27. package/build/coverage/types.js +14 -0
  28. package/build/coverage/types.js.map +1 -0
  29. package/build/executor/gws.d.ts +2 -0
  30. package/build/executor/gws.js +2 -2
  31. package/build/executor/gws.js.map +1 -1
  32. package/build/factory/manifest.yaml +177 -3
  33. package/build/factory/patches.js +2 -0
  34. package/build/factory/patches.js.map +1 -1
  35. package/build/server/handler.js +36 -3
  36. package/build/server/handler.js.map +1 -1
  37. package/build/server/handlers/calendar.js +8 -4
  38. package/build/server/handlers/calendar.js.map +1 -1
  39. package/build/server/handlers/drive.js +0 -16
  40. package/build/server/handlers/drive.js.map +1 -1
  41. package/build/server/scratchpad/adapters/send-email-draft.js +11 -3
  42. package/build/server/scratchpad/adapters/send-email-draft.js.map +1 -1
  43. package/build/server/scratchpad/adapters/send-email.js +8 -2
  44. package/build/server/scratchpad/adapters/send-email.js.map +1 -1
  45. package/build/server/session/context.d.ts +7 -0
  46. package/build/server/session/context.js +56 -0
  47. package/build/server/session/context.js.map +1 -0
  48. package/build/server/session/index.d.ts +9 -0
  49. package/build/server/session/index.js +14 -0
  50. package/build/server/session/index.js.map +1 -0
  51. package/build/server/session/tracker.d.ts +36 -0
  52. package/build/server/session/tracker.js +135 -0
  53. package/build/server/session/tracker.js.map +1 -0
  54. package/build/services/calendar/patch.js +4 -2
  55. package/build/services/calendar/patch.js.map +1 -1
  56. package/build/services/docs/patch.d.ts +8 -0
  57. package/build/services/docs/patch.js +72 -0
  58. package/build/services/docs/patch.js.map +1 -0
  59. package/build/services/drive/patch.js +165 -10
  60. package/build/services/drive/patch.js.map +1 -1
  61. package/build/services/gmail/patch.js +12 -7
  62. package/build/services/gmail/patch.js.map +1 -1
  63. package/package.json +2 -2
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Session context formatter — builds a markdown footer with ambient
3
+ * workspace awareness (email deltas, next calendar event).
4
+ */
5
+ /** Format the session context footer for a tool response. */
6
+ export function sessionContext(_toolName, email, tracker) {
7
+ if (!email)
8
+ return '';
9
+ const session = tracker.getContext(email);
10
+ if (!session?.initialized)
11
+ return '';
12
+ const lines = [];
13
+ // Email delta
14
+ const delta = session.currentUnreadCount - session.baselineUnreadCount;
15
+ if (delta > 0) {
16
+ lines.push(`- ${delta} new unread email${delta !== 1 ? 's' : ''} since session start (${session.currentUnreadCount} unread, ${session.currentTodayEmailCount} today)`);
17
+ }
18
+ else if (delta < 0) {
19
+ const abs = Math.abs(delta);
20
+ lines.push(`- ${abs} fewer unread since session start (${session.currentUnreadCount} unread, ${session.currentTodayEmailCount} today)`);
21
+ }
22
+ else {
23
+ lines.push(`- No new unread emails since session start (${session.currentUnreadCount} unread, ${session.currentTodayEmailCount} today)`);
24
+ }
25
+ // Next event
26
+ if (session.nextEvent) {
27
+ const label = formatEventTime(session.nextEvent.startTime);
28
+ lines.push(`- Next: "${session.nextEvent.summary}" ${label}`);
29
+ }
30
+ else {
31
+ lines.push('- No more events today');
32
+ }
33
+ return `\n\n---\n**Session context** (${email}):\n${lines.join('\n')}`;
34
+ }
35
+ /** Format event start as relative ("in 25 min") or absolute ("at 2:30 PM"). */
36
+ function formatEventTime(startTime) {
37
+ if (!startTime)
38
+ return '';
39
+ try {
40
+ const start = new Date(startTime);
41
+ if (isNaN(start.getTime()))
42
+ return `at ${startTime}`;
43
+ const diffMs = start.getTime() - Date.now();
44
+ if (diffMs < 0)
45
+ return 'now (started)';
46
+ const diffMin = Math.round(diffMs / 60_000);
47
+ if (diffMin < 120) {
48
+ return diffMin <= 1 ? 'in 1 min' : `in ${diffMin} min`;
49
+ }
50
+ return `at ${start.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true })}`;
51
+ }
52
+ catch {
53
+ return `at ${startTime}`;
54
+ }
55
+ }
56
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/server/session/context.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,6DAA6D;AAC7D,MAAM,UAAU,cAAc,CAC5B,SAAiB,EACjB,KAAyB,EACzB,OAAuB;IAEvB,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IAEtB,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,CAAC,OAAO,EAAE,WAAW;QAAE,OAAO,EAAE,CAAC;IAErC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,cAAc;IACd,MAAM,KAAK,GAAG,OAAO,CAAC,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IACvE,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,oBAAoB,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,yBAAyB,OAAO,CAAC,kBAAkB,YAAY,OAAO,CAAC,sBAAsB,SAAS,CAAC,CAAC;IACzK,CAAC;SAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,sCAAsC,OAAO,CAAC,kBAAkB,YAAY,OAAO,CAAC,sBAAsB,SAAS,CAAC,CAAC;IAC1I,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,+CAA+C,OAAO,CAAC,kBAAkB,YAAY,OAAO,CAAC,sBAAsB,SAAS,CAAC,CAAC;IAC3I,CAAC;IAED,aAAa;IACb,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC3D,KAAK,CAAC,IAAI,CAAC,YAAY,OAAO,CAAC,SAAS,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC;IAChE,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,iCAAiC,KAAK,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACzE,CAAC;AAED,+EAA+E;AAC/E,SAAS,eAAe,CAAC,SAAiB;IACxC,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;QAClC,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAAE,OAAO,MAAM,SAAS,EAAE,CAAC;QAErD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5C,IAAI,MAAM,GAAG,CAAC;YAAE,OAAO,eAAe,CAAC;QAEvC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QAC5C,IAAI,OAAO,GAAG,GAAG,EAAE,CAAC;YAClB,OAAO,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,OAAO,MAAM,CAAC;QACzD,CAAC;QAED,OAAO,MAAM,KAAK,CAAC,kBAAkB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IACzG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,SAAS,EAAE,CAAC;IAC3B,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Session module — lazy singleton for the session tracker.
3
+ */
4
+ import { SessionTracker } from './tracker.js';
5
+ /** Get (or create) the singleton session tracker. */
6
+ export declare function getSessionTracker(): SessionTracker;
7
+ export { SessionTracker } from './tracker.js';
8
+ export type { AccountSession, NextEvent } from './tracker.js';
9
+ export { sessionContext } from './context.js';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Session module — lazy singleton for the session tracker.
3
+ */
4
+ import { SessionTracker } from './tracker.js';
5
+ let _tracker;
6
+ /** Get (or create) the singleton session tracker. */
7
+ export function getSessionTracker() {
8
+ if (!_tracker)
9
+ _tracker = new SessionTracker();
10
+ return _tracker;
11
+ }
12
+ export { SessionTracker } from './tracker.js';
13
+ export { sessionContext } from './context.js';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/session/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,IAAI,QAAoC,CAAC;AAEzC,qDAAqD;AACrD,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC,QAAQ;QAAE,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;IAC/C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Session tracker — per-account in-memory state for ambient context.
3
+ *
4
+ * Captures baseline workspace counters on first use per account,
5
+ * refreshes periodically via fire-and-forget, and exposes current
6
+ * deltas for context injection.
7
+ *
8
+ * Refresh is gated by epoch distance — only polls Google APIs when
9
+ * at least REFRESH_EPOCH_INTERVAL tool calls have elapsed since the
10
+ * last refresh, keeping API usage bounded.
11
+ */
12
+ export interface NextEvent {
13
+ summary: string;
14
+ startTime: string;
15
+ }
16
+ export interface AccountSession {
17
+ baselineUnreadCount: number;
18
+ currentUnreadCount: number;
19
+ baselineTodayEmailCount: number;
20
+ currentTodayEmailCount: number;
21
+ nextEvent: NextEvent | null;
22
+ lastRefreshedEpoch: number;
23
+ initialized: boolean;
24
+ }
25
+ export declare class SessionTracker {
26
+ private sessions;
27
+ /** Capture baseline on first call per account. Blocks until complete. */
28
+ ensureBaseline(email: string, epoch: number): Promise<void>;
29
+ /** Fire-and-forget async refresh, gated by epoch staleness. Never throws. */
30
+ refresh(email: string, epoch: number): void;
31
+ /** Return current session data, or undefined if not tracked. */
32
+ getContext(email: string): AccountSession | undefined;
33
+ /** Clear all state (for testing). */
34
+ reset(): void;
35
+ private _doRefresh;
36
+ }
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Session tracker — per-account in-memory state for ambient context.
3
+ *
4
+ * Captures baseline workspace counters on first use per account,
5
+ * refreshes periodically via fire-and-forget, and exposes current
6
+ * deltas for context injection.
7
+ *
8
+ * Refresh is gated by epoch distance — only polls Google APIs when
9
+ * at least REFRESH_EPOCH_INTERVAL tool calls have elapsed since the
10
+ * last refresh, keeping API usage bounded.
11
+ */
12
+ import { execute } from '../../executor/gws.js';
13
+ /** Minimum epoch distance between refresh polls per account. */
14
+ const REFRESH_EPOCH_INTERVAL = 10;
15
+ /** Format today's date as YYYY/MM/DD for Gmail search queries. */
16
+ function todayQuery() {
17
+ const d = new Date();
18
+ return `${d.getFullYear()}/${String(d.getMonth() + 1).padStart(2, '0')}/${String(d.getDate()).padStart(2, '0')}`;
19
+ }
20
+ /** ISO string for end of today (23:59:59 local time). */
21
+ function endOfDayISO() {
22
+ const d = new Date();
23
+ d.setHours(23, 59, 59, 999);
24
+ return d.toISOString();
25
+ }
26
+ async function fetchUnreadCount(account) {
27
+ const result = await execute([
28
+ 'gmail', 'users', 'messages', 'list',
29
+ '--params', JSON.stringify({ userId: 'me', q: 'is:unread', maxResults: 1 }),
30
+ ], { account });
31
+ const data = result.data;
32
+ return Number(data.resultSizeEstimate ?? 0);
33
+ }
34
+ async function fetchTodayEmailCount(account) {
35
+ const result = await execute([
36
+ 'gmail', 'users', 'messages', 'list',
37
+ '--params', JSON.stringify({ userId: 'me', q: `after:${todayQuery()}`, maxResults: 1 }),
38
+ ], { account });
39
+ const data = result.data;
40
+ return Number(data.resultSizeEstimate ?? 0);
41
+ }
42
+ async function fetchNextEvent(account) {
43
+ const result = await execute([
44
+ 'calendar', 'events', 'list',
45
+ '--params', JSON.stringify({
46
+ calendarId: 'primary',
47
+ timeMin: new Date().toISOString(),
48
+ timeMax: endOfDayISO(),
49
+ maxResults: 1,
50
+ orderBy: 'startTime',
51
+ singleEvents: true,
52
+ }),
53
+ ], { account });
54
+ const data = result.data;
55
+ const items = (data.items ?? []);
56
+ if (items.length === 0)
57
+ return null;
58
+ const event = items[0];
59
+ const start = event.start;
60
+ return {
61
+ summary: String(event.summary ?? '(no title)'),
62
+ startTime: start?.dateTime ?? start?.date ?? '',
63
+ };
64
+ }
65
+ export class SessionTracker {
66
+ sessions = new Map();
67
+ /** Capture baseline on first call per account. Blocks until complete. */
68
+ async ensureBaseline(email, epoch) {
69
+ if (this.sessions.has(email))
70
+ return;
71
+ try {
72
+ const [unread, today, nextEvt] = await Promise.allSettled([
73
+ fetchUnreadCount(email),
74
+ fetchTodayEmailCount(email),
75
+ fetchNextEvent(email),
76
+ ]);
77
+ const session = {
78
+ baselineUnreadCount: unread.status === 'fulfilled' ? unread.value : 0,
79
+ currentUnreadCount: unread.status === 'fulfilled' ? unread.value : 0,
80
+ baselineTodayEmailCount: today.status === 'fulfilled' ? today.value : 0,
81
+ currentTodayEmailCount: today.status === 'fulfilled' ? today.value : 0,
82
+ nextEvent: nextEvt.status === 'fulfilled' ? nextEvt.value : null,
83
+ lastRefreshedEpoch: epoch,
84
+ initialized: true,
85
+ };
86
+ this.sessions.set(email, session);
87
+ }
88
+ catch (err) {
89
+ process.stderr.write(`[gws-mcp] session baseline failed for ${email}: ${err instanceof Error ? err.message : String(err)}\n`);
90
+ }
91
+ }
92
+ /** Fire-and-forget async refresh, gated by epoch staleness. Never throws. */
93
+ refresh(email, epoch) {
94
+ const session = this.sessions.get(email);
95
+ if (!session?.initialized)
96
+ return;
97
+ if (epoch - session.lastRefreshedEpoch < REFRESH_EPOCH_INTERVAL)
98
+ return;
99
+ void this._doRefresh(email, epoch);
100
+ }
101
+ /** Return current session data, or undefined if not tracked. */
102
+ getContext(email) {
103
+ return this.sessions.get(email);
104
+ }
105
+ /** Clear all state (for testing). */
106
+ reset() {
107
+ this.sessions.clear();
108
+ }
109
+ async _doRefresh(email, epoch) {
110
+ const session = this.sessions.get(email);
111
+ if (!session)
112
+ return;
113
+ try {
114
+ const [unread, today, nextEvt] = await Promise.allSettled([
115
+ fetchUnreadCount(email),
116
+ fetchTodayEmailCount(email),
117
+ fetchNextEvent(email),
118
+ ]);
119
+ // Guard against stale write: a newer refresh may have landed while we awaited
120
+ if (session.lastRefreshedEpoch > epoch)
121
+ return;
122
+ if (unread.status === 'fulfilled')
123
+ session.currentUnreadCount = unread.value;
124
+ if (today.status === 'fulfilled')
125
+ session.currentTodayEmailCount = today.value;
126
+ if (nextEvt.status === 'fulfilled')
127
+ session.nextEvent = nextEvt.value;
128
+ session.lastRefreshedEpoch = epoch;
129
+ }
130
+ catch (err) {
131
+ process.stderr.write(`[gws-mcp] session refresh failed for ${email}: ${err instanceof Error ? err.message : String(err)}\n`);
132
+ }
133
+ }
134
+ }
135
+ //# sourceMappingURL=tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../../src/server/session/tracker.ts"],"names":[],"mappings":"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"}
@@ -82,7 +82,8 @@ export const calendarPatch = {
82
82
  const summary = requireString(params, 'summary');
83
83
  const start = requireString(params, 'start');
84
84
  const end = requireString(params, 'end');
85
- const args = ['calendar', '+insert', '--summary', summary, '--start', start, '--end', end];
85
+ const calendarId = params.calendarId || 'primary';
86
+ const args = ['calendar', '+insert', '--calendar', calendarId, '--summary', summary, '--start', start, '--end', end];
86
87
  if (params.description)
87
88
  args.push('--description', String(params.description));
88
89
  if (params.location)
@@ -102,9 +103,10 @@ export const calendarPatch = {
102
103
  },
103
104
  delete: async (params, account) => {
104
105
  const eventId = requireString(params, 'eventId');
106
+ const calendarId = params.calendarId || 'primary';
105
107
  await execute([
106
108
  'calendar', 'events', 'delete',
107
- '--params', JSON.stringify({ calendarId: 'primary', eventId }),
109
+ '--params', JSON.stringify({ calendarId, eventId }),
108
110
  ], { account });
109
111
  return {
110
112
  text: `Event deleted: ${eventId}` + nextSteps('calendar', 'delete', { email: account }),
@@ -1 +1 @@
1
- {"version":3,"file":"patch.js","sourceRoot":"","sources":["../../../src/services/calendar/patch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"patch.js","sourceRoot":"","sources":["../../../src/services/calendar/patch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Docs patch — custom handlers for operations that use batchUpdate.
3
+ *
4
+ * insertText and replaceText use documents.batchUpdate which requires
5
+ * a --json request body, not --params.
6
+ */
7
+ import type { ServicePatch } from '../../factory/types.js';
8
+ export declare const docsPatch: ServicePatch;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Docs patch — custom handlers for operations that use batchUpdate.
3
+ *
4
+ * insertText and replaceText use documents.batchUpdate which requires
5
+ * a --json request body, not --params.
6
+ */
7
+ import { execute } from '../../executor/gws.js';
8
+ import { nextSteps } from '../../server/formatting/next-steps.js';
9
+ import { requireString } from '../../server/handlers/validate.js';
10
+ export const docsPatch = {
11
+ customHandlers: {
12
+ insertText: async (params, account) => {
13
+ const documentId = requireString(params, 'documentId');
14
+ const text = requireString(params, 'text');
15
+ const index = Number(params.index);
16
+ if (!Number.isInteger(index) || index < 1) {
17
+ throw new Error('index must be a positive integer (1 = start of document body)');
18
+ }
19
+ const body = {
20
+ requests: [{
21
+ insertText: {
22
+ text,
23
+ location: { index },
24
+ },
25
+ }],
26
+ };
27
+ await execute([
28
+ 'docs', 'documents', 'batchUpdate',
29
+ '--params', JSON.stringify({ documentId }),
30
+ '--json', JSON.stringify(body),
31
+ ], { account });
32
+ return {
33
+ text: `Text inserted at index ${index}.\n\n**Document:** ${documentId}\n**Inserted:** ${text.length} characters` +
34
+ nextSteps('docs', 'insertText', { email: account }),
35
+ refs: { documentId, index, length: text.length },
36
+ };
37
+ },
38
+ replaceText: async (params, account) => {
39
+ const documentId = requireString(params, 'documentId');
40
+ const findText = requireString(params, 'findText');
41
+ const replaceWith = requireString(params, 'replaceWith');
42
+ const matchCase = params.matchCase !== false;
43
+ const body = {
44
+ requests: [{
45
+ replaceAllText: {
46
+ containsText: {
47
+ text: findText,
48
+ matchCase,
49
+ },
50
+ replaceText: replaceWith,
51
+ },
52
+ }],
53
+ };
54
+ const result = await execute([
55
+ 'docs', 'documents', 'batchUpdate',
56
+ '--params', JSON.stringify({ documentId }),
57
+ '--json', JSON.stringify(body),
58
+ ], { account });
59
+ // Extract occurrence count from the reply
60
+ const data = result.data;
61
+ const replies = data.replies || [];
62
+ const replaceReply = replies[0]?.replaceAllText;
63
+ const occurrences = replaceReply?.occurrencesChanged || 0;
64
+ return {
65
+ text: `Text replaced.\n\n**Document:** ${documentId}\n**Found:** "${findText}"\n**Replaced with:** "${replaceWith}"\n**Occurrences:** ${occurrences}` +
66
+ nextSteps('docs', 'replaceText', { email: account }),
67
+ refs: { documentId, occurrences },
68
+ };
69
+ },
70
+ },
71
+ };
72
+ //# sourceMappingURL=patch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patch.js","sourceRoot":"","sources":["../../../src/services/docs/patch.ts"],"names":[],"mappings":"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"}
@@ -13,7 +13,7 @@ import { execute } from '../../executor/gws.js';
13
13
  import { formatFileList, formatFileDetail } from '../../server/formatting/markdown.js';
14
14
  import { nextSteps } from '../../server/formatting/next-steps.js';
15
15
  import { requireString } from '../../server/handlers/validate.js';
16
- import { ensureWorkspaceDir, resolveWorkspacePath, verifyPathSafety } from '../../executor/workspace.js';
16
+ import { ensureWorkspaceDir, getWorkspaceDir, resolveWorkspacePath, verifyPathSafety } from '../../executor/workspace.js';
17
17
  import { isTextFile, formatFileOutput, buildImageBlock, buildImageBlockFromFile, isImageFile } from '../../executor/file-output.js';
18
18
  /** Read a file from workspace and build the output result with optional inline content. */
19
19
  async function readWorkspaceFile(filePath, filename, mimeType) {
@@ -57,7 +57,7 @@ export const drivePatch = {
57
57
  // Get file metadata for filename and mime type
58
58
  const metaResult = await execute([
59
59
  'drive', 'files', 'get',
60
- '--params', JSON.stringify({ fileId, fields: 'name,mimeType' }),
60
+ '--params', JSON.stringify({ fileId, fields: 'name,mimeType', supportsAllDrives: true }),
61
61
  ], { account });
62
62
  const meta = metaResult.data;
63
63
  const filename = String(params.outputPath || meta.name || `file-${fileId}`);
@@ -69,11 +69,12 @@ export const drivePatch = {
69
69
  const outputPath = resolveWorkspacePath(filename);
70
70
  await verifyPathSafety(outputPath);
71
71
  // Download directly to disk via --output (preserves binary integrity)
72
+ // cwd must match workspace so gws directory-fence accepts the output path
72
73
  await execute([
73
74
  'drive', 'files', 'get',
74
- '--params', JSON.stringify({ fileId, alt: 'media' }),
75
+ '--params', JSON.stringify({ fileId, alt: 'media', supportsAllDrives: true }),
75
76
  '--output', outputPath,
76
- ], { account });
77
+ ], { account, cwd: getWorkspaceDir() });
77
78
  const output = await readWorkspaceFile(outputPath, filename, mimeType);
78
79
  return {
79
80
  text: formatFileOutput(output) + nextSteps('drive', 'download', { email: account }),
@@ -92,7 +93,7 @@ export const drivePatch = {
92
93
  // Get file metadata
93
94
  const metaResult = await execute([
94
95
  'drive', 'files', 'get',
95
- '--params', JSON.stringify({ fileId, fields: 'name,mimeType,size' }),
96
+ '--params', JSON.stringify({ fileId, fields: 'name,mimeType,size', supportsAllDrives: true }),
96
97
  ], { account });
97
98
  const meta = metaResult.data;
98
99
  const filename = String(meta.name || `image-${fileId}`);
@@ -106,9 +107,9 @@ export const drivePatch = {
106
107
  try {
107
108
  await execute([
108
109
  'drive', 'files', 'get',
109
- '--params', JSON.stringify({ fileId, alt: 'media' }),
110
+ '--params', JSON.stringify({ fileId, alt: 'media', supportsAllDrives: true }),
110
111
  '--output', tmpPath,
111
- ], { account });
112
+ ], { account, cwd: path.dirname(tmpPath) });
112
113
  const buffer = await fs.readFile(tmpPath);
113
114
  const imageBlock = buildImageBlock(buffer, filename, mimeType);
114
115
  if (!imageBlock) {
@@ -141,7 +142,7 @@ export const drivePatch = {
141
142
  // Get source file name
142
143
  const metaResult = await execute([
143
144
  'drive', 'files', 'get',
144
- '--params', JSON.stringify({ fileId, fields: 'name' }),
145
+ '--params', JSON.stringify({ fileId, fields: 'name', supportsAllDrives: true }),
145
146
  ], { account });
146
147
  const meta = metaResult.data;
147
148
  const baseName = String(meta.name || `export-${fileId}`).replace(/\.[^.]+$/, '');
@@ -153,11 +154,12 @@ export const drivePatch = {
153
154
  const outputPath = resolveWorkspacePath(filename);
154
155
  await verifyPathSafety(outputPath);
155
156
  // Export directly to disk via --output (preserves binary integrity)
157
+ // cwd must match workspace so gws directory-fence accepts the output path
156
158
  await execute([
157
159
  'drive', 'files', 'export',
158
- '--params', JSON.stringify({ fileId, mimeType }),
160
+ '--params', JSON.stringify({ fileId, mimeType, supportsAllDrives: true }),
159
161
  '--output', outputPath,
160
- ], { account });
162
+ ], { account, cwd: getWorkspaceDir() });
161
163
  const output = await readWorkspaceFile(outputPath, filename, mimeType);
162
164
  return {
163
165
  text: formatFileOutput(output) + nextSteps('drive', 'export', { email: account }),
@@ -172,6 +174,159 @@ export const drivePatch = {
172
174
  ...(output.imageBlock ? { content: [output.imageBlock] } : {}),
173
175
  };
174
176
  },
177
+ listComments: async (params, account) => {
178
+ const fileId = requireString(params, 'fileId');
179
+ const includeDeleted = params.includeDeleted ? 'true' : 'false';
180
+ const result = await execute([
181
+ 'drive', 'comments', 'list',
182
+ '--params', JSON.stringify({
183
+ fileId,
184
+ includeDeleted,
185
+ fields: 'comments(id, content, htmlContent, author(displayName, emailAddress), createdTime, modifiedTime, resolved, quotedFileContent, replies(id, content, author(displayName), createdTime)), nextPageToken',
186
+ supportsAllDrives: true,
187
+ }),
188
+ ], { account });
189
+ const data = result.data;
190
+ const comments = (data.comments || []);
191
+ if (comments.length === 0) {
192
+ return {
193
+ text: 'No comments on this file.' +
194
+ nextSteps('drive', 'listComments', { email: account }),
195
+ refs: { fileId, count: 0 },
196
+ };
197
+ }
198
+ const lines = comments.map((c) => {
199
+ const author = c.author?.displayName || 'Unknown';
200
+ const resolved = c.resolved ? ' [RESOLVED]' : '';
201
+ const quoted = c.quotedFileContent
202
+ ? `\n > "${c.quotedFileContent.value}"`
203
+ : '';
204
+ const replies = (c.replies || []);
205
+ const replyLines = replies.map((r) => {
206
+ const rAuthor = r.author?.displayName || 'Unknown';
207
+ return ` - **${rAuthor}:** ${r.content}`;
208
+ }).join('\n');
209
+ return `- **${author}**${resolved}: ${c.content}${quoted}` +
210
+ (replyLines ? `\n${replyLines}` : '') +
211
+ `\n _ID: ${c.id}_`;
212
+ });
213
+ return {
214
+ text: `## Comments (${comments.length})\n\n${lines.join('\n\n')}` +
215
+ nextSteps('drive', 'listComments', { email: account }),
216
+ refs: { fileId, count: comments.length },
217
+ };
218
+ },
219
+ getComment: async (params, account) => {
220
+ const fileId = requireString(params, 'fileId');
221
+ const commentId = requireString(params, 'commentId');
222
+ const result = await execute([
223
+ 'drive', 'comments', 'get',
224
+ '--params', JSON.stringify({
225
+ fileId,
226
+ commentId,
227
+ fields: 'id, content, htmlContent, author(displayName, emailAddress), createdTime, modifiedTime, resolved, quotedFileContent, replies(id, content, htmlContent, author(displayName), createdTime)',
228
+ supportsAllDrives: true,
229
+ }),
230
+ ], { account });
231
+ const c = result.data;
232
+ const author = c.author?.displayName || 'Unknown';
233
+ const resolved = c.resolved ? ' [RESOLVED]' : '';
234
+ const quoted = c.quotedFileContent
235
+ ? `\n> "${c.quotedFileContent.value}"`
236
+ : '';
237
+ const replies = (c.replies || []);
238
+ const replyLines = replies.map((r) => {
239
+ const rAuthor = r.author?.displayName || 'Unknown';
240
+ return `- **${rAuthor}** (${r.createdTime}): ${r.content}`;
241
+ }).join('\n');
242
+ return {
243
+ text: `## Comment by ${author}${resolved}\n\n${c.content}${quoted}\n\n**Created:** ${c.createdTime}\n**Modified:** ${c.modifiedTime}` +
244
+ (replyLines ? `\n\n### Replies\n\n${replyLines}` : '') +
245
+ nextSteps('drive', 'getComment', { email: account }),
246
+ refs: { commentId: c.id, fileId, resolved: c.resolved },
247
+ };
248
+ },
249
+ addComment: async (params, account) => {
250
+ const fileId = requireString(params, 'fileId');
251
+ const content = requireString(params, 'content');
252
+ const quotedText = params.quotedText ? String(params.quotedText) : undefined;
253
+ const body = { content };
254
+ if (quotedText) {
255
+ body.quotedFileContent = { value: quotedText };
256
+ }
257
+ const result = await execute([
258
+ 'drive', 'comments', 'create',
259
+ '--params', JSON.stringify({
260
+ fileId,
261
+ fields: 'id, content, htmlContent, author(displayName), createdTime, quotedFileContent',
262
+ supportsAllDrives: true,
263
+ }),
264
+ '--json', JSON.stringify(body),
265
+ ], { account });
266
+ const data = result.data;
267
+ return {
268
+ text: `Comment added.\n\n**ID:** ${data.id}\n**Content:** ${data.content}` +
269
+ (quotedText ? `\n**Anchored to:** "${quotedText}"` : '') +
270
+ nextSteps('drive', 'addComment', { email: account }),
271
+ refs: { commentId: data.id, fileId },
272
+ };
273
+ },
274
+ resolveComment: async (params, account) => {
275
+ const fileId = requireString(params, 'fileId');
276
+ const commentId = requireString(params, 'commentId');
277
+ const resolved = params.resolved !== false;
278
+ // Fetch existing comment to preserve content when updating
279
+ const existing = await execute([
280
+ 'drive', 'comments', 'get',
281
+ '--params', JSON.stringify({
282
+ fileId,
283
+ commentId,
284
+ fields: 'content',
285
+ supportsAllDrives: true,
286
+ }),
287
+ ], { account });
288
+ const existingData = existing.data;
289
+ const result = await execute([
290
+ 'drive', 'comments', 'update',
291
+ '--params', JSON.stringify({
292
+ fileId,
293
+ commentId,
294
+ fields: 'id, content, resolved',
295
+ supportsAllDrives: true,
296
+ }),
297
+ '--json', JSON.stringify({
298
+ content: existingData.content || '',
299
+ resolved,
300
+ }),
301
+ ], { account });
302
+ const data = result.data;
303
+ return {
304
+ text: `Comment ${resolved ? 'resolved' : 'reopened'}.\n\n**ID:** ${data.id}\n**Resolved:** ${resolved}` +
305
+ nextSteps('drive', 'resolveComment', { email: account }),
306
+ refs: { commentId: data.id, fileId, resolved },
307
+ };
308
+ },
309
+ replyToComment: async (params, account) => {
310
+ const fileId = requireString(params, 'fileId');
311
+ const commentId = requireString(params, 'commentId');
312
+ const content = requireString(params, 'content');
313
+ const result = await execute([
314
+ 'drive', 'replies', 'create',
315
+ '--params', JSON.stringify({
316
+ fileId,
317
+ commentId,
318
+ fields: 'id, content, htmlContent, author(displayName), createdTime',
319
+ supportsAllDrives: true,
320
+ }),
321
+ '--json', JSON.stringify({ content }),
322
+ ], { account });
323
+ const data = result.data;
324
+ return {
325
+ text: `Reply added.\n\n**ID:** ${data.id}\n**Content:** ${data.content}` +
326
+ nextSteps('drive', 'replyToComment', { email: account }),
327
+ refs: { replyId: data.id, commentId, fileId },
328
+ };
329
+ },
175
330
  },
176
331
  };
177
332
  //# sourceMappingURL=patch.js.map