reeboot 1.0.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 (110) hide show
  1. package/README.md +361 -0
  2. package/container/Dockerfile +48 -0
  3. package/container/entrypoint.sh +8 -0
  4. package/dist/agent-runner/index.d.ts +9 -0
  5. package/dist/agent-runner/index.d.ts.map +1 -0
  6. package/dist/agent-runner/index.js +21 -0
  7. package/dist/agent-runner/index.js.map +1 -0
  8. package/dist/agent-runner/interface.d.ts +56 -0
  9. package/dist/agent-runner/interface.d.ts.map +1 -0
  10. package/dist/agent-runner/interface.js +5 -0
  11. package/dist/agent-runner/interface.js.map +1 -0
  12. package/dist/agent-runner/pi-runner.d.ts +41 -0
  13. package/dist/agent-runner/pi-runner.d.ts.map +1 -0
  14. package/dist/agent-runner/pi-runner.js +162 -0
  15. package/dist/agent-runner/pi-runner.js.map +1 -0
  16. package/dist/channels/interface.d.ts +63 -0
  17. package/dist/channels/interface.d.ts.map +1 -0
  18. package/dist/channels/interface.js +33 -0
  19. package/dist/channels/interface.js.map +1 -0
  20. package/dist/channels/registry.d.ts +30 -0
  21. package/dist/channels/registry.d.ts.map +1 -0
  22. package/dist/channels/registry.js +71 -0
  23. package/dist/channels/registry.js.map +1 -0
  24. package/dist/channels/signal.d.ts +51 -0
  25. package/dist/channels/signal.d.ts.map +1 -0
  26. package/dist/channels/signal.js +263 -0
  27. package/dist/channels/signal.js.map +1 -0
  28. package/dist/channels/web.d.ts +35 -0
  29. package/dist/channels/web.d.ts.map +1 -0
  30. package/dist/channels/web.js +65 -0
  31. package/dist/channels/web.js.map +1 -0
  32. package/dist/channels/whatsapp.d.ts +25 -0
  33. package/dist/channels/whatsapp.d.ts.map +1 -0
  34. package/dist/channels/whatsapp.js +150 -0
  35. package/dist/channels/whatsapp.js.map +1 -0
  36. package/dist/config.d.ts +366 -0
  37. package/dist/config.d.ts.map +1 -0
  38. package/dist/config.js +140 -0
  39. package/dist/config.js.map +1 -0
  40. package/dist/context.d.ts +69 -0
  41. package/dist/context.d.ts.map +1 -0
  42. package/dist/context.js +166 -0
  43. package/dist/context.js.map +1 -0
  44. package/dist/credential-proxy.d.ts +25 -0
  45. package/dist/credential-proxy.d.ts.map +1 -0
  46. package/dist/credential-proxy.js +96 -0
  47. package/dist/credential-proxy.js.map +1 -0
  48. package/dist/daemon.d.ts +25 -0
  49. package/dist/daemon.d.ts.map +1 -0
  50. package/dist/daemon.js +138 -0
  51. package/dist/daemon.js.map +1 -0
  52. package/dist/db/index.d.ts +23 -0
  53. package/dist/db/index.d.ts.map +1 -0
  54. package/dist/db/index.js +113 -0
  55. package/dist/db/index.js.map +1 -0
  56. package/dist/db/schema.d.ts +408 -0
  57. package/dist/db/schema.d.ts.map +1 -0
  58. package/dist/db/schema.js +55 -0
  59. package/dist/db/schema.js.map +1 -0
  60. package/dist/doctor.d.ts +23 -0
  61. package/dist/doctor.d.ts.map +1 -0
  62. package/dist/doctor.js +217 -0
  63. package/dist/doctor.js.map +1 -0
  64. package/dist/extensions/loader.d.ts +19 -0
  65. package/dist/extensions/loader.d.ts.map +1 -0
  66. package/dist/extensions/loader.js +124 -0
  67. package/dist/extensions/loader.js.map +1 -0
  68. package/dist/index.d.ts +3 -0
  69. package/dist/index.d.ts.map +1 -0
  70. package/dist/index.js +561 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/orchestrator.d.ts +60 -0
  73. package/dist/orchestrator.d.ts.map +1 -0
  74. package/dist/orchestrator.js +313 -0
  75. package/dist/orchestrator.js.map +1 -0
  76. package/dist/packages.d.ts +21 -0
  77. package/dist/packages.d.ts.map +1 -0
  78. package/dist/packages.js +116 -0
  79. package/dist/packages.js.map +1 -0
  80. package/dist/scheduler-registry.d.ts +8 -0
  81. package/dist/scheduler-registry.d.ts.map +1 -0
  82. package/dist/scheduler-registry.js +14 -0
  83. package/dist/scheduler-registry.js.map +1 -0
  84. package/dist/scheduler.d.ts +60 -0
  85. package/dist/scheduler.d.ts.map +1 -0
  86. package/dist/scheduler.js +143 -0
  87. package/dist/scheduler.js.map +1 -0
  88. package/dist/server.d.ts +18 -0
  89. package/dist/server.d.ts.map +1 -0
  90. package/dist/server.js +489 -0
  91. package/dist/server.js.map +1 -0
  92. package/dist/setup-wizard.d.ts +12 -0
  93. package/dist/setup-wizard.d.ts.map +1 -0
  94. package/dist/setup-wizard.js +163 -0
  95. package/dist/setup-wizard.js.map +1 -0
  96. package/extensions/confirm-destructive.ts +59 -0
  97. package/extensions/custom-compaction.ts +114 -0
  98. package/extensions/protected-paths.ts +30 -0
  99. package/extensions/sandbox/index.ts +317 -0
  100. package/extensions/sandbox/package-lock.json +92 -0
  101. package/extensions/sandbox/package.json +19 -0
  102. package/extensions/scheduler-tool.ts +65 -0
  103. package/extensions/session-name.ts +27 -0
  104. package/extensions/token-meter.ts +55 -0
  105. package/package.json +68 -0
  106. package/skills/send-message/SKILL.md +27 -0
  107. package/skills/web-search/SKILL.md +32 -0
  108. package/templates/global-agents.md +23 -0
  109. package/templates/main-agents.md +28 -0
  110. package/webchat/index.html +421 -0
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Signal channel adapter
3
+ *
4
+ * Uses bbernhard/signal-cli-rest-api Docker sidecar.
5
+ *
6
+ * Receive strategy depends on the API mode reported by /v1/about:
7
+ * - json-rpc mode → WebSocket on ws://host/v1/receive/<number>
8
+ * - normal/native mode → HTTP polling GET /v1/receive/<number>
9
+ *
10
+ * Sends via POST /v2/send (same for all modes).
11
+ */
12
+ import { execSync } from 'child_process';
13
+ import { WebSocket } from 'ws';
14
+ import { createIncomingMessage } from './interface.js';
15
+ import { registerChannel } from './registry.js';
16
+ const CHUNK_SIZE = 4096;
17
+ const CHUNK_DELAY_MS = 100;
18
+ const DEFAULT_POLL_INTERVAL_MS = 1000;
19
+ const DEFAULT_API_PORT = 8080;
20
+ const WS_RECONNECT_DELAY_MS = 3000;
21
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
22
+ /**
23
+ * Check if a signal-cli-rest-api Docker container is running.
24
+ * Returns true if found, false otherwise.
25
+ */
26
+ export function detectSignalContainer() {
27
+ try {
28
+ const output = execSync('docker ps --filter name=signal-cli-rest-api --format "{{.Names}}"', { stdio: ['pipe', 'pipe', 'pipe'] }).toString().trim();
29
+ return output.length > 0 && output.includes('signal-cli-rest-api');
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ /**
36
+ * Check if Docker daemon is running.
37
+ */
38
+ function isDockerRunning() {
39
+ try {
40
+ execSync('docker info', { stdio: ['pipe', 'pipe', 'pipe'] });
41
+ return true;
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }
47
+ // ─── SignalAdapter ─────────────────────────────────────────────────────────────
48
+ export class SignalAdapter {
49
+ _status = 'disconnected';
50
+ _connectedAt = null;
51
+ _bus = null;
52
+ // HTTP polling (normal/native mode)
53
+ _pollTimer = null;
54
+ // WebSocket (json-rpc mode)
55
+ _ws = null;
56
+ _wsReconnectTimer = null;
57
+ _wsStopped = false;
58
+ _phoneNumber;
59
+ _apiPort;
60
+ _pollInterval;
61
+ constructor(opts = {}) {
62
+ this._phoneNumber = opts.phoneNumber ?? '';
63
+ this._apiPort = opts.apiPort ?? DEFAULT_API_PORT;
64
+ this._pollInterval = opts.pollInterval ?? DEFAULT_POLL_INTERVAL_MS;
65
+ }
66
+ get _baseUrl() {
67
+ return `http://127.0.0.1:${this._apiPort}`;
68
+ }
69
+ get _wsBaseUrl() {
70
+ return `ws://127.0.0.1:${this._apiPort}`;
71
+ }
72
+ async init(config, bus) {
73
+ const signalConfig = config;
74
+ if (signalConfig.phoneNumber)
75
+ this._setPhoneNumber(signalConfig.phoneNumber);
76
+ if (signalConfig.apiPort)
77
+ this._setApiPort(signalConfig.apiPort);
78
+ this._bus = bus;
79
+ this._status = 'disconnected';
80
+ }
81
+ _setPhoneNumber(n) { this._phoneNumber = n; }
82
+ _setApiPort(p) { this._apiPort = p; }
83
+ async start() {
84
+ if (!isDockerRunning()) {
85
+ this._status = 'error';
86
+ console.error('[Signal] Docker is not running — cannot start Signal adapter');
87
+ return;
88
+ }
89
+ if (!detectSignalContainer()) {
90
+ console.warn('[Signal] signal-cli-rest-api container not found — try: reeboot channels login signal');
91
+ }
92
+ // Detect API mode from /v1/about
93
+ let mode = 'normal';
94
+ try {
95
+ const res = await fetch(`${this._baseUrl}/v1/about`);
96
+ if (res.ok) {
97
+ const body = await res.json();
98
+ mode = body?.mode ?? 'normal';
99
+ }
100
+ }
101
+ catch {
102
+ // Assume normal mode if unreachable
103
+ }
104
+ this._status = 'connected';
105
+ this._connectedAt = new Date().toISOString();
106
+ if (mode === 'json-rpc') {
107
+ console.log('[Signal] Connected āœ“ — listening via WebSocket (json-rpc mode)');
108
+ this._wsStopped = false;
109
+ this._connectWebSocket();
110
+ }
111
+ else {
112
+ console.log(`[Signal] Connected āœ“ — polling for messages (${mode} mode)`);
113
+ this._startPolling();
114
+ }
115
+ }
116
+ // ── WebSocket receive (json-rpc mode) ──────────────────────────────────────
117
+ _connectWebSocket() {
118
+ if (this._wsStopped || !this._phoneNumber)
119
+ return;
120
+ const encoded = encodeURIComponent(this._phoneNumber);
121
+ const url = `${this._wsBaseUrl}/v1/receive/${encoded}`;
122
+ const ws = new WebSocket(url);
123
+ this._ws = ws;
124
+ ws.on('message', (data) => {
125
+ try {
126
+ const msg = JSON.parse(data.toString());
127
+ this._handleIncomingMessage(msg);
128
+ }
129
+ catch {
130
+ // Ignore unparseable frames
131
+ }
132
+ });
133
+ ws.on('error', (err) => {
134
+ console.error(`[Signal] WebSocket error: ${err.message}`);
135
+ });
136
+ ws.on('close', () => {
137
+ this._ws = null;
138
+ if (!this._wsStopped) {
139
+ // Reconnect after delay
140
+ this._wsReconnectTimer = setTimeout(() => {
141
+ this._connectWebSocket();
142
+ }, WS_RECONNECT_DELAY_MS);
143
+ }
144
+ });
145
+ }
146
+ // ── HTTP polling (normal/native mode) ─────────────────────────────────────
147
+ _startPolling() {
148
+ if (this._pollTimer)
149
+ return;
150
+ this._pollTimer = setInterval(() => {
151
+ this._poll().catch((err) => {
152
+ console.error(`[Signal] Poll error: ${err}`);
153
+ });
154
+ }, this._pollInterval);
155
+ }
156
+ async _poll() {
157
+ if (!this._phoneNumber)
158
+ return;
159
+ try {
160
+ const encoded = encodeURIComponent(this._phoneNumber);
161
+ const res = await fetch(`${this._baseUrl}/v1/receive/${encoded}`);
162
+ if (!res.ok)
163
+ return;
164
+ const messages = await res.json();
165
+ for (const msg of messages) {
166
+ this._handleIncomingMessage(msg);
167
+ }
168
+ }
169
+ catch {
170
+ // Poll errors are non-fatal
171
+ }
172
+ }
173
+ // ── Shared message handler ─────────────────────────────────────────────────
174
+ _handleIncomingMessage(msg) {
175
+ const envelope = msg?.envelope;
176
+ if (!envelope)
177
+ return;
178
+ const source = envelope.sourceNumber ?? envelope.source ?? '';
179
+ let text = '';
180
+ let peerId = source;
181
+ if (envelope.dataMessage) {
182
+ // Regular incoming message from another user — ignore if it's from ourselves
183
+ if (source === this._phoneNumber)
184
+ return;
185
+ text = envelope.dataMessage.message ?? '';
186
+ }
187
+ else if (envelope.syncMessage?.sentMessage) {
188
+ // Note-to-self: message synced from our own device
189
+ const sent = envelope.syncMessage.sentMessage;
190
+ text = sent.message ?? '';
191
+ peerId = sent.destinationNumber ?? sent.destination ?? source;
192
+ }
193
+ if (!text)
194
+ return;
195
+ this._bus?.publish(createIncomingMessage({
196
+ channelType: 'signal',
197
+ peerId,
198
+ content: text,
199
+ raw: msg,
200
+ }));
201
+ }
202
+ // ── Stop ───────────────────────────────────────────────────────────────────
203
+ async stop() {
204
+ // Stop HTTP polling
205
+ if (this._pollTimer) {
206
+ clearInterval(this._pollTimer);
207
+ this._pollTimer = null;
208
+ }
209
+ // Stop WebSocket
210
+ this._wsStopped = true;
211
+ if (this._wsReconnectTimer) {
212
+ clearTimeout(this._wsReconnectTimer);
213
+ this._wsReconnectTimer = null;
214
+ }
215
+ if (this._ws) {
216
+ this._ws.close();
217
+ this._ws = null;
218
+ }
219
+ this._status = 'disconnected';
220
+ this._connectedAt = null;
221
+ }
222
+ // ── Send ───────────────────────────────────────────────────────────────────
223
+ async send(peerId, content) {
224
+ const text = content.text ?? '';
225
+ if (text.length <= CHUNK_SIZE) {
226
+ await this._sendChunk(peerId, text);
227
+ return;
228
+ }
229
+ let offset = 0;
230
+ while (offset < text.length) {
231
+ const chunk = text.slice(offset, offset + CHUNK_SIZE);
232
+ await this._sendChunk(peerId, chunk);
233
+ offset += CHUNK_SIZE;
234
+ if (offset < text.length) {
235
+ await new Promise(r => setTimeout(r, CHUNK_DELAY_MS));
236
+ }
237
+ }
238
+ }
239
+ async _sendChunk(peerId, text) {
240
+ const res = await fetch(`${this._baseUrl}/v2/send`, {
241
+ method: 'POST',
242
+ headers: { 'Content-Type': 'application/json' },
243
+ body: JSON.stringify({
244
+ message: text,
245
+ number: this._phoneNumber,
246
+ recipients: [peerId],
247
+ }),
248
+ });
249
+ if (!res.ok) {
250
+ throw new Error(`Signal send failed: HTTP ${res.status}`);
251
+ }
252
+ }
253
+ // ── Status ─────────────────────────────────────────────────────────────────
254
+ status() {
255
+ return this._status;
256
+ }
257
+ connectedAt() {
258
+ return this._connectedAt;
259
+ }
260
+ }
261
+ // Self-register at module import time
262
+ registerChannel('signal', () => new SignalAdapter());
263
+ //# sourceMappingURL=signal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal.js","sourceRoot":"","sources":["../../src/channels/signal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Web channel adapter
3
+ *
4
+ * Thin ChannelAdapter wrapping the existing WebSocket handler so it
5
+ * participates in the ChannelRegistry and MessageBus.
6
+ *
7
+ * The actual WebSocket connection management is handled by server.ts;
8
+ * this adapter bridges it to the bus by providing a way for the WS handler
9
+ * to push IncomingMessages and for the orchestrator to call send().
10
+ *
11
+ * In Phase 1 the WebChat already works via ws-chat.ts — this adapter
12
+ * registers as "web" so the registry knows about it and can report status.
13
+ */
14
+ import type { ChannelAdapter, ChannelConfig, MessageBus, MessageContent, ChannelStatus } from './interface.js';
15
+ export declare class WebAdapter implements ChannelAdapter {
16
+ private _status;
17
+ private _connectedAt;
18
+ private _bus;
19
+ private _senders;
20
+ init(_config: ChannelConfig, bus: MessageBus): Promise<void>;
21
+ start(): Promise<void>;
22
+ stop(): Promise<void>;
23
+ send(peerId: string, content: MessageContent): Promise<void>;
24
+ status(): ChannelStatus;
25
+ connectedAt(): string | null;
26
+ /**
27
+ * Register a sender function for a connected WebSocket peer.
28
+ * Called by the WS chat handler when a client connects.
29
+ */
30
+ registerPeer(peerId: string, sender: (content: MessageContent) => Promise<void>): void;
31
+ unregisterPeer(peerId: string): void;
32
+ getBus(): MessageBus | null;
33
+ }
34
+ export declare const webAdapter: WebAdapter;
35
+ //# sourceMappingURL=web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/channels/web.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG/G,qBAAa,UAAW,YAAW,cAAc;IAC/C,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,IAAI,CAA2B;IAEvC,OAAO,CAAC,QAAQ,CAAiE;IAE3E,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAMrB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlE,MAAM,IAAI,aAAa;IAIvB,WAAW,IAAI,MAAM,GAAG,IAAI;IAI5B;;;OAGG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAItF,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIpC,MAAM,IAAI,UAAU,GAAG,IAAI;CAG5B;AAGD,eAAO,MAAM,UAAU,YAAmB,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Web channel adapter
3
+ *
4
+ * Thin ChannelAdapter wrapping the existing WebSocket handler so it
5
+ * participates in the ChannelRegistry and MessageBus.
6
+ *
7
+ * The actual WebSocket connection management is handled by server.ts;
8
+ * this adapter bridges it to the bus by providing a way for the WS handler
9
+ * to push IncomingMessages and for the orchestrator to call send().
10
+ *
11
+ * In Phase 1 the WebChat already works via ws-chat.ts — this adapter
12
+ * registers as "web" so the registry knows about it and can report status.
13
+ */
14
+ import { registerChannel } from './registry.js';
15
+ export class WebAdapter {
16
+ _status = 'disconnected';
17
+ _connectedAt = null;
18
+ _bus = null;
19
+ // Map of peerId → send function (registered by the WS handler)
20
+ _senders = new Map();
21
+ async init(_config, bus) {
22
+ this._bus = bus;
23
+ this._status = 'initializing';
24
+ }
25
+ async start() {
26
+ // WebSocket server lifecycle is managed by Fastify; we just mark connected
27
+ this._status = 'connected';
28
+ this._connectedAt = new Date().toISOString();
29
+ }
30
+ async stop() {
31
+ this._status = 'disconnected';
32
+ this._connectedAt = null;
33
+ this._senders.clear();
34
+ }
35
+ async send(peerId, content) {
36
+ const sender = this._senders.get(peerId);
37
+ if (sender) {
38
+ await sender(content);
39
+ }
40
+ }
41
+ status() {
42
+ return this._status;
43
+ }
44
+ connectedAt() {
45
+ return this._connectedAt;
46
+ }
47
+ /**
48
+ * Register a sender function for a connected WebSocket peer.
49
+ * Called by the WS chat handler when a client connects.
50
+ */
51
+ registerPeer(peerId, sender) {
52
+ this._senders.set(peerId, sender);
53
+ }
54
+ unregisterPeer(peerId) {
55
+ this._senders.delete(peerId);
56
+ }
57
+ getBus() {
58
+ return this._bus;
59
+ }
60
+ }
61
+ // Singleton instance so server.ts can access the same object
62
+ export const webAdapter = new WebAdapter();
63
+ // Self-register at import time
64
+ registerChannel('web', () => webAdapter);
65
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/channels/web.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,OAAO,UAAU;IACb,OAAO,GAAkB,cAAc,CAAC;IACxC,YAAY,GAAkB,IAAI,CAAC;IACnC,IAAI,GAAsB,IAAI,CAAC;IACvC,+DAA+D;IACvD,QAAQ,GAAG,IAAI,GAAG,EAAsD,CAAC;IAEjF,KAAK,CAAC,IAAI,CAAC,OAAsB,EAAE,GAAe;QAChD,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,IAAI,CAAC,OAAO,GAAG,cAAc,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,KAAK;QACT,2EAA2E;QAC3E,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC;QAC3B,IAAI,CAAC,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,CAAC,OAAO,GAAG,cAAc,CAAC;QAC9B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,OAAuB;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED;;;OAGG;IACH,YAAY,CAAC,MAAc,EAAE,MAAkD;QAC7E,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,cAAc,CAAC,MAAc;QAC3B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;CACF;AAED,6DAA6D;AAC7D,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC;AAE3C,+BAA+B;AAC/B,eAAe,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * WhatsApp channel adapter
3
+ *
4
+ * Uses @whiskeysockets/baileys v7 (pinned to 7.0.0-rc.9).
5
+ * Auth state persisted at authDir (default: ~/.reeboot/channels/whatsapp/auth/).
6
+ */
7
+ import type { ChannelAdapter, ChannelConfig, MessageBus, MessageContent, ChannelStatus } from './interface.js';
8
+ export declare class WhatsAppAdapter implements ChannelAdapter {
9
+ private _authDir;
10
+ private _status;
11
+ private _connectedAt;
12
+ private _bus;
13
+ private _config;
14
+ private _socket;
15
+ private _reconnecting;
16
+ constructor(authDir?: string);
17
+ init(config: ChannelConfig, bus: MessageBus): Promise<void>;
18
+ start(): Promise<void>;
19
+ private _connect;
20
+ stop(): Promise<void>;
21
+ send(peerId: string, content: MessageContent): Promise<void>;
22
+ status(): ChannelStatus;
23
+ connectedAt(): string | null;
24
+ }
25
+ //# sourceMappingURL=whatsapp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whatsapp.d.ts","sourceRoot":"","sources":["../../src/channels/whatsapp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAO/G,qBAAa,eAAgB,YAAW,cAAc;IACpD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,aAAa,CAAS;gBAElB,OAAO,CAAC,EAAE,MAAM;IAItB,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAId,QAAQ;IAgGhB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IASrB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBlE,MAAM,IAAI,aAAa;IAIvB,WAAW,IAAI,MAAM,GAAG,IAAI;CAG7B"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * WhatsApp channel adapter
3
+ *
4
+ * Uses @whiskeysockets/baileys v7 (pinned to 7.0.0-rc.9).
5
+ * Auth state persisted at authDir (default: ~/.reeboot/channels/whatsapp/auth/).
6
+ */
7
+ import { join } from 'path';
8
+ import { homedir } from 'os';
9
+ import { mkdirSync } from 'fs';
10
+ import { createIncomingMessage } from './interface.js';
11
+ import { registerChannel } from './registry.js';
12
+ const CHUNK_SIZE = 4096;
13
+ const CHUNK_DELAY_MS = 100;
14
+ export class WhatsAppAdapter {
15
+ _authDir;
16
+ _status = 'disconnected';
17
+ _connectedAt = null;
18
+ _bus = null;
19
+ _config = null;
20
+ _socket = null;
21
+ _reconnecting = false;
22
+ constructor(authDir) {
23
+ this._authDir = authDir ?? join(homedir(), '.reeboot', 'channels', 'whatsapp', 'auth');
24
+ }
25
+ async init(config, bus) {
26
+ this._config = config;
27
+ this._bus = bus;
28
+ this._status = 'initializing';
29
+ }
30
+ async start() {
31
+ await this._connect();
32
+ }
33
+ async _connect() {
34
+ const { makeWASocket, useMultiFileAuthState, DisconnectReason, Browsers, fetchLatestWaWebVersion, } = await import('@whiskeysockets/baileys');
35
+ const qrTerminal = await import('qrcode-terminal');
36
+ mkdirSync(this._authDir, { recursive: true });
37
+ const { state, saveCreds } = await useMultiFileAuthState(this._authDir);
38
+ // Fetch the current WhatsApp Web version from WA servers.
39
+ // The version bundled in Baileys RC is often stale and gets rejected (405).
40
+ let version;
41
+ try {
42
+ const result = await fetchLatestWaWebVersion({});
43
+ version = result.version;
44
+ console.log(`[WhatsApp] Using WA Web version: ${version.join('.')}`);
45
+ }
46
+ catch (err) {
47
+ console.warn(`[WhatsApp] Could not fetch latest WA version, using default: ${err}`);
48
+ version = [2, 3000, 1027934701];
49
+ }
50
+ const sock = makeWASocket({
51
+ version,
52
+ auth: state,
53
+ browser: Browsers.ubuntu('Chrome'),
54
+ });
55
+ this._socket = sock;
56
+ sock.ev.on('creds.update', saveCreds);
57
+ sock.ev.on('connection.update', async (update) => {
58
+ const { connection, lastDisconnect, qr } = update;
59
+ if (qr) {
60
+ console.log('\nšŸ“± Scan this QR code with WhatsApp (Settings → Linked Devices → Link a Device):\n');
61
+ qrTerminal.default.generate(qr, { small: true });
62
+ console.log('');
63
+ }
64
+ if (connection === 'open') {
65
+ this._status = 'connected';
66
+ this._connectedAt = new Date().toISOString();
67
+ this._reconnecting = false;
68
+ console.log('[WhatsApp] Connected āœ“ — ready to receive messages');
69
+ }
70
+ else if (connection === 'close') {
71
+ this._status = 'disconnected';
72
+ this._connectedAt = null;
73
+ const statusCode = lastDisconnect?.error?.output?.statusCode;
74
+ const loggedOut = statusCode === DisconnectReason.loggedOut;
75
+ if (loggedOut) {
76
+ this._status = 'error';
77
+ }
78
+ else if (!this._reconnecting) {
79
+ this._reconnecting = true;
80
+ await this._connect();
81
+ }
82
+ }
83
+ });
84
+ sock.ev.on('messages.upsert', ({ type, messages }) => {
85
+ for (const msg of messages) {
86
+ const peerId = msg.key.remoteJid;
87
+ const fromMe = msg.key.fromMe;
88
+ const text = msg.message?.conversation ||
89
+ msg.message?.extendedTextMessage?.text ||
90
+ msg.message?.imageMessage?.caption ||
91
+ '';
92
+ // Only process notify-type messages
93
+ if (type !== 'notify')
94
+ continue;
95
+ // Skip messages sent by this device, except self-chat ("message yourself")
96
+ if (fromMe && peerId !== sock.user?.id?.replace(/:.*/, '') + '@s.whatsapp.net')
97
+ continue;
98
+ if (!peerId)
99
+ continue;
100
+ if (!text)
101
+ continue;
102
+ this._bus?.publish(createIncomingMessage({
103
+ channelType: 'whatsapp',
104
+ peerId,
105
+ content: text,
106
+ raw: msg,
107
+ }));
108
+ }
109
+ });
110
+ }
111
+ async stop() {
112
+ this._reconnecting = true; // prevent reconnect on close
113
+ if (this._socket) {
114
+ try {
115
+ this._socket.end();
116
+ }
117
+ catch { /* ignore */ }
118
+ this._socket = null;
119
+ }
120
+ this._status = 'disconnected';
121
+ }
122
+ async send(peerId, content) {
123
+ if (!this._socket)
124
+ throw new Error('WhatsApp not connected');
125
+ const text = content.text ?? '';
126
+ if (text.length <= CHUNK_SIZE) {
127
+ await this._socket.sendMessage(peerId, { text });
128
+ return;
129
+ }
130
+ // Chunk into CHUNK_SIZE pieces
131
+ let offset = 0;
132
+ while (offset < text.length) {
133
+ const chunk = text.slice(offset, offset + CHUNK_SIZE);
134
+ await this._socket.sendMessage(peerId, { text: chunk });
135
+ offset += CHUNK_SIZE;
136
+ if (offset < text.length) {
137
+ await new Promise(r => setTimeout(r, CHUNK_DELAY_MS));
138
+ }
139
+ }
140
+ }
141
+ status() {
142
+ return this._status;
143
+ }
144
+ connectedAt() {
145
+ return this._connectedAt;
146
+ }
147
+ }
148
+ // Self-register at module import time
149
+ registerChannel('whatsapp', () => new WhatsAppAdapter());
150
+ //# sourceMappingURL=whatsapp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whatsapp.js","sourceRoot":"","sources":["../../src/channels/whatsapp.ts"],"names":[],"mappings":"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"}