@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.
- package/build/__tests__/server/handlers/drive.test.js +2 -15
- package/build/__tests__/server/handlers/drive.test.js.map +1 -1
- package/build/__tests__/server/session/context.test.d.ts +1 -0
- package/build/__tests__/server/session/context.test.js +101 -0
- package/build/__tests__/server/session/context.test.js.map +1 -0
- package/build/__tests__/server/session/tracker.test.d.ts +1 -0
- package/build/__tests__/server/session/tracker.test.js +146 -0
- package/build/__tests__/server/session/tracker.test.js.map +1 -0
- package/build/accounts/oauth.js +17 -8
- package/build/accounts/oauth.js.map +1 -1
- package/build/coverage/analyze.d.ts +13 -0
- package/build/coverage/analyze.js +49 -0
- package/build/coverage/analyze.js.map +1 -0
- package/build/coverage/baseline.d.ts +8 -0
- package/build/coverage/baseline.js +91 -0
- package/build/coverage/baseline.js.map +1 -0
- package/build/coverage/compare.d.ts +6 -0
- package/build/coverage/compare.js +129 -0
- package/build/coverage/compare.js.map +1 -0
- package/build/coverage/discover.d.ts +7 -0
- package/build/coverage/discover.js +168 -0
- package/build/coverage/discover.js.map +1 -0
- package/build/coverage/report.d.ts +6 -0
- package/build/coverage/report.js +93 -0
- package/build/coverage/report.js.map +1 -0
- package/build/coverage/types.d.ts +70 -0
- package/build/coverage/types.js +14 -0
- package/build/coverage/types.js.map +1 -0
- package/build/executor/gws.d.ts +2 -0
- package/build/executor/gws.js +2 -2
- package/build/executor/gws.js.map +1 -1
- package/build/factory/manifest.yaml +177 -3
- package/build/factory/patches.js +2 -0
- package/build/factory/patches.js.map +1 -1
- package/build/server/handler.js +36 -3
- package/build/server/handler.js.map +1 -1
- package/build/server/handlers/calendar.js +8 -4
- package/build/server/handlers/calendar.js.map +1 -1
- package/build/server/handlers/drive.js +0 -16
- package/build/server/handlers/drive.js.map +1 -1
- package/build/server/scratchpad/adapters/send-email-draft.js +11 -3
- package/build/server/scratchpad/adapters/send-email-draft.js.map +1 -1
- package/build/server/scratchpad/adapters/send-email.js +8 -2
- package/build/server/scratchpad/adapters/send-email.js.map +1 -1
- package/build/server/session/context.d.ts +7 -0
- package/build/server/session/context.js +56 -0
- package/build/server/session/context.js.map +1 -0
- package/build/server/session/index.d.ts +9 -0
- package/build/server/session/index.js +14 -0
- package/build/server/session/index.js.map +1 -0
- package/build/server/session/tracker.d.ts +36 -0
- package/build/server/session/tracker.js +135 -0
- package/build/server/session/tracker.js.map +1 -0
- package/build/services/calendar/patch.js +4 -2
- package/build/services/calendar/patch.js.map +1 -1
- package/build/services/docs/patch.d.ts +8 -0
- package/build/services/docs/patch.js +72 -0
- package/build/services/docs/patch.js.map +1 -0
- package/build/services/drive/patch.js +165 -10
- package/build/services/drive/patch.js.map +1 -1
- package/build/services/gmail/patch.js +12 -7
- package/build/services/gmail/patch.js.map +1 -1
- 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
|
|
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
|
|
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
|