@aaronsb/google-workspace-mcp 2.0.0 → 2.1.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 (75) hide show
  1. package/build/__tests__/server/queue.test.js +5 -0
  2. package/build/__tests__/server/queue.test.js.map +1 -1
  3. package/build/server/formatting/markdown.d.ts +7 -0
  4. package/build/server/formatting/markdown.js +1 -1
  5. package/build/server/formatting/markdown.js.map +1 -1
  6. package/build/server/formatting/next-steps.js +19 -0
  7. package/build/server/formatting/next-steps.js.map +1 -1
  8. package/build/server/handler.d.ts +4 -0
  9. package/build/server/handler.js +17 -1
  10. package/build/server/handler.js.map +1 -1
  11. package/build/server/queue.js +2 -0
  12. package/build/server/queue.js.map +1 -1
  13. package/build/server/scratchpad/__tests__/json-path.test.d.ts +4 -0
  14. package/build/server/scratchpad/__tests__/json-path.test.js +121 -0
  15. package/build/server/scratchpad/__tests__/json-path.test.js.map +1 -0
  16. package/build/server/scratchpad/__tests__/manager.test.d.ts +5 -0
  17. package/build/server/scratchpad/__tests__/manager.test.js +886 -0
  18. package/build/server/scratchpad/__tests__/manager.test.js.map +1 -0
  19. package/build/server/scratchpad/__tests__/validate.test.d.ts +4 -0
  20. package/build/server/scratchpad/__tests__/validate.test.js +112 -0
  21. package/build/server/scratchpad/__tests__/validate.test.js.map +1 -0
  22. package/build/server/scratchpad/adapters/import-doc.d.ts +16 -0
  23. package/build/server/scratchpad/adapters/import-doc.js +123 -0
  24. package/build/server/scratchpad/adapters/import-doc.js.map +1 -0
  25. package/build/server/scratchpad/adapters/import-drive.d.ts +12 -0
  26. package/build/server/scratchpad/adapters/import-drive.js +52 -0
  27. package/build/server/scratchpad/adapters/import-drive.js.map +1 -0
  28. package/build/server/scratchpad/adapters/import-email.d.ts +13 -0
  29. package/build/server/scratchpad/adapters/import-email.js +87 -0
  30. package/build/server/scratchpad/adapters/import-email.js.map +1 -0
  31. package/build/server/scratchpad/adapters/import-meet.d.ts +12 -0
  32. package/build/server/scratchpad/adapters/import-meet.js +109 -0
  33. package/build/server/scratchpad/adapters/import-meet.js.map +1 -0
  34. package/build/server/scratchpad/adapters/import-sheet.d.ts +12 -0
  35. package/build/server/scratchpad/adapters/import-sheet.js +55 -0
  36. package/build/server/scratchpad/adapters/import-sheet.js.map +1 -0
  37. package/build/server/scratchpad/adapters/index.d.ts +15 -0
  38. package/build/server/scratchpad/adapters/index.js +18 -0
  39. package/build/server/scratchpad/adapters/index.js.map +1 -0
  40. package/build/server/scratchpad/adapters/send-calendar.d.ts +15 -0
  41. package/build/server/scratchpad/adapters/send-calendar.js +50 -0
  42. package/build/server/scratchpad/adapters/send-calendar.js.map +1 -0
  43. package/build/server/scratchpad/adapters/send-doc.d.ts +18 -0
  44. package/build/server/scratchpad/adapters/send-doc.js +77 -0
  45. package/build/server/scratchpad/adapters/send-doc.js.map +1 -0
  46. package/build/server/scratchpad/adapters/send-email-draft.d.ts +12 -0
  47. package/build/server/scratchpad/adapters/send-email-draft.js +52 -0
  48. package/build/server/scratchpad/adapters/send-email-draft.js.map +1 -0
  49. package/build/server/scratchpad/adapters/send-email.d.ts +15 -0
  50. package/build/server/scratchpad/adapters/send-email.js +73 -0
  51. package/build/server/scratchpad/adapters/send-email.js.map +1 -0
  52. package/build/server/scratchpad/adapters/send-sheet.d.ts +13 -0
  53. package/build/server/scratchpad/adapters/send-sheet.js +71 -0
  54. package/build/server/scratchpad/adapters/send-sheet.js.map +1 -0
  55. package/build/server/scratchpad/adapters/send-task.d.ts +12 -0
  56. package/build/server/scratchpad/adapters/send-task.js +53 -0
  57. package/build/server/scratchpad/adapters/send-task.js.map +1 -0
  58. package/build/server/scratchpad/adapters/send-workspace.d.ts +11 -0
  59. package/build/server/scratchpad/adapters/send-workspace.js +69 -0
  60. package/build/server/scratchpad/adapters/send-workspace.js.map +1 -0
  61. package/build/server/scratchpad/handler.d.ts +9 -0
  62. package/build/server/scratchpad/handler.js +476 -0
  63. package/build/server/scratchpad/handler.js.map +1 -0
  64. package/build/server/scratchpad/json-path.d.ts +12 -0
  65. package/build/server/scratchpad/json-path.js +75 -0
  66. package/build/server/scratchpad/json-path.js.map +1 -0
  67. package/build/server/scratchpad/manager.d.ts +140 -0
  68. package/build/server/scratchpad/manager.js +561 -0
  69. package/build/server/scratchpad/manager.js.map +1 -0
  70. package/build/server/scratchpad/validate.d.ts +7 -0
  71. package/build/server/scratchpad/validate.js +96 -0
  72. package/build/server/scratchpad/validate.js.map +1 -0
  73. package/build/server/tools.js +48 -1
  74. package/build/server/tools.js.map +1 -1
  75. package/package.json +1 -1
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Import adapter: meet — loads a Meet conference transcript into a scratchpad.
3
+ * Imports as markdown with speaker attribution. No live binding (transcripts are read-only).
4
+ */
5
+ import { execute } from '../../../executor/gws.js';
6
+ export async function importMeet(scratchpads, scratchpadId, sourceParams) {
7
+ const { email, conferenceId } = sourceParams;
8
+ if (!email || !conferenceId) {
9
+ return { text: 'email and conferenceId are required for meet import.', refs: { error: true } };
10
+ }
11
+ try {
12
+ const parent = conferenceId.startsWith('conferenceRecords/')
13
+ ? conferenceId
14
+ : `conferenceRecords/${conferenceId}`;
15
+ // Step 1: List transcripts
16
+ const transcriptsResult = await execute([
17
+ 'meet', 'conferenceRecords', 'transcripts', 'list',
18
+ '--params', JSON.stringify({ parent }),
19
+ ], { account: email, format: 'json' });
20
+ const transcriptsData = transcriptsResult.data;
21
+ const transcripts = (transcriptsData?.transcripts ?? []);
22
+ if (transcripts.length === 0) {
23
+ return {
24
+ text: `No transcripts found for conference ${conferenceId}.\nScratchpad ${scratchpadId} unchanged.`,
25
+ refs: { scratchpadId, conferenceId },
26
+ };
27
+ }
28
+ // Step 2: Fetch entries and participants in parallel
29
+ const transcriptName = String(transcripts[0].name ?? '');
30
+ const [entriesResult, participantsResult] = await Promise.all([
31
+ execute([
32
+ 'meet', 'conferenceRecords', 'transcripts', 'entries', 'list',
33
+ '--params', JSON.stringify({ parent: transcriptName, pageSize: 100 }),
34
+ ], { account: email, format: 'json' }),
35
+ execute([
36
+ 'meet', 'conferenceRecords', 'participants', 'list',
37
+ '--params', JSON.stringify({ parent, pageSize: 100 }),
38
+ ], { account: email, format: 'json' }),
39
+ ]);
40
+ const entriesData = entriesResult.data;
41
+ const entries = (entriesData?.transcriptEntries ?? []);
42
+ if (entries.length === 0) {
43
+ return {
44
+ text: `Transcript found but no entries available yet (may still be processing).\nScratchpad ${scratchpadId} unchanged.`,
45
+ refs: { scratchpadId, conferenceId, transcriptName },
46
+ };
47
+ }
48
+ // Step 3: Build participant lookup
49
+ const participantsData = participantsResult.data;
50
+ const participants = (participantsData?.participants ?? []);
51
+ const nameMap = new Map();
52
+ for (const p of participants) {
53
+ const name = String(p.name ?? '');
54
+ const signedinUser = p.signedinUser;
55
+ const displayName = String(signedinUser?.displayName ?? p.name ?? 'Unknown');
56
+ if (name)
57
+ nameMap.set(name, displayName);
58
+ }
59
+ // Step 4: Format as markdown transcript
60
+ const lines = [
61
+ `# Meeting Transcript`,
62
+ ``,
63
+ `**Conference:** ${conferenceId}`,
64
+ `**Entries:** ${entries.length}`,
65
+ ``,
66
+ ];
67
+ let currentSpeaker = '';
68
+ for (const entry of entries) {
69
+ const participantName = String(entry.participant ?? '');
70
+ const speaker = nameMap.get(participantName) ?? String(entry.participantDisplayName ?? participantName);
71
+ const text = String(entry.text ?? '');
72
+ const time = formatTime(entry.startTime);
73
+ if (speaker !== currentSpeaker) {
74
+ if (currentSpeaker)
75
+ lines.push('');
76
+ lines.push(`**${speaker}** (${time}):`);
77
+ currentSpeaker = speaker;
78
+ }
79
+ lines.push(text);
80
+ }
81
+ scratchpads.appendRawLines(scratchpadId, lines);
82
+ scratchpads.setFormat(scratchpadId, 'markdown');
83
+ // No live binding — transcripts are read-only
84
+ return {
85
+ text: `Imported transcript (${entries.length} entries, ${lines.length} lines) into scratchpad ${scratchpadId}.`,
86
+ refs: { scratchpadId, conferenceId, entries: entries.length, linesImported: lines.length },
87
+ };
88
+ }
89
+ catch (err) {
90
+ const message = err instanceof Error ? err.message : String(err);
91
+ return {
92
+ text: `Import failed: ${message}`,
93
+ refs: { error: true, scratchpadId },
94
+ };
95
+ }
96
+ }
97
+ function formatTime(time) {
98
+ if (!time)
99
+ return '';
100
+ const s = String(time);
101
+ try {
102
+ const d = new Date(s);
103
+ return d.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
104
+ }
105
+ catch {
106
+ return s;
107
+ }
108
+ }
109
+ //# sourceMappingURL=import-meet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-meet.js","sourceRoot":"","sources":["../../../../src/server/scratchpad/adapters/import-meet.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Import adapter: sheet — loads a Google Sheet as CSV lines into a scratchpad.
3
+ */
4
+ import type { HandlerResponse } from '../../handler.js';
5
+ import type { ScratchpadManager } from '../manager.js';
6
+ interface SheetImportParams {
7
+ email: string;
8
+ spreadsheetId: string;
9
+ range?: string;
10
+ }
11
+ export declare function importSheet(scratchpads: ScratchpadManager, scratchpadId: string, sourceParams: SheetImportParams): Promise<HandlerResponse>;
12
+ export {};
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Import adapter: sheet — loads a Google Sheet as CSV lines into a scratchpad.
3
+ */
4
+ import { execute } from '../../../executor/gws.js';
5
+ export async function importSheet(scratchpads, scratchpadId, sourceParams) {
6
+ const { email, spreadsheetId, range } = sourceParams;
7
+ if (!email || !spreadsheetId) {
8
+ return { text: 'email and spreadsheetId are required for sheet import.', refs: { error: true } };
9
+ }
10
+ try {
11
+ const params = { spreadsheetId };
12
+ if (range)
13
+ params.range = range;
14
+ // Default to first sheet if no range specified
15
+ const rangeArg = range ?? 'Sheet1';
16
+ const result = await execute([
17
+ 'sheets', 'spreadsheets', 'values', 'get',
18
+ '--params', JSON.stringify({ spreadsheetId, range: rangeArg }),
19
+ ], { account: email });
20
+ const data = result.data;
21
+ const values = (data.values ?? []);
22
+ if (values.length === 0) {
23
+ return {
24
+ text: `Sheet ${spreadsheetId} (${rangeArg}) has no data.\nScratchpad ${scratchpadId} unchanged.`,
25
+ refs: { scratchpadId, spreadsheetId },
26
+ };
27
+ }
28
+ // Convert to CSV lines
29
+ const csvLines = values.map(row => row.map(escapeCsvField).join(','));
30
+ scratchpads.appendRawLines(scratchpadId, csvLines);
31
+ scratchpads.setFormat(scratchpadId, 'csv');
32
+ return {
33
+ text: `Imported sheet as CSV (${csvLines.length} rows) into scratchpad ${scratchpadId}.`,
34
+ refs: { scratchpadId, spreadsheetId, range: rangeArg, rowsImported: csvLines.length },
35
+ };
36
+ }
37
+ catch (err) {
38
+ const message = err instanceof Error ? err.message : String(err);
39
+ return {
40
+ text: `Import failed: ${message}`,
41
+ refs: { error: true, scratchpadId },
42
+ };
43
+ }
44
+ }
45
+ /** Escape a CSV field: quote if it contains comma, newline, or double-quote. */
46
+ function escapeCsvField(field) {
47
+ if (field === undefined || field === null)
48
+ return '';
49
+ const s = String(field);
50
+ if (s.includes(',') || s.includes('"') || s.includes('\n')) {
51
+ return `"${s.replace(/"/g, '""')}"`;
52
+ }
53
+ return s;
54
+ }
55
+ //# sourceMappingURL=import-sheet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-sheet.js","sourceRoot":"","sources":["../../../../src/server/scratchpad/adapters/import-sheet.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Adapter registry for scratchpad send and import operations.
3
+ */
4
+ export { sendEmail } from './send-email.js';
5
+ export { sendEmailDraft } from './send-email-draft.js';
6
+ export { sendDocCreate, sendDocWrite } from './send-doc.js';
7
+ export { sendWorkspace } from './send-workspace.js';
8
+ export { sendSheetWrite } from './send-sheet.js';
9
+ export { sendCalendarEvent } from './send-calendar.js';
10
+ export { sendTaskCreate } from './send-task.js';
11
+ export { importEmail } from './import-email.js';
12
+ export { importDoc } from './import-doc.js';
13
+ export { importSheet } from './import-sheet.js';
14
+ export { importDriveFile } from './import-drive.js';
15
+ export { importMeet } from './import-meet.js';
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Adapter registry for scratchpad send and import operations.
3
+ */
4
+ // Send adapters
5
+ export { sendEmail } from './send-email.js';
6
+ export { sendEmailDraft } from './send-email-draft.js';
7
+ export { sendDocCreate, sendDocWrite } from './send-doc.js';
8
+ export { sendWorkspace } from './send-workspace.js';
9
+ export { sendSheetWrite } from './send-sheet.js';
10
+ export { sendCalendarEvent } from './send-calendar.js';
11
+ export { sendTaskCreate } from './send-task.js';
12
+ // Import adapters
13
+ export { importEmail } from './import-email.js';
14
+ export { importDoc } from './import-doc.js';
15
+ export { importSheet } from './import-sheet.js';
16
+ export { importDriveFile } from './import-drive.js';
17
+ export { importMeet } from './import-meet.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/server/scratchpad/adapters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,gBAAgB;AAChB,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,kBAAkB;AAClB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Send adapter: calendar_event — creates a calendar event with scratchpad content as description.
3
+ */
4
+ import type { HandlerResponse } from '../../handler.js';
5
+ import type { ScratchpadManager } from '../manager.js';
6
+ interface CalendarEventParams {
7
+ email: string;
8
+ summary: string;
9
+ start: string;
10
+ end: string;
11
+ location?: string;
12
+ attendees?: string;
13
+ }
14
+ export declare function sendCalendarEvent(scratchpads: ScratchpadManager, scratchpadId: string, targetParams: CalendarEventParams): Promise<HandlerResponse>;
15
+ export {};
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Send adapter: calendar_event — creates a calendar event with scratchpad content as description.
3
+ */
4
+ import { execute } from '../../../executor/gws.js';
5
+ import { nextSteps } from '../../formatting/next-steps.js';
6
+ export async function sendCalendarEvent(scratchpads, scratchpadId, targetParams) {
7
+ const content = scratchpads.getContent(scratchpadId);
8
+ if (content === null) {
9
+ return { text: `Scratchpad ${scratchpadId} not found.`, refs: { error: true } };
10
+ }
11
+ const { email, summary, start, end, location, attendees } = targetParams;
12
+ if (!email || !summary || !start || !end) {
13
+ return {
14
+ text: `Send failed: email, summary, start, and end are required for calendar_event.\nScratchpad ${scratchpadId} is still active.`,
15
+ refs: { error: true, scratchpadId },
16
+ };
17
+ }
18
+ const args = [
19
+ 'calendar', '+insert',
20
+ '--summary', summary,
21
+ '--start', start,
22
+ '--end', end,
23
+ '--description', content,
24
+ ];
25
+ if (location)
26
+ args.push('--location', location);
27
+ if (attendees)
28
+ args.push('--attendees', attendees);
29
+ try {
30
+ const result = await execute(args, { account: email });
31
+ const data = result.data;
32
+ return {
33
+ text: `Event created: **${summary}**\n\n` +
34
+ `**When:** ${start} – ${end}\n` +
35
+ (location ? `**Where:** ${location}\n` : '') +
36
+ `**Description:** scratchpad content (${content.split('\n').length} lines)\n` +
37
+ `**Event ID:** ${data.id ?? 'unknown'}` +
38
+ nextSteps('calendar', 'create', { email }),
39
+ refs: { scratchpadId, eventId: data.id, summary, start, end },
40
+ };
41
+ }
42
+ catch (err) {
43
+ const message = err instanceof Error ? err.message : String(err);
44
+ return {
45
+ text: `Send failed: ${message}\nScratchpad ${scratchpadId} is still active.`,
46
+ refs: { error: true, scratchpadId },
47
+ };
48
+ }
49
+ }
50
+ //# sourceMappingURL=send-calendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-calendar.js","sourceRoot":"","sources":["../../../../src/server/scratchpad/adapters/send-calendar.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAGnD,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAW3D,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,WAA8B,EAC9B,YAAoB,EACpB,YAAiC;IAEjC,MAAM,OAAO,GAAG,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;IACrD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,EAAE,IAAI,EAAE,cAAc,YAAY,aAAa,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;IAClF,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,YAAY,CAAC;IACzE,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;QACzC,OAAO;YACL,IAAI,EAAE,4FAA4F,YAAY,mBAAmB;YACjI,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE;SACpC,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG;QACX,UAAU,EAAE,SAAS;QACrB,WAAW,EAAE,OAAO;QACpB,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,GAAG;QACZ,eAAe,EAAE,OAAO;KACzB,CAAC;IACF,IAAI,QAAQ;QAAE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAChD,IAAI,SAAS;QAAE,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IAEnD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,MAAM,CAAC,IAA+B,CAAC;QAEpD,OAAO;YACL,IAAI,EAAE,oBAAoB,OAAO,QAAQ;gBACvC,aAAa,KAAK,MAAM,GAAG,IAAI;gBAC/B,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc,QAAQ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5C,wCAAwC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,WAAW;gBAC7E,iBAAiB,IAAI,CAAC,EAAE,IAAI,SAAS,EAAE;gBACvC,SAAS,CAAC,UAAU,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC;YAC5C,IAAI,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE;SAC9D,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO;YACL,IAAI,EAAE,gBAAgB,OAAO,gBAAgB,YAAY,mBAAmB;YAC5E,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE;SACpC,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Send adapters: doc_create and doc_write.
3
+ * doc_create: creates a new Google Doc and writes scratchpad content.
4
+ * doc_write: appends scratchpad content to an existing Google Doc.
5
+ */
6
+ import type { HandlerResponse } from '../../handler.js';
7
+ import type { ScratchpadManager } from '../manager.js';
8
+ interface DocCreateParams {
9
+ email: string;
10
+ title: string;
11
+ }
12
+ interface DocWriteParams {
13
+ email: string;
14
+ documentId: string;
15
+ }
16
+ export declare function sendDocCreate(scratchpads: ScratchpadManager, scratchpadId: string, targetParams: DocCreateParams): Promise<HandlerResponse>;
17
+ export declare function sendDocWrite(scratchpads: ScratchpadManager, scratchpadId: string, targetParams: DocWriteParams): Promise<HandlerResponse>;
18
+ export {};
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Send adapters: doc_create and doc_write.
3
+ * doc_create: creates a new Google Doc and writes scratchpad content.
4
+ * doc_write: appends scratchpad content to an existing Google Doc.
5
+ */
6
+ import { execute } from '../../../executor/gws.js';
7
+ export async function sendDocCreate(scratchpads, scratchpadId, targetParams) {
8
+ const content = scratchpads.getContent(scratchpadId);
9
+ if (content === null) {
10
+ return { text: `Scratchpad ${scratchpadId} not found.`, refs: { error: true } };
11
+ }
12
+ const { email, title } = targetParams;
13
+ if (!email || !title) {
14
+ return {
15
+ text: `Send failed: email and title are required for doc_create.\nScratchpad ${scratchpadId} is still active.`,
16
+ refs: { error: true, scratchpadId },
17
+ };
18
+ }
19
+ try {
20
+ // Step 1: Create empty doc (title goes in --json request body)
21
+ const createResult = await execute([
22
+ 'docs', 'documents', 'create',
23
+ '--json', JSON.stringify({ title }),
24
+ ], { account: email });
25
+ const doc = createResult.data;
26
+ const documentId = doc.documentId;
27
+ // Step 2: Write content
28
+ await execute([
29
+ 'docs', '+write',
30
+ '--document', documentId,
31
+ '--text', content,
32
+ ], { account: email });
33
+ return {
34
+ text: `Document created from scratchpad.\n\n**Title:** ${title}\n**Document ID:** ${documentId}`,
35
+ refs: { scratchpadId, documentId, title },
36
+ };
37
+ }
38
+ catch (err) {
39
+ const message = err instanceof Error ? err.message : String(err);
40
+ return {
41
+ text: `Send failed: ${message}\nScratchpad ${scratchpadId} is still active.`,
42
+ refs: { error: true, scratchpadId },
43
+ };
44
+ }
45
+ }
46
+ export async function sendDocWrite(scratchpads, scratchpadId, targetParams) {
47
+ const content = scratchpads.getContent(scratchpadId);
48
+ if (content === null) {
49
+ return { text: `Scratchpad ${scratchpadId} not found.`, refs: { error: true } };
50
+ }
51
+ const { email, documentId } = targetParams;
52
+ if (!email || !documentId) {
53
+ return {
54
+ text: `Send failed: email and documentId are required for doc_write.\nScratchpad ${scratchpadId} is still active.`,
55
+ refs: { error: true, scratchpadId },
56
+ };
57
+ }
58
+ try {
59
+ await execute([
60
+ 'docs', '+write',
61
+ '--document', documentId,
62
+ '--text', content,
63
+ ], { account: email });
64
+ return {
65
+ text: `Content appended to document ${documentId}.`,
66
+ refs: { scratchpadId, documentId },
67
+ };
68
+ }
69
+ catch (err) {
70
+ const message = err instanceof Error ? err.message : String(err);
71
+ return {
72
+ text: `Send failed: ${message}\nScratchpad ${scratchpadId} is still active.`,
73
+ refs: { error: true, scratchpadId },
74
+ };
75
+ }
76
+ }
77
+ //# sourceMappingURL=send-doc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-doc.js","sourceRoot":"","sources":["../../../../src/server/scratchpad/adapters/send-doc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Send adapter: email_draft — creates a Gmail draft from scratchpad content.
3
+ */
4
+ import type { HandlerResponse } from '../../handler.js';
5
+ import type { ScratchpadManager } from '../manager.js';
6
+ interface EmailDraftTargetParams {
7
+ email: string;
8
+ to?: string;
9
+ subject?: string;
10
+ }
11
+ export declare function sendEmailDraft(scratchpads: ScratchpadManager, scratchpadId: string, targetParams: EmailDraftTargetParams): Promise<HandlerResponse>;
12
+ export {};
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Send adapter: email_draft — creates a Gmail draft from scratchpad content.
3
+ */
4
+ import { execute } from '../../../executor/gws.js';
5
+ export async function sendEmailDraft(scratchpads, scratchpadId, targetParams) {
6
+ const content = scratchpads.getContent(scratchpadId);
7
+ if (content === null) {
8
+ return { text: `Scratchpad ${scratchpadId} not found.`, refs: { error: true } };
9
+ }
10
+ const { email, to, subject } = targetParams;
11
+ if (!email) {
12
+ return {
13
+ text: `Send failed: email (account) is required.\nScratchpad ${scratchpadId} is still active.`,
14
+ refs: { error: true, scratchpadId },
15
+ };
16
+ }
17
+ // Build raw RFC 2822 message for drafts.create
18
+ // Strip CRLF to prevent header injection
19
+ const sanitize = (s) => s.replace(/[\r\n]/g, '');
20
+ const headers = [];
21
+ if (to)
22
+ headers.push(`To: ${sanitize(to)}`);
23
+ if (subject)
24
+ headers.push(`Subject: ${sanitize(subject)}`);
25
+ headers.push('Content-Type: text/plain; charset=utf-8');
26
+ headers.push('');
27
+ headers.push(content);
28
+ const raw = Buffer.from(headers.join('\r\n')).toString('base64url');
29
+ try {
30
+ const result = await execute([
31
+ 'gmail', 'users', 'drafts', 'create',
32
+ '--params', JSON.stringify({
33
+ userId: 'me',
34
+ requestBody: { message: { raw } },
35
+ }),
36
+ ], { account: email });
37
+ const data = result.data;
38
+ const draftId = data.id ?? 'unknown';
39
+ return {
40
+ text: `Draft created.\n\n**Draft ID:** ${draftId}${to ? `\n**To:** ${to}` : ''}${subject ? `\n**Subject:** ${subject}` : ''}`,
41
+ refs: { scratchpadId, draftId },
42
+ };
43
+ }
44
+ catch (err) {
45
+ const message = err instanceof Error ? err.message : String(err);
46
+ return {
47
+ text: `Send failed: ${message}\nScratchpad ${scratchpadId} is still active.`,
48
+ refs: { error: true, scratchpadId },
49
+ };
50
+ }
51
+ }
52
+ //# sourceMappingURL=send-email-draft.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-email-draft.js","sourceRoot":"","sources":["../../../../src/server/scratchpad/adapters/send-email-draft.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAUnD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,WAA8B,EAC9B,YAAoB,EACpB,YAAoC;IAEpC,MAAM,OAAO,GAAG,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;IACrD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,EAAE,IAAI,EAAE,cAAc,YAAY,aAAa,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;IAClF,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC;IAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,IAAI,EAAE,yDAAyD,YAAY,mBAAmB;YAC9F,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE;SACpC,CAAC;IACJ,CAAC;IAED,+CAA+C;IAC/C,yCAAyC;IACzC,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACzD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,EAAE;QAAE,OAAO,CAAC,IAAI,CAAC,OAAO,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC5C,IAAI,OAAO;QAAE,OAAO,CAAC,IAAI,CAAC,YAAY,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtB,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAEpE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC;YAC3B,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ;YACpC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC;gBACzB,MAAM,EAAE,IAAI;gBACZ,WAAW,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE;aAClC,CAAC;SACH,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAEvB,MAAM,IAAI,GAAG,MAAM,CAAC,IAA+B,CAAC;QACpD,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,IAAI,SAAS,CAAC;QACrC,OAAO;YACL,IAAI,EAAE,mCAAmC,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,kBAAkB,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;YAC7H,IAAI,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE;SAChC,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO;YACL,IAAI,EAAE,gBAAgB,OAAO,gBAAgB,YAAY,mBAAmB;YAC5E,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE;SACpC,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Send adapter: email — delivers scratchpad content as an email.
3
+ * When attachments are present, uses MIME builder for multipart message.
4
+ */
5
+ import type { HandlerResponse } from '../../handler.js';
6
+ import type { ScratchpadManager } from '../manager.js';
7
+ interface EmailTargetParams {
8
+ email: string;
9
+ to: string;
10
+ subject: string;
11
+ cc?: string;
12
+ bcc?: string;
13
+ }
14
+ export declare function sendEmail(scratchpads: ScratchpadManager, scratchpadId: string, targetParams: EmailTargetParams): Promise<HandlerResponse>;
15
+ export {};
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Send adapter: email — delivers scratchpad content as an email.
3
+ * When attachments are present, uses MIME builder for multipart message.
4
+ */
5
+ import * as fs from 'node:fs/promises';
6
+ import { execute } from '../../../executor/gws.js';
7
+ import { buildMimeMessage } from '../../../services/gmail/mime.js';
8
+ import { nextSteps } from '../../formatting/next-steps.js';
9
+ export async function sendEmail(scratchpads, scratchpadId, targetParams) {
10
+ const content = scratchpads.getContent(scratchpadId);
11
+ if (content === null) {
12
+ return { text: `Scratchpad ${scratchpadId} not found.`, refs: { error: true } };
13
+ }
14
+ const { email, to, subject, cc, bcc } = targetParams;
15
+ if (!email || !to || !subject) {
16
+ return {
17
+ text: `Send failed: email, to, and subject are required.\nScratchpad ${scratchpadId} is still active.`,
18
+ refs: { error: true, scratchpadId },
19
+ };
20
+ }
21
+ const attachments = scratchpads.getAttachments(scratchpadId);
22
+ const attachmentRefs = attachments ? [...attachments.values()] : [];
23
+ const hasAttachments = attachmentRefs.some(a => a.location);
24
+ try {
25
+ let data;
26
+ if (hasAttachments) {
27
+ // Build MIME multipart message with attachments
28
+ const mimeAttachments = await Promise.all(attachmentRefs
29
+ .filter(a => a.location)
30
+ .map(async (a) => ({
31
+ filename: a.filename,
32
+ mimeType: a.mimeType,
33
+ content: await fs.readFile(a.location),
34
+ })));
35
+ const raw = buildMimeMessage({
36
+ to, subject, body: content, cc, bcc,
37
+ attachments: mimeAttachments,
38
+ });
39
+ const result = await execute([
40
+ 'gmail', 'users', 'messages', 'send',
41
+ '--params', JSON.stringify({
42
+ userId: 'me',
43
+ requestBody: { raw },
44
+ }),
45
+ ], { account: email });
46
+ data = result.data;
47
+ }
48
+ else {
49
+ // Simple send without attachments
50
+ const args = ['gmail', '+send', '--to', to, '--subject', subject, '--body', content];
51
+ if (cc)
52
+ args.push('--cc', cc);
53
+ if (bcc)
54
+ args.push('--bcc', bcc);
55
+ const result = await execute(args, { account: email });
56
+ data = result.data;
57
+ }
58
+ const attNote = hasAttachments ? ` (${attachmentRefs.filter(a => a.location).length} attachment(s))` : '';
59
+ return {
60
+ text: `Email sent to ${to}${attNote}.\n\n**Subject:** ${subject}\n**Message ID:** ${data.id ?? 'unknown'}` +
61
+ nextSteps('email', 'send', { email }),
62
+ refs: { scratchpadId, id: data.id, threadId: data.threadId, to, subject },
63
+ };
64
+ }
65
+ catch (err) {
66
+ const message = err instanceof Error ? err.message : String(err);
67
+ return {
68
+ text: `Send failed: ${message}\nScratchpad ${scratchpadId} is still active.`,
69
+ refs: { error: true, scratchpadId },
70
+ };
71
+ }
72
+ }
73
+ //# sourceMappingURL=send-email.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-email.js","sourceRoot":"","sources":["../../../../src/server/scratchpad/adapters/send-email.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Send adapter: sheet_write — writes scratchpad CSV content to a Google Sheet.
3
+ * Parses CSV lines back into a values array for spreadsheets.values.update.
4
+ */
5
+ import type { HandlerResponse } from '../../handler.js';
6
+ import type { ScratchpadManager } from '../manager.js';
7
+ interface SheetWriteParams {
8
+ email: string;
9
+ spreadsheetId: string;
10
+ range?: string;
11
+ }
12
+ export declare function sendSheetWrite(scratchpads: ScratchpadManager, scratchpadId: string, targetParams: SheetWriteParams): Promise<HandlerResponse>;
13
+ export {};