hyperclaw 5.0.0 → 5.0.2

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 (199) hide show
  1. package/LICENSE +2 -1
  2. package/README.md +449 -99
  3. package/dist/a2ui-protocol-Gzm29Gaw.js +75 -0
  4. package/dist/agents-routing-Biy5ew4a.js +4 -0
  5. package/dist/agents-routing-CL3HQNoM.js +327 -0
  6. package/dist/api-keys-guide-CGn5BSF7.js +149 -0
  7. package/dist/api-keys-guide-ChbThbPj.js +149 -0
  8. package/dist/audit-BJohI_vC.js +441 -0
  9. package/dist/audit-NPIMmOSq.js +441 -0
  10. package/dist/bounty-tools-BUqUKjt0.js +211 -0
  11. package/dist/bounty-tools-CY_i91DU.js +211 -0
  12. package/dist/browser-tools-CxJY6pAn.js +5 -0
  13. package/dist/browser-tools-JZ9ji6AW.js +179 -0
  14. package/dist/chat-qVuqhlPu.js +258 -0
  15. package/dist/claw-tasks-B-8RRMdq.js +80 -0
  16. package/dist/claw-tasks-Cyzdbhz_.js +80 -0
  17. package/dist/connector-1x1rCBHz.js +162 -0
  18. package/dist/connector-B4jeCULG.js +305 -0
  19. package/dist/connector-B7qngfkT.js +286 -0
  20. package/dist/connector-B8BK0GBo.js +531 -0
  21. package/dist/connector-BE9eJs8-.js +182 -0
  22. package/dist/connector-BEe-DTGQ.js +189 -0
  23. package/dist/connector-BU7p5ZgB.js +167 -0
  24. package/dist/connector-BUzzq7Ij.js +568 -0
  25. package/dist/connector-BpDqLgnW.js +419 -0
  26. package/dist/connector-BpW88ut2.js +189 -0
  27. package/dist/connector-Bxv-gy8U.js +167 -0
  28. package/dist/connector-Bz14zcJv.js +213 -0
  29. package/dist/connector-C1zP5-5q.js +85 -0
  30. package/dist/connector-CAcpcovF.js +498 -0
  31. package/dist/connector-CJgVjS58.js +181 -0
  32. package/dist/connector-Cf53D6qV.js +425 -0
  33. package/dist/connector-CyHmlbNz.js +508 -0
  34. package/dist/connector-D22mJGVu.js +340 -0
  35. package/dist/connector-D6RtMmlL.js +225 -0
  36. package/dist/connector-D9EnT8A4.js +280 -0
  37. package/dist/connector-DNDwIh37.js +239 -0
  38. package/dist/connector-Di27MeO4.js +350 -0
  39. package/dist/connector-Do0BPiHt.js +194 -0
  40. package/dist/connector-DvLwOfJy.js +192 -0
  41. package/dist/connector-DvU83NSq.js +181 -0
  42. package/dist/connector-DxskpDc_.js +173 -0
  43. package/dist/connector-byy3eISx.js +552 -0
  44. package/dist/connector-vV89hsyd.js +218 -0
  45. package/dist/cost-tracker-Ca1UPZ33.js +103 -0
  46. package/dist/cost-tracker-fnaj_6M9.js +103 -0
  47. package/dist/credentials-store-BxijEirw.js +77 -0
  48. package/dist/credentials-store-CA8UtK0T.js +77 -0
  49. package/dist/credentials-store-CPkVO6-z.js +4 -0
  50. package/dist/credentials-store-Cm7DH-kh.js +4 -0
  51. package/dist/cron-tasks-L0mz1yyU.js +82 -0
  52. package/dist/cron-tasks-_pqQCmxc.js +82 -0
  53. package/dist/daemon-7ViroziB.js +5 -0
  54. package/dist/daemon-BfyKmZhr.js +318 -0
  55. package/dist/daemon-CNyunwkR.js +5 -0
  56. package/dist/daemon-CindY8OK.js +318 -0
  57. package/dist/delivery-DVHmv1IR.js +4 -0
  58. package/dist/delivery-DgiZcJBp.js +4 -0
  59. package/dist/delivery-DpMX0Yyc.js +95 -0
  60. package/dist/delivery-otAU4alM.js +95 -0
  61. package/dist/destructive-gate-CA0DtA5K.js +101 -0
  62. package/dist/destructive-gate-DZt71UZR.js +101 -0
  63. package/dist/developer-keys-Cnd1kswV.js +127 -0
  64. package/dist/developer-keys-DENo3ZA6.js +8 -0
  65. package/dist/doctor-Dgjoc3DG.js +230 -0
  66. package/dist/doctor-RwsOhtAl.js +6 -0
  67. package/dist/engine-B0kLfRL0.js +256 -0
  68. package/dist/engine-BJUpRUOv.js +7 -0
  69. package/dist/engine-D_VeoZHw.js +305 -0
  70. package/dist/engine-JjRnhlsE.js +7 -0
  71. package/dist/env-resolve-17ekEU6p.js +10 -0
  72. package/dist/env-resolve-BFJXWl94.js +115 -0
  73. package/dist/env-resolve-Z2XF6leB.js +115 -0
  74. package/dist/env-resolve-bDYssfih.js +10 -0
  75. package/dist/extraction-tools-DbxnxIco.js +5 -0
  76. package/dist/extraction-tools-Dg7AHS35.js +91 -0
  77. package/dist/form_data-CGAy4HE0.js +8657 -0
  78. package/dist/gmail-watch-setup-C3uSWznp.js +40 -0
  79. package/dist/health-DUjluWHQ.js +6 -0
  80. package/dist/health-DVfkpUQW.js +152 -0
  81. package/dist/heartbeat-engine-CrgL4mrP.js +83 -0
  82. package/dist/heartbeat-engine-Ut6pXBD6.js +83 -0
  83. package/dist/hub-9LaKnLjY.js +6 -0
  84. package/dist/hub-BO6bj8Yj.js +515 -0
  85. package/dist/hub-Bu52YZqW.js +6 -0
  86. package/dist/hub-CfwUz9YW.js +515 -0
  87. package/dist/hyperclawbot-BrcoYLOp.js +505 -0
  88. package/dist/hyperclawbot-CBiDSKsa.js +505 -0
  89. package/dist/inference-0mlFQqIm.js +922 -0
  90. package/dist/inference-DHR82Gh7.js +6 -0
  91. package/dist/inference-DhA8jpfH.js +2692 -0
  92. package/dist/inference-SzqFe_nk.js +6 -0
  93. package/dist/knowledge-graph-BrYpSgxW.js +131 -0
  94. package/dist/knowledge-graph-DE5lSF02.js +131 -0
  95. package/dist/loader-9JqY6Nlq.js +4 -0
  96. package/dist/loader-BkDi8MD9.js +400 -0
  97. package/dist/loader-Cjdd1kw4.js +400 -0
  98. package/dist/loader-DI2qDRPC.js +4 -0
  99. package/dist/logger-Cp8wC7F8.js +83 -0
  100. package/dist/logger-DCT2l9GV.js +83 -0
  101. package/dist/manager-3cq3DydI.js +4 -0
  102. package/dist/manager-B2Gls5RG.js +218 -0
  103. package/dist/manager-BUrFrPuq.js +117 -0
  104. package/dist/manager-Bi9UYyVR.js +105 -0
  105. package/dist/manager-Biz9ixWJ.js +40 -0
  106. package/dist/manager-CBUHJiY7.js +6 -0
  107. package/dist/manager-CVLLaKmq.js +218 -0
  108. package/dist/manager-CWNSML5D.js +117 -0
  109. package/dist/manager-SJe9gt-q.js +4 -0
  110. package/dist/mcp-CUoTCMw-.js +139 -0
  111. package/dist/mcp-loader-BIz-450x.js +94 -0
  112. package/dist/mcp-loader-CvxRDtPC.js +94 -0
  113. package/dist/memory-OL77OMOr.js +270 -0
  114. package/dist/memory-auto-CpQHZlEJ.js +306 -0
  115. package/dist/memory-auto-D-L2q21G.js +306 -0
  116. package/dist/memory-auto-DTcy5VBy.js +5 -0
  117. package/dist/memory-auto-Z6LCf-iK.js +5 -0
  118. package/dist/memory-gUi4VaIf.js +4 -0
  119. package/dist/memory-integration-B8RSN4pr.js +91 -0
  120. package/dist/memory-integration-g2vxwgoE.js +91 -0
  121. package/dist/moltbook-B-40gQOL.js +81 -0
  122. package/dist/moltbook-Cl8cQfxJ.js +81 -0
  123. package/dist/node-TWxRm84k.js +222 -0
  124. package/dist/nodes-registry-C9dCFwjh.js +52 -0
  125. package/dist/nodes-registry-DKRtsbNg.js +52 -0
  126. package/dist/oauth-flow-CeaaGAz0.js +150 -0
  127. package/dist/oauth-flow-JCfporKq.js +150 -0
  128. package/dist/oauth-provider-4R0EJlsT.js +110 -0
  129. package/dist/oauth-provider-B4dzn56l.js +110 -0
  130. package/dist/observability-CDZmeHfa.js +89 -0
  131. package/dist/observability-nZ3CBIxG.js +89 -0
  132. package/dist/onboard-BBBWcfhp.js +10 -0
  133. package/dist/onboard-BVOtKQdh.js +3641 -0
  134. package/dist/onboard-Bw28IRQ3.js +4070 -0
  135. package/dist/onboard-CGNIw27w.js +11 -0
  136. package/dist/orchestrator-BovkM63z.js +6 -0
  137. package/dist/orchestrator-CcKx1Ovk.js +189 -0
  138. package/dist/orchestrator-DSbpkP1X.js +189 -0
  139. package/dist/orchestrator-DcFfDLTX.js +6 -0
  140. package/dist/osint-B4_m3VHQ.js +277 -0
  141. package/dist/osint-B6BZKQAD.js +277 -0
  142. package/dist/pairing-B6RArWhD.js +196 -0
  143. package/dist/pairing-BsQ08DLq.js +4 -0
  144. package/dist/pc-access-B0KocJNe.js +819 -0
  145. package/dist/pc-access-DkzmugZ7.js +8 -0
  146. package/dist/pending-approval-BgNjjuI2.js +22 -0
  147. package/dist/pending-approval-C_HkX1QL.js +22 -0
  148. package/dist/providers-DxiamZSL.js +5 -0
  149. package/dist/providers-Dy15rDb7.js +657 -0
  150. package/dist/reminders-store-CzUY0zYx.js +58 -0
  151. package/dist/renderer-ANNfXsHn.js +225 -0
  152. package/dist/rules-BSQwwAYC.js +103 -0
  153. package/dist/run-main.js +142 -132
  154. package/dist/runner-BHRSOPEU.js +1271 -0
  155. package/dist/runner-CJFJUtPm.js +1271 -0
  156. package/dist/sdk/index.js +2 -2
  157. package/dist/sdk/index.mjs +2 -2
  158. package/dist/security--oQObeJO.js +4 -0
  159. package/dist/security-wBOg0TA8.js +73 -0
  160. package/dist/server-Brl_HQUB.js +1255 -0
  161. package/dist/server-CbTTpB5m.js +1255 -0
  162. package/dist/server-DP_bPzvI.js +4 -0
  163. package/dist/server-DhfipkwN.js +4 -0
  164. package/dist/session-store-B09r5HgB.js +5 -0
  165. package/dist/session-store-DCTQIVur.js +113 -0
  166. package/dist/sessions-tools-BdlN6Pb6.js +95 -0
  167. package/dist/sessions-tools-JVLDKSJ_.js +5 -0
  168. package/dist/skill-loader-B5oeliGu.js +7 -0
  169. package/dist/skill-loader-Wf3brNOj.js +160 -0
  170. package/dist/skill-runtime-BGlvly2s.js +102 -0
  171. package/dist/skill-runtime-BXWd-Ktf.js +102 -0
  172. package/dist/skill-runtime-DhL2T76p.js +5 -0
  173. package/dist/skill-runtime-jgklm02e.js +5 -0
  174. package/dist/src-BbPa6Q8p.js +63 -0
  175. package/dist/src-BeXtfkK2.js +458 -0
  176. package/dist/src-Bhybpk1J.js +63 -0
  177. package/dist/src-CGQjRI4N.js +20 -0
  178. package/dist/src-DMJ4-uqk.js +458 -0
  179. package/dist/sub-agent-tools-CmE345s_.js +39 -0
  180. package/dist/sub-agent-tools-DHY-4WWM.js +39 -0
  181. package/dist/theme-D0smfC_l.js +8 -0
  182. package/dist/theme-DajRRZbA.js +180 -0
  183. package/dist/tool-policy-DZvF8xlQ.js +189 -0
  184. package/dist/tool-policy-DgNqFWYn.js +189 -0
  185. package/dist/tts-elevenlabs-C06nUxMK.js +61 -0
  186. package/dist/tts-elevenlabs-JeFaGNJU.js +61 -0
  187. package/dist/update-check-BVEqHhFY.js +83 -0
  188. package/dist/update-check-w4XuxVl7.js +81 -0
  189. package/dist/vision-JOtOS1Br.js +121 -0
  190. package/dist/vision-fky3elEo.js +121 -0
  191. package/dist/vision-tools-C8B3776g.js +5 -0
  192. package/dist/vision-tools-CB28ZCO_.js +5 -0
  193. package/dist/vision-tools-dwn9p4el.js +51 -0
  194. package/dist/vision-tools-vPPwQ-0N.js +51 -0
  195. package/dist/voice-transcription-B6RtplmN.js +138 -0
  196. package/dist/voice-transcription-DBo5hXmu.js +138 -0
  197. package/dist/website-watch-tools-B-jRAeTe.js +139 -0
  198. package/dist/website-watch-tools-BC9xAL67.js +5 -0
  199. package/package.json +1 -1
@@ -0,0 +1,508 @@
1
+ const require_chunk = require('./chunk-jS-bbMI5.js');
2
+ const chalk = require_chunk.__toESM(require("chalk"));
3
+ const fs_extra = require_chunk.__toESM(require("fs-extra"));
4
+ const path = require_chunk.__toESM(require("path"));
5
+ const os = require_chunk.__toESM(require("os"));
6
+ const child_process = require_chunk.__toESM(require("child_process"));
7
+ const http = require_chunk.__toESM(require("http"));
8
+ const https = require_chunk.__toESM(require("https"));
9
+ const events = require_chunk.__toESM(require("events"));
10
+
11
+ //#region extensions/signal/src/connector.ts
12
+ const STATE_DIR = path.default.join(os.default.homedir(), ".hyperclaw");
13
+ const PAIRING_EXPIRY_MS = 60 * 60 * 1e3;
14
+ const SSE_RECONNECT_DELAY_MS = 5e3;
15
+ function cliReq(daemonUrl, method, endpoint, body) {
16
+ return new Promise((resolve, reject) => {
17
+ const base = daemonUrl.replace(/\/$/, "");
18
+ const url = new URL(endpoint.startsWith("/") ? endpoint : `/${endpoint}`, base);
19
+ const isHttps = url.protocol === "https:";
20
+ const mod = isHttps ? https.default : http.default;
21
+ const payload = body ? JSON.stringify(body) : null;
22
+ const req = mod.request({
23
+ hostname: url.hostname,
24
+ port: parseInt(url.port || (isHttps ? "443" : "8080"), 10),
25
+ path: url.pathname + (url.search || ""),
26
+ method,
27
+ headers: payload ? {
28
+ "Content-Type": "application/json",
29
+ "Content-Length": Buffer.byteLength(payload)
30
+ } : {}
31
+ }, (res) => {
32
+ let data = "";
33
+ res.on("data", (c) => data += c.toString());
34
+ res.on("end", () => {
35
+ if (!data.trim()) {
36
+ resolve({});
37
+ return;
38
+ }
39
+ try {
40
+ resolve(JSON.parse(data));
41
+ } catch {
42
+ resolve({ raw: data });
43
+ }
44
+ });
45
+ });
46
+ req.on("error", reject);
47
+ if (payload) req.write(payload);
48
+ req.end();
49
+ });
50
+ }
51
+ function chunkText(text, limit, mode) {
52
+ if (mode === "newline") {
53
+ const paragraphs = text.split(/\n\s*\n/);
54
+ const result = [];
55
+ let buf = "";
56
+ for (const p of paragraphs) if ((buf + (buf ? "\n\n" : "") + p).length > limit) {
57
+ if (buf) {
58
+ result.push(buf);
59
+ buf = "";
60
+ }
61
+ if (p.length > limit) {
62
+ const subs = p.match(new RegExp(`.{1,${limit}}`, "gs")) || [p];
63
+ result.push(...subs.slice(0, -1));
64
+ buf = subs[subs.length - 1];
65
+ } else buf = p;
66
+ } else buf = buf ? `${buf}\n\n${p}` : p;
67
+ if (buf) result.push(buf);
68
+ return result;
69
+ }
70
+ return text.match(new RegExp(`.{1,${limit}}`, "gs")) || [text];
71
+ }
72
+ function normalizeSender(source, sourceUuid) {
73
+ if (sourceUuid) return `uuid:${sourceUuid}`;
74
+ return source ?? "";
75
+ }
76
+ function senderAllowed(sender, allowList) {
77
+ if (!allowList.length) return false;
78
+ return allowList.some((p) => {
79
+ if (p === "*") return true;
80
+ if (p === sender) return true;
81
+ if (p.startsWith("uuid:") && sender === p) return true;
82
+ if (!p.startsWith("uuid:") && sender === `uuid:${p}`) return true;
83
+ return false;
84
+ });
85
+ }
86
+ function resolveAccount(id, raw, state) {
87
+ const host = raw.httpHost ?? "127.0.0.1";
88
+ const port = raw.httpPort ?? 8080;
89
+ const daemonUrl = raw.httpUrl ?? `http://${host}:${port}`;
90
+ const hasExternalUrl = !!raw.httpUrl;
91
+ return {
92
+ id,
93
+ name: raw.name ?? id,
94
+ account: raw.account ?? "",
95
+ cliPath: raw.cliPath ?? "signal-cli",
96
+ daemonUrl,
97
+ autoStart: raw.autoStart ?? !hasExternalUrl,
98
+ startupTimeoutMs: Math.min(raw.startupTimeoutMs ?? 15e3, 12e4),
99
+ receiveMode: raw.receiveMode ?? "on-start",
100
+ dmPolicy: raw.dmPolicy ?? "pairing",
101
+ allowFrom: raw.allowFrom ?? [],
102
+ groupPolicy: raw.groupPolicy ?? "allowlist",
103
+ groupAllowFrom: raw.groupAllowFrom ?? [],
104
+ historyLimit: raw.historyLimit ?? 50,
105
+ dmHistoryLimit: raw.dmHistoryLimit ?? 50,
106
+ textChunkLimit: raw.textChunkLimit ?? 4e3,
107
+ chunkMode: raw.chunkMode ?? "length",
108
+ mediaMaxMb: raw.mediaMaxMb ?? 8,
109
+ ignoreAttachments: raw.ignoreAttachments ?? false,
110
+ ignoreStories: raw.ignoreStories ?? false,
111
+ sendReadReceipts: raw.sendReadReceipts ?? false,
112
+ configWrites: raw.configWrites ?? true,
113
+ actions: {
114
+ reactions: true,
115
+ ...raw.actions
116
+ },
117
+ reactionLevel: raw.reactionLevel ?? "minimal",
118
+ approvedPairings: state.approved,
119
+ pendingPairings: state.pending
120
+ };
121
+ }
122
+ var SingleAccountConnector = class extends events.EventEmitter {
123
+ acc;
124
+ daemon = null;
125
+ sseActive = false;
126
+ sseReconnect = false;
127
+ constructor(acc) {
128
+ super();
129
+ this.acc = acc;
130
+ }
131
+ async connect() {
132
+ if (this.acc.autoStart) await this._spawnDaemon();
133
+ await cliReq(this.acc.daemonUrl, "GET", "/v1/accounts");
134
+ await this._loadState();
135
+ console.log(chalk.default.green(` 🦅 Signal[${this.acc.id}]: ${this.acc.account || "linked"} connected via ${this.acc.daemonUrl}`));
136
+ this.emit("connected", {
137
+ accountId: this.acc.id,
138
+ account: this.acc.account,
139
+ daemonUrl: this.acc.daemonUrl
140
+ });
141
+ if (this.acc.receiveMode === "on-start") this._startSSE();
142
+ }
143
+ disconnect() {
144
+ this.sseReconnect = false;
145
+ this.sseActive = false;
146
+ if (this.daemon) {
147
+ this.daemon.kill();
148
+ this.daemon = null;
149
+ }
150
+ }
151
+ async _spawnDaemon() {
152
+ const { cliPath, account, httpHost, httpPort } = {
153
+ cliPath: this.acc.cliPath,
154
+ account: this.acc.account,
155
+ httpHost: new URL(this.acc.daemonUrl).hostname,
156
+ httpPort: parseInt(new URL(this.acc.daemonUrl).port || "8080", 10)
157
+ };
158
+ if (!account) throw new Error(`Signal[${this.acc.id}]: 'account' (phone number) is required for autoStart`);
159
+ console.log(chalk.default.gray(` Signal[${this.acc.id}]: spawning daemon ${cliPath} -a ${account} daemon --http...`));
160
+ this.daemon = (0, child_process.spawn)(cliPath, [
161
+ "-a",
162
+ account,
163
+ "daemon",
164
+ "--http",
165
+ `--port=${httpPort}`,
166
+ `--http-host=${httpHost}`
167
+ ], {
168
+ detached: false,
169
+ stdio: [
170
+ "ignore",
171
+ "pipe",
172
+ "pipe"
173
+ ]
174
+ });
175
+ this.daemon.stderr?.on("data", (d) => {
176
+ const line = d.toString().trim();
177
+ if (line) console.log(chalk.default.gray(` [signal-cli] ${line}`));
178
+ });
179
+ this.daemon.on("exit", (code) => {
180
+ console.log(chalk.default.yellow(` ⚠ Signal[${this.acc.id}]: daemon exited (code ${code})`));
181
+ });
182
+ const deadline = Date.now() + this.acc.startupTimeoutMs;
183
+ while (Date.now() < deadline) try {
184
+ await cliReq(this.acc.daemonUrl, "GET", "/v1/accounts");
185
+ return;
186
+ } catch {
187
+ await new Promise((r) => setTimeout(r, 500));
188
+ }
189
+ throw new Error(`Signal[${this.acc.id}]: daemon did not start within ${this.acc.startupTimeoutMs}ms`);
190
+ }
191
+ _startSSE() {
192
+ this.sseReconnect = true;
193
+ this._connectSSE();
194
+ }
195
+ _connectSSE() {
196
+ if (!this.sseReconnect) return;
197
+ const url = new URL("/v1/events", this.acc.daemonUrl);
198
+ if (this.acc.account) url.searchParams.set("account", this.acc.account);
199
+ const isHttps = url.protocol === "https:";
200
+ const mod = isHttps ? https.default : http.default;
201
+ const req = mod.request({
202
+ hostname: url.hostname,
203
+ port: parseInt(url.port || (isHttps ? "443" : "8080"), 10),
204
+ path: url.pathname + url.search,
205
+ method: "GET",
206
+ headers: {
207
+ Accept: "text/event-stream",
208
+ "Cache-Control": "no-cache"
209
+ }
210
+ }, (res) => {
211
+ this.sseActive = true;
212
+ let buf = "";
213
+ res.on("data", (chunk) => {
214
+ buf += chunk.toString();
215
+ const lines = buf.split("\n");
216
+ buf = lines.pop() ?? "";
217
+ let dataLine = "";
218
+ for (const line of lines) if (line.startsWith("data:")) dataLine = line.slice(5).trim();
219
+ else if (line === "" && dataLine) {
220
+ try {
221
+ this._handleEnvelope(JSON.parse(dataLine));
222
+ } catch {}
223
+ dataLine = "";
224
+ }
225
+ });
226
+ res.on("end", () => {
227
+ this.sseActive = false;
228
+ if (this.sseReconnect) {
229
+ console.log(chalk.default.yellow(` Signal[${this.acc.id}]: SSE disconnected, reconnecting...`));
230
+ setTimeout(() => this._connectSSE(), SSE_RECONNECT_DELAY_MS);
231
+ }
232
+ });
233
+ res.on("error", () => {
234
+ this.sseActive = false;
235
+ if (this.sseReconnect) setTimeout(() => this._connectSSE(), SSE_RECONNECT_DELAY_MS);
236
+ });
237
+ });
238
+ req.on("error", () => {
239
+ if (this.sseReconnect) setTimeout(() => this._connectSSE(), SSE_RECONNECT_DELAY_MS);
240
+ });
241
+ req.end();
242
+ }
243
+ _handleEnvelope(ev) {
244
+ const envelope = ev.envelope ?? ev;
245
+ if (!envelope) return;
246
+ if (this.acc.ignoreStories && envelope.storyMessage) return;
247
+ const dataMessage = envelope.dataMessage ?? envelope.syncMessage?.sentMessage?.dataMessage;
248
+ if (!dataMessage) return;
249
+ if (!dataMessage.message && !dataMessage.attachments?.length) return;
250
+ const source = envelope.source;
251
+ const sourceUuid = envelope.sourceUuid;
252
+ const from = normalizeSender(source, sourceUuid);
253
+ const timestamp = envelope.timestamp ?? Date.now();
254
+ const msgId = String(timestamp);
255
+ const text = dataMessage.message?.trim() ?? "";
256
+ const groupInfo = dataMessage.groupInfo ?? dataMessage.groupV2;
257
+ if (groupInfo?.groupId) this._routeGroup(from, groupInfo.groupId, text, msgId, dataMessage);
258
+ else this._routeDM(from, text, msgId, dataMessage);
259
+ }
260
+ async _routeDM(from, text, msgId, dataMessage) {
261
+ const acc = this.acc;
262
+ if (acc.dmPolicy === "disabled") return;
263
+ if (acc.sendReadReceipts) this._sendReadReceipt(from, parseInt(msgId, 10)).catch(() => {});
264
+ if (acc.dmPolicy === "open") {
265
+ this._emitMessage(from, from, text, msgId, true, void 0, dataMessage);
266
+ return;
267
+ }
268
+ if (acc.dmPolicy === "allowlist") {
269
+ if (!senderAllowed(from, acc.allowFrom)) {
270
+ console.log(chalk.default.gray(` signal[${acc.id}]: drop DM from ${from} (dmPolicy=allowlist)`));
271
+ return;
272
+ }
273
+ this._emitMessage(from, from, text, msgId, true, void 0, dataMessage);
274
+ return;
275
+ }
276
+ if (acc.dmPolicy === "pairing") {
277
+ const now = Date.now();
278
+ for (const [code$1, entry] of Object.entries(acc.pendingPairings)) if (entry.expiresAt < now) delete acc.pendingPairings[code$1];
279
+ if (acc.approvedPairings.includes(from) || senderAllowed(from, acc.allowFrom)) {
280
+ this._emitMessage(from, from, text, msgId, true, void 0, dataMessage);
281
+ return;
282
+ }
283
+ const upper = text.trim().toUpperCase();
284
+ const existing = Object.entries(acc.pendingPairings).find(([code$1]) => code$1 === upper);
285
+ if (existing && existing[1].sender === from) {
286
+ acc.approvedPairings.push(from);
287
+ delete acc.pendingPairings[upper];
288
+ await this._saveState();
289
+ await this.sendMessage(from, "🦅 Paired!");
290
+ this.emit("pairing:approved", {
291
+ accountId: acc.id,
292
+ sender: from
293
+ });
294
+ return;
295
+ }
296
+ const code = Array.from({ length: 6 }, () => "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"[Math.floor(Math.random() * 32)]).join("");
297
+ acc.pendingPairings[code] = {
298
+ sender: from,
299
+ expiresAt: now + PAIRING_EXPIRY_MS
300
+ };
301
+ await this._saveState();
302
+ await this.sendMessage(from, `🦅 Pairing code: ${code}\nApprove: hyperclaw pairing approve signal ${code}\n(Expires in 1 hour)`);
303
+ }
304
+ }
305
+ _routeGroup(from, groupId, text, msgId, dataMessage) {
306
+ const acc = this.acc;
307
+ if (acc.groupPolicy === "disabled") return;
308
+ if (acc.groupPolicy === "allowlist") {
309
+ const combined = [...acc.groupAllowFrom ?? [], ...acc.allowFrom ?? []];
310
+ if (combined.length && !senderAllowed(from, combined)) {
311
+ console.log(chalk.default.gray(` signal[${acc.id}]: drop group msg from ${from} in ${groupId} (allowlist)`));
312
+ return;
313
+ }
314
+ }
315
+ const chatId = `signal:group:${groupId}`;
316
+ this._emitMessage(from, chatId, text, msgId, false, groupId, dataMessage);
317
+ }
318
+ _emitMessage(from, chatId, text, msgId, isDM, groupId, dataMessage) {
319
+ const attachments = [];
320
+ if (!this.acc.ignoreAttachments && Array.isArray(dataMessage?.attachments)) for (const att of dataMessage.attachments) {
321
+ const sizeMb = (att.size ?? 0) / (1024 * 1024);
322
+ if (sizeMb <= this.acc.mediaMaxMb) attachments.push(att.id ?? att.filename ?? "");
323
+ }
324
+ const payload = {
325
+ accountId: this.acc.id,
326
+ id: msgId,
327
+ from,
328
+ chatId,
329
+ text,
330
+ timestamp: new Date(parseInt(msgId, 10)).toISOString(),
331
+ isDM,
332
+ ...groupId ? { groupId } : {},
333
+ ...attachments.length ? { attachments } : {}
334
+ };
335
+ this.emit("message", payload);
336
+ }
337
+ async sendMessage(recipient, text, groupId) {
338
+ const chunks = chunkText(text, this.acc.textChunkLimit, this.acc.chunkMode);
339
+ for (const chunk of chunks) {
340
+ const body = {
341
+ number: this.acc.account,
342
+ message: chunk
343
+ };
344
+ if (groupId) body.group_id = groupId;
345
+ else {
346
+ const resolvedRecipient = recipient.startsWith("uuid:") ? void 0 : recipient;
347
+ const resolvedUuid = recipient.startsWith("uuid:") ? recipient.slice(5) : void 0;
348
+ if (resolvedUuid) body.recipients = [{ uuid: resolvedUuid }];
349
+ else body.recipients = [resolvedRecipient];
350
+ }
351
+ await cliReq(this.acc.daemonUrl, "POST", "/v2/send", body);
352
+ }
353
+ }
354
+ async sendTyping(recipient, groupId, stop = false) {
355
+ try {
356
+ const body = {
357
+ number: this.acc.account,
358
+ stop
359
+ };
360
+ if (groupId) body.group_id = groupId;
361
+ else body.recipient = recipient.startsWith("uuid:") ? { uuid: recipient.slice(5) } : recipient;
362
+ await cliReq(this.acc.daemonUrl, "PUT", "/v1/typing", body);
363
+ } catch {}
364
+ }
365
+ async _sendReadReceipt(sender, timestamp) {
366
+ const body = {
367
+ number: this.acc.account,
368
+ receipt_type: "read",
369
+ timestamps: [timestamp]
370
+ };
371
+ if (sender.startsWith("uuid:")) body.recipient = { uuid: sender.slice(5) };
372
+ else body.recipient = sender;
373
+ await cliReq(this.acc.daemonUrl, "POST", "/v1/receipts", body);
374
+ }
375
+ async addReaction(recipient, emoji, targetTimestamp, targetAuthor, groupId) {
376
+ if (!this.acc.actions.reactions || this.acc.reactionLevel === "off" || this.acc.reactionLevel === "ack") return;
377
+ const body = {
378
+ number: this.acc.account,
379
+ emoji,
380
+ target_author: targetAuthor ?? recipient,
381
+ timestamp: targetTimestamp,
382
+ remove: false
383
+ };
384
+ if (groupId) body.group_id = groupId;
385
+ else body.recipient = recipient.startsWith("uuid:") ? { uuid: recipient.slice(5) } : recipient;
386
+ await cliReq(this.acc.daemonUrl, "POST", `/v1/reactions/${encodeURIComponent(this.acc.account)}`, body);
387
+ }
388
+ async removeReaction(recipient, emoji, targetTimestamp, targetAuthor, groupId) {
389
+ if (!this.acc.actions.reactions) return;
390
+ const body = {
391
+ number: this.acc.account,
392
+ emoji,
393
+ target_author: targetAuthor ?? recipient,
394
+ timestamp: targetTimestamp,
395
+ remove: true
396
+ };
397
+ if (groupId) body.group_id = groupId;
398
+ else body.recipient = recipient.startsWith("uuid:") ? { uuid: recipient.slice(5) } : recipient;
399
+ await cliReq(this.acc.daemonUrl, "POST", `/v1/reactions/${encodeURIComponent(this.acc.account)}`, body);
400
+ }
401
+ approvePairing(code) {
402
+ const upper = code.toUpperCase();
403
+ const entry = this.acc.pendingPairings[upper];
404
+ if (!entry) return false;
405
+ if (Date.now() > entry.expiresAt) {
406
+ delete this.acc.pendingPairings[upper];
407
+ this._saveState();
408
+ return false;
409
+ }
410
+ this.acc.approvedPairings.push(entry.sender);
411
+ delete this.acc.pendingPairings[upper];
412
+ this._saveState();
413
+ return true;
414
+ }
415
+ listPendingPairings() {
416
+ const now = Date.now();
417
+ const result = {};
418
+ for (const [code, entry] of Object.entries(this.acc.pendingPairings)) if (entry.expiresAt > now) result[code] = entry.sender;
419
+ return result;
420
+ }
421
+ _stateFile() {
422
+ return path.default.join(STATE_DIR, `signal-state-${this.acc.id}.json`);
423
+ }
424
+ async _saveState() {
425
+ await fs_extra.default.ensureDir(STATE_DIR);
426
+ await fs_extra.default.writeJson(this._stateFile(), {
427
+ approvedPairings: this.acc.approvedPairings,
428
+ pendingPairings: this.acc.pendingPairings
429
+ }, { spaces: 2 });
430
+ }
431
+ async _loadState() {
432
+ try {
433
+ const s = await fs_extra.default.readJson(this._stateFile());
434
+ if (Array.isArray(s.approvedPairings)) this.acc.approvedPairings = s.approvedPairings;
435
+ if (s.pendingPairings && typeof s.pendingPairings === "object") this.acc.pendingPairings = s.pendingPairings;
436
+ } catch {}
437
+ }
438
+ };
439
+ var SignalConnector = class extends events.EventEmitter {
440
+ accounts = /* @__PURE__ */ new Map();
441
+ rawConfig;
442
+ constructor(config) {
443
+ super();
444
+ this.rawConfig = config;
445
+ }
446
+ async connect() {
447
+ const cfg = this.rawConfig;
448
+ const accountDefs = cfg.accounts ?? { default: cfg };
449
+ for (const [id, rawAcc] of Object.entries(accountDefs)) {
450
+ const merged = {
451
+ ...cfg,
452
+ ...rawAcc
453
+ };
454
+ const state = {
455
+ approved: cfg.approvedPairings ?? [],
456
+ pending: cfg.pendingPairings ?? {}
457
+ };
458
+ const acc = resolveAccount(id, merged, state);
459
+ if (!acc.account && acc.autoStart) {
460
+ console.log(chalk.default.yellow(` ⚠ Signal[${id}]: 'account' required for autoStart — skipping`));
461
+ continue;
462
+ }
463
+ const conn = new SingleAccountConnector(acc);
464
+ await conn._loadState();
465
+ conn.on("message", (msg) => this.emit("message", msg));
466
+ conn.on("connected", (info) => this.emit("connected", info));
467
+ conn.on("pairing:approved", (info) => this.emit("pairing:approved", info));
468
+ await conn.connect();
469
+ this.accounts.set(id, conn);
470
+ }
471
+ }
472
+ disconnect() {
473
+ for (const conn of this.accounts.values()) conn.disconnect();
474
+ this.accounts.clear();
475
+ }
476
+ _acc(accountId = "default") {
477
+ const conn = this.accounts.get(accountId);
478
+ if (!conn) throw new Error(`Signal: account '${accountId}' not found`);
479
+ return conn;
480
+ }
481
+ async sendMessage(recipient, text, groupId, accountId) {
482
+ return this._acc(accountId).sendMessage(recipient, text, groupId);
483
+ }
484
+ async sendTyping(recipient, groupId, stop, accountId) {
485
+ return this._acc(accountId).sendTyping(recipient, groupId, stop);
486
+ }
487
+ async addReaction(recipient, emoji, targetTimestamp, targetAuthor, groupId, accountId) {
488
+ return this._acc(accountId).addReaction(recipient, emoji, targetTimestamp, targetAuthor, groupId);
489
+ }
490
+ async removeReaction(recipient, emoji, targetTimestamp, targetAuthor, groupId, accountId) {
491
+ return this._acc(accountId).removeReaction(recipient, emoji, targetTimestamp, targetAuthor, groupId);
492
+ }
493
+ approvePairing(code, accountId) {
494
+ return this._acc(accountId).approvePairing(code);
495
+ }
496
+ listPendingPairings(accountId) {
497
+ return this._acc(accountId).listPendingPairings();
498
+ }
499
+ getAccountIds() {
500
+ return Array.from(this.accounts.keys());
501
+ }
502
+ isRunning() {
503
+ return this.accounts.size > 0;
504
+ }
505
+ };
506
+
507
+ //#endregion
508
+ exports.SignalConnector = SignalConnector;