0xkobold 0.1.0 → 0.3.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 (170) hide show
  1. package/HEARTBEAT.md +48 -32
  2. package/README.md +426 -157
  3. package/dist/package.json +5 -2
  4. package/dist/src/agent/bootstrap-loader.js +138 -0
  5. package/dist/src/agent/bootstrap-loader.js.map +1 -0
  6. package/dist/src/agent/context-pruning.js +279 -0
  7. package/dist/src/agent/context-pruning.js.map +1 -0
  8. package/dist/src/agent/dynamic-personality.js +211 -0
  9. package/dist/src/agent/dynamic-personality.js.map +1 -0
  10. package/dist/src/agent/embedded-runner.js +79 -0
  11. package/dist/src/agent/embedded-runner.js.map +1 -0
  12. package/dist/src/agent/index.js +16 -0
  13. package/dist/src/agent/index.js.map +1 -0
  14. package/dist/src/agent/system-prompt.js +84 -0
  15. package/dist/src/agent/system-prompt.js.map +1 -0
  16. package/dist/src/agent/task-router.js +194 -0
  17. package/dist/src/agent/task-router.js.map +1 -0
  18. package/dist/src/agent/tools/index.js +2 -0
  19. package/dist/src/agent/tools/index.js.map +1 -0
  20. package/dist/src/agent/tools/spawn-agent.js +200 -0
  21. package/dist/src/agent/tools/spawn-agent.js.map +1 -0
  22. package/dist/src/agent/types/definitions.js +317 -0
  23. package/dist/src/agent/types/definitions.js.map +1 -0
  24. package/dist/src/agent/types/index.js +2 -0
  25. package/dist/src/agent/types/index.js.map +1 -0
  26. package/dist/src/agent/user-profile.js +300 -0
  27. package/dist/src/agent/user-profile.js.map +1 -0
  28. package/dist/src/agents/task-router.js +194 -0
  29. package/dist/src/agents/task-router.js.map +1 -0
  30. package/dist/src/agents/tools/index.js +2 -0
  31. package/dist/src/agents/tools/index.js.map +1 -0
  32. package/dist/src/agents/tools/spawn-agent.js +200 -0
  33. package/dist/src/agents/tools/spawn-agent.js.map +1 -0
  34. package/dist/src/agents/types/definitions.js +317 -0
  35. package/dist/src/agents/types/definitions.js.map +1 -0
  36. package/dist/src/agents/types/index.js +2 -0
  37. package/dist/src/agents/types/index.js.map +1 -0
  38. package/dist/src/auth/device-auth.js +202 -0
  39. package/dist/src/auth/device-auth.js.map +1 -0
  40. package/dist/src/auth/index.js +3 -0
  41. package/dist/src/auth/index.js.map +1 -0
  42. package/dist/src/channels/index.js +8 -0
  43. package/dist/src/channels/index.js.map +1 -0
  44. package/dist/src/channels/slack/webhook.js +128 -0
  45. package/dist/src/channels/slack/webhook.js.map +1 -0
  46. package/dist/src/channels/telegram/bot.js +223 -0
  47. package/dist/src/channels/telegram/bot.js.map +1 -0
  48. package/dist/src/channels/whatsapp/integration.js +325 -0
  49. package/dist/src/channels/whatsapp/integration.js.map +1 -0
  50. package/dist/src/cli/commands/check.js +69 -0
  51. package/dist/src/cli/commands/check.js.map +1 -0
  52. package/dist/src/cli/commands/embedded.js +36 -0
  53. package/dist/src/cli/commands/embedded.js.map +1 -0
  54. package/dist/src/cli/commands/gateway.js +127 -166
  55. package/dist/src/cli/commands/gateway.js.map +1 -1
  56. package/dist/src/cli/commands/migrate.js +24 -0
  57. package/dist/src/cli/commands/migrate.js.map +1 -0
  58. package/dist/src/cli/commands/tailscale.js +81 -0
  59. package/dist/src/cli/commands/tailscale.js.map +1 -0
  60. package/dist/src/cli/commands/telegram.js +111 -0
  61. package/dist/src/cli/commands/telegram.js.map +1 -0
  62. package/dist/src/cli/commands/tui.js +40 -22
  63. package/dist/src/cli/commands/tui.js.map +1 -1
  64. package/dist/src/cli/commands/whatsapp.js +116 -0
  65. package/dist/src/cli/commands/whatsapp.js.map +1 -0
  66. package/dist/src/cli/program-fixed.js +1 -0
  67. package/dist/src/cli/program-fixed.js.map +1 -0
  68. package/dist/src/cli/program.js +30 -29
  69. package/dist/src/cli/program.js.map +1 -1
  70. package/dist/src/config/index.js +2 -9
  71. package/dist/src/config/index.js.map +1 -1
  72. package/dist/src/config/manager.js +222 -0
  73. package/dist/src/config/manager.js.map +1 -0
  74. package/dist/src/documents/index.js +3 -0
  75. package/dist/src/documents/index.js.map +1 -0
  76. package/dist/src/documents/pdf.js +168 -0
  77. package/dist/src/documents/pdf.js.map +1 -0
  78. package/dist/src/extensions/core/agent-lifecycle-extension.js +323 -0
  79. package/dist/src/extensions/core/agent-lifecycle-extension.js.map +1 -0
  80. package/dist/src/extensions/core/agent-orchestrator-extension.js +642 -0
  81. package/dist/src/extensions/core/agent-orchestrator-extension.js.map +1 -0
  82. package/dist/src/extensions/core/agent-workspace-extension.js +174 -0
  83. package/dist/src/extensions/core/agent-workspace-extension.js.map +1 -0
  84. package/dist/src/extensions/core/autonomous-executor-extension.js +145 -0
  85. package/dist/src/extensions/core/autonomous-executor-extension.js.map +1 -0
  86. package/dist/src/extensions/core/autonomous-subagent-extension.js +333 -0
  87. package/dist/src/extensions/core/autonomous-subagent-extension.js.map +1 -0
  88. package/dist/src/extensions/core/deprecated/agent-lifecycle-extension.js +323 -0
  89. package/dist/src/extensions/core/deprecated/agent-lifecycle-extension.js.map +1 -0
  90. package/dist/src/extensions/core/deprecated/autonomous-subagent-extension.js +333 -0
  91. package/dist/src/extensions/core/deprecated/autonomous-subagent-extension.js.map +1 -0
  92. package/dist/src/extensions/core/deprecated/subagent-extension.js +647 -0
  93. package/dist/src/extensions/core/deprecated/subagent-extension.js.map +1 -0
  94. package/dist/src/extensions/core/mode-manager-extension.js +11 -0
  95. package/dist/src/extensions/core/mode-manager-extension.js.map +1 -1
  96. package/dist/src/extensions/core/persona-loader-extension.js +61 -129
  97. package/dist/src/extensions/core/persona-loader-extension.js.map +1 -1
  98. package/dist/src/extensions/core/websearch-enhanced-extension.js +705 -0
  99. package/dist/src/extensions/core/websearch-enhanced-extension.js.map +1 -0
  100. package/dist/src/extensions/core/websearch-v2-extension.js +303 -0
  101. package/dist/src/extensions/core/websearch-v2-extension.js.map +1 -0
  102. package/dist/src/gateway/client.js +318 -0
  103. package/dist/src/gateway/client.js.map +1 -0
  104. package/dist/src/gateway/discord-bot.js +185 -0
  105. package/dist/src/gateway/discord-bot.js.map +1 -0
  106. package/dist/src/gateway/index.js +10 -350
  107. package/dist/src/gateway/index.js.map +1 -1
  108. package/dist/src/gateway/server.js +325 -0
  109. package/dist/src/gateway/server.js.map +1 -0
  110. package/dist/src/gateway/websocket-server.js +142 -0
  111. package/dist/src/gateway/websocket-server.js.map +1 -0
  112. package/dist/src/heartbeat/checkin.js +185 -0
  113. package/dist/src/heartbeat/checkin.js.map +1 -0
  114. package/dist/src/heartbeat/index.js +5 -0
  115. package/dist/src/heartbeat/index.js.map +1 -0
  116. package/dist/src/heartbeat/notifications.js +216 -0
  117. package/dist/src/heartbeat/notifications.js.map +1 -0
  118. package/dist/src/heartbeat/scheduler.js +284 -0
  119. package/dist/src/heartbeat/scheduler.js.map +1 -0
  120. package/dist/src/index.js +21 -3
  121. package/dist/src/index.js.map +1 -1
  122. package/dist/src/infra/index.js +3 -0
  123. package/dist/src/infra/index.js.map +1 -0
  124. package/dist/src/infra/tailscale.js +163 -0
  125. package/dist/src/infra/tailscale.js.map +1 -0
  126. package/dist/src/media/audio.js +130 -0
  127. package/dist/src/media/audio.js.map +1 -0
  128. package/dist/src/media/index.js +4 -0
  129. package/dist/src/media/index.js.map +1 -0
  130. package/dist/src/media/vision.js +131 -0
  131. package/dist/src/media/vision.js.map +1 -0
  132. package/dist/src/migration/openclaw.js +498 -0
  133. package/dist/src/migration/openclaw.js.map +1 -0
  134. package/dist/src/mode/auto-detector.js +211 -0
  135. package/dist/src/mode/auto-detector.js.map +1 -0
  136. package/dist/src/mode/index.js +3 -0
  137. package/dist/src/mode/index.js.map +1 -0
  138. package/dist/src/mode/natural-switcher.js +123 -0
  139. package/dist/src/mode/natural-switcher.js.map +1 -0
  140. package/dist/src/sandbox/docker-runner.js +228 -0
  141. package/dist/src/sandbox/docker-runner.js.map +1 -0
  142. package/dist/src/sandbox/index.js +3 -0
  143. package/dist/src/sandbox/index.js.map +1 -0
  144. package/dist/src/skills/builtin/api-worker.js +88 -0
  145. package/dist/src/skills/builtin/api-worker.js.map +1 -0
  146. package/dist/src/skills/builtin/duplicate-detector.js +469 -0
  147. package/dist/src/skills/builtin/duplicate-detector.js.map +1 -0
  148. package/dist/src/skills/builtin/nextjs-worker.js +55 -0
  149. package/dist/src/skills/builtin/nextjs-worker.js.map +1 -0
  150. package/dist/src/skills/builtin/real-workers.js +166 -0
  151. package/dist/src/skills/builtin/real-workers.js.map +1 -0
  152. package/dist/src/skills/builtin/sql-worker.js +61 -0
  153. package/dist/src/skills/builtin/sql-worker.js.map +1 -0
  154. package/dist/src/skills/builtin/test-worker.js +79 -0
  155. package/dist/src/skills/builtin/test-worker.js.map +1 -0
  156. package/dist/src/skills/builtin/web-research.js +77 -0
  157. package/dist/src/skills/builtin/web-research.js.map +1 -0
  158. package/dist/src/skills/framework.js +250 -0
  159. package/dist/src/skills/framework.js.map +1 -0
  160. package/dist/src/skills/index.js +12 -10
  161. package/dist/src/skills/index.js.map +1 -1
  162. package/dist/src/streaming/block-streamer.js +172 -0
  163. package/dist/src/streaming/block-streamer.js.map +1 -0
  164. package/dist/src/streaming/index.js +2 -0
  165. package/dist/src/streaming/index.js.map +1 -0
  166. package/dist/src/workspace/index.js +2 -0
  167. package/dist/src/workspace/index.js.map +1 -0
  168. package/dist/src/workspace/manager.js +181 -0
  169. package/dist/src/workspace/manager.js.map +1 -0
  170. package/package.json +5 -2
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Slack Integration - v0.3.0
3
+ *
4
+ * Webhook and slash command support for Slack.
5
+ */
6
+ import { EventEmitter } from "events";
7
+ import { getRealGateway } from "../../gateway/index.js";
8
+ class SlackIntegration extends EventEmitter {
9
+ config;
10
+ connected = false;
11
+ gatewayConnectionId;
12
+ constructor(config) {
13
+ super();
14
+ this.config = {
15
+ port: 3001,
16
+ ...config,
17
+ };
18
+ }
19
+ /**
20
+ * Send message via webhook
21
+ */
22
+ async sendMessage(text, options) {
23
+ const payload = { text };
24
+ if (options?.channel)
25
+ payload.channel = options.channel;
26
+ if (options?.username)
27
+ payload.username = options.username;
28
+ if (options?.iconEmoji)
29
+ payload.icon_emoji = options.iconEmoji;
30
+ if (options?.blocks)
31
+ payload.blocks = options.blocks;
32
+ try {
33
+ const response = await fetch(this.config.webhookUrl, {
34
+ method: "POST",
35
+ headers: { "Content-Type": "application/json" },
36
+ body: JSON.stringify(payload),
37
+ });
38
+ if (!response.ok) {
39
+ const error = await response.text();
40
+ return { ok: false, error };
41
+ }
42
+ return { ok: true };
43
+ }
44
+ catch (error) {
45
+ return { ok: false, error: String(error) };
46
+ }
47
+ }
48
+ /**
49
+ * Send rich message with blocks
50
+ */
51
+ async sendRichMessage(blocks) {
52
+ return this.sendMessage("", { blocks });
53
+ }
54
+ /**
55
+ * Send typing indicator (simulated via webhook)
56
+ */
57
+ async sendTyping(channel) {
58
+ // Slack webhooks don't support typing, but we can simulate with a status update
59
+ console.log(`[Slack] Typing in ${channel}`);
60
+ }
61
+ /**
62
+ * Handle incoming webhook
63
+ */
64
+ handleWebhook(payload) {
65
+ console.log(`[Slack] ${payload.type}: ${payload.text.slice(0, 50)}...`);
66
+ // Forward to gateway
67
+ this.forwardToGateway(payload);
68
+ this.emit("message", payload);
69
+ }
70
+ /**
71
+ * Verify Slack signature
72
+ */
73
+ verifySignature(body, timestamp, signature) {
74
+ if (!this.config.signingSecret) {
75
+ // Skip verification if no secret configured
76
+ return true;
77
+ }
78
+ // Simple verification - in production use proper HMAC
79
+ const crypto = require("node:crypto");
80
+ const hmac = crypto.createHmac("sha256", this.config.signingSecret);
81
+ hmac.update(`v0:${timestamp}:${body}`);
82
+ const expected = `v0=${hmac.digest("hex")}`;
83
+ return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
84
+ }
85
+ /**
86
+ * Forward to gateway
87
+ */
88
+ forwardToGateway(message) {
89
+ const gateway = getRealGateway();
90
+ gateway.emit("message", {
91
+ connection: {
92
+ id: this.gatewayConnectionId,
93
+ type: "slack",
94
+ channel: message.channel || "webhook",
95
+ user: message.user,
96
+ },
97
+ data: {
98
+ type: "chat",
99
+ id: Date.now().toString(),
100
+ payload: message,
101
+ timestamp: message.timestamp,
102
+ },
103
+ });
104
+ }
105
+ getStatus() {
106
+ return {
107
+ connected: true,
108
+ webhook: this.config.webhookUrl,
109
+ };
110
+ }
111
+ }
112
+ // Singleton
113
+ let instance = null;
114
+ export function getSlackIntegration(config) {
115
+ if (!instance && config) {
116
+ instance = new SlackIntegration(config);
117
+ }
118
+ if (!instance) {
119
+ throw new Error("Slack not initialized");
120
+ }
121
+ return instance;
122
+ }
123
+ export function resetSlackIntegration() {
124
+ instance = null;
125
+ }
126
+ export { SlackIntegration };
127
+ export default SlackIntegration;
128
+ //# sourceMappingURL=webhook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../../../src/channels/slack/webhook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Telegram Bot Completion - v0.3.0
3
+ *
4
+ * Full Telegram bot integration with webhook/polling, inline queries, and group support.
5
+ */
6
+ import TelegramBot from "node-telegram-bot-api";
7
+ import { EventEmitter } from "events";
8
+ import { getRealGateway } from "../../gateway/index.js";
9
+ class TelegramIntegration extends EventEmitter {
10
+ config;
11
+ bot;
12
+ connected = false;
13
+ gatewayConnectionId;
14
+ constructor(config) {
15
+ super();
16
+ this.config = {
17
+ mode: "polling",
18
+ port: 3000,
19
+ allowedUpdates: ["message", "edited_message", "callback_query"],
20
+ ...config,
21
+ };
22
+ }
23
+ /**
24
+ * Start Telegram bot
25
+ */
26
+ async start() {
27
+ if (!this.config.token) {
28
+ throw new Error("Telegram bot token required");
29
+ }
30
+ console.log("[Telegram] Starting bot...");
31
+ this.bot = new TelegramBot(this.config.token, {
32
+ polling: this.config.mode === "polling",
33
+ webHook: this.config.mode === "webhook" ? {
34
+ port: this.config.port,
35
+ } : false,
36
+ });
37
+ // Setup webhook if needed
38
+ if (this.config.mode === "webhook" && this.config.webhookUrl) {
39
+ await this.bot.setWebHook(this.config.webhookUrl);
40
+ console.log(`[Telegram] Webhook set: ${this.config.webhookUrl}`);
41
+ }
42
+ // Handle messages
43
+ this.bot.on("message", (msg) => this.handleMessage(msg));
44
+ this.bot.on("edited_message", (msg) => this.handleMessage(msg, true));
45
+ this.bot.on("callback_query", (query) => this.handleCallback(query));
46
+ // Handle polling errors
47
+ this.bot.on("polling_error", (err) => {
48
+ console.error("[Telegram] Polling error:", err.message);
49
+ this.emit("error", err);
50
+ });
51
+ this.connected = true;
52
+ console.log("[Telegram] Bot started successfully");
53
+ // Register with gateway
54
+ this.registerWithGateway();
55
+ this.emit("connected", { bot: this.bot });
56
+ }
57
+ /**
58
+ * Stop Telegram bot
59
+ */
60
+ async stop() {
61
+ console.log("[Telegram] Stopping...");
62
+ this.unregisterFromGateway();
63
+ if (this.bot) {
64
+ if (this.config.mode === "webhook") {
65
+ await this.bot.deleteWebHook();
66
+ }
67
+ else {
68
+ await this.bot.stopPolling();
69
+ }
70
+ this.bot = undefined;
71
+ }
72
+ this.connected = false;
73
+ console.log("[Telegram] Stopped");
74
+ }
75
+ /**
76
+ * Send message
77
+ */
78
+ async sendMessage(chatId, text, options) {
79
+ if (!this.bot) {
80
+ throw new Error("Bot not initialized");
81
+ }
82
+ const sendOptions = {};
83
+ if (options?.parseMode)
84
+ sendOptions.parse_mode = options.parseMode;
85
+ if (options?.replyTo)
86
+ sendOptions.reply_to_message_id = options.replyTo;
87
+ if (options?.buttons) {
88
+ sendOptions.reply_markup = {
89
+ inline_keyboard: options.buttons.map(row => row.map(btn => ({ text: btn.text, callback_data: btn.callbackData }))),
90
+ };
91
+ }
92
+ await this.bot.sendMessage(chatId, text, sendOptions);
93
+ }
94
+ /**
95
+ * Send typing indicator
96
+ */
97
+ async sendTyping(chatId) {
98
+ if (!this.bot)
99
+ return;
100
+ await this.bot.sendChatAction(chatId, "typing");
101
+ }
102
+ /**
103
+ * Send photo
104
+ */
105
+ async sendPhoto(chatId, photo, caption) {
106
+ if (!this.bot)
107
+ return;
108
+ await this.bot.sendPhoto(chatId, photo, { caption });
109
+ }
110
+ /**
111
+ * Handle incoming message
112
+ */
113
+ handleMessage(msg, edited = false) {
114
+ const message = {
115
+ id: msg.message_id,
116
+ from: {
117
+ id: msg.from?.id || 0,
118
+ username: msg.from?.username,
119
+ firstName: msg.from?.first_name,
120
+ },
121
+ chat: {
122
+ id: msg.chat.id,
123
+ type: msg.chat.type,
124
+ title: msg.chat.title,
125
+ },
126
+ text: msg.text,
127
+ caption: msg.caption,
128
+ date: msg.date * 1000,
129
+ isGroup: msg.chat.type !== "private",
130
+ entities: msg.entities?.map(e => ({ type: e.type, offset: e.offset, length: e.length })),
131
+ };
132
+ console.log(`[Telegram] ${edited ? "Edited" : "New"} message from ${message.from.username || message.from.id}`);
133
+ // Forward to gateway
134
+ this.forwardToGateway(message);
135
+ this.emit("message", message);
136
+ }
137
+ /**
138
+ * Handle callback query
139
+ */
140
+ handleCallback(query) {
141
+ console.log("[Telegram] Callback query:", query.data);
142
+ // Answer callback to remove loading state
143
+ this.bot?.answerCallbackQuery(query.id);
144
+ this.emit("callback", {
145
+ id: query.id,
146
+ from: query.from,
147
+ data: query.data,
148
+ message: query.message,
149
+ });
150
+ }
151
+ /**
152
+ * Forward to gateway
153
+ */
154
+ forwardToGateway(message) {
155
+ const gateway = getRealGateway();
156
+ gateway.emit("message", {
157
+ connection: {
158
+ id: this.gatewayConnectionId,
159
+ type: "telegram",
160
+ channel: message.isGroup ? "group" : "dm",
161
+ user: String(message.from.id),
162
+ },
163
+ data: {
164
+ type: "chat",
165
+ id: String(message.id),
166
+ payload: message,
167
+ timestamp: message.date,
168
+ },
169
+ });
170
+ }
171
+ /**
172
+ * Register with gateway
173
+ */
174
+ registerWithGateway() {
175
+ const gateway = getRealGateway();
176
+ this.gatewayConnectionId = gateway.registerConnection({
177
+ type: "telegram",
178
+ channel: "telegram",
179
+ user: "bot",
180
+ });
181
+ gateway.on("message", (event) => {
182
+ if (event.type === "telegram" && event.message) {
183
+ const { chatId, text, options } = event.message;
184
+ this.sendMessage(chatId, text, options).catch(console.error);
185
+ }
186
+ });
187
+ }
188
+ /**
189
+ * Unregister from gateway
190
+ */
191
+ unregisterFromGateway() {
192
+ if (this.gatewayConnectionId) {
193
+ const gateway = getRealGateway();
194
+ gateway.removeConnection(this.gatewayConnectionId);
195
+ this.gatewayConnectionId = undefined;
196
+ }
197
+ }
198
+ getStatus() {
199
+ return {
200
+ connected: this.connected,
201
+ mode: this.config.mode,
202
+ bot: this.bot ? "initialized" : undefined,
203
+ };
204
+ }
205
+ }
206
+ // Singleton
207
+ let instance = null;
208
+ export function getTelegramIntegration(config) {
209
+ if (!instance && config) {
210
+ instance = new TelegramIntegration(config);
211
+ }
212
+ if (!instance) {
213
+ throw new Error("Telegram not initialized");
214
+ }
215
+ return instance;
216
+ }
217
+ export function resetTelegramIntegration() {
218
+ instance?.stop();
219
+ instance = null;
220
+ }
221
+ export { TelegramIntegration };
222
+ export default TelegramIntegration;
223
+ //# sourceMappingURL=bot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bot.js","sourceRoot":"","sources":["../../../../src/channels/telegram/bot.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,WAAW,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAiCxD,MAAM,mBAAoB,SAAQ,YAAY;IACpC,MAAM,CAAiB;IACvB,GAAG,CAAe;IAClB,SAAS,GAAG,KAAK,CAAC;IAClB,mBAAmB,CAAU;IAErC,YAAY,MAAsB;QAChC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,MAAM,GAAG;YACZ,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,IAAI;YACV,cAAc,EAAE,CAAC,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,CAAC;YAC/D,GAAG,MAAM;SACV,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAE1C,IAAI,CAAC,GAAG,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;YAC5C,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS;YACvC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC;gBACxC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAK;aACxB,CAAC,CAAC,CAAC,KAAK;SACV,CAAC,CAAC;QAEH,0BAA0B;QAC1B,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YAC7D,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,kBAAkB;QAClB,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QACtE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;QAErE,wBAAwB;QACxB,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,GAAG,EAAE,EAAE;YACnC,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YACxD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;QAEnD,wBAAwB;QACxB,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAE3B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI;QACR,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACtC,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAE7B,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACnC,MAAM,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YACjC,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YAC/B,CAAC;YACD,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;QACvB,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,MAAuB,EAAE,IAAY,EAAE,OAIxD;QACC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,WAAW,GAAQ,EAAE,CAAC;QAC5B,IAAI,OAAO,EAAE,SAAS;YAAE,WAAW,CAAC,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;QACnE,IAAI,OAAO,EAAE,OAAO;YAAE,WAAW,CAAC,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;QACxE,IAAI,OAAO,EAAE,OAAO,EAAE,CAAC;YACrB,WAAW,CAAC,YAAY,GAAG;gBACzB,eAAe,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CACzC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,CACtE;aACF,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;IACxD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,MAAuB;QACtC,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE,OAAO;QACtB,MAAM,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,MAAuB,EAAE,KAAsB,EAAE,OAAgB;QAC/E,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE,OAAO;QACtB,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACK,aAAa,CAAC,GAAwB,EAAE,MAAM,GAAG,KAAK;QAC5D,MAAM,OAAO,GAAoB;YAC/B,EAAE,EAAE,GAAG,CAAC,UAAU;YAClB,IAAI,EAAE;gBACJ,EAAE,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC;gBACrB,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ;gBAC5B,SAAS,EAAE,GAAG,CAAC,IAAI,EAAE,UAAU;aAChC;YACD,IAAI,EAAE;gBACJ,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE;gBACf,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAW;gBAC1B,KAAK,EAAG,GAAG,CAAC,IAAY,CAAC,KAAK;aAC/B;YACD,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI;YACrB,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS;YACpC,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;SACzF,CAAC;QAEF,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,iBAAiB,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAEhH,qBAAqB;QACrB,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAE/B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,KAAgC;QACrD,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAEtD,0CAA0C;QAC1C,IAAI,CAAC,GAAG,EAAE,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAExC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YACpB,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,gBAAgB,CAAC,OAAwB;QAC/C,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;QAEjC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE;YACtB,UAAU,EAAE;gBACV,EAAE,EAAE,IAAI,CAAC,mBAAmB;gBAC5B,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;gBACzC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;aAC9B;YACD,IAAI,EAAE;gBACJ,IAAI,EAAE,MAAM;gBACZ,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBACtB,OAAO,EAAE,OAAO;gBAChB,SAAS,EAAE,OAAO,CAAC,IAAI;aACxB;SACF,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,mBAAmB;QACzB,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;QAEjC,IAAI,CAAC,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC;YACpD,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,UAAU;YACnB,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,KAAU,EAAE,EAAE;YACnC,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC/C,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC;gBAChD,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,qBAAqB;QAC3B,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;YACjC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YACnD,IAAI,CAAC,mBAAmB,GAAG,SAAS,CAAC;QACvC,CAAC;IACH,CAAC;IAED,SAAS;QACP,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI;YACtB,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;SAC1C,CAAC;IACJ,CAAC;CACF;AAED,YAAY;AACZ,IAAI,QAAQ,GAA+B,IAAI,CAAC;AAEhD,MAAM,UAAU,sBAAsB,CAAC,MAAuB;IAC5D,IAAI,CAAC,QAAQ,IAAI,MAAM,EAAE,CAAC;QACxB,QAAQ,GAAG,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,QAAQ,EAAE,IAAI,EAAE,CAAC;IACjB,QAAQ,GAAG,IAAI,CAAC;AAClB,CAAC;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAC/B,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1,325 @@
1
+ /**
2
+ * WhatsApp Integration - v0.3.0
3
+ *
4
+ * Real WhatsApp channel using Baileys library.
5
+ * Part of "The Gap Closer" - matching OpenClaw's multi-channel support.
6
+ */
7
+ import { makeWASocket, DisconnectReason, useMultiFileAuthState, fetchLatestBaileysVersion, makeCacheableSignalKeyStore, } from "@whiskeysockets/baileys";
8
+ import { EventEmitter } from "events";
9
+ import * as fs from "node:fs/promises";
10
+ import * as path from "node:path";
11
+ import { getRealGateway } from "../../gateway/index.js";
12
+ const DEFAULT_CONFIG = {
13
+ sessionPath: path.join(process.env.HOME || "~", ".0xkobold", "whatsapp-session"),
14
+ qrTimeout: 60000,
15
+ reconnectInterval: 5000,
16
+ markOnlineOnConnect: true,
17
+ defaultMessageDelay: 1000,
18
+ };
19
+ class WhatsAppIntegration extends EventEmitter {
20
+ config;
21
+ socket = null;
22
+ connected = false;
23
+ qrCode = null;
24
+ gatewayConnectionId;
25
+ reconnectTimer;
26
+ sendQueue = [];
27
+ constructor(config = {}) {
28
+ super();
29
+ this.config = { ...DEFAULT_CONFIG, ...config };
30
+ }
31
+ /**
32
+ * Start WhatsApp connection
33
+ */
34
+ async start() {
35
+ if (this.connected)
36
+ return;
37
+ console.log("[WhatsApp] Starting connection...");
38
+ // Ensure session directory exists
39
+ await fs.mkdir(this.config.sessionPath, { recursive: true });
40
+ // Get latest Baileys version
41
+ const { version, isLatest } = await fetchLatestBaileysVersion();
42
+ console.log(`[WhatsApp] Using Baileys v${version.join(".")} (latest: ${isLatest})`);
43
+ // Load auth state
44
+ const { state, saveCreds } = await useMultiFileAuthState(this.config.sessionPath);
45
+ // Create socket
46
+ this.socket = makeWASocket({
47
+ version,
48
+ logger: { info: () => { }, error: () => { }, debug: () => { }, warn: () => { } },
49
+ printQRInTerminal: true,
50
+ auth: {
51
+ creds: state.creds,
52
+ keys: makeCacheableSignalKeyStore(state.keys, { info: () => { } }),
53
+ },
54
+ markOnlineOnConnect: this.config.markOnlineOnConnect,
55
+ defaultQueryTimeoutMs: 60000,
56
+ });
57
+ // Handle connection updates
58
+ this.socket.ev.on("connection.update", async (update) => {
59
+ const { connection, lastDisconnect, qr } = update;
60
+ // QR code for pairing
61
+ if (qr) {
62
+ this.qrCode = qr;
63
+ console.log("[WhatsApp] QR Code generated - scan with WhatsApp app");
64
+ this.emit("qr", qr);
65
+ }
66
+ // Connection established
67
+ if (connection === "open") {
68
+ this.connected = true;
69
+ this.qrCode = null;
70
+ console.log("[WhatsApp] ✅ Connected successfully");
71
+ // Register with gateway
72
+ this.registerWithGateway();
73
+ // Process queued messages
74
+ this.processSendQueue();
75
+ this.emit("connected", { user: this.socket?.user });
76
+ }
77
+ // Connection closed
78
+ if (connection === "close") {
79
+ this.connected = false;
80
+ this.unregisterFromGateway();
81
+ const shouldReconnect = lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut;
82
+ console.log(`[WhatsApp] Disconnected. Reconnect: ${shouldReconnect}`);
83
+ this.emit("disconnected", { shouldReconnect });
84
+ if (shouldReconnect) {
85
+ this.scheduleReconnect();
86
+ }
87
+ }
88
+ });
89
+ // Handle credentials update
90
+ this.socket.ev.on("creds.update", saveCreds);
91
+ // Handle messages
92
+ this.socket.ev.on("messages.upsert", async (event) => {
93
+ for (const msg of event.messages) {
94
+ if (msg.key.fromMe)
95
+ continue; // Skip own messages
96
+ await this.handleIncomingMessage(msg);
97
+ }
98
+ });
99
+ // Handle group events
100
+ this.socket.ev.on("groups.upsert", (groups) => {
101
+ console.log("[WhatsApp] Groups updated:", groups.length);
102
+ });
103
+ }
104
+ /**
105
+ * Stop WhatsApp connection
106
+ */
107
+ async stop() {
108
+ console.log("[WhatsApp] Stopping...");
109
+ if (this.reconnectTimer) {
110
+ clearTimeout(this.reconnectTimer);
111
+ }
112
+ this.unregisterFromGateway();
113
+ if (this.socket) {
114
+ await this.socket.logout();
115
+ this.socket = null;
116
+ }
117
+ this.connected = false;
118
+ console.log("[WhatsApp] Stopped");
119
+ }
120
+ /**
121
+ * Send text message
122
+ */
123
+ async sendText(to, text) {
124
+ const jid = this.formatJid(to);
125
+ return new Promise((resolve, reject) => {
126
+ if (!this.connected || !this.socket) {
127
+ // Queue for later
128
+ this.sendQueue.push({
129
+ to: jid,
130
+ message: { text },
131
+ resolve,
132
+ });
133
+ return;
134
+ }
135
+ this.socket.sendMessage(jid, { text })
136
+ .then(resolve)
137
+ .catch(reject);
138
+ });
139
+ }
140
+ /**
141
+ * Send typing indicator
142
+ */
143
+ async sendTyping(to) {
144
+ if (!this.connected || !this.socket)
145
+ return;
146
+ const jid = this.formatJid(to);
147
+ await this.socket.sendPresenceUpdate("composing", jid);
148
+ }
149
+ /**
150
+ * Send image
151
+ */
152
+ async sendImage(to, imagePath, caption) {
153
+ if (!this.connected || !this.socket) {
154
+ throw new Error("Not connected");
155
+ }
156
+ const jid = this.formatJid(to);
157
+ const imageBuffer = await fs.readFile(imagePath);
158
+ return this.socket.sendMessage(jid, {
159
+ image: imageBuffer,
160
+ caption,
161
+ });
162
+ }
163
+ /**
164
+ * Get groups
165
+ */
166
+ async getGroups() {
167
+ if (!this.connected || !this.socket) {
168
+ throw new Error("Not connected");
169
+ }
170
+ const groups = await this.socket.groupFetchAllParticipating();
171
+ return Object.keys(groups);
172
+ }
173
+ /**
174
+ * Handle incoming message
175
+ */
176
+ async handleIncomingMessage(msg) {
177
+ const from = msg.key.remoteJid || "";
178
+ const isGroup = from.endsWith("@g.us");
179
+ // Extract message body
180
+ let body = "";
181
+ let type = "text";
182
+ if (msg.message?.conversation) {
183
+ body = msg.message.conversation;
184
+ }
185
+ else if (msg.message?.extendedTextMessage?.text) {
186
+ body = msg.message.extendedTextMessage.text;
187
+ }
188
+ else if (msg.message?.imageMessage) {
189
+ body = msg.message.imageMessage.caption || "";
190
+ type = "image";
191
+ }
192
+ else if (msg.message?.videoMessage) {
193
+ body = msg.message.videoMessage.caption || "";
194
+ type = "video";
195
+ }
196
+ const message = {
197
+ id: msg.key.id || "",
198
+ from,
199
+ fromMe: msg.key.fromMe || false,
200
+ body,
201
+ type,
202
+ timestamp: msg.messageTimestamp ? Number(msg.messageTimestamp) * 1000 : Date.now(),
203
+ isGroup,
204
+ groupName: isGroup ? await this.getGroupName(from) : undefined,
205
+ senderName: msg.pushName,
206
+ };
207
+ console.log(`[WhatsApp] Message from ${isGroup ? "group" : "user"}: ${body.slice(0, 50)}...`);
208
+ // Forward to gateway
209
+ this.forwardToGateway(message);
210
+ this.emit("message", message);
211
+ }
212
+ /**
213
+ * Forward to gateway
214
+ */
215
+ forwardToGateway(message) {
216
+ const gateway = getRealGateway();
217
+ gateway.emit("message", {
218
+ connection: {
219
+ id: this.gatewayConnectionId,
220
+ type: "whatsapp",
221
+ channel: message.isGroup ? "group" : "dm",
222
+ user: message.from,
223
+ },
224
+ data: {
225
+ type: "chat",
226
+ id: message.id,
227
+ payload: message,
228
+ timestamp: message.timestamp,
229
+ },
230
+ });
231
+ }
232
+ /**
233
+ * Register with gateway
234
+ */
235
+ registerWithGateway() {
236
+ const gateway = getRealGateway();
237
+ this.gatewayConnectionId = gateway.registerConnection({
238
+ type: "whatsapp",
239
+ channel: "whatsapp",
240
+ user: this.socket?.user?.id,
241
+ });
242
+ // Listen for gateway messages to send to WhatsApp
243
+ gateway.on("message", (event) => {
244
+ if (event.type === "whatsapp") {
245
+ const data = event.message;
246
+ this.sendText(data.to, data.text).catch(console.error);
247
+ }
248
+ });
249
+ }
250
+ /**
251
+ * Unregister from gateway
252
+ */
253
+ unregisterFromGateway() {
254
+ if (this.gatewayConnectionId) {
255
+ const gateway = getRealGateway();
256
+ gateway.removeConnection(this.gatewayConnectionId);
257
+ this.gatewayConnectionId = undefined;
258
+ }
259
+ }
260
+ /**
261
+ * Get group name
262
+ */
263
+ async getGroupName(jid) {
264
+ if (!this.socket)
265
+ return undefined;
266
+ try {
267
+ const metadata = await this.socket.groupMetadata(jid);
268
+ return metadata.subject;
269
+ }
270
+ catch {
271
+ return undefined;
272
+ }
273
+ }
274
+ /**
275
+ * Format JID
276
+ */
277
+ formatJid(input) {
278
+ if (input.includes("@"))
279
+ return input;
280
+ return `${input.replace(/\D/g, "")}@s.whatsapp.net`;
281
+ }
282
+ /**
283
+ * Process queued messages
284
+ */
285
+ processSendQueue() {
286
+ while (this.sendQueue.length > 0 && this.connected) {
287
+ const item = this.sendQueue.shift();
288
+ if (item) {
289
+ this.socket?.sendMessage(item.to, item.message)
290
+ .then(item.resolve)
291
+ .catch(console.error);
292
+ }
293
+ }
294
+ }
295
+ /**
296
+ * Schedule reconnect
297
+ */
298
+ scheduleReconnect() {
299
+ this.reconnectTimer = setTimeout(async () => {
300
+ console.log("[WhatsApp] Reconnecting...");
301
+ await this.start();
302
+ }, this.config.reconnectInterval);
303
+ }
304
+ getStatus() {
305
+ return {
306
+ connected: this.connected,
307
+ qr: this.qrCode,
308
+ user: this.socket?.user?.id,
309
+ };
310
+ }
311
+ }
312
+ // Singleton
313
+ let instance = null;
314
+ export function getWhatsAppIntegration(config) {
315
+ if (!instance) {
316
+ instance = new WhatsAppIntegration(config);
317
+ }
318
+ return instance;
319
+ }
320
+ export function resetWhatsAppIntegration() {
321
+ instance?.stop();
322
+ instance = null;
323
+ }
324
+ export default WhatsAppIntegration;
325
+ //# sourceMappingURL=integration.js.map