hyperclaw 4.0.2 ā 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +246 -60
- package/dist/a2ui-protocol-CfBI44-Q.js +75 -0
- package/dist/agents-routing-ChHiZp36.js +327 -0
- package/dist/agents-routing-ChqZ6l2S.js +4 -0
- package/dist/api-keys-guide-BCcOl0Q7.js +149 -0
- package/dist/api-keys-guide-CGn5BSF7.js +149 -0
- package/dist/audit-BJohI_vC.js +441 -0
- package/dist/audit-BaIiyWFu.js +441 -0
- package/dist/bounty-tools-CY_i91DU.js +211 -0
- package/dist/bounty-tools-DWudyZie.js +211 -0
- package/dist/browser-tools-BsTeGMnX.js +5 -0
- package/dist/browser-tools-D8_rLe2p.js +179 -0
- package/dist/claw-tasks-CgTsiNE8.js +80 -0
- package/dist/claw-tasks-Cyzdbhz_.js +80 -0
- package/dist/connector-5N0-X_xs.js +194 -0
- package/dist/connector-B3v0qcXg.js +425 -0
- package/dist/connector-B8R3iBY1.js +280 -0
- package/dist/connector-BAM-08NN.js +189 -0
- package/dist/connector-BC8FIVu4.js +181 -0
- package/dist/connector-BDmwwaVc.js +213 -0
- package/dist/connector-BGjbBy69.js +225 -0
- package/dist/connector-BO2SRzfG.js +218 -0
- package/dist/connector-BfXky0L3.js +167 -0
- package/dist/connector-BiiSJpx3.js +192 -0
- package/dist/connector-BnDmIhIu.js +85 -0
- package/dist/connector-C1HSoUyk.js +189 -0
- package/dist/connector-CKQHZOXg.js +568 -0
- package/dist/connector-CRl-iidy.js +239 -0
- package/dist/connector-Ci9glMD-.js +340 -0
- package/dist/connector-CjtZIEDj.js +181 -0
- package/dist/connector-Ck6JtOsX.js +531 -0
- package/dist/connector-D8Kelee0.js +286 -0
- package/dist/connector-DAnRJ0oP.js +162 -0
- package/dist/connector-DXTp5PE8.js +508 -0
- package/dist/connector-Dih6dUPP.js +173 -0
- package/dist/connector-DqTH_tPX.js +182 -0
- package/dist/connector-DrnEiiyP.js +419 -0
- package/dist/connector-DtR5GGTX.js +167 -0
- package/dist/connector-Tky_qS_K.js +350 -0
- package/dist/connector-ZSc3oTTy.js +305 -0
- package/dist/connector-sW5yhU1m.js +498 -0
- package/dist/connector-u3ICd3Ic.js +552 -0
- package/dist/cost-tracker-Ca1UPZ33.js +103 -0
- package/dist/cost-tracker-DD9wtWsr.js +103 -0
- package/dist/credentials-store-C6ir0Dae.js +4 -0
- package/dist/credentials-store-CA8UtK0T.js +77 -0
- package/dist/credentials-store-Cm7DH-kh.js +4 -0
- package/dist/credentials-store-H13LqOwJ.js +77 -0
- package/dist/cron-tasks-Bli7Kzd2.js +82 -0
- package/dist/cron-tasks-_pqQCmxc.js +82 -0
- package/dist/daemon-7ViroziB.js +5 -0
- package/dist/daemon-BfyKmZhr.js +318 -0
- package/dist/daemon-Bg4GtCmc.js +318 -0
- package/dist/daemon-DhmwY8k4.js +5 -0
- package/dist/delivery-BmIYy9VQ.js +4 -0
- package/dist/delivery-DVHmv1IR.js +4 -0
- package/dist/delivery-DpMX0Yyc.js +95 -0
- package/dist/delivery-pWUPBp1F.js +95 -0
- package/dist/destructive-gate-D6vWOdEl.js +101 -0
- package/dist/destructive-gate-DZt71UZR.js +101 -0
- package/dist/developer-keys-CPWT7Q6S.js +8 -0
- package/dist/developer-keys-DrrcUqFa.js +127 -0
- package/dist/doctor-BvCe8BBk.js +230 -0
- package/dist/doctor-CxyPLYsJ.js +6 -0
- package/dist/engine-B0kLfRL0.js +256 -0
- package/dist/engine-BJUpRUOv.js +7 -0
- package/dist/engine-CEDSqXfw.js +256 -0
- package/dist/engine-Da4JMNpI.js +7 -0
- package/dist/env-resolve-17ekEU6p.js +10 -0
- package/dist/env-resolve-CiXbWYwe.js +10 -0
- package/dist/env-resolve-CmGWhWXJ.js +115 -0
- package/dist/env-resolve-Z2XF6leB.js +115 -0
- package/dist/extraction-tools-HOZstZ0y.js +91 -0
- package/dist/extraction-tools-m4lmAv7l.js +5 -0
- package/dist/form_data-Cz040rio.js +8657 -0
- package/dist/gmail-watch-setup-Du7DVV7S.js +40 -0
- package/dist/health-B-asI__D.js +6 -0
- package/dist/health-Ds2YlpTB.js +152 -0
- package/dist/heartbeat-engine-BYT5ayQH.js +83 -0
- package/dist/heartbeat-engine-Ut6pXBD6.js +83 -0
- package/dist/hub-9LaKnLjY.js +6 -0
- package/dist/hub-CfwUz9YW.js +515 -0
- package/dist/hub-D0XwdjM-.js +515 -0
- package/dist/hub-LiD5Iztb.js +6 -0
- package/dist/hyperclawbot-CBiDSKsa.js +505 -0
- package/dist/hyperclawbot-zvczQgKx.js +505 -0
- package/dist/inference-0mlFQqIm.js +922 -0
- package/dist/inference-BKVkBREb.js +6 -0
- package/dist/inference-DCXH4Q3x.js +922 -0
- package/dist/inference-SzqFe_nk.js +6 -0
- package/dist/knowledge-graph-DE5lSF02.js +131 -0
- package/dist/knowledge-graph-iBG76fvm.js +131 -0
- package/dist/loader-BkDi8MD9.js +400 -0
- package/dist/loader-CC45xGpC.js +4 -0
- package/dist/loader-CnEdOyjT.js +400 -0
- package/dist/loader-DI2qDRPC.js +4 -0
- package/dist/logger-Cp8wC7F8.js +83 -0
- package/dist/logger-ybOp7VOC.js +83 -0
- package/dist/manager-03ipO9R0.js +105 -0
- package/dist/manager-B2Gls5RG.js +218 -0
- package/dist/manager-BpDfbDjg.js +117 -0
- package/dist/manager-Bxl0sqlh.js +4 -0
- package/dist/manager-CWNSML5D.js +117 -0
- package/dist/manager-CrVDn6eN.js +6 -0
- package/dist/manager-FCgF1plu.js +218 -0
- package/dist/manager-SJe9gt-q.js +4 -0
- package/dist/manager-rgCsaWT1.js +40 -0
- package/dist/mcp-CfoSU4Uz.js +139 -0
- package/dist/mcp-loader-CvxRDtPC.js +94 -0
- package/dist/mcp-loader-DkRBsLpk.js +94 -0
- package/dist/memory-BlHL7JCO.js +4 -0
- package/dist/memory-DsS_eFvJ.js +270 -0
- package/dist/memory-auto-BkvtSFUw.js +5 -0
- package/dist/memory-auto-Bnz_-1wP.js +306 -0
- package/dist/memory-auto-CpQHZlEJ.js +306 -0
- package/dist/memory-auto-Z6LCf-iK.js +5 -0
- package/dist/memory-integration-cSYkZyEo.js +91 -0
- package/dist/memory-integration-g2vxwgoE.js +91 -0
- package/dist/moltbook-BtLDZTfM.js +81 -0
- package/dist/moltbook-Cl8cQfxJ.js +81 -0
- package/dist/node-Dw2Gi-cP.js +222 -0
- package/dist/nodes-registry-B8dmrlLv.js +52 -0
- package/dist/nodes-registry-C9dCFwjh.js +52 -0
- package/dist/oauth-flow-CeaaGAz0.js +150 -0
- package/dist/oauth-flow-DQPvMHRH.js +150 -0
- package/dist/oauth-provider-B4dzn56l.js +110 -0
- package/dist/oauth-provider-Uo4Nib_c.js +110 -0
- package/dist/observability-BV-Yx0V9.js +89 -0
- package/dist/observability-nZ3CBIxG.js +89 -0
- package/dist/onboard-0WoDxbv_.js +10 -0
- package/dist/onboard-BBBWcfhp.js +10 -0
- package/dist/onboard-BXNXCQp4.js +4070 -0
- package/dist/onboard-Bw28IRQ3.js +4070 -0
- package/dist/orchestrator-BovkM63z.js +6 -0
- package/dist/orchestrator-DSbpkP1X.js +189 -0
- package/dist/orchestrator-DmnEvMaL.js +189 -0
- package/dist/orchestrator-RI3bpqqc.js +6 -0
- package/dist/osint-B4_m3VHQ.js +277 -0
- package/dist/pairing-6iM27aD8.js +196 -0
- package/dist/pairing-dGoiGepK.js +4 -0
- package/dist/pc-access-CgCsYrpt.js +8 -0
- package/dist/pc-access-_iH2aorG.js +819 -0
- package/dist/pending-approval-BgNjjuI2.js +22 -0
- package/dist/pending-approval-CUXjysAo.js +22 -0
- package/dist/reminders-store-Drjed_-h.js +58 -0
- package/dist/renderer-BVQrd0_g.js +225 -0
- package/dist/rules-BE4GV6cV.js +103 -0
- package/dist/run-main.js +1639 -460
- package/dist/runner-CJFJUtPm.js +1271 -0
- package/dist/runner-DatMMYYE.js +1271 -0
- package/dist/sdk/index.js +2 -2
- package/dist/sdk/index.mjs +2 -2
- package/dist/security-BqNyT4ID.js +4 -0
- package/dist/security-tpgqPWWH.js +73 -0
- package/dist/server-Brl_HQUB.js +1255 -0
- package/dist/server-D4wVHiX9.js +4 -0
- package/dist/server-Dh3JlBFB.js +1255 -0
- package/dist/server-DhfipkwN.js +4 -0
- package/dist/session-store-BUiPz0Vv.js +5 -0
- package/dist/session-store-is4B6qmD.js +113 -0
- package/dist/sessions-tools-CbUTFe4i.js +5 -0
- package/dist/sessions-tools-CeqD7iil.js +95 -0
- package/dist/skill-loader-BaNLVmJy.js +7 -0
- package/dist/skill-loader-HgpF6Vqs.js +159 -0
- package/dist/skill-runtime-BXWd-Ktf.js +102 -0
- package/dist/skill-runtime-CJN24QPW.js +102 -0
- package/dist/skill-runtime-jgklm02e.js +5 -0
- package/dist/skill-runtime-w1ig_lcw.js +5 -0
- package/dist/src-Bhybpk1J.js +63 -0
- package/dist/src-BxPHKO5x.js +63 -0
- package/dist/src-DIc-L2IG.js +20 -0
- package/dist/src-DMJ4-uqk.js +458 -0
- package/dist/src-g_rNx5rh.js +458 -0
- package/dist/sub-agent-tools-CHQoHz9c.js +39 -0
- package/dist/sub-agent-tools-DHY-4WWM.js +39 -0
- package/dist/theme-DcxwcUgZ.js +180 -0
- package/dist/theme-cx0fkgWC.js +8 -0
- package/dist/tool-policy-CNT-mF2Z.js +189 -0
- package/dist/tool-policy-DZvF8xlQ.js +189 -0
- package/dist/tts-elevenlabs-BRosZv-f.js +61 -0
- package/dist/tts-elevenlabs-C06nUxMK.js +61 -0
- package/dist/update-check-C2Dz85wJ.js +81 -0
- package/dist/update-check-w4XuxVl7.js +81 -0
- package/dist/vision-BMmiIKy7.js +121 -0
- package/dist/vision-JOtOS1Br.js +121 -0
- package/dist/vision-tools-CB28ZCO_.js +5 -0
- package/dist/vision-tools-DVuYc17I.js +51 -0
- package/dist/vision-tools-U3YC4L-g.js +5 -0
- package/dist/vision-tools-vPPwQ-0N.js +51 -0
- package/dist/voice-transcription-B555DbWR.js +138 -0
- package/dist/voice-transcription-DBo5hXmu.js +138 -0
- package/dist/website-watch-tools-DFMrJU-R.js +139 -0
- package/dist/website-watch-tools-Du3W5sN7.js +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1,400 @@
|
|
|
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
|
+
|
|
7
|
+
//#region src/hooks/loader.ts
|
|
8
|
+
const BUILTIN_HOOKS = [
|
|
9
|
+
{
|
|
10
|
+
id: "session-memory",
|
|
11
|
+
name: "Session Memory",
|
|
12
|
+
description: "Writes a summary of each session to MEMORY.md on close.",
|
|
13
|
+
trigger: "session:end",
|
|
14
|
+
eligible: true,
|
|
15
|
+
enabled: true,
|
|
16
|
+
builtin: true,
|
|
17
|
+
tags: ["memory", "sessions"],
|
|
18
|
+
version: "1.0.0"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: "command-logger",
|
|
22
|
+
name: "Command Logger",
|
|
23
|
+
description: "Logs every AI command execution to the daily log file.",
|
|
24
|
+
trigger: "message:sent",
|
|
25
|
+
eligible: true,
|
|
26
|
+
enabled: false,
|
|
27
|
+
builtin: true,
|
|
28
|
+
tags: ["logging", "debug"],
|
|
29
|
+
version: "1.0.0"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: "gateway-health",
|
|
33
|
+
name: "Gateway Health Monitor",
|
|
34
|
+
description: "Pings the gateway every 5 minutes and logs latency.",
|
|
35
|
+
trigger: "cron",
|
|
36
|
+
eligible: true,
|
|
37
|
+
enabled: true,
|
|
38
|
+
builtin: true,
|
|
39
|
+
tags: ["health", "monitoring"],
|
|
40
|
+
version: "1.1.0"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: "auto-backup",
|
|
44
|
+
name: "Auto Backup",
|
|
45
|
+
description: "Backs up AGENTS.md and config to ~/.hyperclaw/backups/ daily.",
|
|
46
|
+
trigger: "cron",
|
|
47
|
+
eligible: true,
|
|
48
|
+
enabled: false,
|
|
49
|
+
builtin: true,
|
|
50
|
+
tags: ["backup", "config"],
|
|
51
|
+
version: "1.0.0"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: "dm-guard",
|
|
55
|
+
name: "DM Guard",
|
|
56
|
+
description: "Enforces DM policy and logs policy violations.",
|
|
57
|
+
trigger: "message:received",
|
|
58
|
+
eligible: true,
|
|
59
|
+
enabled: true,
|
|
60
|
+
builtin: true,
|
|
61
|
+
tags: ["security", "dm-policy"],
|
|
62
|
+
version: "2.0.0"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: "voice-wake",
|
|
66
|
+
name: "Voice Wake Detector",
|
|
67
|
+
description: "Listens for wake word and starts voice session (macOS/iOS only).",
|
|
68
|
+
trigger: "gateway:start",
|
|
69
|
+
eligible: process.platform === "darwin",
|
|
70
|
+
enabled: false,
|
|
71
|
+
builtin: true,
|
|
72
|
+
tags: ["voice", "macos"],
|
|
73
|
+
version: "1.0.0"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: "morning-briefing",
|
|
77
|
+
name: "Morning Briefing (Heartbeat)",
|
|
78
|
+
description: "Proactive daily briefing: agent generates summary from MEMORY, reminders, knowledge graph. Writes to HEARTBEAT.md.",
|
|
79
|
+
trigger: "cron",
|
|
80
|
+
eligible: true,
|
|
81
|
+
enabled: false,
|
|
82
|
+
builtin: true,
|
|
83
|
+
tags: [
|
|
84
|
+
"heartbeat",
|
|
85
|
+
"briefing",
|
|
86
|
+
"automation"
|
|
87
|
+
],
|
|
88
|
+
version: "1.0.0"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: "website-watch",
|
|
92
|
+
name: "Website Change Monitor",
|
|
93
|
+
description: "Every 15 min, checks watched URLs for changes. Use watch_website_add tool to add URLs.",
|
|
94
|
+
trigger: "cron",
|
|
95
|
+
eligible: true,
|
|
96
|
+
enabled: true,
|
|
97
|
+
builtin: true,
|
|
98
|
+
tags: ["automation", "monitoring"],
|
|
99
|
+
version: "1.0.0"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: "voice-note-transcription",
|
|
103
|
+
name: "Voice Note Transcription",
|
|
104
|
+
description: "Transcribes incoming voice messages via Whisper (OPENAI_API_KEY). Used by channels when audioPath is set.",
|
|
105
|
+
trigger: "message:received",
|
|
106
|
+
eligible: true,
|
|
107
|
+
enabled: true,
|
|
108
|
+
builtin: true,
|
|
109
|
+
tags: [
|
|
110
|
+
"voice",
|
|
111
|
+
"transcription",
|
|
112
|
+
"messaging"
|
|
113
|
+
],
|
|
114
|
+
version: "1.0.0"
|
|
115
|
+
}
|
|
116
|
+
];
|
|
117
|
+
var HookLoader = class {
|
|
118
|
+
stateFile;
|
|
119
|
+
state = {};
|
|
120
|
+
constructor() {
|
|
121
|
+
this.stateFile = path.default.join(os.default.homedir(), ".hyperclaw", "hooks-state.json");
|
|
122
|
+
this.loadState();
|
|
123
|
+
}
|
|
124
|
+
loadState() {
|
|
125
|
+
try {
|
|
126
|
+
this.state = fs_extra.default.readJsonSync(this.stateFile);
|
|
127
|
+
} catch {
|
|
128
|
+
this.state = {};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
saveState() {
|
|
132
|
+
fs_extra.default.ensureDirSync(path.default.dirname(this.stateFile));
|
|
133
|
+
fs_extra.default.writeJsonSync(this.stateFile, this.state, { spaces: 2 });
|
|
134
|
+
}
|
|
135
|
+
isEnabled(hook) {
|
|
136
|
+
if (this.state[hook.id] !== void 0) return this.state[hook.id].enabled;
|
|
137
|
+
return hook.enabled;
|
|
138
|
+
}
|
|
139
|
+
getHooks(eligibleOnly = false) {
|
|
140
|
+
const hooks = eligibleOnly ? BUILTIN_HOOKS.filter((h) => h.eligible) : BUILTIN_HOOKS;
|
|
141
|
+
return hooks.map((h) => ({
|
|
142
|
+
...h,
|
|
143
|
+
enabled: this.isEnabled(h),
|
|
144
|
+
eligible: h.eligible
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
list(eligibleOnly = false) {
|
|
148
|
+
const hooks = this.getHooks(eligibleOnly);
|
|
149
|
+
console.log(chalk.default.bold.cyan("\n ā” HYPERCLAW HOOKS\n"));
|
|
150
|
+
for (const hook of hooks) {
|
|
151
|
+
const dot = hook.enabled ? chalk.default.green("ā") : chalk.default.gray("ā");
|
|
152
|
+
const eligBadge = hook.eligible ? "" : chalk.default.red(" [ineligible]");
|
|
153
|
+
const builtinBadge = hook.builtin ? chalk.default.gray(" [builtin]") : "";
|
|
154
|
+
console.log(` ${dot} ${chalk.default.white(hook.id)}${eligBadge}${builtinBadge}`);
|
|
155
|
+
console.log(` ${chalk.default.gray(hook.description)}`);
|
|
156
|
+
console.log(` ${chalk.default.gray(`trigger: ${hook.trigger} v${hook.version} tags: ${hook.tags.join(", ")}`)}`);
|
|
157
|
+
console.log();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
info(id) {
|
|
161
|
+
const hook = BUILTIN_HOOKS.find((h) => h.id === id);
|
|
162
|
+
if (!hook) {
|
|
163
|
+
console.log(chalk.default.red(` ā Hook not found: ${id}`));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const enabled = this.isEnabled(hook);
|
|
167
|
+
console.log(chalk.default.bold.cyan(`\n Hook: ${hook.name}\n`));
|
|
168
|
+
console.log(` ID: ${hook.id}`);
|
|
169
|
+
console.log(` Status: ${enabled ? chalk.default.green("enabled") : chalk.default.gray("disabled")}`);
|
|
170
|
+
console.log(` Eligible: ${hook.eligible ? chalk.default.green("yes") : chalk.default.red("no ā OS not supported")}`);
|
|
171
|
+
console.log(` Trigger: ${hook.trigger}`);
|
|
172
|
+
console.log(` Description: ${hook.description}`);
|
|
173
|
+
console.log(` Tags: ${hook.tags.join(", ")}`);
|
|
174
|
+
console.log(` Version: ${hook.version}`);
|
|
175
|
+
console.log();
|
|
176
|
+
}
|
|
177
|
+
enable(id) {
|
|
178
|
+
const hook = BUILTIN_HOOKS.find((h) => h.id === id);
|
|
179
|
+
if (!hook) {
|
|
180
|
+
console.log(chalk.default.red(` ā Hook not found: ${id}`));
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
if (!hook.eligible) {
|
|
184
|
+
console.log(chalk.default.red(` ā Hook not eligible on this OS: ${id}`));
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
this.state[id] = { enabled: true };
|
|
188
|
+
this.saveState();
|
|
189
|
+
console.log(chalk.default.green(` ā Hook enabled: ${id}`));
|
|
190
|
+
}
|
|
191
|
+
disable(id) {
|
|
192
|
+
const hook = BUILTIN_HOOKS.find((h) => h.id === id);
|
|
193
|
+
if (!hook) {
|
|
194
|
+
console.log(chalk.default.red(` ā Hook not found: ${id}`));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
this.state[id] = { enabled: false };
|
|
198
|
+
this.saveState();
|
|
199
|
+
console.log(chalk.default.green(` ā Hook disabled: ${id}`));
|
|
200
|
+
}
|
|
201
|
+
async install(pack) {
|
|
202
|
+
const s = require("ora")(`Installing hook pack: ${pack}...`).start();
|
|
203
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
204
|
+
s.succeed(`Hook pack installed: ${pack}`);
|
|
205
|
+
console.log(chalk.default.gray(` Run: hyperclaw hooks list to see new hooks`));
|
|
206
|
+
}
|
|
207
|
+
/** Execute enabled hooks for a trigger. Fire-and-forget. */
|
|
208
|
+
async execute(trigger, payload) {
|
|
209
|
+
const toRun = BUILTIN_HOOKS.filter((h) => h.trigger === trigger && h.eligible && this.isEnabled(h));
|
|
210
|
+
for (const hook of toRun) this.runHandler(hook, payload).catch((err) => console.error(`[hooks] ${hook.id} error:`, err?.message || err));
|
|
211
|
+
}
|
|
212
|
+
/** Execute a single cron hook by ID. Used by CronRunner. */
|
|
213
|
+
async executeCronHook(hookId) {
|
|
214
|
+
const hook = BUILTIN_HOOKS.find((h) => h.id === hookId && h.trigger === "cron" && h.eligible && this.isEnabled(h));
|
|
215
|
+
if (hook) await this.runHandler(hook, {}).catch((err) => console.error(`[hooks] ${hook.id} error:`, err?.message || err));
|
|
216
|
+
}
|
|
217
|
+
/** Start cron schedules: gateway-health (5 min), auto-backup (3am), website-watch (15 min), morning-briefing (8am), + user cron-tasks. */
|
|
218
|
+
startCronScheduler() {
|
|
219
|
+
const cron = require("node-cron");
|
|
220
|
+
const stops = [];
|
|
221
|
+
const t1 = cron.schedule("*/5 * * * *", () => {
|
|
222
|
+
this.executeCronHook("gateway-health").catch(() => {});
|
|
223
|
+
});
|
|
224
|
+
const t2 = cron.schedule("0 3 * * *", () => {
|
|
225
|
+
this.executeCronHook("auto-backup").catch(() => {});
|
|
226
|
+
});
|
|
227
|
+
const t3 = cron.schedule("*/15 * * * *", () => {
|
|
228
|
+
this.executeCronHook("website-watch").catch(() => {});
|
|
229
|
+
});
|
|
230
|
+
const t4 = cron.schedule("0 8 * * *", () => {
|
|
231
|
+
this.executeCronHook("morning-briefing").catch(() => {});
|
|
232
|
+
});
|
|
233
|
+
stops.push(() => {
|
|
234
|
+
t1.stop();
|
|
235
|
+
t2.stop();
|
|
236
|
+
t3.stop();
|
|
237
|
+
t4.stop();
|
|
238
|
+
});
|
|
239
|
+
(async () => {
|
|
240
|
+
try {
|
|
241
|
+
const { loadCronTasks, runCronTask } = await Promise.resolve().then(() => require("./cron-tasks-Bli7Kzd2.js"));
|
|
242
|
+
const tasks = await loadCronTasks();
|
|
243
|
+
let port = 18789;
|
|
244
|
+
try {
|
|
245
|
+
const cfg = await fs_extra.default.readJson(path.default.join(os.default.homedir(), ".hyperclaw", "hyperclaw.json"));
|
|
246
|
+
port = cfg?.gateway?.port ?? 18789;
|
|
247
|
+
} catch {}
|
|
248
|
+
for (const task of tasks) {
|
|
249
|
+
if (!task.enabled) continue;
|
|
250
|
+
try {
|
|
251
|
+
const t = cron.schedule(task.schedule, () => runCronTask(task, port).catch(() => {}));
|
|
252
|
+
stops.push(() => t.stop());
|
|
253
|
+
} catch {}
|
|
254
|
+
}
|
|
255
|
+
} catch {}
|
|
256
|
+
})();
|
|
257
|
+
return () => {
|
|
258
|
+
stops.forEach((s) => s());
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
async runHandler(hook, payload) {
|
|
262
|
+
const handlers = {
|
|
263
|
+
"session-memory": async () => {
|
|
264
|
+
const sessionId = payload?.sessionId;
|
|
265
|
+
const turnCount = payload?.turnCount ?? 0;
|
|
266
|
+
const newFacts = payload?.newFacts;
|
|
267
|
+
if (turnCount > 0 && sessionId) {
|
|
268
|
+
const entry = `\n- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}: Session ${sessionId} closed after ${turnCount} turns\n`;
|
|
269
|
+
await fs_extra.default.appendFile(path.default.join(os.default.homedir(), ".hyperclaw", "MEMORY.md"), entry);
|
|
270
|
+
}
|
|
271
|
+
try {
|
|
272
|
+
const { onSessionEnd } = await Promise.resolve().then(() => require("./memory-integration-cSYkZyEo.js"));
|
|
273
|
+
await onSessionEnd({
|
|
274
|
+
sessionId,
|
|
275
|
+
turnCount,
|
|
276
|
+
newFacts
|
|
277
|
+
});
|
|
278
|
+
} catch {}
|
|
279
|
+
},
|
|
280
|
+
"command-logger": async () => {
|
|
281
|
+
const logDir = path.default.join(os.default.homedir(), ".hyperclaw", "logs");
|
|
282
|
+
const logFile = path.default.join(logDir, `commands-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.log`);
|
|
283
|
+
await fs_extra.default.ensureDir(logDir);
|
|
284
|
+
const msg = String(payload?.message ?? "").slice(0, 100);
|
|
285
|
+
const resp = String(payload?.response ?? "").slice(0, 200);
|
|
286
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] msg=${msg} | resp=${resp}\n`;
|
|
287
|
+
await fs_extra.default.appendFile(logFile, line);
|
|
288
|
+
},
|
|
289
|
+
"dm-guard": async () => {
|
|
290
|
+
if (payload?.channel) {
|
|
291
|
+
const auditDir = path.default.join(os.default.homedir(), ".hyperclaw", "logs");
|
|
292
|
+
await fs_extra.default.ensureDir(auditDir);
|
|
293
|
+
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] message:received channel=${payload.channel}\n`;
|
|
294
|
+
await fs_extra.default.appendFile(path.default.join(auditDir, "dm-guard.log"), line);
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
"gateway-health": async () => {
|
|
298
|
+
const hcDir = path.default.join(os.default.homedir(), ".hyperclaw");
|
|
299
|
+
let port = 18789;
|
|
300
|
+
try {
|
|
301
|
+
const cfg = await fs_extra.default.readJson(path.default.join(hcDir, "hyperclaw.json"));
|
|
302
|
+
if (cfg?.gateway?.port) port = cfg.gateway.port;
|
|
303
|
+
} catch {}
|
|
304
|
+
const logDir = path.default.join(hcDir, "logs");
|
|
305
|
+
const logFile = path.default.join(logDir, "gateway-health.log");
|
|
306
|
+
const start = Date.now();
|
|
307
|
+
try {
|
|
308
|
+
const http = await import("http");
|
|
309
|
+
await new Promise((resolve, reject) => {
|
|
310
|
+
const req = http.get(`http://127.0.0.1:${port}/api/status`, (res) => {
|
|
311
|
+
let data = "";
|
|
312
|
+
res.on("data", (c) => data += c);
|
|
313
|
+
res.on("end", () => {
|
|
314
|
+
resolve();
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
req.on("error", reject);
|
|
318
|
+
req.setTimeout(5e3, () => {
|
|
319
|
+
req.destroy();
|
|
320
|
+
reject(new Error("Timeout"));
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
const latency = Date.now() - start;
|
|
324
|
+
await fs_extra.default.ensureDir(logDir);
|
|
325
|
+
await fs_extra.default.appendFile(logFile, `[${(/* @__PURE__ */ new Date()).toISOString()}] OK latency=${latency}ms\n`);
|
|
326
|
+
} catch (e) {
|
|
327
|
+
await fs_extra.default.ensureDir(logDir);
|
|
328
|
+
await fs_extra.default.appendFile(logFile, `[${(/* @__PURE__ */ new Date()).toISOString()}] FAIL ${e.message}\n`);
|
|
329
|
+
}
|
|
330
|
+
},
|
|
331
|
+
"auto-backup": async () => {
|
|
332
|
+
const hcDir = path.default.join(os.default.homedir(), ".hyperclaw");
|
|
333
|
+
const backupDir = path.default.join(hcDir, "backups");
|
|
334
|
+
await fs_extra.default.ensureDir(backupDir);
|
|
335
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
336
|
+
for (const f of [
|
|
337
|
+
"hyperclaw.json",
|
|
338
|
+
"AGENTS.md",
|
|
339
|
+
"MEMORY.md",
|
|
340
|
+
"SOUL.md"
|
|
341
|
+
]) {
|
|
342
|
+
const src = path.default.join(hcDir, f);
|
|
343
|
+
if (await fs_extra.default.pathExists(src)) await fs_extra.default.copy(src, path.default.join(backupDir, `${f}.${ts}.bak`));
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
"voice-wake": async () => {},
|
|
347
|
+
"morning-briefing": async () => {
|
|
348
|
+
try {
|
|
349
|
+
const { runMorningBriefing, persistBriefing } = await Promise.resolve().then(() => require("./heartbeat-engine-BYT5ayQH.js"));
|
|
350
|
+
const text = await runMorningBriefing();
|
|
351
|
+
await persistBriefing(text);
|
|
352
|
+
} catch (e) {
|
|
353
|
+
const logDir = path.default.join(os.default.homedir(), ".hyperclaw", "logs");
|
|
354
|
+
await fs_extra.default.ensureDir(logDir);
|
|
355
|
+
await fs_extra.default.appendFile(path.default.join(logDir, "heartbeat-errors.log"), `[${(/* @__PURE__ */ new Date()).toISOString()}] ${e.message}\n`);
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
"website-watch": async () => {
|
|
359
|
+
const path$2 = await import("path");
|
|
360
|
+
const os$2 = await import("os");
|
|
361
|
+
const fs$1 = await import("fs-extra");
|
|
362
|
+
const watchFile = path$2.join(os$2.homedir(), ".hyperclaw", "website-watches.json");
|
|
363
|
+
if (!await fs$1.pathExists(watchFile)) return;
|
|
364
|
+
const watches = await fs$1.readJson(watchFile).catch(() => ({}));
|
|
365
|
+
const crypto = await import("crypto");
|
|
366
|
+
const https = await import("https");
|
|
367
|
+
const http = await import("http");
|
|
368
|
+
const fetch = (u) => new Promise((res, rej) => {
|
|
369
|
+
const c = u.startsWith("https") ? https : http;
|
|
370
|
+
const req = c.get(u, { timeout: 1e4 }, (r) => {
|
|
371
|
+
let d = "";
|
|
372
|
+
r.on("data", (x) => d += x);
|
|
373
|
+
r.on("end", () => res(d));
|
|
374
|
+
});
|
|
375
|
+
req.on("error", rej);
|
|
376
|
+
});
|
|
377
|
+
const hash = (s) => crypto.createHash("sha256").update(s.replace(/\s+/g, " ").slice(0, 5e4)).digest("hex").slice(0, 16);
|
|
378
|
+
for (const url of Object.keys(watches)) try {
|
|
379
|
+
const content = await fetch(url);
|
|
380
|
+
const h = hash(content);
|
|
381
|
+
if (h !== watches[url].lastHash) {
|
|
382
|
+
watches[url].lastHash = h;
|
|
383
|
+
watches[url].lastCheck = (/* @__PURE__ */ new Date()).toISOString();
|
|
384
|
+
}
|
|
385
|
+
} catch {}
|
|
386
|
+
await fs$1.writeJson(watchFile, watches, { spaces: 2 });
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
const fn = handlers[hook.id];
|
|
390
|
+
if (fn) await fn();
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
//#endregion
|
|
395
|
+
Object.defineProperty(exports, 'HookLoader', {
|
|
396
|
+
enumerable: true,
|
|
397
|
+
get: function () {
|
|
398
|
+
return HookLoader;
|
|
399
|
+
}
|
|
400
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
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
|
+
|
|
7
|
+
//#region src/logging/logger.ts
|
|
8
|
+
const LEVEL_COLOR = {
|
|
9
|
+
debug: chalk.default.gray,
|
|
10
|
+
info: chalk.default.cyan,
|
|
11
|
+
warn: chalk.default.yellow,
|
|
12
|
+
error: chalk.default.red,
|
|
13
|
+
silent: chalk.default.gray
|
|
14
|
+
};
|
|
15
|
+
const LOG_DIR = path.default.join(os.default.homedir(), ".hyperclaw", "logs");
|
|
16
|
+
const LOG_FILE = path.default.join(LOG_DIR, "hyperclaw.log");
|
|
17
|
+
const MAX_LOG_BYTES = 5 * 1024 * 1024;
|
|
18
|
+
function formatConsole(entry) {
|
|
19
|
+
const ts = chalk.default.gray(entry.ts.slice(11, 23));
|
|
20
|
+
const level = LEVEL_COLOR[entry.level](entry.level.toUpperCase().padEnd(5));
|
|
21
|
+
const mod = chalk.default.blue(`[${entry.module}]`);
|
|
22
|
+
const data = entry.data ? chalk.default.gray(" " + JSON.stringify(entry.data)) : "";
|
|
23
|
+
return ` ${ts} ${level} ${mod} ${entry.message}${data}`;
|
|
24
|
+
}
|
|
25
|
+
async function tailLog(lines = 50) {
|
|
26
|
+
if (!await fs_extra.default.pathExists(LOG_FILE)) {
|
|
27
|
+
console.log(chalk.default.gray("\n No log file yet. Start the daemon first.\n"));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const content = await fs_extra.default.readFile(LOG_FILE, "utf8");
|
|
31
|
+
const all = content.trim().split("\n").filter(Boolean);
|
|
32
|
+
const tail = all.slice(-lines);
|
|
33
|
+
console.log(chalk.default.bold.cyan(`\n š LAST ${tail.length} LOG ENTRIES\n`));
|
|
34
|
+
for (const line of tail) try {
|
|
35
|
+
const entry = JSON.parse(line);
|
|
36
|
+
console.log(formatConsole(entry));
|
|
37
|
+
} catch {
|
|
38
|
+
console.log(chalk.default.gray(" " + line));
|
|
39
|
+
}
|
|
40
|
+
console.log();
|
|
41
|
+
}
|
|
42
|
+
async function streamLog() {
|
|
43
|
+
console.log(chalk.default.bold.cyan("\n š” STREAMING LOGS (Ctrl+C to stop)\n"));
|
|
44
|
+
await fs_extra.default.ensureDir(LOG_DIR);
|
|
45
|
+
await fs_extra.default.ensureFile(LOG_FILE);
|
|
46
|
+
const { createReadStream } = await import("fs");
|
|
47
|
+
const { Tail } = await import("tail").catch(() => ({ Tail: null }));
|
|
48
|
+
if (Tail) {
|
|
49
|
+
const tail = new Tail(LOG_FILE);
|
|
50
|
+
tail.on("line", (line) => {
|
|
51
|
+
try {
|
|
52
|
+
const entry = JSON.parse(line);
|
|
53
|
+
console.log(formatConsole(entry));
|
|
54
|
+
} catch {
|
|
55
|
+
console.log(chalk.default.gray(" " + line));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
const { spawn } = await import("child_process");
|
|
60
|
+
const proc = spawn("tail", ["-f", LOG_FILE], { stdio: [
|
|
61
|
+
"ignore",
|
|
62
|
+
"pipe",
|
|
63
|
+
"ignore"
|
|
64
|
+
] });
|
|
65
|
+
proc.stdout?.on("data", (chunk) => {
|
|
66
|
+
const lines = chunk.toString().split("\n");
|
|
67
|
+
for (const line of lines) {
|
|
68
|
+
if (!line.trim()) continue;
|
|
69
|
+
try {
|
|
70
|
+
const entry = JSON.parse(line);
|
|
71
|
+
console.log(formatConsole(entry));
|
|
72
|
+
} catch {
|
|
73
|
+
console.log(chalk.default.gray(" " + line));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
await new Promise(() => {});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
82
|
+
exports.streamLog = streamLog;
|
|
83
|
+
exports.tailLog = tailLog;
|
|
@@ -0,0 +1,83 @@
|
|
|
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
|
+
|
|
7
|
+
//#region src/logging/logger.ts
|
|
8
|
+
const LEVEL_COLOR = {
|
|
9
|
+
debug: chalk.default.gray,
|
|
10
|
+
info: chalk.default.cyan,
|
|
11
|
+
warn: chalk.default.yellow,
|
|
12
|
+
error: chalk.default.red,
|
|
13
|
+
silent: chalk.default.gray
|
|
14
|
+
};
|
|
15
|
+
const LOG_DIR = path.default.join(os.default.homedir(), ".hyperclaw", "logs");
|
|
16
|
+
const LOG_FILE = path.default.join(LOG_DIR, "hyperclaw.log");
|
|
17
|
+
const MAX_LOG_BYTES = 5 * 1024 * 1024;
|
|
18
|
+
function formatConsole(entry) {
|
|
19
|
+
const ts = chalk.default.gray(entry.ts.slice(11, 23));
|
|
20
|
+
const level = LEVEL_COLOR[entry.level](entry.level.toUpperCase().padEnd(5));
|
|
21
|
+
const mod = chalk.default.blue(`[${entry.module}]`);
|
|
22
|
+
const data = entry.data ? chalk.default.gray(" " + JSON.stringify(entry.data)) : "";
|
|
23
|
+
return ` ${ts} ${level} ${mod} ${entry.message}${data}`;
|
|
24
|
+
}
|
|
25
|
+
async function tailLog(lines = 50) {
|
|
26
|
+
if (!await fs_extra.default.pathExists(LOG_FILE)) {
|
|
27
|
+
console.log(chalk.default.gray("\n No log file yet. Start the daemon first.\n"));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const content = await fs_extra.default.readFile(LOG_FILE, "utf8");
|
|
31
|
+
const all = content.trim().split("\n").filter(Boolean);
|
|
32
|
+
const tail = all.slice(-lines);
|
|
33
|
+
console.log(chalk.default.bold.cyan(`\n š LAST ${tail.length} LOG ENTRIES\n`));
|
|
34
|
+
for (const line of tail) try {
|
|
35
|
+
const entry = JSON.parse(line);
|
|
36
|
+
console.log(formatConsole(entry));
|
|
37
|
+
} catch {
|
|
38
|
+
console.log(chalk.default.gray(" " + line));
|
|
39
|
+
}
|
|
40
|
+
console.log();
|
|
41
|
+
}
|
|
42
|
+
async function streamLog() {
|
|
43
|
+
console.log(chalk.default.bold.cyan("\n š” STREAMING LOGS (Ctrl+C to stop)\n"));
|
|
44
|
+
await fs_extra.default.ensureDir(LOG_DIR);
|
|
45
|
+
await fs_extra.default.ensureFile(LOG_FILE);
|
|
46
|
+
const { createReadStream } = await import("fs");
|
|
47
|
+
const { Tail } = await import("tail").catch(() => ({ Tail: null }));
|
|
48
|
+
if (Tail) {
|
|
49
|
+
const tail = new Tail(LOG_FILE);
|
|
50
|
+
tail.on("line", (line) => {
|
|
51
|
+
try {
|
|
52
|
+
const entry = JSON.parse(line);
|
|
53
|
+
console.log(formatConsole(entry));
|
|
54
|
+
} catch {
|
|
55
|
+
console.log(chalk.default.gray(" " + line));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
const { spawn } = await import("child_process");
|
|
60
|
+
const proc = spawn("tail", ["-f", LOG_FILE], { stdio: [
|
|
61
|
+
"ignore",
|
|
62
|
+
"pipe",
|
|
63
|
+
"ignore"
|
|
64
|
+
] });
|
|
65
|
+
proc.stdout?.on("data", (chunk) => {
|
|
66
|
+
const lines = chunk.toString().split("\n");
|
|
67
|
+
for (const line of lines) {
|
|
68
|
+
if (!line.trim()) continue;
|
|
69
|
+
try {
|
|
70
|
+
const entry = JSON.parse(line);
|
|
71
|
+
console.log(formatConsole(entry));
|
|
72
|
+
} catch {
|
|
73
|
+
console.log(chalk.default.gray(" " + line));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
await new Promise(() => {});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
82
|
+
exports.streamLog = streamLog;
|
|
83
|
+
exports.tailLog = tailLog;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const require_chunk = require('./chunk-jS-bbMI5.js');
|
|
2
|
+
const chalk = require_chunk.__toESM(require("chalk"));
|
|
3
|
+
const crypto = require_chunk.__toESM(require("crypto"));
|
|
4
|
+
const child_process = require_chunk.__toESM(require("child_process"));
|
|
5
|
+
const util = require_chunk.__toESM(require("util"));
|
|
6
|
+
const net = require_chunk.__toESM(require("net"));
|
|
7
|
+
|
|
8
|
+
//#region packages/gateway/src/manager.ts
|
|
9
|
+
const execAsync = (0, util.promisify)(child_process.exec);
|
|
10
|
+
var GatewayManager = class {
|
|
11
|
+
generateToken() {
|
|
12
|
+
return crypto.default.randomBytes(32).toString("hex");
|
|
13
|
+
}
|
|
14
|
+
async isRunning(port) {
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
const socket = new net.default.Socket();
|
|
17
|
+
socket.setTimeout(500);
|
|
18
|
+
socket.on("connect", () => {
|
|
19
|
+
socket.destroy();
|
|
20
|
+
resolve(true);
|
|
21
|
+
});
|
|
22
|
+
socket.on("error", () => resolve(false));
|
|
23
|
+
socket.on("timeout", () => resolve(false));
|
|
24
|
+
try {
|
|
25
|
+
socket.connect(port, "127.0.0.1");
|
|
26
|
+
} catch {
|
|
27
|
+
resolve(false);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
async detectTailscale() {
|
|
32
|
+
try {
|
|
33
|
+
const { stdout } = await execAsync("tailscale ip -4 2>/dev/null");
|
|
34
|
+
return stdout.trim() || null;
|
|
35
|
+
} catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async detectRuntime() {
|
|
40
|
+
for (const runtime of [
|
|
41
|
+
"bun",
|
|
42
|
+
"deno",
|
|
43
|
+
"node"
|
|
44
|
+
]) try {
|
|
45
|
+
await execAsync(`which ${runtime}`);
|
|
46
|
+
return runtime;
|
|
47
|
+
} catch {}
|
|
48
|
+
return "node";
|
|
49
|
+
}
|
|
50
|
+
bindLabel(bind, custom) {
|
|
51
|
+
const map = {
|
|
52
|
+
"127.0.0.1": "Loopback only (this machine)",
|
|
53
|
+
"0.0.0.0": "All interfaces (LAN accessible)",
|
|
54
|
+
"tailscale": "Tailscale IP (VPN peers only)",
|
|
55
|
+
"custom": `Custom: ${custom || "?"}`
|
|
56
|
+
};
|
|
57
|
+
return map[bind];
|
|
58
|
+
}
|
|
59
|
+
exposureLabel(e) {
|
|
60
|
+
const map = {
|
|
61
|
+
"off": "Off ā no Tailscale exposure",
|
|
62
|
+
"serve": "Serve ā accessible to your Tailscale devices",
|
|
63
|
+
"funnel": "Funnel ā publicly accessible via Tailscale URL"
|
|
64
|
+
};
|
|
65
|
+
return map[e];
|
|
66
|
+
}
|
|
67
|
+
async applyTailscaleExposure(exposure, port) {
|
|
68
|
+
if (exposure === "off") return;
|
|
69
|
+
try {
|
|
70
|
+
if (exposure === "serve") await execAsync(`tailscale serve ${port}`);
|
|
71
|
+
else if (exposure === "funnel") await execAsync(`tailscale funnel ${port}`);
|
|
72
|
+
} catch {
|
|
73
|
+
console.log(chalk.default.yellow("ā ļø Tailscale exposure failed ā check tailscale is running"));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
getWsUrl(config) {
|
|
77
|
+
const host = config.bind === "127.0.0.1" ? "127.0.0.1" : config.bind === "custom" ? config.customBind || "localhost" : "localhost";
|
|
78
|
+
return `ws://${host}:${config.port}`;
|
|
79
|
+
}
|
|
80
|
+
getHttpUrl(config) {
|
|
81
|
+
return `http://localhost:${config.port}`;
|
|
82
|
+
}
|
|
83
|
+
async showStatus(config) {
|
|
84
|
+
const running = await this.isRunning(config.port);
|
|
85
|
+
const statusIcon = running ? chalk.default.green("ā RUNNING") : chalk.default.red("ā STOPPED");
|
|
86
|
+
const ws = this.getWsUrl(config);
|
|
87
|
+
console.log(chalk.default.cyan("\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā"));
|
|
88
|
+
console.log(chalk.default.cyan("ā š GATEWAY STATUS ā"));
|
|
89
|
+
console.log(chalk.default.cyan("ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā£"));
|
|
90
|
+
console.log(chalk.default.cyan(`ā Status: ${statusIcon.padEnd(29)}ā`));
|
|
91
|
+
console.log(chalk.default.cyan(`ā Address: ${chalk.default.white(ws).padEnd(29)}ā`));
|
|
92
|
+
console.log(chalk.default.cyan(`ā Auth: ${chalk.default.yellow("token (masked)").padEnd(29)}ā`));
|
|
93
|
+
console.log(chalk.default.cyan(`ā Bind: ${chalk.default.gray(config.bind).padEnd(29)}ā`));
|
|
94
|
+
console.log(chalk.default.cyan(`ā Tailscale: ${chalk.default.gray(config.tailscaleExposure).padEnd(27)}ā`));
|
|
95
|
+
console.log(chalk.default.cyan("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n"));
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
//#endregion
|
|
100
|
+
Object.defineProperty(exports, 'GatewayManager', {
|
|
101
|
+
enumerable: true,
|
|
102
|
+
get: function () {
|
|
103
|
+
return GatewayManager;
|
|
104
|
+
}
|
|
105
|
+
});
|