hyperclaw 5.2.7 → 5.2.9
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/dist/a2ui-protocol-DEsfqO7h.js +75 -0
- package/dist/agents-routing-Cee7wrfi.js +398 -0
- package/dist/agents-routing-ChorJKFL.js +6 -0
- package/dist/agents-routing-Cpg20-1e.js +398 -0
- package/dist/agents-routing-uNzqjgOr.js +6 -0
- package/dist/api-key-validation-DgOBmp8Y.js +64 -0
- package/dist/api-key-validation-DydlUth1.js +64 -0
- package/dist/api-keys-guide--73Bq0Ey.js +149 -0
- package/dist/api-keys-guide-DqRGa4x7.js +149 -0
- package/dist/audit-CX5poVMR.js +445 -0
- package/dist/audit-Dntx9fG9.js +445 -0
- package/dist/banner-B_rR7FPO.js +7 -0
- package/dist/banner-Bb7CderS.js +143 -0
- package/dist/bounty-tools-BoU1NN5N.js +211 -0
- package/dist/bounty-tools-Dn9Yq7V1.js +211 -0
- package/dist/browser-tools-CJ9M9o22.js +179 -0
- package/dist/browser-tools-CXxWxA1c.js +5 -0
- package/dist/chat-C07wF0mM.js +494 -0
- package/dist/chat-D1Zc73I5.js +513 -0
- package/dist/claw-tasks-BLqd1a0Q.js +80 -0
- package/dist/claw-tasks-ChqkHdFs.js +80 -0
- package/dist/config-BlLlJ6Er.js +7 -0
- package/dist/config-Bzues-G2.js +7 -0
- package/dist/config-DGAAJ49A.js +261 -0
- package/dist/config-SgDxKyfV.js +261 -0
- package/dist/connector-1efnZgQN.js +566 -0
- package/dist/connector-B5q1_srT.js +286 -0
- package/dist/connector-BMFLJ4fr.js +508 -0
- package/dist/connector-BZYv9siY.js +189 -0
- package/dist/connector-B_XkXm-j.js +218 -0
- package/dist/connector-BkY1I6gf.js +189 -0
- package/dist/connector-C2Z3RN1z.js +350 -0
- package/dist/connector-C7aYvVzU.js +225 -0
- package/dist/connector-CXXYOyHw.js +164 -0
- package/dist/connector-Ca1J23HX.js +167 -0
- package/dist/connector-Cjqc656I.js +181 -0
- package/dist/connector-CluRienN.js +425 -0
- package/dist/connector-CuNz2eP-.js +305 -0
- package/dist/connector-DHL_oeHy.js +552 -0
- package/dist/connector-DJ79rd1L.js +173 -0
- package/dist/connector-DcLE6xCZ.js +239 -0
- package/dist/connector-DcyQTJnJ.js +162 -0
- package/dist/connector-DgyX9qSc.js +192 -0
- package/dist/connector-DnDXXZ7L.js +182 -0
- package/dist/connector-DqUslg-X.js +213 -0
- package/dist/connector-Duc-HmRZ.js +85 -0
- package/dist/connector-IV0QFer8.js +498 -0
- package/dist/connector-OnsLxE8G.js +194 -0
- package/dist/connector-UYu_TS0X.js +204 -0
- package/dist/connector-cCA5ffmp.js +340 -0
- package/dist/connector-fbNfx4_L.js +568 -0
- package/dist/connector-fi2vlwbO.js +276 -0
- package/dist/connector-l3LD8IDN.js +419 -0
- package/dist/cost-tracker-CgEXyEtz.js +103 -0
- package/dist/cost-tracker-DCXDUzBI.js +103 -0
- package/dist/credentials-store-1LDtNReY.js +89 -0
- package/dist/credentials-store-BFxEJR00.js +7 -0
- package/dist/credentials-store-Bmm9e1SS.js +7 -0
- package/dist/credentials-store-D8ERbGR2.js +89 -0
- package/dist/cron-tasks-1E6wKpTv.js +85 -0
- package/dist/cron-tasks-OQbgmenS.js +85 -0
- package/dist/daemon-B13UIqvL.js +7 -0
- package/dist/daemon-CzOW-1PS.js +421 -0
- package/dist/daemon-aVX-WGz1.js +421 -0
- package/dist/daemon-iFmVBPXN.js +7 -0
- package/dist/delivery-B8YGmrq5.js +4 -0
- package/dist/delivery-DWsU6gx-.js +95 -0
- package/dist/delivery-Pko6sSkt.js +4 -0
- package/dist/delivery-hMHFRZwy.js +95 -0
- package/dist/destructive-gate-C2TrWsp2.js +101 -0
- package/dist/destructive-gate-bnkroJWG.js +101 -0
- package/dist/developer-keys-BWXHaWxY.js +127 -0
- package/dist/developer-keys-CzDxVczE.js +8 -0
- package/dist/device-auth-store-C1bCwXO2.js +7 -0
- package/dist/device-auth-store-DIZTOz4V.js +88 -0
- package/dist/doctor-C6nAGdH8.js +233 -0
- package/dist/doctor-mgWumA25.js +6 -0
- package/dist/engine-BGRTi0fo.js +327 -0
- package/dist/engine-BvCEhaUn.js +7 -0
- package/dist/engine-ByQ-0sWM.js +7 -0
- package/dist/engine-gnMjO743.js +327 -0
- package/dist/env-resolve-BdagnXhK.js +151 -0
- package/dist/env-resolve-CHxjGo8u.js +151 -0
- package/dist/env-resolve-NEtsGacw.js +10 -0
- package/dist/env-resolve-pIETNTpQ.js +10 -0
- package/dist/extraction-tools-BE6z_Yw5.js +91 -0
- package/dist/extraction-tools-CJsdyBST.js +5 -0
- package/dist/form_data-B2_0EoWj.js +8657 -0
- package/dist/gmail-watch-setup-1RGIHNdu.js +42 -0
- package/dist/gmail-watch-setup-Brkj94Sy.js +42 -0
- package/dist/health-BMUmUNoe.js +152 -0
- package/dist/health-C8n9RH5O.js +6 -0
- package/dist/heartbeat-engine-D6oSpgxx.js +89 -0
- package/dist/heartbeat-engine-aRbab8a5.js +89 -0
- package/dist/hub-BJM2KXLO.js +6 -0
- package/dist/hub-Bb_dYECE.js +512 -0
- package/dist/hyperclawbot-CgrV46DA.js +516 -0
- package/dist/hyperclawbot-DzP_v3iA.js +516 -0
- package/dist/inference-BHJFPEKL.js +8 -0
- package/dist/inference-CFBkvLpE.js +2854 -0
- package/dist/inference-G4MbdErG.js +8 -0
- package/dist/inference-vweXyh27.js +2854 -0
- package/dist/knowledge-graph-9UNrsiIY.js +134 -0
- package/dist/knowledge-graph-yeMPBPP8.js +134 -0
- package/dist/loader-BXYJl25e.js +6 -0
- package/dist/loader-DIPs649t.js +410 -0
- package/dist/loader-Dq_cDlOW.js +6 -0
- package/dist/loader-gTdKBwiI.js +410 -0
- package/dist/logger-C3ZCDSkc.js +86 -0
- package/dist/logger-CG38Idq4.js +86 -0
- package/dist/manager--wG9JdFW.js +120 -0
- package/dist/manager-BI3izlRG.js +120 -0
- package/dist/manager-BNc21xgG.js +6 -0
- package/dist/manager-CQ3MWNHY.js +250 -0
- package/dist/manager-DWJ7WZcY.js +250 -0
- package/dist/manager-DYfzqckn.js +35 -0
- package/dist/mcp-CklaYr_6.js +142 -0
- package/dist/mcp-SsMEvl28.js +142 -0
- package/dist/mcp-loader-9v8eUsNI.js +93 -0
- package/dist/mcp-loader-DLrp_oZJ.js +93 -0
- package/dist/memory-BCYvdqwo.js +273 -0
- package/dist/memory-BGgCBSx1.js +6 -0
- package/dist/memory-auto-Bh52cQJP.js +5 -0
- package/dist/memory-auto-Bow9u_L7.js +306 -0
- package/dist/memory-auto-BupvVwNd.js +306 -0
- package/dist/memory-auto-CgBAI8mm.js +5 -0
- package/dist/memory-integration-4oGqX6rr.js +91 -0
- package/dist/memory-integration-CveUEI3V.js +91 -0
- package/dist/moltbook-B3DNdh40.js +81 -0
- package/dist/moltbook-xP7VXKlX.js +81 -0
- package/dist/node-C4esBfbX.js +226 -0
- package/dist/node-urDjajMt.js +226 -0
- package/dist/nodes-registry-Cd4eWw80.js +52 -0
- package/dist/nodes-registry-DLUZhEMS.js +52 -0
- package/dist/oauth-flow-BbLQTzZk.js +148 -0
- package/dist/oauth-flow-Bt-LaRHV.js +148 -0
- package/dist/oauth-provider-CVTKgj35.js +111 -0
- package/dist/oauth-provider-UZyG84s7.js +111 -0
- package/dist/observability-BtLyuxcz.js +89 -0
- package/dist/observability-lwYm4aoB.js +89 -0
- package/dist/onboard-B3drurt-.js +3812 -0
- package/dist/onboard-BV5Poocl.js +13 -0
- package/dist/onboard-DEwuHrMj.js +14 -0
- package/dist/onboard-UiynbNQy.js +3909 -0
- package/dist/orchestrator-BXyIgAeH.js +189 -0
- package/dist/orchestrator-DMZkAVa5.js +189 -0
- package/dist/orchestrator-MLTc4NYu.js +6 -0
- package/dist/orchestrator-rVGu7yYr.js +6 -0
- package/dist/osint-Bsf6RGPv.js +283 -0
- package/dist/osint-chat-Ark94iFc.js +789 -0
- package/dist/osint-chat-Hn8qpsC1.js +836 -0
- package/dist/osint-f9DeXT6j.js +283 -0
- package/dist/pairing-2vAiDBjN.js +6 -0
- package/dist/pairing-B4NoBvyE.js +207 -0
- package/dist/pc-access-BLnc-DYp.js +858 -0
- package/dist/pc-access-CTNtG2LD.js +8 -0
- package/dist/pending-approval-C4ZaHHWl.js +22 -0
- package/dist/pending-approval-CHUZ_qT6.js +22 -0
- package/dist/reminders-store-BixTWL1h.js +58 -0
- package/dist/renderer-B1ToXngl.js +228 -0
- package/dist/rules-Cqen1Mpt.js +106 -0
- package/dist/run-main.js +98 -94
- package/dist/runner-B9xANekJ.js +1274 -0
- package/dist/runner-Cr1_mwnU.js +1274 -0
- package/dist/security--17Fxo5Z.js +4 -0
- package/dist/security-B4vH02lO.js +4 -0
- package/dist/security-DP1qtJfL.js +90 -0
- package/dist/security-HOOGCw5z.js +90 -0
- package/dist/server-CRhXiGI9.js +4 -0
- package/dist/server-DUDXqJSo.js +1365 -0
- package/dist/server-De4H45Ju.js +1365 -0
- package/dist/server-ha59nA8a.js +4 -0
- package/dist/session-store-7sEPyV16.js +5 -0
- package/dist/session-store-Ce2QMSL_.js +141 -0
- package/dist/sessions-tools-CWr_pDtp.js +5 -0
- package/dist/sessions-tools-DKVu9aIN.js +95 -0
- package/dist/skill-loader-DK19Jm4e.js +7 -0
- package/dist/skill-loader-Dfs9VNM-.js +160 -0
- package/dist/skill-runtime-BRp2D8Jb.js +5 -0
- package/dist/skill-runtime-BeKh2rD_.js +5 -0
- package/dist/skill-runtime-C8bNwKwz.js +104 -0
- package/dist/skill-runtime-CcpC2Zfc.js +104 -0
- package/dist/src-B8LzGLSY.js +63 -0
- package/dist/src-BxmkZ9RH.js +63 -0
- package/dist/src-DUoc6_kn.js +458 -0
- package/dist/src-DjTtmSRg.js +20 -0
- package/dist/src-n_46LPDi.js +458 -0
- package/dist/sub-agent-tools-CldaMfd5.js +39 -0
- package/dist/sub-agent-tools-q5JqEze_.js +39 -0
- package/dist/tool-policy-DtGf3Ifq.js +189 -0
- package/dist/tool-policy-QXF3MMxu.js +189 -0
- package/dist/tts-elevenlabs-1zWD3QJw.js +64 -0
- package/dist/tts-elevenlabs-y6HGWWDS.js +64 -0
- package/dist/update-check-C4te7JmY.js +6 -0
- package/dist/update-check-GDue_it1.js +98 -0
- package/dist/vision-DV2ubVjr.js +167 -0
- package/dist/vision-tools-Cb86uMdh.js +5 -0
- package/dist/vision-tools-CbVfyTZT.js +5 -0
- package/dist/vision-tools-DieVQp6s.js +51 -0
- package/dist/vision-tools-DlnxaZjg.js +51 -0
- package/dist/vision-u4kMThdo.js +167 -0
- package/dist/voice-transcription-BolTT_HG.js +170 -0
- package/dist/voice-transcription-DgON5qaF.js +170 -0
- package/dist/website-watch-tools-B8L_NgwT.js +5 -0
- package/dist/website-watch-tools-Drm5HjIX.js +176 -0
- package/package.json +4 -1
- package/static/chat.html +9 -3
|
@@ -0,0 +1,286 @@
|
|
|
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 net = require_chunk.__toESM(require("net"));
|
|
7
|
+
const events = require_chunk.__toESM(require("events"));
|
|
8
|
+
const tls = require_chunk.__toESM(require("tls"));
|
|
9
|
+
|
|
10
|
+
//#region extensions/email/src/connector.ts
|
|
11
|
+
const STATE_FILE = path.default.join(os.default.homedir(), ".hyperclaw", "email-state.json");
|
|
12
|
+
var IMAPClient = class {
|
|
13
|
+
sock = null;
|
|
14
|
+
buffer = "";
|
|
15
|
+
tag = 0;
|
|
16
|
+
pendingCallbacks = /* @__PURE__ */ new Map();
|
|
17
|
+
async connect(host, port, username, password) {
|
|
18
|
+
await new Promise((resolve, reject) => {
|
|
19
|
+
this.sock = tls.default.connect({
|
|
20
|
+
host,
|
|
21
|
+
port,
|
|
22
|
+
rejectUnauthorized: true
|
|
23
|
+
}, () => resolve());
|
|
24
|
+
this.sock.on("error", reject);
|
|
25
|
+
this.sock.on("data", (chunk) => {
|
|
26
|
+
this.buffer += chunk.toString();
|
|
27
|
+
this.processBuffer();
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
await this.waitForUntagged("OK");
|
|
31
|
+
await this.command(`LOGIN "${this.escapeQuoted(username)}" "${this.escapeQuoted(password)}"`);
|
|
32
|
+
}
|
|
33
|
+
disconnect() {
|
|
34
|
+
this.sock?.end();
|
|
35
|
+
this.sock = null;
|
|
36
|
+
}
|
|
37
|
+
async selectFolder(folder) {
|
|
38
|
+
const resp = await this.command(`SELECT "${folder}"`);
|
|
39
|
+
const existsMatch = resp.match(/\* (\d+) EXISTS/);
|
|
40
|
+
const unseenMatch = resp.match(/UNSEEN (\d+)/);
|
|
41
|
+
return {
|
|
42
|
+
exists: existsMatch ? parseInt(existsMatch[1]) : 0,
|
|
43
|
+
unseen: unseenMatch ? parseInt(unseenMatch[1]) : 0
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async searchUnseen() {
|
|
47
|
+
const resp = await this.command("SEARCH UNSEEN");
|
|
48
|
+
const match = resp.match(/\* SEARCH ([\d ]+)/);
|
|
49
|
+
if (!match || !match[1].trim()) return [];
|
|
50
|
+
return match[1].trim().split(" ").map(Number).filter(Boolean);
|
|
51
|
+
}
|
|
52
|
+
async fetchEmail(uid) {
|
|
53
|
+
const resp = await this.command(`FETCH ${uid} (RFC822.HEADER BODY[TEXT])`);
|
|
54
|
+
const fromMatch = resp.match(/^From:\s*(.+)$/im);
|
|
55
|
+
const subjectMatch = resp.match(/^Subject:\s*(.+)$/im);
|
|
56
|
+
const msgIdMatch = resp.match(/^Message-ID:\s*(.+)$/im);
|
|
57
|
+
const bodyMatch = resp.match(/BODY\[TEXT\] \{(\d+)\}([\s\S]+?)(?:\* \d+ FETCH|\w+ OK)/);
|
|
58
|
+
if (!fromMatch) return null;
|
|
59
|
+
const body = bodyMatch ? decodeQP(bodyMatch[2].trim()) : "";
|
|
60
|
+
return {
|
|
61
|
+
from: fromMatch[1].trim(),
|
|
62
|
+
subject: decodeHeader(subjectMatch ? subjectMatch[1].trim() : "(no subject)"),
|
|
63
|
+
body: body.slice(0, 4e3),
|
|
64
|
+
messageId: msgIdMatch ? msgIdMatch[1].trim() : ""
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async markSeen(uid) {
|
|
68
|
+
await this.command(`STORE ${uid} +FLAGS (\\Seen)`);
|
|
69
|
+
}
|
|
70
|
+
async command(cmd) {
|
|
71
|
+
const tag = `HC${++this.tag}`;
|
|
72
|
+
return new Promise((resolve, reject) => {
|
|
73
|
+
this.pendingCallbacks.set(tag, resolve);
|
|
74
|
+
this.sock?.write(`${tag} ${cmd}\r\n`);
|
|
75
|
+
setTimeout(() => {
|
|
76
|
+
this.pendingCallbacks.delete(tag);
|
|
77
|
+
reject(new Error(`IMAP timeout: ${tag} ${cmd.slice(0, 30)}`));
|
|
78
|
+
}, 15e3);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
async waitForUntagged(keyword) {
|
|
82
|
+
await new Promise((resolve) => {
|
|
83
|
+
const check = () => {
|
|
84
|
+
if (this.buffer.includes(`* ${keyword}`) || this.buffer.includes(`OK ${keyword}`)) resolve();
|
|
85
|
+
else setTimeout(check, 100);
|
|
86
|
+
};
|
|
87
|
+
setTimeout(check, 100);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
processBuffer() {
|
|
91
|
+
const lines = this.buffer.split("\r\n");
|
|
92
|
+
this.buffer = lines.pop() || "";
|
|
93
|
+
for (const line of lines) {
|
|
94
|
+
const tagMatch = line.match(/^(HC\d+) (OK|NO|BAD)/);
|
|
95
|
+
if (tagMatch) {
|
|
96
|
+
const cb = this.pendingCallbacks.get(tagMatch[1]);
|
|
97
|
+
if (cb) {
|
|
98
|
+
this.pendingCallbacks.delete(tagMatch[1]);
|
|
99
|
+
cb(this.buffer + line);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
escapeQuoted(s) {
|
|
105
|
+
return s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
var SMTPClient = class {
|
|
109
|
+
async send(config, to, subject, body) {
|
|
110
|
+
return new Promise((resolve, reject) => {
|
|
111
|
+
const sock = net.default.createConnection(config.smtpPort, config.smtpHost);
|
|
112
|
+
let buf = "";
|
|
113
|
+
let tlsSock = null;
|
|
114
|
+
let upgraded = false;
|
|
115
|
+
let authenticated = false;
|
|
116
|
+
const write = (s) => {
|
|
117
|
+
const target = tlsSock || sock;
|
|
118
|
+
target.write(s + "\r\n");
|
|
119
|
+
};
|
|
120
|
+
const onData = (chunk) => {
|
|
121
|
+
buf += chunk.toString();
|
|
122
|
+
const lines = buf.split("\r\n");
|
|
123
|
+
buf = lines.pop() || "";
|
|
124
|
+
for (const line of lines) {
|
|
125
|
+
const code = parseInt(line.slice(0, 3));
|
|
126
|
+
if (line.startsWith("220") && !upgraded) write(`EHLO hyperclaw.ai`);
|
|
127
|
+
else if (line.includes("250") && line.includes("STARTTLS") && !upgraded) write("STARTTLS");
|
|
128
|
+
else if (line.startsWith("220") && !upgraded) {
|
|
129
|
+
upgraded = true;
|
|
130
|
+
tlsSock = tls.default.connect({
|
|
131
|
+
socket: sock,
|
|
132
|
+
servername: config.smtpHost
|
|
133
|
+
});
|
|
134
|
+
tlsSock.on("data", onData);
|
|
135
|
+
tlsSock.on("error", reject);
|
|
136
|
+
write(`EHLO hyperclaw.ai`);
|
|
137
|
+
} else if (line.startsWith("250") && upgraded && !authenticated) write(`AUTH LOGIN`);
|
|
138
|
+
else if (line.startsWith("334") && !authenticated) {
|
|
139
|
+
const b64user = Buffer.from(config.username).toString("base64");
|
|
140
|
+
const b64pass = Buffer.from(config.password).toString("base64");
|
|
141
|
+
if (line.includes("VXNlcm5hbWU")) write(b64user);
|
|
142
|
+
else {
|
|
143
|
+
write(b64pass);
|
|
144
|
+
authenticated = true;
|
|
145
|
+
}
|
|
146
|
+
} else if (line.startsWith("235")) write(`MAIL FROM:<${config.username}>`);
|
|
147
|
+
else if (line.startsWith("250") && authenticated) if (buf.includes("RCPT") || !buf) write(`RCPT TO:<${to}>`);
|
|
148
|
+
else write(`DATA`);
|
|
149
|
+
else if (line.startsWith("354")) {
|
|
150
|
+
const date = (/* @__PURE__ */ new Date()).toUTCString();
|
|
151
|
+
const msg = `From: ${config.username}\r\nTo: ${to}\r\nSubject: ${subject}\r\nDate: ${date}\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n` + body + "\r\n.";
|
|
152
|
+
write(msg);
|
|
153
|
+
} else if (line.startsWith("250") && buf.includes(".")) write("QUIT");
|
|
154
|
+
else if (line.startsWith("221")) {
|
|
155
|
+
sock.destroy();
|
|
156
|
+
resolve();
|
|
157
|
+
} else if (code >= 400) {
|
|
158
|
+
sock.destroy();
|
|
159
|
+
reject(new Error(`SMTP error: ${line}`));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
sock.on("data", onData);
|
|
164
|
+
sock.on("error", reject);
|
|
165
|
+
sock.setTimeout(15e3, () => {
|
|
166
|
+
sock.destroy();
|
|
167
|
+
reject(new Error("SMTP timeout"));
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
function decodeQP(text) {
|
|
173
|
+
return text.replace(/=\r\n/g, "").replace(/=([0-9A-F]{2})/gi, (_, hex) => String.fromCharCode(parseInt(hex, 16)));
|
|
174
|
+
}
|
|
175
|
+
function decodeHeader(text) {
|
|
176
|
+
return text.replace(/=\?UTF-8\?[BQ]\?([^?]+)\?=/gi, (_, enc) => {
|
|
177
|
+
try {
|
|
178
|
+
return Buffer.from(enc, "base64").toString("utf8");
|
|
179
|
+
} catch {
|
|
180
|
+
return enc;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
function extractEmail(from) {
|
|
185
|
+
const match = from.match(/<([^>]+)>/) || from.match(/[\w.+-]+@[\w-]+\.[a-z]{2,}/i);
|
|
186
|
+
return match ? match[1] || match[0] : from;
|
|
187
|
+
}
|
|
188
|
+
var EmailConnector = class extends events.EventEmitter {
|
|
189
|
+
config;
|
|
190
|
+
pollTimer = null;
|
|
191
|
+
running = false;
|
|
192
|
+
lastSeenUid = 0;
|
|
193
|
+
smtp = new SMTPClient();
|
|
194
|
+
constructor(config) {
|
|
195
|
+
super();
|
|
196
|
+
this.config = {
|
|
197
|
+
imapPort: 993,
|
|
198
|
+
smtpPort: 587,
|
|
199
|
+
pollIntervalMs: 3e4,
|
|
200
|
+
inboxFolder: "INBOX",
|
|
201
|
+
markAsRead: true,
|
|
202
|
+
subjectPrefix: "",
|
|
203
|
+
fromAllowlist: [],
|
|
204
|
+
...config
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
async connect() {
|
|
208
|
+
await this.loadState();
|
|
209
|
+
const imap = new IMAPClient();
|
|
210
|
+
await imap.connect(this.config.imapHost, this.config.imapPort, this.config.username, this.config.password);
|
|
211
|
+
const { exists } = await imap.selectFolder(this.config.inboxFolder);
|
|
212
|
+
imap.disconnect();
|
|
213
|
+
console.log(chalk.default.green(` 🦅 Email: ${this.config.username} — ${exists} messages in inbox`));
|
|
214
|
+
this.running = true;
|
|
215
|
+
this.emit("connected", { username: this.config.username });
|
|
216
|
+
this.startPolling();
|
|
217
|
+
}
|
|
218
|
+
disconnect() {
|
|
219
|
+
this.running = false;
|
|
220
|
+
if (this.pollTimer) clearInterval(this.pollTimer);
|
|
221
|
+
}
|
|
222
|
+
startPolling() {
|
|
223
|
+
this.poll();
|
|
224
|
+
this.pollTimer = setInterval(() => this.poll(), this.config.pollIntervalMs);
|
|
225
|
+
}
|
|
226
|
+
/** Trigger immediate poll (e.g. from Gmail Pub/Sub webhook) */
|
|
227
|
+
triggerPoll() {
|
|
228
|
+
if (this.running) this.poll();
|
|
229
|
+
}
|
|
230
|
+
async poll() {
|
|
231
|
+
if (!this.running) return;
|
|
232
|
+
const imap = new IMAPClient();
|
|
233
|
+
try {
|
|
234
|
+
await imap.connect(this.config.imapHost, this.config.imapPort, this.config.username, this.config.password);
|
|
235
|
+
await imap.selectFolder(this.config.inboxFolder);
|
|
236
|
+
const unseenUids = await imap.searchUnseen();
|
|
237
|
+
const newUids = unseenUids.filter((uid) => uid > this.lastSeenUid);
|
|
238
|
+
for (const uid of newUids) {
|
|
239
|
+
const email = await imap.fetchEmail(uid);
|
|
240
|
+
if (!email) continue;
|
|
241
|
+
const fromAddr = extractEmail(email.from);
|
|
242
|
+
if (this.config.subjectPrefix && !email.subject.startsWith(this.config.subjectPrefix)) continue;
|
|
243
|
+
if (this.config.fromAllowlist.length > 0 && !this.config.fromAllowlist.includes(fromAddr)) continue;
|
|
244
|
+
if (this.config.markAsRead) await imap.markSeen(uid);
|
|
245
|
+
this.lastSeenUid = Math.max(this.lastSeenUid, uid);
|
|
246
|
+
await this.saveState();
|
|
247
|
+
this.emit("message", {
|
|
248
|
+
id: email.messageId || String(uid),
|
|
249
|
+
channelId: "email",
|
|
250
|
+
from: fromAddr,
|
|
251
|
+
chatId: fromAddr,
|
|
252
|
+
text: `Subject: ${email.subject}\n\n${email.body}`,
|
|
253
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
254
|
+
isDM: true
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
} catch (err) {
|
|
258
|
+
if (this.running) console.log(chalk.default.yellow(` ⚠ Email poll error: ${err.message}`));
|
|
259
|
+
} finally {
|
|
260
|
+
imap.disconnect();
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
async sendMessage(to, text, subject) {
|
|
264
|
+
await this.smtp.send(this.config, to, subject || `🦅 HyperClaw`, text);
|
|
265
|
+
}
|
|
266
|
+
async reply(to, originalSubject, text) {
|
|
267
|
+
const replySubject = originalSubject.startsWith("Re: ") ? originalSubject : `Re: ${originalSubject}`;
|
|
268
|
+
await this.sendMessage(to, text, replySubject);
|
|
269
|
+
}
|
|
270
|
+
async loadState() {
|
|
271
|
+
try {
|
|
272
|
+
const s = await fs_extra.default.readJson(STATE_FILE);
|
|
273
|
+
this.lastSeenUid = s.lastSeenUid || 0;
|
|
274
|
+
} catch {}
|
|
275
|
+
}
|
|
276
|
+
async saveState() {
|
|
277
|
+
await fs_extra.default.ensureDir(path.default.dirname(STATE_FILE));
|
|
278
|
+
await fs_extra.default.writeJson(STATE_FILE, { lastSeenUid: this.lastSeenUid }, { spaces: 2 });
|
|
279
|
+
}
|
|
280
|
+
isRunning() {
|
|
281
|
+
return this.running;
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
//#endregion
|
|
286
|
+
exports.EmailConnector = EmailConnector;
|