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.
- package/README.md +361 -0
- package/container/Dockerfile +48 -0
- package/container/entrypoint.sh +8 -0
- package/dist/agent-runner/index.d.ts +9 -0
- package/dist/agent-runner/index.d.ts.map +1 -0
- package/dist/agent-runner/index.js +21 -0
- package/dist/agent-runner/index.js.map +1 -0
- package/dist/agent-runner/interface.d.ts +56 -0
- package/dist/agent-runner/interface.d.ts.map +1 -0
- package/dist/agent-runner/interface.js +5 -0
- package/dist/agent-runner/interface.js.map +1 -0
- package/dist/agent-runner/pi-runner.d.ts +41 -0
- package/dist/agent-runner/pi-runner.d.ts.map +1 -0
- package/dist/agent-runner/pi-runner.js +162 -0
- package/dist/agent-runner/pi-runner.js.map +1 -0
- package/dist/channels/interface.d.ts +63 -0
- package/dist/channels/interface.d.ts.map +1 -0
- package/dist/channels/interface.js +33 -0
- package/dist/channels/interface.js.map +1 -0
- package/dist/channels/registry.d.ts +30 -0
- package/dist/channels/registry.d.ts.map +1 -0
- package/dist/channels/registry.js +71 -0
- package/dist/channels/registry.js.map +1 -0
- package/dist/channels/signal.d.ts +51 -0
- package/dist/channels/signal.d.ts.map +1 -0
- package/dist/channels/signal.js +263 -0
- package/dist/channels/signal.js.map +1 -0
- package/dist/channels/web.d.ts +35 -0
- package/dist/channels/web.d.ts.map +1 -0
- package/dist/channels/web.js +65 -0
- package/dist/channels/web.js.map +1 -0
- package/dist/channels/whatsapp.d.ts +25 -0
- package/dist/channels/whatsapp.d.ts.map +1 -0
- package/dist/channels/whatsapp.js +150 -0
- package/dist/channels/whatsapp.js.map +1 -0
- package/dist/config.d.ts +366 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +140 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +69 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +166 -0
- package/dist/context.js.map +1 -0
- package/dist/credential-proxy.d.ts +25 -0
- package/dist/credential-proxy.d.ts.map +1 -0
- package/dist/credential-proxy.js +96 -0
- package/dist/credential-proxy.js.map +1 -0
- package/dist/daemon.d.ts +25 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +138 -0
- package/dist/daemon.js.map +1 -0
- package/dist/db/index.d.ts +23 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +113 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.d.ts +408 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +55 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/doctor.d.ts +23 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +217 -0
- package/dist/doctor.js.map +1 -0
- package/dist/extensions/loader.d.ts +19 -0
- package/dist/extensions/loader.d.ts.map +1 -0
- package/dist/extensions/loader.js +124 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +561 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestrator.d.ts +60 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +313 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/packages.d.ts +21 -0
- package/dist/packages.d.ts.map +1 -0
- package/dist/packages.js +116 -0
- package/dist/packages.js.map +1 -0
- package/dist/scheduler-registry.d.ts +8 -0
- package/dist/scheduler-registry.d.ts.map +1 -0
- package/dist/scheduler-registry.js +14 -0
- package/dist/scheduler-registry.js.map +1 -0
- package/dist/scheduler.d.ts +60 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +143 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/server.d.ts +18 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +489 -0
- package/dist/server.js.map +1 -0
- package/dist/setup-wizard.d.ts +12 -0
- package/dist/setup-wizard.d.ts.map +1 -0
- package/dist/setup-wizard.js +163 -0
- package/dist/setup-wizard.js.map +1 -0
- package/extensions/confirm-destructive.ts +59 -0
- package/extensions/custom-compaction.ts +114 -0
- package/extensions/protected-paths.ts +30 -0
- package/extensions/sandbox/index.ts +317 -0
- package/extensions/sandbox/package-lock.json +92 -0
- package/extensions/sandbox/package.json +19 -0
- package/extensions/scheduler-tool.ts +65 -0
- package/extensions/session-name.ts +27 -0
- package/extensions/token-meter.ts +55 -0
- package/package.json +68 -0
- package/skills/send-message/SKILL.md +27 -0
- package/skills/web-search/SKILL.md +32 -0
- package/templates/global-agents.md +23 -0
- package/templates/main-agents.md +28 -0
- 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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"}
|