visionclaw 0.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 (158) hide show
  1. package/README.md +116 -0
  2. package/dist/agent/context.d.ts +56 -0
  3. package/dist/agent/context.d.ts.map +1 -0
  4. package/dist/agent/context.js +142 -0
  5. package/dist/agent/context.js.map +1 -0
  6. package/dist/agent/loop.d.ts +18 -0
  7. package/dist/agent/loop.d.ts.map +1 -0
  8. package/dist/agent/loop.js +323 -0
  9. package/dist/agent/loop.js.map +1 -0
  10. package/dist/agent/session.d.ts +49 -0
  11. package/dist/agent/session.d.ts.map +1 -0
  12. package/dist/agent/session.js +200 -0
  13. package/dist/agent/session.js.map +1 -0
  14. package/dist/agent/system-prompt.d.ts +10 -0
  15. package/dist/agent/system-prompt.d.ts.map +1 -0
  16. package/dist/agent/system-prompt.js +167 -0
  17. package/dist/agent/system-prompt.js.map +1 -0
  18. package/dist/calendar/google-calendar.d.ts +46 -0
  19. package/dist/calendar/google-calendar.d.ts.map +1 -0
  20. package/dist/calendar/google-calendar.js +132 -0
  21. package/dist/calendar/google-calendar.js.map +1 -0
  22. package/dist/calendar/scheduler.d.ts +7 -0
  23. package/dist/calendar/scheduler.d.ts.map +1 -0
  24. package/dist/calendar/scheduler.js +33 -0
  25. package/dist/calendar/scheduler.js.map +1 -0
  26. package/dist/channels/discord.d.ts +19 -0
  27. package/dist/channels/discord.d.ts.map +1 -0
  28. package/dist/channels/discord.js +169 -0
  29. package/dist/channels/discord.js.map +1 -0
  30. package/dist/channels/gmail.d.ts +31 -0
  31. package/dist/channels/gmail.d.ts.map +1 -0
  32. package/dist/channels/gmail.js +300 -0
  33. package/dist/channels/gmail.js.map +1 -0
  34. package/dist/channels/interface.d.ts +45 -0
  35. package/dist/channels/interface.d.ts.map +1 -0
  36. package/dist/channels/interface.js +2 -0
  37. package/dist/channels/interface.js.map +1 -0
  38. package/dist/channels/manager.d.ts +36 -0
  39. package/dist/channels/manager.d.ts.map +1 -0
  40. package/dist/channels/manager.js +108 -0
  41. package/dist/channels/manager.js.map +1 -0
  42. package/dist/channels/queue.d.ts +17 -0
  43. package/dist/channels/queue.d.ts.map +1 -0
  44. package/dist/channels/queue.js +85 -0
  45. package/dist/channels/queue.js.map +1 -0
  46. package/dist/channels/slack.d.ts +17 -0
  47. package/dist/channels/slack.d.ts.map +1 -0
  48. package/dist/channels/slack.js +142 -0
  49. package/dist/channels/slack.js.map +1 -0
  50. package/dist/channels/sms.d.ts +19 -0
  51. package/dist/channels/sms.d.ts.map +1 -0
  52. package/dist/channels/sms.js +111 -0
  53. package/dist/channels/sms.js.map +1 -0
  54. package/dist/channels/telegram.d.ts +28 -0
  55. package/dist/channels/telegram.d.ts.map +1 -0
  56. package/dist/channels/telegram.js +246 -0
  57. package/dist/channels/telegram.js.map +1 -0
  58. package/dist/channels/whatsapp.d.ts +28 -0
  59. package/dist/channels/whatsapp.d.ts.map +1 -0
  60. package/dist/channels/whatsapp.js +292 -0
  61. package/dist/channels/whatsapp.js.map +1 -0
  62. package/dist/config/index.d.ts +24 -0
  63. package/dist/config/index.d.ts.map +1 -0
  64. package/dist/config/index.js +104 -0
  65. package/dist/config/index.js.map +1 -0
  66. package/dist/config/types.d.ts +227 -0
  67. package/dist/config/types.d.ts.map +1 -0
  68. package/dist/config/types.js +45 -0
  69. package/dist/config/types.js.map +1 -0
  70. package/dist/files.d.ts +20 -0
  71. package/dist/files.d.ts.map +1 -0
  72. package/dist/files.js +82 -0
  73. package/dist/files.js.map +1 -0
  74. package/dist/index.d.ts +3 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/dist/index.js +54 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/logger.d.ts +76 -0
  79. package/dist/logger.d.ts.map +1 -0
  80. package/dist/logger.js +384 -0
  81. package/dist/logger.js.map +1 -0
  82. package/dist/memory/store.d.ts +24 -0
  83. package/dist/memory/store.d.ts.map +1 -0
  84. package/dist/memory/store.js +71 -0
  85. package/dist/memory/store.js.map +1 -0
  86. package/dist/obs/server.d.ts +10 -0
  87. package/dist/obs/server.d.ts.map +1 -0
  88. package/dist/obs/server.js +406 -0
  89. package/dist/obs/server.js.map +1 -0
  90. package/dist/onboarding/google-auth.d.ts +11 -0
  91. package/dist/onboarding/google-auth.d.ts.map +1 -0
  92. package/dist/onboarding/google-auth.js +113 -0
  93. package/dist/onboarding/google-auth.js.map +1 -0
  94. package/dist/onboarding/index.d.ts +2 -0
  95. package/dist/onboarding/index.d.ts.map +1 -0
  96. package/dist/onboarding/index.js +213 -0
  97. package/dist/onboarding/index.js.map +1 -0
  98. package/dist/onboarding/macos-permissions.d.ts +37 -0
  99. package/dist/onboarding/macos-permissions.d.ts.map +1 -0
  100. package/dist/onboarding/macos-permissions.js +207 -0
  101. package/dist/onboarding/macos-permissions.js.map +1 -0
  102. package/dist/skills/install.d.ts +7 -0
  103. package/dist/skills/install.d.ts.map +1 -0
  104. package/dist/skills/install.js +63 -0
  105. package/dist/skills/install.js.map +1 -0
  106. package/dist/tools/browser.d.ts +7 -0
  107. package/dist/tools/browser.d.ts.map +1 -0
  108. package/dist/tools/browser.js +202 -0
  109. package/dist/tools/browser.js.map +1 -0
  110. package/dist/tools/calendar.d.ts +12 -0
  111. package/dist/tools/calendar.d.ts.map +1 -0
  112. package/dist/tools/calendar.js +210 -0
  113. package/dist/tools/calendar.js.map +1 -0
  114. package/dist/tools/computer-use.d.ts +28 -0
  115. package/dist/tools/computer-use.d.ts.map +1 -0
  116. package/dist/tools/computer-use.js +311 -0
  117. package/dist/tools/computer-use.js.map +1 -0
  118. package/dist/tools/coordinate-resolver.d.ts +26 -0
  119. package/dist/tools/coordinate-resolver.d.ts.map +1 -0
  120. package/dist/tools/coordinate-resolver.js +157 -0
  121. package/dist/tools/coordinate-resolver.js.map +1 -0
  122. package/dist/tools/desktop-executor.d.ts +52 -0
  123. package/dist/tools/desktop-executor.d.ts.map +1 -0
  124. package/dist/tools/desktop-executor.js +202 -0
  125. package/dist/tools/desktop-executor.js.map +1 -0
  126. package/dist/tools/finish.d.ts +5 -0
  127. package/dist/tools/finish.d.ts.map +1 -0
  128. package/dist/tools/finish.js +18 -0
  129. package/dist/tools/finish.js.map +1 -0
  130. package/dist/tools/index.d.ts +7 -0
  131. package/dist/tools/index.d.ts.map +1 -0
  132. package/dist/tools/index.js +37 -0
  133. package/dist/tools/index.js.map +1 -0
  134. package/dist/tools/memory.d.ts +14 -0
  135. package/dist/tools/memory.d.ts.map +1 -0
  136. package/dist/tools/memory.js +269 -0
  137. package/dist/tools/memory.js.map +1 -0
  138. package/dist/tools/notify.d.ts +12 -0
  139. package/dist/tools/notify.d.ts.map +1 -0
  140. package/dist/tools/notify.js +108 -0
  141. package/dist/tools/notify.js.map +1 -0
  142. package/dist/tools/screenshot.d.ts +7 -0
  143. package/dist/tools/screenshot.d.ts.map +1 -0
  144. package/dist/tools/screenshot.js +189 -0
  145. package/dist/tools/screenshot.js.map +1 -0
  146. package/dist/tools/skill.d.ts +8 -0
  147. package/dist/tools/skill.d.ts.map +1 -0
  148. package/dist/tools/skill.js +133 -0
  149. package/dist/tools/skill.js.map +1 -0
  150. package/dist/tools/upgrade.d.ts +5 -0
  151. package/dist/tools/upgrade.d.ts.map +1 -0
  152. package/dist/tools/upgrade.js +89 -0
  153. package/dist/tools/upgrade.js.map +1 -0
  154. package/dist/tools/wait.d.ts +5 -0
  155. package/dist/tools/wait.d.ts.map +1 -0
  156. package/dist/tools/wait.js +21 -0
  157. package/dist/tools/wait.js.map +1 -0
  158. package/package.json +61 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-calendar.js","sourceRoot":"","sources":["../../src/calendar/google-calendar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { VisionClawConfig } from "../config/types.js";
2
+ /**
3
+ * Get a summary of upcoming calendar events for context injection.
4
+ * Called on each agent wake to inform the agent of due/upcoming tasks.
5
+ */
6
+ export declare function getCalendarSummary(config: VisionClawConfig): Promise<string>;
7
+ //# sourceMappingURL=scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/calendar/scheduler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAI3D;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,MAAM,CAAC,CA+BjB"}
@@ -0,0 +1,33 @@
1
+ import { logger } from "../logger.js";
2
+ import { GoogleCalendarClient } from "./google-calendar.js";
3
+ /**
4
+ * Get a summary of upcoming calendar events for context injection.
5
+ * Called on each agent wake to inform the agent of due/upcoming tasks.
6
+ */
7
+ export async function getCalendarSummary(config) {
8
+ try {
9
+ const client = new GoogleCalendarClient(config);
10
+ const now = new Date();
11
+ const futureWindow = new Date(now.getTime() + 24 * 60 * 60 * 1000 // Next 24 hours
12
+ );
13
+ const events = await client.listUpcomingEvents(now, futureWindow);
14
+ if (events.length === 0) {
15
+ return "";
16
+ }
17
+ const lines = events.map((event) => {
18
+ const start = event.start?.dateTime ?? event.start?.date ?? "unknown";
19
+ const end = event.end?.dateTime ?? event.end?.date ?? "";
20
+ const summary = event.summary ?? "(no title)";
21
+ const description = event.description
22
+ ? ` - ${event.description.substring(0, 100)}`
23
+ : "";
24
+ return `- ${start}${end ? ` to ${end}` : ""}: ${summary}${description}`;
25
+ });
26
+ return lines.join("\n");
27
+ }
28
+ catch (err) {
29
+ logger.warn(`Calendar summary failed: ${err instanceof Error ? err.message : String(err)}`);
30
+ return "";
31
+ }
32
+ }
33
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/calendar/scheduler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAAwB;IAExB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,YAAY,GAAG,IAAI,IAAI,CAC3B,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,gBAAgB;SACrD,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QAElE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACjC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,QAAQ,IAAI,KAAK,CAAC,KAAK,EAAE,IAAI,IAAI,SAAS,CAAC;YACtE,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,EAAE,QAAQ,IAAI,KAAK,CAAC,GAAG,EAAE,IAAI,IAAI,EAAE,CAAC;YACzD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,YAAY,CAAC;YAC9C,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW;gBACnC,CAAC,CAAC,MAAM,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;gBAC7C,CAAC,CAAC,EAAE,CAAC;YACP,OAAO,KAAK,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,GAAG,WAAW,EAAE,CAAC;QAC1E,CAAC,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CACT,4BAA4B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC/E,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { EventEmitter } from "node:events";
2
+ import type { VisionClawConfig } from "../config/types.js";
3
+ import type { ChannelAdapter, MessageAttachment } from "./interface.js";
4
+ /**
5
+ * Discord channel adapter.
6
+ * Connects via WebSocket gateway -- no public URL needed.
7
+ * Supports multimodal inbound (images, files) and outbound (images, files).
8
+ */
9
+ export declare class DiscordAdapter extends EventEmitter implements ChannelAdapter {
10
+ readonly name = "discord";
11
+ private config;
12
+ private client;
13
+ constructor(config: VisionClawConfig);
14
+ start(): Promise<void>;
15
+ stop(): Promise<void>;
16
+ sendMessage(to: string, message: string, attachments?: MessageAttachment[]): Promise<void>;
17
+ private processInboundMessage;
18
+ }
19
+ //# sourceMappingURL=discord.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discord.d.ts","sourceRoot":"","sources":["../../src/channels/discord.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAW3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAkB,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExF;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,YAAa,YAAW,cAAc;IACxE,QAAQ,CAAC,IAAI,aAAa;IAC1B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,MAAM,CAAuB;gBAEzB,MAAM,EAAE,gBAAgB;IAK9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwCtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAOrB,WAAW,CACf,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,iBAAiB,EAAE,GAChC,OAAO,CAAC,IAAI,CAAC;YA4DF,qBAAqB;CAiEpC"}
@@ -0,0 +1,169 @@
1
+ import { EventEmitter } from "node:events";
2
+ import { Client, GatewayIntentBits, Partials, AttachmentBuilder, } from "discord.js";
3
+ import fs from "node:fs";
4
+ import { logger } from "../logger.js";
5
+ import { uploadMedia } from "../files.js";
6
+ /**
7
+ * Discord channel adapter.
8
+ * Connects via WebSocket gateway -- no public URL needed.
9
+ * Supports multimodal inbound (images, files) and outbound (images, files).
10
+ */
11
+ export class DiscordAdapter extends EventEmitter {
12
+ name = "discord";
13
+ config;
14
+ client = null;
15
+ constructor(config) {
16
+ super();
17
+ this.config = config;
18
+ }
19
+ async start() {
20
+ const discordConfig = this.config.channels.discord;
21
+ if (!discordConfig?.botToken) {
22
+ throw new Error("Discord bot token not configured");
23
+ }
24
+ this.client = new Client({
25
+ intents: [
26
+ GatewayIntentBits.Guilds,
27
+ GatewayIntentBits.GuildMessages,
28
+ GatewayIntentBits.DirectMessages,
29
+ GatewayIntentBits.MessageContent,
30
+ ],
31
+ partials: [Partials.Channel], // Required for DMs
32
+ });
33
+ const allowedChannelIds = discordConfig.allowedChannelIds;
34
+ this.client.on("messageCreate", (msg) => {
35
+ // Ignore bot's own messages
36
+ if (msg.author.bot)
37
+ return;
38
+ // Filter by allowed channels/DMs if configured
39
+ if (allowedChannelIds.length > 0 && !allowedChannelIds.includes(msg.channelId)) {
40
+ // Allow DMs through regardless
41
+ if (!msg.channel.isDMBased())
42
+ return;
43
+ }
44
+ // Process asynchronously to allow media downloads
45
+ void this.processInboundMessage(msg);
46
+ });
47
+ this.client.on("error", (err) => {
48
+ this.emit("error", err);
49
+ });
50
+ await this.client.login(discordConfig.botToken);
51
+ logger.channel("discord", `Logged in as ${this.client.user?.tag ?? "unknown"}`);
52
+ }
53
+ async stop() {
54
+ if (this.client) {
55
+ await this.client.destroy();
56
+ this.client = null;
57
+ }
58
+ }
59
+ async sendMessage(to, message, attachments) {
60
+ if (!this.client) {
61
+ throw new Error("Discord client not started");
62
+ }
63
+ const channel = await this.client.channels.fetch(to);
64
+ if (!channel?.isTextBased()) {
65
+ throw new Error(`Discord channel ${to} is not a text channel`);
66
+ }
67
+ if (!("send" in channel)) {
68
+ throw new Error(`Cannot send to Discord channel ${to}`);
69
+ }
70
+ // Build Discord attachments from local paths or URLs
71
+ const discordAttachments = [];
72
+ if (attachments) {
73
+ for (const att of attachments) {
74
+ if (att.localPath && fs.existsSync(att.localPath)) {
75
+ discordAttachments.push(new AttachmentBuilder(att.localPath, {
76
+ name: att.filename ?? att.localPath.split("/").pop(),
77
+ }));
78
+ }
79
+ else if (att.url) {
80
+ discordAttachments.push(new AttachmentBuilder(att.url, {
81
+ name: att.filename ?? "attachment",
82
+ }));
83
+ }
84
+ }
85
+ }
86
+ // Split long messages (Discord has a 2000 char limit)
87
+ const MAX_LENGTH = 2000;
88
+ if (message.trim()) {
89
+ if (message.length <= MAX_LENGTH) {
90
+ await channel.send({
91
+ content: message,
92
+ files: discordAttachments,
93
+ });
94
+ }
95
+ else {
96
+ // Send attachments with first chunk
97
+ const chunks = [];
98
+ for (let i = 0; i < message.length; i += MAX_LENGTH) {
99
+ chunks.push(message.substring(i, i + MAX_LENGTH));
100
+ }
101
+ for (let i = 0; i < chunks.length; i++) {
102
+ await channel.send({
103
+ content: chunks[i],
104
+ files: i === 0 ? discordAttachments : undefined,
105
+ });
106
+ }
107
+ }
108
+ }
109
+ else if (discordAttachments.length > 0) {
110
+ await channel.send({ files: discordAttachments });
111
+ }
112
+ }
113
+ async processInboundMessage(msg) {
114
+ try {
115
+ const senderDisplay = `${msg.author.displayName} (${msg.author.id})`;
116
+ const commandMessage = {
117
+ id: `discord-${msg.id}`,
118
+ channel: "discord",
119
+ sender: senderDisplay,
120
+ text: msg.content,
121
+ attachments: [],
122
+ timestamp: msg.createdAt.toISOString(),
123
+ meta: {
124
+ channelId: msg.channelId,
125
+ guildId: msg.guildId,
126
+ authorId: msg.author.id,
127
+ username: msg.author.username,
128
+ },
129
+ };
130
+ // Download attachments and upload to S3
131
+ for (const att of msg.attachments.values()) {
132
+ const mimeType = att.contentType ?? "application/octet-stream";
133
+ const filename = att.name;
134
+ let publicUrl;
135
+ try {
136
+ const response = await fetch(att.url);
137
+ if (response.ok) {
138
+ const buffer = Buffer.from(await response.arrayBuffer());
139
+ const s3Url = await uploadMedia(buffer, filename, mimeType);
140
+ publicUrl = s3Url ?? undefined;
141
+ }
142
+ }
143
+ catch (err) {
144
+ logger.warn(`Discord: Failed to download attachment: ${err instanceof Error ? err.message : String(err)}`);
145
+ }
146
+ const type = mimeType.startsWith("image/")
147
+ ? "image"
148
+ : mimeType.startsWith("audio/")
149
+ ? "audio"
150
+ : mimeType.startsWith("video/")
151
+ ? "video"
152
+ : "file";
153
+ commandMessage.attachments.push({
154
+ type,
155
+ url: publicUrl ?? att.url,
156
+ filename,
157
+ mimeType,
158
+ });
159
+ }
160
+ if (commandMessage.text || commandMessage.attachments.length > 0) {
161
+ this.emit("message", commandMessage);
162
+ }
163
+ }
164
+ catch (err) {
165
+ logger.warn(`Discord: Error processing message: ${err instanceof Error ? err.message : String(err)}`);
166
+ }
167
+ }
168
+ }
169
+ //# sourceMappingURL=discord.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discord.js","sourceRoot":"","sources":["../../src/channels/discord.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { EventEmitter } from "node:events";
2
+ import type { VisionClawConfig } from "../config/types.js";
3
+ import type { ChannelAdapter, MessageAttachment } from "./interface.js";
4
+ /**
5
+ * Gmail channel adapter.
6
+ * Uses the agent's dedicated Gmail account to receive and send emails.
7
+ *
8
+ * On startup, captures the current historyId and only processes
9
+ * messages that arrive AFTER that point via the Gmail History API.
10
+ * This prevents old unread emails from flooding the agent.
11
+ */
12
+ export declare class GmailAdapter extends EventEmitter implements ChannelAdapter {
13
+ readonly name = "gmail";
14
+ private config;
15
+ private gmail;
16
+ private pollInterval;
17
+ private lastHistoryId;
18
+ private processedMessageIds;
19
+ private initialized;
20
+ constructor(config: VisionClawConfig);
21
+ start(): Promise<void>;
22
+ stop(): Promise<void>;
23
+ sendMessage(to: string, message: string, attachments?: MessageAttachment[]): Promise<void>;
24
+ /**
25
+ * Poll for new messages using the Gmail History API.
26
+ * Only fetches messages added since the last known historyId,
27
+ * so old unread emails are never processed.
28
+ */
29
+ private pollForMessages;
30
+ }
31
+ //# sourceMappingURL=gmail.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gmail.d.ts","sourceRoot":"","sources":["../../src/channels/gmail.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQ3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAkB,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExF;;;;;;;GAOG;AACH,qBAAa,YAAa,SAAQ,YAAa,YAAW,cAAc;IACtE,QAAQ,CAAC,IAAI,WAAW;IACxB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,KAAK,CAAiB;IAC9B,OAAO,CAAC,YAAY,CAA+C;IACnE,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,WAAW,CAAS;gBAEhB,MAAM,EAAE,gBAAgB;IA4B9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQf,WAAW,CACf,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,iBAAiB,EAAE,GAChC,OAAO,CAAC,IAAI,CAAC;IAehB;;;;OAIG;YACW,eAAe;CAwF9B"}
@@ -0,0 +1,300 @@
1
+ import fs from "node:fs";
2
+ import { EventEmitter } from "node:events";
3
+ import { google } from "googleapis";
4
+ import { loadGoogleTokens, saveGoogleTokens, } from "../config/index.js";
5
+ import { logger } from "../logger.js";
6
+ import { uploadMedia } from "../files.js";
7
+ /**
8
+ * Gmail channel adapter.
9
+ * Uses the agent's dedicated Gmail account to receive and send emails.
10
+ *
11
+ * On startup, captures the current historyId and only processes
12
+ * messages that arrive AFTER that point via the Gmail History API.
13
+ * This prevents old unread emails from flooding the agent.
14
+ */
15
+ export class GmailAdapter extends EventEmitter {
16
+ name = "gmail";
17
+ config;
18
+ gmail;
19
+ pollInterval = null;
20
+ lastHistoryId = null;
21
+ processedMessageIds = new Set();
22
+ initialized = false;
23
+ constructor(config) {
24
+ super();
25
+ this.config = config;
26
+ const tokens = loadGoogleTokens();
27
+ const oauth2Client = new google.auth.OAuth2(config.googleClientId, config.googleClientSecret);
28
+ oauth2Client.setCredentials({
29
+ access_token: tokens.access_token,
30
+ refresh_token: tokens.refresh_token,
31
+ token_type: tokens.token_type,
32
+ expiry_date: tokens.expiry_date,
33
+ });
34
+ oauth2Client.on("tokens", (newTokens) => {
35
+ const existing = loadGoogleTokens();
36
+ saveGoogleTokens({
37
+ ...existing,
38
+ access_token: newTokens.access_token ?? existing.access_token,
39
+ expiry_date: newTokens.expiry_date ?? existing.expiry_date,
40
+ });
41
+ });
42
+ this.gmail = google.gmail({ version: "v1", auth: oauth2Client });
43
+ }
44
+ async start() {
45
+ // Capture current historyId as our baseline.
46
+ // We will only process messages that arrive AFTER this point.
47
+ try {
48
+ const profile = await this.gmail.users.getProfile({ userId: "me" });
49
+ this.lastHistoryId = profile.data.historyId ?? null;
50
+ this.initialized = true;
51
+ logger.channel("gmail", `Baseline historyId: ${this.lastHistoryId}`);
52
+ }
53
+ catch (err) {
54
+ logger.warn(`Gmail: Could not get initial history ID: ${err instanceof Error ? err.message : String(err)}`);
55
+ }
56
+ // Poll for new messages every 30 seconds
57
+ this.pollInterval = setInterval(() => {
58
+ this.pollForMessages().catch((err) => {
59
+ this.emit("error", err instanceof Error ? err : new Error(String(err)));
60
+ });
61
+ }, 30_000);
62
+ }
63
+ stop() {
64
+ if (this.pollInterval) {
65
+ clearInterval(this.pollInterval);
66
+ this.pollInterval = null;
67
+ }
68
+ return Promise.resolve();
69
+ }
70
+ async sendMessage(to, message, attachments) {
71
+ const raw = createRawEmail({
72
+ from: this.config.gmail,
73
+ to,
74
+ subject: "Message from " + this.config.agentName,
75
+ body: message,
76
+ attachments,
77
+ });
78
+ await this.gmail.users.messages.send({
79
+ userId: "me",
80
+ requestBody: { raw },
81
+ });
82
+ }
83
+ /**
84
+ * Poll for new messages using the Gmail History API.
85
+ * Only fetches messages added since the last known historyId,
86
+ * so old unread emails are never processed.
87
+ */
88
+ async pollForMessages() {
89
+ if (!this.initialized || !this.lastHistoryId) {
90
+ return;
91
+ }
92
+ try {
93
+ // Use History API to get only messages added since our last checkpoint
94
+ const historyRes = await this.gmail.users.history.list({
95
+ userId: "me",
96
+ startHistoryId: this.lastHistoryId,
97
+ historyTypes: ["messageAdded"],
98
+ labelId: "INBOX",
99
+ });
100
+ // Update historyId for next poll
101
+ if (historyRes.data.historyId) {
102
+ this.lastHistoryId = historyRes.data.historyId;
103
+ }
104
+ const history = historyRes.data.history ?? [];
105
+ // Extract new message IDs from history records
106
+ const newMessageIds = [];
107
+ for (const record of history) {
108
+ const added = record.messagesAdded ?? [];
109
+ for (const item of added) {
110
+ const msgId = item.message?.id;
111
+ if (msgId && !this.processedMessageIds.has(msgId)) {
112
+ newMessageIds.push(msgId);
113
+ }
114
+ }
115
+ }
116
+ if (newMessageIds.length === 0) {
117
+ return;
118
+ }
119
+ logger.channel("gmail", `${newMessageIds.length} new message(s) detected`);
120
+ for (const msgId of newMessageIds) {
121
+ this.processedMessageIds.add(msgId);
122
+ // Keep the set from growing unbounded
123
+ if (this.processedMessageIds.size > 1000) {
124
+ const entries = Array.from(this.processedMessageIds);
125
+ this.processedMessageIds = new Set(entries.slice(-500));
126
+ }
127
+ try {
128
+ const full = await this.gmail.users.messages.get({
129
+ userId: "me",
130
+ id: msgId,
131
+ format: "full",
132
+ });
133
+ // Always mark as read to prevent re-processing
134
+ await this.gmail.users.messages.modify({
135
+ userId: "me",
136
+ id: msgId,
137
+ requestBody: { removeLabelIds: ["UNREAD"] },
138
+ });
139
+ const commandMessage = await parseGmailMessage(full.data, msgId, this.gmail);
140
+ if (commandMessage) {
141
+ this.emit("message", commandMessage);
142
+ }
143
+ }
144
+ catch (err) {
145
+ logger.warn(`Gmail: Error processing message ${msgId}: ${err instanceof Error ? err.message : String(err)}`);
146
+ }
147
+ }
148
+ }
149
+ catch (err) {
150
+ const errMsg = err instanceof Error ? err.message : String(err);
151
+ // If historyId is too old, Gmail returns 404. Reset baseline.
152
+ if (errMsg.includes("404") || errMsg.includes("historyId")) {
153
+ logger.warn("Gmail: History expired, resetting baseline");
154
+ try {
155
+ const profile = await this.gmail.users.getProfile({ userId: "me" });
156
+ this.lastHistoryId = profile.data.historyId ?? null;
157
+ }
158
+ catch {
159
+ // noop
160
+ }
161
+ return;
162
+ }
163
+ logger.warn(`Gmail poll error: ${errMsg}`);
164
+ }
165
+ }
166
+ }
167
+ /**
168
+ * Parse a Gmail API message into a CommandMessage.
169
+ * Downloads attachments and uploads them to S3.
170
+ */
171
+ async function parseGmailMessage(msg, id, gmail) {
172
+ const headers = msg.payload?.headers ?? [];
173
+ const from = headers.find((h) => h.name?.toLowerCase() === "from")?.value ?? "unknown";
174
+ const subject = headers.find((h) => h.name?.toLowerCase() === "subject")?.value ?? "";
175
+ const date = headers.find((h) => h.name?.toLowerCase() === "date")?.value ?? "";
176
+ // Extract body text and attachments from parts
177
+ let body = "";
178
+ const attachments = [];
179
+ if (msg.payload?.body?.data) {
180
+ body = Buffer.from(msg.payload.body.data, "base64url").toString("utf-8");
181
+ }
182
+ if (msg.payload?.parts) {
183
+ for (const part of msg.payload.parts) {
184
+ // Text body
185
+ if (part.mimeType === "text/plain" && part.body?.data && !body) {
186
+ body = Buffer.from(part.body.data, "base64url").toString("utf-8");
187
+ continue;
188
+ }
189
+ // Attachment with attachmentId
190
+ const attachmentId = part.body?.attachmentId;
191
+ const filename = part.filename ?? "";
192
+ const mimeType = part.mimeType ?? "application/octet-stream";
193
+ if (attachmentId && filename) {
194
+ try {
195
+ const attRes = await gmail.users.messages.attachments.get({
196
+ userId: "me",
197
+ messageId: id,
198
+ id: attachmentId,
199
+ });
200
+ if (attRes.data.data) {
201
+ const buffer = Buffer.from(attRes.data.data, "base64url");
202
+ const url = await uploadMedia(buffer, filename, mimeType);
203
+ const type = mimeType.startsWith("image/")
204
+ ? "image"
205
+ : mimeType.startsWith("audio/")
206
+ ? "audio"
207
+ : mimeType.startsWith("video/")
208
+ ? "video"
209
+ : "file";
210
+ attachments.push({ type, url: url ?? undefined, filename, mimeType });
211
+ }
212
+ }
213
+ catch (err) {
214
+ logger.warn(`Gmail: Failed to download attachment ${filename}: ${err instanceof Error ? err.message : String(err)}`);
215
+ }
216
+ }
217
+ }
218
+ }
219
+ // If no plain text body, summarize from subject only
220
+ if (!body.trim()) {
221
+ if (!subject.trim() && attachments.length === 0) {
222
+ return null;
223
+ }
224
+ body = attachments.length > 0 ? "(attachments only)" : "(no text body)";
225
+ }
226
+ return {
227
+ id,
228
+ channel: "gmail",
229
+ sender: from,
230
+ text: subject ? `[Subject: ${subject}]\n${body}` : body,
231
+ attachments,
232
+ timestamp: date.trim() ? date : new Date().toISOString(),
233
+ meta: { subject, messageId: msg.id, threadId: msg.threadId },
234
+ };
235
+ }
236
+ /**
237
+ * Create a base64url-encoded raw email for the Gmail API.
238
+ * Supports optional file attachments via MIME multipart.
239
+ */
240
+ function createRawEmail(options) {
241
+ const hasAttachments = options.attachments && options.attachments.length > 0;
242
+ if (!hasAttachments) {
243
+ // Simple text email
244
+ const email = [
245
+ `From: ${options.from}`,
246
+ `To: ${options.to}`,
247
+ `Subject: ${options.subject}`,
248
+ `Content-Type: text/plain; charset=utf-8`,
249
+ "",
250
+ options.body,
251
+ ].join("\r\n");
252
+ return Buffer.from(email).toString("base64url");
253
+ }
254
+ // Multipart MIME email with attachments
255
+ const boundary = `----VisionClaw${Date.now()}`;
256
+ const parts = [];
257
+ parts.push(`From: ${options.from}`);
258
+ parts.push(`To: ${options.to}`);
259
+ parts.push(`Subject: ${options.subject}`);
260
+ parts.push(`MIME-Version: 1.0`);
261
+ parts.push(`Content-Type: multipart/mixed; boundary="${boundary}"`);
262
+ parts.push("");
263
+ // Text body part
264
+ parts.push(`--${boundary}`);
265
+ parts.push(`Content-Type: text/plain; charset=utf-8`);
266
+ parts.push("");
267
+ parts.push(options.body);
268
+ // Attachment parts
269
+ for (const att of options.attachments ?? []) {
270
+ let b64Data = null;
271
+ const filename = att.filename ?? "attachment";
272
+ const mimeType = att.mimeType ?? "application/octet-stream";
273
+ if (att.localPath && fs.existsSync(att.localPath)) {
274
+ // Read local file and encode as base64
275
+ b64Data = fs.readFileSync(att.localPath).toString("base64");
276
+ }
277
+ else if (att.base64) {
278
+ b64Data = att.base64;
279
+ }
280
+ else if (att.url) {
281
+ // Include URL as a link (can't inline remote URLs in MIME)
282
+ parts.push(`--${boundary}`);
283
+ parts.push(`Content-Type: text/plain; charset=utf-8`);
284
+ parts.push("");
285
+ parts.push(`[Attachment: ${filename}] ${att.url}`);
286
+ continue;
287
+ }
288
+ if (b64Data) {
289
+ parts.push(`--${boundary}`);
290
+ parts.push(`Content-Type: ${mimeType}`);
291
+ parts.push(`Content-Transfer-Encoding: base64`);
292
+ parts.push(`Content-Disposition: attachment; filename="${filename}"`);
293
+ parts.push("");
294
+ parts.push(b64Data);
295
+ }
296
+ }
297
+ parts.push(`--${boundary}--`);
298
+ return Buffer.from(parts.join("\r\n")).toString("base64url");
299
+ }
300
+ //# sourceMappingURL=gmail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gmail.js","sourceRoot":"","sources":["../../src/channels/gmail.ts"],"names":[],"mappings":"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"}