hyperclaw 4.0.0 → 4.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 (156) hide show
  1. package/README.md +53 -18
  2. package/dist/a2ui-protocol-CT_jDEU9.js +75 -0
  3. package/dist/agents-routing-683Q2JGp.js +129 -0
  4. package/dist/agents-routing-BpZBswBH.js +4 -0
  5. package/dist/api-keys-guide-Bzig1R5W.js +149 -0
  6. package/dist/api-keys-guide-Dq5Obbp4.js +149 -0
  7. package/dist/audit-BYxPlnTQ.js +248 -0
  8. package/dist/bounty-tools-C6LyzxM-.js +211 -0
  9. package/dist/browser-tools-CQBSbIuO.js +5 -0
  10. package/dist/browser-tools-YQmwRLLM.js +179 -0
  11. package/dist/claw-tasks-BRLUvFRD.js +80 -0
  12. package/dist/connector-3HnyH8fn.js +167 -0
  13. package/dist/connector-6PMZo5Ky.js +189 -0
  14. package/dist/connector-B6eoF3DD.js +181 -0
  15. package/dist/connector-B9tLG8UZ.js +196 -0
  16. package/dist/connector-BOlqjXWP.js +182 -0
  17. package/dist/connector-BP8zsbP8.js +189 -0
  18. package/dist/connector-BPoSevxp.js +286 -0
  19. package/dist/connector-BRHj773i.js +163 -0
  20. package/dist/connector-BToxU-jV.js +267 -0
  21. package/dist/connector-BliDVsJQ.js +239 -0
  22. package/dist/connector-Bv6s9oP7.js +88 -0
  23. package/dist/connector-By5wWGTR.js +343 -0
  24. package/dist/connector-C1BaFFgN.js +213 -0
  25. package/dist/connector-CRRWY5Wv.js +167 -0
  26. package/dist/connector-CXPQVGyI.js +85 -0
  27. package/dist/connector-Cdk1CXKi.js +194 -0
  28. package/dist/connector-CwlgFgjx.js +181 -0
  29. package/dist/connector-DFchk6l7.js +178 -0
  30. package/dist/connector-DKw7tRAy.js +192 -0
  31. package/dist/connector-DRv1ahC_.js +343 -0
  32. package/dist/connector-DU63KW94.js +165 -0
  33. package/dist/connector-Dbvb1Cj9.js +280 -0
  34. package/dist/connector-DcZdQcgR.js +173 -0
  35. package/dist/connector-DxKL8VvZ.js +182 -0
  36. package/dist/connector-T_YdZtzv.js +162 -0
  37. package/dist/connector-i4gOS9xL.js +154 -0
  38. package/dist/connector-rHXE1ZD2.js +167 -0
  39. package/dist/connector-wdUXChwa.js +172 -0
  40. package/dist/cost-tracker-pVE15Yq4.js +103 -0
  41. package/dist/credentials-store-BvnMPJwi.js +4 -0
  42. package/dist/credentials-store-sb-TRLwR.js +77 -0
  43. package/dist/cron-tasks-BvDFNyiE.js +82 -0
  44. package/dist/delivery-B-SJqXLn.js +95 -0
  45. package/dist/delivery-D5Z98EVq.js +95 -0
  46. package/dist/delivery-DCOXhXEO.js +5 -0
  47. package/dist/delivery-VgFeuu2J.js +5 -0
  48. package/dist/destructive-gate-m-dWqUFg.js +101 -0
  49. package/dist/developer-keys-JaJK3T27.js +127 -0
  50. package/dist/developer-keys-kyqmtWK3.js +8 -0
  51. package/dist/doctor-3oi89QIc.js +175 -0
  52. package/dist/doctor-Cf1XSfp9.js +4 -0
  53. package/dist/engine-B4eMiTgl.js +7 -0
  54. package/dist/engine-B8M7dYul.js +7 -0
  55. package/dist/engine-BhT-1M9W.js +256 -0
  56. package/dist/engine-D49jnSd_.js +256 -0
  57. package/dist/env-resolve-DWOQ45jG.js +9 -0
  58. package/dist/env-resolve-szSWl0UF.js +94 -0
  59. package/dist/extraction-tools-D3qDFBJ1.js +91 -0
  60. package/dist/extraction-tools-DLr_AEwq.js +5 -0
  61. package/dist/form_data-B_hIUrxU.js +8657 -0
  62. package/dist/gmail-watch-setup-Czt8rXaX.js +40 -0
  63. package/dist/heartbeat-engine-CRqfPcFM.js +83 -0
  64. package/dist/hub-DTsqe5Bt.js +6 -0
  65. package/dist/hub-FrPTA33j.js +515 -0
  66. package/dist/hyperclawbot-D9KCtc4P.js +480 -0
  67. package/dist/hyperclawbot-DfMGowZC.js +480 -0
  68. package/dist/hyperclawbot-Dw27pJo4.js +480 -0
  69. package/dist/inference-CTWJeX9Q.js +922 -0
  70. package/dist/inference-ix607p7k.js +6 -0
  71. package/dist/knowledge-graph-DqA-Fztl.js +131 -0
  72. package/dist/loader-CISCqBto.js +400 -0
  73. package/dist/loader-CYMQ8VOS.js +4 -0
  74. package/dist/logger-8tEtAd3y.js +83 -0
  75. package/dist/manager-CPjeRe-6.js +4 -0
  76. package/dist/manager-Cwzj7w5R.js +105 -0
  77. package/dist/manager-DLmZI-9R.js +6 -0
  78. package/dist/manager-DSGhn5i3.js +117 -0
  79. package/dist/manager-DgyF52mg.js +218 -0
  80. package/dist/manager-Dm8nrMFx.js +40 -0
  81. package/dist/mcp-B_9Ber63.js +139 -0
  82. package/dist/mcp-loader-DSM5UiFG.js +94 -0
  83. package/dist/mcp-loader-j5ZLLw5O.js +94 -0
  84. package/dist/memory-BI1kPkAN.js +4 -0
  85. package/dist/memory-BVFGkxxK.js +270 -0
  86. package/dist/memory-auto-Bc7euou4.js +306 -0
  87. package/dist/memory-auto-DPfbkMVt.js +5 -0
  88. package/dist/memory-integration-DZExqWr4.js +91 -0
  89. package/dist/moltbook-B6ZeGN5_.js +81 -0
  90. package/dist/node-pwL6O_KX.js +222 -0
  91. package/dist/nodes-registry-CsPm_-CJ.js +52 -0
  92. package/dist/oauth-flow-CpWlgvNB.js +150 -0
  93. package/dist/oauth-provider-BZb6qOw5.js +110 -0
  94. package/dist/observability-B43YvNQV.js +89 -0
  95. package/dist/onboard-3q20ZyHj.js +9 -0
  96. package/dist/onboard-Bd_wsYdi.js +4086 -0
  97. package/dist/onboard-CAN7x3me.js +3026 -0
  98. package/dist/onboard-DnegOHMh.js +3026 -0
  99. package/dist/onboard-RYtDlYBw.js +9 -0
  100. package/dist/onboard-aTwlQs-4.js +9 -0
  101. package/dist/orchestrator-BSp2M5EU.js +189 -0
  102. package/dist/orchestrator-C7ko5tWa.js +6 -0
  103. package/dist/orchestrator-DfPkIx2Z.js +6 -0
  104. package/dist/orchestrator-NJQsmiBE.js +189 -0
  105. package/dist/pairing-DU0_J28n.js +87 -0
  106. package/dist/pairing-DWllbSbO.js +4 -0
  107. package/dist/pc-access-Ly-uA8mn.js +8 -0
  108. package/dist/pc-access-NxBvTrRj.js +819 -0
  109. package/dist/pending-approval-DIHvwwWS.js +22 -0
  110. package/dist/puppeteer-2o3QOwAy.js +2 -2
  111. package/dist/puppeteer-BYTMp3BI.js +2 -2
  112. package/dist/puppeteer-DQ45qwWk.js +2 -2
  113. package/dist/reminders-store-D79qdfN0.js +58 -0
  114. package/dist/renderer-pqlDRKbH.js +225 -0
  115. package/dist/rules-BooT_qFP.js +103 -0
  116. package/dist/run-main.js +366 -1109
  117. package/dist/runner-Bu--_RXw.js +810 -0
  118. package/dist/runner-D1rjuMTJ.js +810 -0
  119. package/dist/sdk/index.js +2 -2
  120. package/dist/sdk/index.mjs +2 -2
  121. package/dist/security-C-5URby1.js +73 -0
  122. package/dist/security-_xve79aq.js +4 -0
  123. package/dist/server-0kgyELx4.js +1047 -0
  124. package/dist/server-BIuTobTC.js +4 -0
  125. package/dist/server-BRlCEjyT.js +1047 -0
  126. package/dist/server-CCI1hv45.js +1047 -0
  127. package/dist/server-DU9POoWc.js +4 -0
  128. package/dist/server-RBqwE_GN.js +4 -0
  129. package/dist/session-store-CujxByI6.js +113 -0
  130. package/dist/session-store-qpJUg2M1.js +5 -0
  131. package/dist/sessions-tools-CB2qbwIk.js +5 -0
  132. package/dist/sessions-tools-DHMaTZIs.js +95 -0
  133. package/dist/skill-loader-BkceKkIg.js +7 -0
  134. package/dist/skill-loader-DhgIwK4J.js +159 -0
  135. package/dist/skill-runtime--LqxWrp5.js +102 -0
  136. package/dist/skill-runtime-C5l0Tgt-.js +5 -0
  137. package/dist/skill-runtime-DsXK_HYG.js +102 -0
  138. package/dist/skill-runtime-IVTiqrMR.js +5 -0
  139. package/dist/src-BEVLgaF1.js +63 -0
  140. package/dist/src-Bgu_OxTQ.js +458 -0
  141. package/dist/src-Bq-oKt7Z.js +458 -0
  142. package/dist/src-DWCUhnD4.js +20 -0
  143. package/dist/src-cfRTjFef.js +63 -0
  144. package/dist/sub-agent-tools-BD9DF8_g.js +39 -0
  145. package/dist/sub-agent-tools-V7b3T9_s.js +39 -0
  146. package/dist/tool-policy-DNvNRnve.js +189 -0
  147. package/dist/tts-elevenlabs-BUOGKL-k.js +61 -0
  148. package/dist/update-check-BD4qH7Am.js +81 -0
  149. package/dist/vision-DRq-f-Dj.js +121 -0
  150. package/dist/vision-tools-CFZEpQKm.js +5 -0
  151. package/dist/vision-tools-CQnBI9aa.js +51 -0
  152. package/dist/voice-transcription-CbQBToY0.js +138 -0
  153. package/dist/voice-transcription-CgWq54hn.js +138 -0
  154. package/dist/website-watch-tools-Bk_TnwuE.js +5 -0
  155. package/dist/website-watch-tools-DraMPxdl.js +139 -0
  156. package/package.json +1 -1
@@ -0,0 +1,1047 @@
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 crypto = require_chunk.__toESM(require("crypto"));
6
+ const child_process = require_chunk.__toESM(require("child_process"));
7
+ const http = require_chunk.__toESM(require("http"));
8
+ const ws = require_chunk.__toESM(require("ws"));
9
+
10
+ //#region packages/gateway/src/server.ts
11
+ let activeServer = null;
12
+ var GatewayServer = class {
13
+ wss = null;
14
+ httpServer = null;
15
+ sessions = /* @__PURE__ */ new Map();
16
+ transcripts = /* @__PURE__ */ new Map();
17
+ sessionStore = null;
18
+ config;
19
+ startedAt = "";
20
+ stopCron = null;
21
+ channelRunner = null;
22
+ constructor(config) {
23
+ this.config = config;
24
+ }
25
+ async start() {
26
+ this.httpServer = http.default.createServer((req, res) => {
27
+ this.handleHttp(req, res);
28
+ });
29
+ this.wss = new ws.WebSocketServer({ server: this.httpServer });
30
+ this.wss.on("connection", this.handleConnection.bind(this));
31
+ await new Promise((resolve, reject) => {
32
+ this.httpServer.listen(this.config.port, this.config.bind, () => resolve());
33
+ this.httpServer.on("error", reject);
34
+ });
35
+ this.startedAt = (/* @__PURE__ */ new Date()).toISOString();
36
+ activeServer = this;
37
+ try {
38
+ this.sessionStore = await this.config.deps.createSessionStore(this.config.deps.getHyperClawDir());
39
+ } catch (_) {
40
+ this.sessionStore = null;
41
+ }
42
+ const icon = this.config.daemonMode ? "🩸" : "🦅";
43
+ const color = this.config.daemonMode ? chalk.default.red.bind(chalk.default) : chalk.default.hex("#06b6d4");
44
+ console.log(color(`\n ${icon} Gateway started: ws://${this.config.bind}:${this.config.port}\n`));
45
+ this.channelRunner = await this.config.deps.startChannelRunners({
46
+ port: this.config.port,
47
+ bind: this.config.bind,
48
+ authToken: this.config.deps.resolveGatewayToken(this.config.authToken)
49
+ });
50
+ if (this.config.hooks && this.config.deps.createHookLoader) {
51
+ const loader = this.config.deps.createHookLoader();
52
+ loader.execute("gateway:start", {}).catch(() => {});
53
+ this.stopCron = loader.startCronScheduler();
54
+ }
55
+ }
56
+ async stop() {
57
+ if (this.channelRunner) {
58
+ await this.channelRunner.stop();
59
+ this.channelRunner = null;
60
+ }
61
+ if (this.stopCron) {
62
+ this.stopCron();
63
+ this.stopCron = null;
64
+ }
65
+ for (const s of this.sessions.values()) s.socket.close(1001, "Gateway shutting down");
66
+ this.sessions.clear();
67
+ this.wss?.close();
68
+ await new Promise((resolve) => this.httpServer?.close(() => resolve()));
69
+ activeServer = null;
70
+ }
71
+ /** Returns false and sends 401 if auth required but missing/invalid. */
72
+ async requireAuth(req, res) {
73
+ const token = this.config.deps.resolveGatewayToken(this.config.authToken);
74
+ const auth = req.headers.authorization;
75
+ if (!token && !auth) return true;
76
+ if (!auth || !auth.startsWith("Bearer ")) {
77
+ res.writeHead(401, { "Content-Type": "application/json" });
78
+ res.end(JSON.stringify({
79
+ error: "Unauthorized",
80
+ hint: "Authorization: Bearer <gateway_token_or_developer_key>"
81
+ }));
82
+ return false;
83
+ }
84
+ const bearer = auth.slice(7);
85
+ if (token && bearer === token) return true;
86
+ if (this.config.deps.validateApiAuth) {
87
+ const ok = await this.config.deps.validateApiAuth(bearer);
88
+ if (ok) return true;
89
+ }
90
+ res.writeHead(401, { "Content-Type": "application/json" });
91
+ res.end(JSON.stringify({
92
+ error: "Unauthorized",
93
+ hint: "Authorization: Bearer <gateway_token_or_developer_key>"
94
+ }));
95
+ return false;
96
+ }
97
+ async handleHttp(req, res) {
98
+ const url = (req.url || "/").split("?")[0];
99
+ res.setHeader("Access-Control-Allow-Origin", "*");
100
+ res.setHeader("Content-Type", "application/json");
101
+ if (req.method === "OPTIONS") {
102
+ res.writeHead(204);
103
+ res.end();
104
+ return;
105
+ }
106
+ if (url === "/api/v1/check") {
107
+ res.writeHead(200);
108
+ res.end(JSON.stringify({
109
+ ok: true,
110
+ service: "hyperclaw",
111
+ version: "4.0.2"
112
+ }));
113
+ return;
114
+ }
115
+ if (url === "/api/v1/pi" && req.method === "POST") {
116
+ if (!await this.requireAuth(req, res)) return;
117
+ let body = "";
118
+ req.on("data", (c) => body += c);
119
+ req.on("end", async () => {
120
+ try {
121
+ const handler = this.config.deps.createPiRPCHandler((msg, opts) => this.callAgent(msg, {
122
+ currentSessionId: opts?.currentSessionId,
123
+ source: opts?.source
124
+ }), () => this.getSessionsList());
125
+ const rpcReq = JSON.parse(body || "{}");
126
+ const rpcRes = await handler(rpcReq);
127
+ res.writeHead(200);
128
+ res.end(JSON.stringify(rpcRes));
129
+ } catch (e) {
130
+ res.writeHead(500);
131
+ res.end(JSON.stringify({
132
+ jsonrpc: "2.0",
133
+ error: {
134
+ code: -32700,
135
+ message: e.message || "Parse error"
136
+ }
137
+ }));
138
+ }
139
+ });
140
+ return;
141
+ }
142
+ if (url === "/api/status") {
143
+ const cfg = this.loadConfig();
144
+ res.writeHead(200);
145
+ res.end(JSON.stringify({
146
+ running: true,
147
+ port: this.config.port,
148
+ channels: this.config.enabledChannels,
149
+ model: cfg?.provider?.modelId || "unknown",
150
+ agentName: cfg?.identity?.agentName || "Hyper",
151
+ sessions: this.sessions.size,
152
+ uptime: this.startedAt ? `${Math.round((Date.now() - new Date(this.startedAt).getTime()) / 1e3)}s` : "0s"
153
+ }));
154
+ return;
155
+ }
156
+ if (url === "/api/traces" && req.method === "GET") {
157
+ if (!await this.requireAuth(req, res)) return;
158
+ (async () => {
159
+ const params = new URL(req.url || "", "http://localhost").searchParams;
160
+ const limit = Math.min(100, parseInt(params.get("limit") || "50", 10) || 50);
161
+ try {
162
+ const traces = this.config.deps.listTraces ? await this.config.deps.listTraces(this.config.deps.getHyperClawDir(), limit) : [];
163
+ res.writeHead(200);
164
+ res.end(JSON.stringify({ traces }));
165
+ } catch {
166
+ res.writeHead(500);
167
+ res.end(JSON.stringify({ error: "Failed to list traces" }));
168
+ }
169
+ })();
170
+ return;
171
+ }
172
+ if (url === "/api/costs" && req.method === "GET") {
173
+ if (!await this.requireAuth(req, res)) return;
174
+ (async () => {
175
+ const params = new URL(req.url || "", "http://localhost").searchParams;
176
+ const sessionId = params.get("sessionId");
177
+ const hcDir = this.config.deps.getHyperClawDir();
178
+ try {
179
+ if (sessionId && this.config.deps.getSessionSummary) {
180
+ const summary = await this.config.deps.getSessionSummary(hcDir, sessionId);
181
+ res.writeHead(200);
182
+ res.end(JSON.stringify({
183
+ sessionId,
184
+ summary
185
+ }));
186
+ } else if (this.config.deps.getGlobalSummary) {
187
+ const summary = await this.config.deps.getGlobalSummary(this.config.deps.getHyperClawDir());
188
+ res.writeHead(200);
189
+ res.end(JSON.stringify({ summary }));
190
+ }
191
+ } catch (e) {
192
+ res.writeHead(500);
193
+ res.end(JSON.stringify({ error: e.message }));
194
+ }
195
+ })();
196
+ return;
197
+ }
198
+ if (url === "/api/remote/restart" && req.method === "POST") {
199
+ const auth = req.headers.authorization;
200
+ const token = this.config.deps.resolveGatewayToken(this.config.authToken);
201
+ if (token && auth !== `Bearer ${token}`) {
202
+ res.writeHead(401);
203
+ res.end(JSON.stringify({ error: "Unauthorized" }));
204
+ return;
205
+ }
206
+ (async () => {
207
+ const hcDir = this.config.deps.getHyperClawDir();
208
+ const pidFile = path.default.join(hcDir, "gateway.pid");
209
+ let didSpawn = false;
210
+ try {
211
+ if (await fs_extra.default.pathExists(pidFile)) {
212
+ const storedPid = parseInt(await fs_extra.default.readFile(pidFile, "utf8"), 10);
213
+ if (storedPid === process.pid && this.config.daemonMode) {
214
+ const runMainPath = this.config.deps.getRunMainPath?.() || process.argv[1] || require.main?.filename || path.default.resolve(process.cwd(), "dist/run-main.js");
215
+ const child = (0, child_process.spawn)(process.execPath, [
216
+ runMainPath,
217
+ "daemon",
218
+ "restart"
219
+ ], {
220
+ detached: true,
221
+ stdio: "ignore",
222
+ env: process.env,
223
+ cwd: process.cwd()
224
+ });
225
+ child.unref();
226
+ didSpawn = true;
227
+ }
228
+ }
229
+ } catch {}
230
+ res.writeHead(200);
231
+ res.end(JSON.stringify({
232
+ accepted: true,
233
+ message: didSpawn ? "Restarting daemon..." : "Gateway does not run as daemon. Run: hyperclaw daemon start, or from remote: ssh user@host \"hyperclaw daemon restart\"",
234
+ restarted: didSpawn
235
+ }));
236
+ })();
237
+ return;
238
+ }
239
+ if (url === "/api/v1/tts" && req.method === "POST") {
240
+ if (!await this.requireAuth(req, res)) return;
241
+ let body = "";
242
+ req.on("data", (c) => body += c);
243
+ req.on("end", async () => {
244
+ try {
245
+ const { text } = JSON.parse(body || "{}");
246
+ const cfg = this.loadConfig();
247
+ const apiKey = cfg?.talkMode?.apiKey || process.env.ELEVENLABS_API_KEY;
248
+ if (!apiKey || !text) {
249
+ res.writeHead(400);
250
+ res.end(JSON.stringify({ error: "Missing text or ELEVENLABS_API_KEY" }));
251
+ return;
252
+ }
253
+ const audio = this.config.deps.textToSpeech ? await this.config.deps.textToSpeech(text.slice(0, 4e3), {
254
+ apiKey,
255
+ voiceId: cfg?.talkMode?.voiceId,
256
+ modelId: cfg?.talkMode?.modelId
257
+ }) : null;
258
+ if (!audio) {
259
+ res.writeHead(502);
260
+ res.end(JSON.stringify({ error: "TTS failed" }));
261
+ return;
262
+ }
263
+ res.writeHead(200, { "Content-Type": "application/json" });
264
+ res.end(JSON.stringify({
265
+ format: "mp3",
266
+ data: audio
267
+ }));
268
+ } catch (e) {
269
+ res.writeHead(500);
270
+ res.end(JSON.stringify({ error: e.message }));
271
+ }
272
+ });
273
+ return;
274
+ }
275
+ if (url === "/api/nodes" && req.method === "GET") {
276
+ if (!await this.requireAuth(req, res)) return;
277
+ try {
278
+ const NR = this.config.deps.NodeRegistry;
279
+ const nodes = NR ? NR.getNodes().map((n) => ({
280
+ nodeId: n.nodeId,
281
+ platform: n.platform,
282
+ capabilities: n.capabilities,
283
+ deviceName: n.deviceName,
284
+ connectedAt: n.connectedAt,
285
+ lastSeenAt: n.lastSeenAt
286
+ })) : [];
287
+ res.writeHead(200);
288
+ res.end(JSON.stringify({ nodes }));
289
+ } catch (e) {
290
+ res.writeHead(500);
291
+ res.end(JSON.stringify({ error: e.message }));
292
+ }
293
+ return;
294
+ }
295
+ if (url === "/api/chat" && req.method === "POST") {
296
+ if (!await this.requireAuth(req, res)) return;
297
+ let body = "";
298
+ req.on("data", (c) => body += c);
299
+ req.on("end", async () => {
300
+ try {
301
+ const { message } = JSON.parse(body);
302
+ const source = req.headers["x-hyperclaw-source"] || "unknown";
303
+ const response = await this.callAgent(message, { source });
304
+ res.writeHead(200);
305
+ res.end(JSON.stringify({ response }));
306
+ } catch (e) {
307
+ res.writeHead(500);
308
+ res.end(JSON.stringify({ error: e.message }));
309
+ }
310
+ });
311
+ return;
312
+ }
313
+ if (url === "/api/webhook/inbound" && req.method === "POST") {
314
+ if (!await this.requireAuth(req, res)) return;
315
+ let body = "";
316
+ req.on("data", (c) => body += c);
317
+ req.on("end", async () => {
318
+ try {
319
+ const parsed = typeof body === "string" ? JSON.parse(body || "{}") : {};
320
+ const message = parsed.message || parsed.text || parsed.prompt || String(parsed);
321
+ if (!message || typeof message !== "string") {
322
+ res.writeHead(400);
323
+ res.end(JSON.stringify({ error: "Body must include \"message\" or \"text\" or \"prompt\"" }));
324
+ return;
325
+ }
326
+ const response = await this.callAgent(message, { source: "webhook:inbound" });
327
+ res.writeHead(200);
328
+ res.end(JSON.stringify({
329
+ ok: true,
330
+ response
331
+ }));
332
+ } catch (e) {
333
+ res.writeHead(500);
334
+ res.end(JSON.stringify({ error: e.message }));
335
+ }
336
+ });
337
+ return;
338
+ }
339
+ if (url === "/api/canvas/state" && req.method === "GET") {
340
+ if (!await this.requireAuth(req, res)) return;
341
+ const getState = this.config.deps.getCanvasState;
342
+ if (getState) getState().then((canvas) => {
343
+ res.writeHead(200, { "Content-Type": "application/json" });
344
+ res.end(JSON.stringify(canvas));
345
+ }).catch((e) => {
346
+ res.writeHead(500);
347
+ res.end(JSON.stringify({ error: e.message }));
348
+ });
349
+ else Promise.resolve().then(() => require("./renderer-CN8ePGog.js")).then(({ CanvasRenderer }) => {
350
+ const renderer = new CanvasRenderer();
351
+ renderer.getOrCreate().then((canvas) => {
352
+ res.writeHead(200, { "Content-Type": "application/json" });
353
+ res.end(JSON.stringify(canvas));
354
+ }).catch((e) => {
355
+ res.writeHead(500);
356
+ res.end(JSON.stringify({ error: e.message }));
357
+ });
358
+ }).catch((e) => {
359
+ res.writeHead(500);
360
+ res.end(JSON.stringify({ error: e.message }));
361
+ });
362
+ return;
363
+ }
364
+ if (url === "/api/canvas/a2ui" && req.method === "GET") {
365
+ if (!await this.requireAuth(req, res)) return;
366
+ const getA2UI = this.config.deps.getCanvasA2UI;
367
+ if (getA2UI) getA2UI().then((jsonl) => {
368
+ res.setHeader("Content-Type", "application/x-ndjson");
369
+ res.setHeader("Cache-Control", "no-cache");
370
+ res.writeHead(200);
371
+ res.end(jsonl + "\n");
372
+ }).catch((e) => {
373
+ res.writeHead(500);
374
+ res.end(JSON.stringify({ error: e.message }));
375
+ });
376
+ else Promise.resolve().then(() => require("./renderer-CN8ePGog.js")).then(({ CanvasRenderer }) => {
377
+ Promise.resolve().then(() => require("./a2ui-protocol-Bw1wBBXC.js")).then(({ toBeginRendering, toJSONL }) => {
378
+ const renderer = new CanvasRenderer();
379
+ renderer.getOrCreate().then((canvas) => {
380
+ const msg = toBeginRendering(canvas);
381
+ res.setHeader("Content-Type", "application/x-ndjson");
382
+ res.setHeader("Cache-Control", "no-cache");
383
+ res.writeHead(200);
384
+ res.end(toJSONL([msg]) + "\n");
385
+ }).catch((e) => {
386
+ res.writeHead(500);
387
+ res.end(JSON.stringify({ error: e.message }));
388
+ });
389
+ });
390
+ }).catch((e) => {
391
+ res.writeHead(500);
392
+ res.end(JSON.stringify({ error: e.message }));
393
+ });
394
+ return;
395
+ }
396
+ if (url === "/chat" || url === "/chat/") {
397
+ res.setHeader("Content-Type", "text/html");
398
+ const fp = path.default.join(process.cwd(), "static", "chat.html");
399
+ if (fs_extra.default.pathExistsSync(fp)) res.end(fs_extra.default.readFileSync(fp, "utf8"));
400
+ else res.end("<!DOCTYPE html><html><body><p>Chat UI: <a href=\"/\">apps/web</a></p></body></html>");
401
+ return;
402
+ }
403
+ if (url === "/dashboard" || url === "/dashboard/") {
404
+ res.setHeader("Content-Type", "text/html");
405
+ const fp = path.default.join(process.cwd(), "static", "dashboard.html");
406
+ if (fs_extra.default.pathExistsSync(fp)) res.end(fs_extra.default.readFileSync(fp, "utf8"));
407
+ else res.end("<!DOCTYPE html><html><body><p>Dashboard: <a href=\"/api/status\">status</a></p></body></html>");
408
+ return;
409
+ }
410
+ if (url === "/" || url === "") {
411
+ res.writeHead(302, { Location: "/dashboard" });
412
+ res.end();
413
+ return;
414
+ }
415
+ if (url.startsWith("/webhook/")) {
416
+ const channelId = url.split("/")[2];
417
+ if (req.method === "GET") {
418
+ const params = new URL(url, "http://x").searchParams;
419
+ if (channelId === "twitter") {
420
+ const crcToken = params.get("crc_token");
421
+ if (crcToken) {
422
+ const verified$1 = this.channelRunner?.verifyWebhook?.(channelId, "crc", crcToken, "");
423
+ if (verified$1) {
424
+ res.writeHead(200, { "Content-Type": "application/json" });
425
+ res.end(verified$1);
426
+ return;
427
+ }
428
+ }
429
+ }
430
+ const mode = params.get("hub.mode") || "";
431
+ const token = params.get("hub.verify_token") || "";
432
+ const challenge = params.get("hub.challenge") || "";
433
+ const verified = this.channelRunner?.verifyWebhook?.(channelId, mode, token, challenge);
434
+ if (verified !== null && verified !== void 0) {
435
+ res.writeHead(200, { "Content-Type": "text/plain" });
436
+ res.end(verified);
437
+ } else {
438
+ res.writeHead(200);
439
+ res.end(JSON.stringify({ ok: true }));
440
+ }
441
+ return;
442
+ }
443
+ if (req.method === "POST") {
444
+ let body = "";
445
+ req.on("data", (c) => body += c);
446
+ req.on("end", async () => {
447
+ const host = req.headers["host"] || "localhost";
448
+ const baseUrl = `${req.headers["x-forwarded-proto"] === "https" ? "https" : "http"}://${host}`;
449
+ let opts;
450
+ if (channelId === "slack") opts = {
451
+ signature: req.headers["x-slack-signature"] || "",
452
+ timestamp: req.headers["x-slack-request-timestamp"] || ""
453
+ };
454
+ else if (channelId === "line") opts = { signature: req.headers["x-line-signature"] || "" };
455
+ else if (channelId === "sms") opts = {
456
+ twilioSignature: req.headers["x-twilio-signature"] || "",
457
+ webhookUrl: `${baseUrl}${req.url}`
458
+ };
459
+ else if (channelId === "instagram" || channelId === "messenger") opts = { signature: req.headers["x-hub-signature-256"] || "" };
460
+ else if (channelId === "viber") opts = { signature: req.headers["x-viber-signature"] || "" };
461
+ let challenge = void 0;
462
+ if (this.channelRunner?.handleWebhook) challenge = await this.channelRunner.handleWebhook(channelId, body, opts).catch(() => void 0);
463
+ this.broadcast({
464
+ type: "webhook:received",
465
+ channelId,
466
+ payload: body
467
+ });
468
+ if (typeof challenge === "string") {
469
+ const contentType = challenge.trim().startsWith("{") ? "application/json" : "text/plain";
470
+ res.writeHead(200, { "Content-Type": contentType });
471
+ res.end(challenge);
472
+ } else {
473
+ res.writeHead(200);
474
+ res.end(JSON.stringify({ ok: true }));
475
+ }
476
+ });
477
+ return;
478
+ }
479
+ }
480
+ res.writeHead(404);
481
+ res.end(JSON.stringify({ error: "Not found" }));
482
+ }
483
+ handleConnection(ws$1, req) {
484
+ const id = crypto.default.randomBytes(8).toString("hex");
485
+ const source = req.headers["x-hyperclaw-source"] || "unknown";
486
+ const authToken = this.config.deps.resolveGatewayToken(this.config.authToken);
487
+ const session = {
488
+ id,
489
+ socket: ws$1,
490
+ authenticated: !authToken,
491
+ source,
492
+ connectedAt: (/* @__PURE__ */ new Date()).toISOString(),
493
+ lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
494
+ };
495
+ this.sessions.set(id, session);
496
+ this.broadcast({
497
+ type: "presence:join",
498
+ sessionId: id,
499
+ source
500
+ }, id);
501
+ console.log(chalk.default.gray(` [gateway] +connect ${source} ${id}`));
502
+ if (authToken && !session.authenticated) this.send(session, {
503
+ type: "connect.challenge",
504
+ sessionId: id
505
+ });
506
+ else {
507
+ this.send(session, {
508
+ type: "connect.ok",
509
+ sessionId: id,
510
+ version: "4.0.2",
511
+ heartbeatInterval: 3e4
512
+ });
513
+ if (this.config.hooks && this.config.deps.createHookLoader) this.config.deps.createHookLoader().execute("session:start", { sessionId: id }).catch(() => {});
514
+ }
515
+ ws$1.on("message", (data) => {
516
+ session.lastActiveAt = (/* @__PURE__ */ new Date()).toISOString();
517
+ try {
518
+ this.handleMessage(session, JSON.parse(data.toString()));
519
+ } catch {
520
+ this.send(session, {
521
+ type: "error",
522
+ message: "Invalid JSON"
523
+ });
524
+ }
525
+ });
526
+ ws$1.on("close", () => {
527
+ const s = this.sessions.get(id);
528
+ if (s?.nodeId && this.config.deps.NodeRegistry) {
529
+ this.config.deps.NodeRegistry.unregister(s.nodeId);
530
+ console.log(chalk.default.gray(` [gateway] -node ${s.nodeId}`));
531
+ }
532
+ if (this.config.hooks && !s?.nodeId && this.config.deps.createHookLoader) {
533
+ const turnCount = this.transcripts.get(id)?.length ?? 0;
534
+ this.config.deps.createHookLoader().execute("session:end", {
535
+ sessionId: id,
536
+ turnCount
537
+ }).catch(() => {});
538
+ }
539
+ this.transcripts.delete(id);
540
+ this.sessions.delete(id);
541
+ this.broadcast({
542
+ type: "presence:leave",
543
+ sessionId: id
544
+ });
545
+ console.log(chalk.default.gray(` [gateway] -disconnect ${id}`));
546
+ });
547
+ ws$1.on("error", (e) => console.log(chalk.default.yellow(` [gateway] error ${id}: ${e.message}`)));
548
+ }
549
+ handleMessage(session, msg) {
550
+ if (msg.type === "node_register") {
551
+ const nodeId = msg.nodeId || `node-${session.id}`;
552
+ const platform = msg.platform === "ios" || msg.platform === "android" ? msg.platform : "ios";
553
+ const capabilities = msg.capabilities || {};
554
+ const authToken = this.config.deps.resolveGatewayToken(this.config.authToken);
555
+ if (authToken && msg.token !== authToken) {
556
+ this.send(session, {
557
+ type: "node:error",
558
+ message: "Invalid token"
559
+ });
560
+ session.socket.close(4001, "Unauthorized");
561
+ return;
562
+ }
563
+ const NR = this.config.deps.NodeRegistry;
564
+ if (!NR) {
565
+ this.send(session, {
566
+ type: "node:error",
567
+ message: "Node registry not available"
568
+ });
569
+ return;
570
+ }
571
+ const cmdIdToResolve = /* @__PURE__ */ new Map();
572
+ session._nodePending = cmdIdToResolve;
573
+ const node = {
574
+ nodeId,
575
+ platform,
576
+ capabilities,
577
+ deviceName: msg.deviceName,
578
+ connectedAt: (/* @__PURE__ */ new Date()).toISOString(),
579
+ lastSeenAt: (/* @__PURE__ */ new Date()).toISOString(),
580
+ send: async (cmd) => {
581
+ return new Promise((resolve) => {
582
+ const timeout = setTimeout(() => {
583
+ cmdIdToResolve.delete(cmd.id);
584
+ resolve({
585
+ ok: false,
586
+ error: "Timeout"
587
+ });
588
+ }, 3e4);
589
+ cmdIdToResolve.set(cmd.id, { resolve: (r) => {
590
+ clearTimeout(timeout);
591
+ resolve(r);
592
+ } });
593
+ this.send(session, {
594
+ type: "node:command",
595
+ id: cmd.id,
596
+ command: cmd.type,
597
+ params: cmd.params
598
+ });
599
+ });
600
+ }
601
+ };
602
+ const protocolVersion = msg.protocolVersion ?? 1;
603
+ NR.register(node);
604
+ session.nodeId = nodeId;
605
+ session.authenticated = true;
606
+ session.source = `node:${platform}`;
607
+ this.send(session, {
608
+ type: "node:registered",
609
+ nodeId,
610
+ sessionId: session.id,
611
+ protocolVersion: Math.min(protocolVersion, 2),
612
+ heartbeatInterval: 3e4,
613
+ capabilities: Object.keys(capabilities)
614
+ });
615
+ console.log(chalk.default.gray(` [gateway] +node ${nodeId} (${platform})`));
616
+ return;
617
+ }
618
+ if (msg.type === "node:unregister" && session.nodeId && this.config.deps.NodeRegistry) {
619
+ this.config.deps.NodeRegistry.unregister(session.nodeId);
620
+ session.nodeId = void 0;
621
+ this.send(session, { type: "node:unregistered" });
622
+ return;
623
+ }
624
+ if (msg.type === "node:command_response" && session._nodePending) {
625
+ const r = session._nodePending.get(msg.id);
626
+ if (r) {
627
+ session._nodePending.delete(msg.id);
628
+ r.resolve({
629
+ ok: msg.ok,
630
+ data: msg.data,
631
+ error: msg.error
632
+ });
633
+ }
634
+ return;
635
+ }
636
+ if (msg.type === "session:restore" && (msg.restoreKey ?? msg.previousSessionId)) {
637
+ const key = String(msg.restoreKey ?? msg.previousSessionId);
638
+ session.restoreKey = key;
639
+ if (this.sessionStore) this.sessionStore.get(key).then((state) => {
640
+ if (state?.transcript?.length) {
641
+ const arr = this.transcripts.get(session.id) || [];
642
+ for (const t of state.transcript) if (!arr.some((x) => x.role === t.role && x.content === t.content)) arr.push(t);
643
+ if (arr.length > 100) arr.splice(0, arr.length - 80);
644
+ this.transcripts.set(session.id, arr);
645
+ this.send(session, {
646
+ type: "session:restored",
647
+ transcript: state.transcript
648
+ });
649
+ }
650
+ }).catch(() => {});
651
+ return;
652
+ }
653
+ if (msg.type === "auth") {
654
+ const resolved = this.config.deps.resolveGatewayToken(this.config.authToken);
655
+ if (resolved && msg.token === resolved) {
656
+ session.authenticated = true;
657
+ this.send(session, {
658
+ type: "auth.ok",
659
+ sessionId: session.id
660
+ });
661
+ } else session.socket.close(4001, "Unauthorized");
662
+ return;
663
+ }
664
+ if (!session.authenticated) {
665
+ this.send(session, {
666
+ type: "error",
667
+ message: "Not authenticated"
668
+ });
669
+ return;
670
+ }
671
+ switch (msg.type) {
672
+ case "ping": {
673
+ if (session.nodeId && this.config.deps.NodeRegistry) this.config.deps.NodeRegistry.updateLastSeen?.(session.nodeId);
674
+ this.send(session, {
675
+ type: "pong",
676
+ ts: Date.now()
677
+ });
678
+ break;
679
+ }
680
+ case "talk:enable":
681
+ session.talkMode = true;
682
+ this.send(session, {
683
+ type: "talk:ok",
684
+ enabled: true
685
+ });
686
+ break;
687
+ case "talk:disable":
688
+ session.talkMode = false;
689
+ this.send(session, {
690
+ type: "talk:ok",
691
+ enabled: false
692
+ });
693
+ break;
694
+ case "elevated:enable": {
695
+ const cfg = this.loadConfig();
696
+ const allowFrom = (cfg?.tools?.elevated)?.allowFrom ?? [];
697
+ const enabled = (cfg?.tools?.elevated)?.enabled === true;
698
+ if (!enabled) {
699
+ this.send(session, {
700
+ type: "error",
701
+ message: "Elevated mode disabled in config"
702
+ });
703
+ break;
704
+ }
705
+ if (allowFrom.length && !allowFrom.includes(session.source) && !allowFrom.includes("*")) {
706
+ this.send(session, {
707
+ type: "error",
708
+ message: "Source not in elevated allowFrom"
709
+ });
710
+ break;
711
+ }
712
+ session.elevated = true;
713
+ this.send(session, {
714
+ type: "elevated:ok",
715
+ enabled: true
716
+ });
717
+ break;
718
+ }
719
+ case "elevated:disable":
720
+ session.elevated = false;
721
+ this.send(session, {
722
+ type: "elevated:ok",
723
+ enabled: false
724
+ });
725
+ break;
726
+ case "chat:message": {
727
+ const content = typeof msg.content === "string" ? msg.content : String(msg.content ?? "");
728
+ if (this.config.hooks && this.config.deps.createHookLoader) this.config.deps.createHookLoader().execute("message:received", { sessionId: session.id }).catch(() => {});
729
+ const onDone = (response) => {
730
+ this.send(session, {
731
+ type: "chat:response",
732
+ content: response
733
+ });
734
+ if (session.talkMode && response) this.synthesizeAndSendAudio(session, response).catch(() => {});
735
+ if (this.config.hooks && this.config.deps.createHookLoader) this.config.deps.createHookLoader().execute("message:sent", {
736
+ sessionId: session.id,
737
+ message: content,
738
+ response
739
+ }).catch(() => {});
740
+ };
741
+ this.callAgent(content, {
742
+ currentSessionId: session.id,
743
+ onToken: (token) => this.send(session, {
744
+ type: "chat:chunk",
745
+ content: token
746
+ }),
747
+ onDone
748
+ }).catch((e) => this.send(session, {
749
+ type: "chat:response",
750
+ content: `Error: ${e.message}`
751
+ }));
752
+ break;
753
+ }
754
+ case "gateway:status":
755
+ this.send(session, {
756
+ type: "gateway:status",
757
+ sessions: this.sessions.size,
758
+ uptime: this.startedAt
759
+ });
760
+ break;
761
+ case "presence:list":
762
+ this.send(session, {
763
+ type: "presence:list",
764
+ sessions: Array.from(this.sessions.entries()).map(([sid, s]) => ({
765
+ id: sid,
766
+ source: s.source
767
+ }))
768
+ });
769
+ break;
770
+ case "config:get":
771
+ this.send(session, {
772
+ type: "config:data",
773
+ config: this.scrubConfig(this.loadConfig())
774
+ });
775
+ break;
776
+ }
777
+ }
778
+ async callAgent(message, opts) {
779
+ const sid = opts?.currentSessionId;
780
+ const sess = sid ? this.sessions.get(sid) : void 0;
781
+ const confirmTriggers = [
782
+ "confirm",
783
+ "yes",
784
+ "ok",
785
+ "elevate"
786
+ ];
787
+ if (sid && confirmTriggers.includes(message.trim().toLowerCase())) {
788
+ const getPending = this.config.deps.getPending;
789
+ const clearPending = this.config.deps.clearPending;
790
+ if (getPending && clearPending) {
791
+ const pending = getPending(sid);
792
+ if (pending) {
793
+ clearPending(sid);
794
+ try {
795
+ const result$1 = await pending.execute();
796
+ opts?.onDone?.(result$1);
797
+ return result$1;
798
+ } catch (e) {
799
+ const err = `Error: ${e.message}`;
800
+ opts?.onDone?.(err);
801
+ return err;
802
+ }
803
+ }
804
+ }
805
+ }
806
+ const cfg = this.loadConfig();
807
+ const elevated = sess?.elevated && (cfg?.tools?.elevated)?.enabled === true;
808
+ const source = opts?.source || sess?.source;
809
+ const hcDir = this.config.deps.getHyperClawDir();
810
+ const runOpts = {
811
+ sessionId: sid,
812
+ source,
813
+ elevated,
814
+ onToken: opts?.onToken,
815
+ onDone: opts?.onDone,
816
+ daemonMode: this.config.daemonMode,
817
+ appendTranscript: (s, role, content) => this.appendTranscript(s, role, content),
818
+ activeServer: activeServer ?? this
819
+ };
820
+ if ((cfg?.observability)?.traces && this.config.deps.createRunTracer && this.config.deps.writeTraceToFile) {
821
+ const tracer = this.config.deps.createRunTracer(sid, source);
822
+ runOpts.onToolCall = tracer.onToolCall;
823
+ runOpts.onToolResult = tracer.onToolResult;
824
+ runOpts.onRunEnd = (usage, err) => {
825
+ tracer.onRunEnd(usage, err);
826
+ this.config.deps.writeTraceToFile(hcDir, tracer.trace).catch(() => {});
827
+ };
828
+ }
829
+ const baseOnRunEnd = runOpts.onRunEnd;
830
+ const recordUsage = this.config.deps.recordUsage;
831
+ runOpts.onRunEnd = (usage, err) => {
832
+ baseOnRunEnd?.(usage, err);
833
+ if (sid && usage && recordUsage) recordUsage(hcDir, sid, usage, {
834
+ source,
835
+ model: cfg?.provider?.modelId ?? void 0
836
+ }).catch(() => {});
837
+ };
838
+ const result = await this.config.deps.runAgentEngine(message, runOpts);
839
+ return result.text;
840
+ }
841
+ appendTranscript(sessionId, role, content) {
842
+ let arr = this.transcripts.get(sessionId);
843
+ if (!arr) {
844
+ arr = [];
845
+ this.transcripts.set(sessionId, arr);
846
+ }
847
+ arr.push({
848
+ role,
849
+ content
850
+ });
851
+ if (arr.length > 100) arr.splice(0, arr.length - 80);
852
+ const sess = this.sessions.get(sessionId);
853
+ const storeKey = sess?.restoreKey || sessionId;
854
+ if (this.sessionStore) this.sessionStore.append(storeKey, role, content, sess?.source).catch(() => {});
855
+ }
856
+ getSessionsList() {
857
+ return Array.from(this.sessions.entries()).map(([id, s]) => ({
858
+ id,
859
+ source: s.source,
860
+ connectedAt: s.connectedAt
861
+ }));
862
+ }
863
+ sendToSession(sessionId, msg) {
864
+ const s = this.sessions.get(sessionId);
865
+ if (!s || s.socket.readyState !== ws.WebSocket.OPEN) return false;
866
+ this.send(s, msg);
867
+ return true;
868
+ }
869
+ getSessionHistory(sessionId, limit = 20) {
870
+ const arr = this.transcripts.get(sessionId) ?? [];
871
+ return arr.slice(-limit);
872
+ }
873
+ send(session, msg) {
874
+ if (session.socket.readyState === ws.WebSocket.OPEN) session.socket.send(JSON.stringify(msg));
875
+ }
876
+ broadcast(msg, excludeId) {
877
+ for (const [id, s] of this.sessions) if (id !== excludeId && s.authenticated) this.send(s, msg);
878
+ }
879
+ async synthesizeAndSendAudio(session, text) {
880
+ const cfg = this.loadConfig();
881
+ const talk = cfg?.talkMode;
882
+ const apiKey = talk?.apiKey || process.env.ELEVENLABS_API_KEY;
883
+ if (!apiKey) return;
884
+ const textToSpeech = this.config.deps.textToSpeech;
885
+ if (!textToSpeech) return;
886
+ const audio = await textToSpeech(text.slice(0, 4e3), {
887
+ apiKey,
888
+ voiceId: talk?.voiceId,
889
+ modelId: talk?.modelId || "eleven_multilingual_v2"
890
+ });
891
+ if (audio) this.send(session, {
892
+ type: "chat:audio",
893
+ format: "mp3",
894
+ data: audio
895
+ });
896
+ }
897
+ loadConfig() {
898
+ if (this.config.deps.loadConfig) return this.config.deps.loadConfig();
899
+ try {
900
+ return fs_extra.default.readJsonSync(this.config.deps.getConfigPath());
901
+ } catch {
902
+ return null;
903
+ }
904
+ }
905
+ scrubConfig(cfg) {
906
+ if (!cfg) return null;
907
+ const s = JSON.parse(JSON.stringify(cfg));
908
+ if (s.provider?.apiKey) s.provider.apiKey = "***";
909
+ if (s.gateway?.authToken) s.gateway.authToken = "***";
910
+ return s;
911
+ }
912
+ getStatus() {
913
+ return {
914
+ running: true,
915
+ port: this.config.port,
916
+ sessions: this.sessions.size,
917
+ startedAt: this.startedAt
918
+ };
919
+ }
920
+ };
921
+ const DEFAULT_PORT = 18789;
922
+ async function startGateway(opts) {
923
+ const deps = opts.deps;
924
+ let base;
925
+ try {
926
+ base = fs_extra.default.readJsonSync(deps.getConfigPath()).gateway;
927
+ } catch {
928
+ base = {
929
+ port: DEFAULT_PORT,
930
+ bind: "127.0.0.1",
931
+ authToken: "",
932
+ runtime: "node",
933
+ enabledChannels: [],
934
+ hooks: true
935
+ };
936
+ }
937
+ const portEnv = process.env.PORT || process.env.HYPERCLAW_PORT;
938
+ const port = portEnv ? parseInt(portEnv, 10) || base.port : base.port;
939
+ const cfg = {
940
+ ...base,
941
+ port: port ?? DEFAULT_PORT,
942
+ bind: base.bind ?? "127.0.0.1",
943
+ authToken: deps.resolveGatewayToken(base.authToken ?? "") ?? base.authToken ?? "",
944
+ runtime: base.runtime ?? "node",
945
+ enabledChannels: base.enabledChannels ?? [],
946
+ hooks: base.hooks ?? true,
947
+ daemonMode: opts.daemonMode,
948
+ deps
949
+ };
950
+ const server = new GatewayServer(cfg);
951
+ await server.start();
952
+ return server;
953
+ }
954
+ function getActiveServer() {
955
+ return activeServer;
956
+ }
957
+
958
+ //#endregion
959
+ //#region src/gateway/deps-provider.ts
960
+ async function createDefaultGatewayDeps() {
961
+ const [paths, envResolve, sessionStore, channelRunner, hookLoader, core, devKeys, pendingApproval, observability, costTracker, tts, nodesRegistry, canvasRenderer, a2ui] = await Promise.all([
962
+ Promise.resolve().then(() => require("./paths-D-QecARF.js")),
963
+ Promise.resolve().then(() => require("./env-resolve-BazAsaKp.js")),
964
+ Promise.resolve().then(() => require("./session-store-v82VTWbD.js")),
965
+ Promise.resolve().then(() => require("./runner-Bu--_RXw.js")),
966
+ Promise.resolve().then(() => require("./loader-aSIGRXBq.js")),
967
+ Promise.resolve().then(() => require("./src-BptR-54a.js")),
968
+ Promise.resolve().then(() => require("./developer-keys-DkZeQzV2.js")),
969
+ Promise.resolve().then(() => require("./pending-approval-Bdf11byB.js")),
970
+ Promise.resolve().then(() => require("./observability-CDaEJACJ.js")),
971
+ Promise.resolve().then(() => require("./cost-tracker-Bae6xRoO.js")),
972
+ Promise.resolve().then(() => require("./tts-elevenlabs-4stMe54k.js")),
973
+ Promise.resolve().then(() => require("./nodes-registry-Bkh_L-d2.js")),
974
+ Promise.resolve().then(() => require("./renderer-CN8ePGog.js")),
975
+ Promise.resolve().then(() => require("./a2ui-protocol-Bw1wBBXC.js"))
976
+ ]);
977
+ const createSessionStore = async (baseDir) => {
978
+ const store = await sessionStore.createFileSessionStore(baseDir);
979
+ return store;
980
+ };
981
+ const createHookLoader = () => new hookLoader.HookLoader();
982
+ const getCanvasState = async () => {
983
+ const renderer = new canvasRenderer.CanvasRenderer();
984
+ const canvas = await renderer.getOrCreate();
985
+ return canvas;
986
+ };
987
+ const getCanvasA2UI = async () => {
988
+ const renderer = new canvasRenderer.CanvasRenderer();
989
+ const canvas = await renderer.getOrCreate();
990
+ const msg = a2ui.toBeginRendering(canvas);
991
+ return a2ui.toJSONL([msg]);
992
+ };
993
+ return {
994
+ getHyperClawDir: paths.getHyperClawDir,
995
+ getConfigPath: paths.getConfigPath,
996
+ resolveGatewayToken: envResolve.resolveGatewayToken,
997
+ validateApiAuth: async (bearer) => (await devKeys.validateDeveloperKey(bearer)).valid,
998
+ createSessionStore,
999
+ startChannelRunners: channelRunner.startChannelRunners,
1000
+ createHookLoader,
1001
+ runAgentEngine: core.runAgentEngine,
1002
+ createPiRPCHandler: core.createPiRPCHandler,
1003
+ listTraces: observability.listTraces,
1004
+ getSessionSummary: costTracker.getSessionSummary,
1005
+ getGlobalSummary: costTracker.getGlobalSummary,
1006
+ recordUsage: costTracker.recordUsage,
1007
+ textToSpeech: tts.textToSpeech,
1008
+ getPending: pendingApproval.getPending,
1009
+ clearPending: pendingApproval.clearPending,
1010
+ createRunTracer: observability.createRunTracer,
1011
+ writeTraceToFile: observability.writeTraceToFile,
1012
+ NodeRegistry: nodesRegistry.NodeRegistry,
1013
+ getCanvasState,
1014
+ getCanvasA2UI
1015
+ };
1016
+ }
1017
+
1018
+ //#endregion
1019
+ //#region src/gateway/server.ts
1020
+ /** Start gateway with default deps (paths, channels, hooks, etc.). */
1021
+ async function startGateway$1(opts) {
1022
+ const deps = await createDefaultGatewayDeps();
1023
+ return startGateway({
1024
+ ...opts,
1025
+ deps
1026
+ });
1027
+ }
1028
+
1029
+ //#endregion
1030
+ Object.defineProperty(exports, 'GatewayServer', {
1031
+ enumerable: true,
1032
+ get: function () {
1033
+ return GatewayServer;
1034
+ }
1035
+ });
1036
+ Object.defineProperty(exports, 'getActiveServer', {
1037
+ enumerable: true,
1038
+ get: function () {
1039
+ return getActiveServer;
1040
+ }
1041
+ });
1042
+ Object.defineProperty(exports, 'startGateway', {
1043
+ enumerable: true,
1044
+ get: function () {
1045
+ return startGateway$1;
1046
+ }
1047
+ });