alvin-bot 5.6.2 → 5.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +1 -1
  3. package/dist/claude.js +1 -102
  4. package/dist/config.js +1 -96
  5. package/dist/engine.js +1 -90
  6. package/dist/find-claude-binary.js +1 -98
  7. package/dist/handlers/async-agent-chunk-handler.js +1 -50
  8. package/dist/handlers/background-bypass.js +1 -75
  9. package/dist/handlers/commands.js +1 -2336
  10. package/dist/handlers/cron-progress.js +1 -52
  11. package/dist/handlers/document.js +1 -194
  12. package/dist/handlers/message.js +1 -959
  13. package/dist/handlers/photo.js +1 -154
  14. package/dist/handlers/platform-message.js +1 -360
  15. package/dist/handlers/stuck-timer.js +1 -54
  16. package/dist/handlers/video.js +1 -237
  17. package/dist/handlers/voice.js +1 -148
  18. package/dist/i18n.js +1 -805
  19. package/dist/index.js +1 -697
  20. package/dist/init-data-dir.js +1 -98
  21. package/dist/middleware/auth.js +1 -233
  22. package/dist/migrate.js +1 -162
  23. package/dist/paths.js +1 -146
  24. package/dist/platforms/discord.js +1 -175
  25. package/dist/platforms/index.js +1 -130
  26. package/dist/platforms/signal.js +1 -205
  27. package/dist/platforms/slack-slash-parser.js +1 -32
  28. package/dist/platforms/slack.js +1 -501
  29. package/dist/platforms/telegram.js +1 -111
  30. package/dist/platforms/types.js +1 -8
  31. package/dist/platforms/whatsapp-auth-helpers.js +1 -53
  32. package/dist/platforms/whatsapp.js +1 -707
  33. package/dist/providers/claude-sdk-provider.js +1 -565
  34. package/dist/providers/codex-cli-provider.js +1 -134
  35. package/dist/providers/index.js +1 -7
  36. package/dist/providers/ollama-provider.js +1 -32
  37. package/dist/providers/openai-compatible.js +1 -406
  38. package/dist/providers/registry.js +1 -352
  39. package/dist/providers/runtime-header.js +1 -45
  40. package/dist/providers/tool-executor.js +1 -475
  41. package/dist/providers/types.js +1 -227
  42. package/dist/services/access.js +1 -144
  43. package/dist/services/allowed-users-gate.js +1 -56
  44. package/dist/services/alvin-dispatch.js +1 -130
  45. package/dist/services/alvin-mcp-tools.js +1 -104
  46. package/dist/services/asset-index.js +1 -224
  47. package/dist/services/async-agent-parser.js +1 -418
  48. package/dist/services/async-agent-watcher.js +1 -443
  49. package/dist/services/auto-diagnostic.js +1 -228
  50. package/dist/services/broadcast.js +1 -52
  51. package/dist/services/browser-manager.js +1 -562
  52. package/dist/services/browser-webfetch.js +1 -127
  53. package/dist/services/browser.js +1 -121
  54. package/dist/services/cdp-bootstrap.js +1 -357
  55. package/dist/services/compaction.js +1 -144
  56. package/dist/services/critical-notify.js +1 -203
  57. package/dist/services/cron-resolver.js +1 -58
  58. package/dist/services/cron-scheduling.js +1 -310
  59. package/dist/services/cron.js +1 -861
  60. package/dist/services/custom-tools.js +1 -317
  61. package/dist/services/delivery-queue.js +1 -173
  62. package/dist/services/delivery-registry.js +1 -21
  63. package/dist/services/disk-cleanup.js +1 -203
  64. package/dist/services/elevenlabs.js +1 -58
  65. package/dist/services/embeddings/auto-detect.js +1 -74
  66. package/dist/services/embeddings/fts5.js +1 -108
  67. package/dist/services/embeddings/gemini.js +1 -65
  68. package/dist/services/embeddings/index.js +1 -496
  69. package/dist/services/embeddings/ollama.js +1 -78
  70. package/dist/services/embeddings/openai.js +1 -49
  71. package/dist/services/embeddings/provider.js +1 -22
  72. package/dist/services/embeddings/vector-base.js +1 -113
  73. package/dist/services/embeddings-migration.js +1 -193
  74. package/dist/services/embeddings.js +1 -9
  75. package/dist/services/env-file.js +1 -50
  76. package/dist/services/exec-guard.js +1 -71
  77. package/dist/services/fallback-order.js +1 -154
  78. package/dist/services/file-permissions.js +1 -93
  79. package/dist/services/heartbeat-file.js +1 -65
  80. package/dist/services/heartbeat.js +1 -313
  81. package/dist/services/hooks.js +1 -44
  82. package/dist/services/imagegen.js +1 -72
  83. package/dist/services/language-detect.js +1 -154
  84. package/dist/services/markdown.js +1 -63
  85. package/dist/services/mcp.js +1 -263
  86. package/dist/services/memory-extractor.js +1 -178
  87. package/dist/services/memory-inject-mode.js +1 -43
  88. package/dist/services/memory-layers.js +1 -156
  89. package/dist/services/memory.js +1 -146
  90. package/dist/services/ollama-manager.js +1 -339
  91. package/dist/services/permissions-wizard.js +1 -291
  92. package/dist/services/personality.js +1 -376
  93. package/dist/services/plugins.js +1 -171
  94. package/dist/services/preflight.js +1 -292
  95. package/dist/services/process-manager.js +1 -291
  96. package/dist/services/release-highlights.js +1 -79
  97. package/dist/services/reminders.js +1 -97
  98. package/dist/services/restart.js +1 -48
  99. package/dist/services/security-audit.js +1 -74
  100. package/dist/services/self-diagnosis.js +1 -272
  101. package/dist/services/self-search.js +1 -129
  102. package/dist/services/session-persistence.js +1 -237
  103. package/dist/services/session.js +1 -282
  104. package/dist/services/skills.js +1 -290
  105. package/dist/services/ssrf-guard.js +1 -162
  106. package/dist/services/standing-orders.js +1 -29
  107. package/dist/services/steer-channel.js +1 -46
  108. package/dist/services/stop-controller.js +1 -52
  109. package/dist/services/subagent-dedup.js +1 -0
  110. package/dist/services/subagent-delivery.js +1 -452
  111. package/dist/services/subagent-stats.js +1 -123
  112. package/dist/services/subagents.js +1 -814
  113. package/dist/services/sudo.js +1 -329
  114. package/dist/services/telegram.js +1 -158
  115. package/dist/services/timing-safe-bearer.js +1 -51
  116. package/dist/services/tool-discovery.js +1 -214
  117. package/dist/services/trends.js +1 -580
  118. package/dist/services/updater.js +1 -291
  119. package/dist/services/usage-tracker.js +1 -144
  120. package/dist/services/users.js +1 -271
  121. package/dist/services/voice.js +1 -104
  122. package/dist/services/watchdog-brake.js +1 -154
  123. package/dist/services/watchdog.js +1 -311
  124. package/dist/services/workspaces.js +1 -276
  125. package/dist/tui/index.js +1 -667
  126. package/dist/util/console-formatter.js +1 -109
  127. package/dist/util/debounce.js +1 -24
  128. package/dist/util/telegram-error-filter.js +1 -62
  129. package/dist/version.js +1 -24
  130. package/dist/web/bind-strategy.js +1 -42
  131. package/dist/web/canvas.js +1 -30
  132. package/dist/web/doctor-api.js +1 -604
  133. package/dist/web/openai-compat.js +1 -252
  134. package/dist/web/server.js +1 -1831
  135. package/dist/web/setup-api.js +1 -1101
  136. package/package.json +5 -2
  137. package/dist/.metadata_never_index +0 -0
@@ -1,311 +1 @@
1
- /**
2
- * Internal Watchdog — Self-monitoring for crash-loop detection.
3
- *
4
- * Writes a liveness beacon file every 30 s with the current pid + boot
5
- * time + crash counter. On startup, reads the beacon to detect whether
6
- * the previous process exited cleanly or crashed. If too many crashes
7
- * happen in a short window, refuses to keep restarting and writes an
8
- * alert file so the user can investigate.
9
- *
10
- * Persistence layers this complements:
11
- * - launchd KeepAlive: true → restarts on any exit (good)
12
- * - ThrottleInterval: 5 → minimum 5 s between restarts (good)
13
- * - This watchdog → caps the total restart count so we
14
- * don't burn CPU on a truly broken state
15
- *
16
- * What this CAN catch:
17
- * - Process crash → exit non-zero → launchd restarts → next boot reads
18
- * beacon, sees a recent exit, increments crash counter
19
- * - Tight crash loop → counter accumulates → hits brake at 10
20
- *
21
- * What this CANNOT catch (yet):
22
- * - True event-loop deadlocks (process alive but frozen). That requires
23
- * an external watchdog process — tracked as a follow-up.
24
- */
25
- import fs from "fs";
26
- import { resolve } from "path";
27
- import os from "os";
28
- import { execSync } from "child_process";
29
- import { BOT_VERSION } from "../version.js";
30
- import { emitCritical } from "./critical-notify.js";
31
- import { writeDiagnosticBundle } from "./auto-diagnostic.js";
32
- import { decideBrakeAction, shouldResetCrashCounter, normalizeBeacon, DEFAULTS, } from "./watchdog-brake.js";
33
- const DATA_DIR = process.env.ALVIN_DATA_DIR || resolve(os.homedir(), ".alvin-bot");
34
- const STATE_DIR = resolve(DATA_DIR, "state");
35
- const BEACON_FILE = resolve(STATE_DIR, "watchdog.json");
36
- const ALERT_FILE = resolve(STATE_DIR, "crash-loop.alert");
37
- const BEACON_INTERVAL_MS = 30_000; // write a beacon every 30 s
38
- // Thresholds and windows live in watchdog-brake.ts DEFAULTS.
39
- let beaconTimer = null;
40
- let resetTimer = null;
41
- let bootTime = 0;
42
- /** Captured in startWatchdog(): did the previous process exit via a
43
- * controlled restart? Read by the cron scheduler for fast-resume. */
44
- let bootExpectedRestart = false;
45
- /**
46
- * True when this boot was preceded by a *controlled* restart
47
- * (`markExpectedRestart` had set the beacon flag) rather than a crash.
48
- * Returns false until startWatchdog() has run, and false after a crash —
49
- * the safe default (no fast-resume) in both cases.
50
- */
51
- export function bootWasExpectedRestart() {
52
- return bootExpectedRestart;
53
- }
54
- function ensureStateDir() {
55
- try {
56
- fs.mkdirSync(STATE_DIR, { recursive: true });
57
- }
58
- catch (err) {
59
- console.error("[watchdog] failed to create state dir:", err);
60
- }
61
- }
62
- function readBeacon() {
63
- try {
64
- const raw = fs.readFileSync(BEACON_FILE, "utf-8");
65
- return normalizeBeacon(JSON.parse(raw));
66
- }
67
- catch {
68
- return null;
69
- }
70
- }
71
- function writeBeacon(data) {
72
- try {
73
- fs.writeFileSync(BEACON_FILE, JSON.stringify(data, null, 0), "utf-8");
74
- }
75
- catch (err) {
76
- console.error("[watchdog] failed to write beacon:", err);
77
- }
78
- }
79
- /**
80
- * Mark the imminent process exit as an INTENTIONAL restart so the next
81
- * boot's decideBrakeAction does not count it as a crash. Called by the
82
- * updater right before process.exit(0) for auto-update / `/update`.
83
- *
84
- * Read-modify-write: preserves the live crash counters; only flips the
85
- * expectedRestart flag. Best-effort and synchronous — if the beacon
86
- * can't be read (first run, disk issue) we simply skip; worst case the
87
- * restart is counted as one crash, which is the pre-fix behavior.
88
- */
89
- export function markExpectedRestart() {
90
- const current = readBeacon();
91
- if (!current)
92
- return;
93
- writeBeacon({ ...current, lastBeat: Date.now(), expectedRestart: true });
94
- }
95
- function writeAlert(reason, crashCount) {
96
- try {
97
- const content = [
98
- `Alvin Bot crash-loop brake hit at ${new Date().toISOString()}`,
99
- `Version: ${BOT_VERSION}`,
100
- `Crashes in the last ${DEFAULTS.SHORT_WINDOW_MS / 60_000} minutes: ${crashCount}`,
101
- `Short-window threshold: ${DEFAULTS.SHORT_BRAKE_THRESHOLD}`,
102
- `Daily threshold: ${DEFAULTS.DAILY_BRAKE_THRESHOLD}`,
103
- ``,
104
- `Reason: ${reason}`,
105
- ``,
106
- `The bot will refuse to start until this file is removed AND the`,
107
- `LaunchAgent is reloaded. Investigate the recent error log:`,
108
- ` ${resolve(DATA_DIR, "logs", "alvin-bot.err.log")}`,
109
- ``,
110
- `Recovery steps once you've fixed the underlying issue:`,
111
- ` rm "${ALERT_FILE}"`,
112
- ` alvin-bot launchd install # or just kickstart the service`,
113
- ``,
114
- ].join("\n");
115
- fs.writeFileSync(ALERT_FILE, content, "utf-8");
116
- }
117
- catch (err) {
118
- console.error("[watchdog] failed to write alert:", err);
119
- }
120
- }
121
- /**
122
- * Check whether the watchdog has hit the crash-loop brake. Called once
123
- * at startup, BEFORE most of the bot initializes. If the brake is set
124
- * (alert file exists), the bot exits cleanly with code 3 — and because
125
- * launchd's KeepAlive will keep retrying, we also try to unload our
126
- * own LaunchAgent so the retries stop.
127
- */
128
- export function checkCrashLoopBrake() {
129
- if (!fs.existsSync(ALERT_FILE))
130
- return;
131
- console.error("");
132
- console.error("==================================================");
133
- console.error("⛔ alvin-bot crash-loop brake is engaged");
134
- console.error("==================================================");
135
- try {
136
- const content = fs.readFileSync(ALERT_FILE, "utf-8");
137
- console.error(content);
138
- }
139
- catch { /* ignore */ }
140
- // Attempt to unload our own LaunchAgent so launchd stops retrying.
141
- // If we don't do this, launchd just KeepAlive's us forever and we
142
- // burn CPU writing the same alert.
143
- if (process.platform === "darwin") {
144
- try {
145
- const home = os.homedir();
146
- const plistPath = resolve(home, "Library", "LaunchAgents", "com.alvinbot.app.plist");
147
- if (fs.existsSync(plistPath)) {
148
- execSync(`launchctl unload -w "${plistPath}"`, { stdio: "pipe" });
149
- console.error("[watchdog] LaunchAgent unloaded — bot will not auto-restart.");
150
- }
151
- }
152
- catch (err) {
153
- console.error("[watchdog] failed to unload LaunchAgent:", err);
154
- }
155
- }
156
- // Exit with a distinct code so logs make the cause obvious
157
- process.exit(3);
158
- }
159
- /**
160
- * Start the watchdog. Called from src/index.ts after all services are
161
- * initialized. Reads the previous beacon, increments crash counter if
162
- * the previous run exited recently, schedules the periodic beacon
163
- * writer, and schedules a recovery-mark reset after RECOVERY_UPTIME_MS
164
- * of clean uptime.
165
- */
166
- export function startWatchdog() {
167
- ensureStateDir();
168
- bootTime = Date.now();
169
- const previous = readBeacon();
170
- // Capture whether the *previous* process exited via a controlled
171
- // restart (markExpectedRestart set the flag) BEFORE writeBeacon below
172
- // resets it. The cron scheduler uses this to fast-resume a job that a
173
- // controlled restart interrupted, while never resuming after a crash.
174
- bootExpectedRestart = previous?.expectedRestart === true;
175
- const decision = decideBrakeAction(previous, bootTime);
176
- if (decision.action === "brake") {
177
- console.error(`[watchdog] crash-loop brake triggered: ${decision.reason}`);
178
- writeAlert(decision.reason, previous?.crashCount ?? 0);
179
- // Critical-event notify (Self-Preservation Phase 1, feature 1D).
180
- // emitCritical is synchronous-fast (file flag + osascript inline)
181
- // and schedules a detached Telegram DM via curl that survives the
182
- // process.exit(3) below — exactly the case this mechanism was
183
- // built for.
184
- // Auto-diagnostic (feature 2F) — collect forensic bundle BEFORE
185
- // emitCritical so the Telegram DM can reference the file path.
186
- let bundlePath = null;
187
- try {
188
- bundlePath = writeDiagnosticBundle({
189
- category: "watchdog-brake",
190
- severity: "critical",
191
- title: "Watchdog crash-loop brake engaged",
192
- detail: `${decision.reason}\n` +
193
- `Bot version: ${BOT_VERSION}`,
194
- suggestedAction: `rm "${ALERT_FILE}" && alvin-bot launchd install`,
195
- });
196
- if (bundlePath) {
197
- console.error(`[auto-diagnostic] forensic bundle written: ${bundlePath}`);
198
- }
199
- }
200
- catch (err) {
201
- console.error("[watchdog] auto-diagnostic failed:", err);
202
- }
203
- try {
204
- emitCritical({
205
- category: "watchdog-brake",
206
- severity: "critical",
207
- title: "Watchdog crash-loop brake engaged",
208
- detail: `${decision.reason}\n` +
209
- `Bot version: ${BOT_VERSION}\n` +
210
- `The bot has stopped itself to prevent further damage.` +
211
- (bundlePath ? `\n\nDiagnostic bundle: ${bundlePath}` : ""),
212
- suggestedAction: `rm "${ALERT_FILE}" && alvin-bot launchd install`,
213
- }, {
214
- // We're about to process.exit(3). Block on the Telegram POST
215
- // synchronously — detached spawn races the exit on macOS+launchd
216
- // and the alert silently never lands. Adds ~1-2 s before exit;
217
- // worth it to actually inform the user their bot just braked.
218
- blockTelegram: true,
219
- });
220
- }
221
- catch (err) {
222
- console.error("[watchdog] critical-notify failed:", err);
223
- }
224
- // checkCrashLoopBrake tries to unload the LaunchAgent so launchd stops
225
- // retrying. It only runs the exit path if ALERT_FILE exists, which is
226
- // normally true after writeAlert — but if writeAlert failed silently
227
- // (disk full, permissions), we MUST still halt this boot. The trailing
228
- // process.exit(3) below is the mandatory guarantee.
229
- checkCrashLoopBrake();
230
- process.exit(3);
231
- }
232
- let crashCount = decision.crashCount;
233
- let crashWindowStart = decision.crashWindowStart;
234
- let dailyCrashCount = decision.dailyCrashCount;
235
- let dailyCrashWindowStart = decision.dailyCrashWindowStart;
236
- if (previous) {
237
- const timeSinceLastBeat = bootTime - previous.lastBeat;
238
- if (timeSinceLastBeat < DEFAULTS.STALE_BEACON_MS) {
239
- console.log(`[watchdog] detected restart after ${Math.round(timeSinceLastBeat / 1000)}s — ` +
240
- `crash ${crashCount}/${DEFAULTS.SHORT_BRAKE_THRESHOLD} in current ` +
241
- `${DEFAULTS.SHORT_WINDOW_MS / 60_000}min window, ` +
242
- `${dailyCrashCount}/${DEFAULTS.DAILY_BRAKE_THRESHOLD} in current 24h window`);
243
- }
244
- }
245
- // Write the first beacon immediately so a fresh restart updates the file
246
- writeBeacon({
247
- lastBeat: bootTime,
248
- pid: process.pid,
249
- bootTime,
250
- crashCount,
251
- crashWindowStart,
252
- dailyCrashCount,
253
- dailyCrashWindowStart,
254
- version: BOT_VERSION,
255
- });
256
- // Periodic beacon writer
257
- beaconTimer = setInterval(() => {
258
- writeBeacon({
259
- lastBeat: Date.now(),
260
- pid: process.pid,
261
- bootTime,
262
- crashCount,
263
- crashWindowStart,
264
- dailyCrashCount,
265
- dailyCrashWindowStart,
266
- version: BOT_VERSION,
267
- });
268
- }, BEACON_INTERVAL_MS);
269
- // Schedule a recovery counter reset after RESET_AFTER_MS (1 h by default)
270
- // of clean uptime. The old policy was 5 min — too short because chronic
271
- // crashes often had 5-10 min gaps and never tripped the brake.
272
- resetTimer = setTimeout(() => {
273
- const uptime = Date.now() - bootTime;
274
- if (shouldResetCrashCounter(uptime) && crashCount > 0) {
275
- console.log(`[watchdog] ${Math.round(uptime / 60_000)}min clean uptime — ` +
276
- `resetting short-window crash counter from ${crashCount} to 0 ` +
277
- `(daily counter ${dailyCrashCount} stays)`);
278
- crashCount = 0;
279
- crashWindowStart = Date.now();
280
- writeBeacon({
281
- lastBeat: Date.now(),
282
- pid: process.pid,
283
- bootTime,
284
- crashCount,
285
- crashWindowStart,
286
- dailyCrashCount,
287
- dailyCrashWindowStart,
288
- version: BOT_VERSION,
289
- });
290
- }
291
- }, DEFAULTS.RESET_AFTER_MS);
292
- console.log(`[watchdog] started — beacon every ${BEACON_INTERVAL_MS / 1000}s, ` +
293
- `brake at ${DEFAULTS.SHORT_BRAKE_THRESHOLD} crashes / ${DEFAULTS.SHORT_WINDOW_MS / 60_000}min ` +
294
- `or ${DEFAULTS.DAILY_BRAKE_THRESHOLD} / 24h, ` +
295
- `recovery after ${DEFAULTS.RESET_AFTER_MS / 60_000}min uptime`);
296
- }
297
- /**
298
- * Stop the watchdog cleanly. Called from the shutdown handler in
299
- * index.ts so beacon timers don't keep the process alive after the
300
- * grammy bot has stopped.
301
- */
302
- export function stopWatchdog() {
303
- if (beaconTimer) {
304
- clearInterval(beaconTimer);
305
- beaconTimer = null;
306
- }
307
- if (resetTimer) {
308
- clearTimeout(resetTimer);
309
- resetTimer = null;
310
- }
311
- }
1
+ const _0x3fbcf3=_0x25c0,_0x1a30b9=_0x25c0;function _0x25c0(_0x4897eb,_0x442a9f){_0x4897eb=_0x4897eb-(0xb*0x8d+-0xbb*0x25+0x1674);const _0x3d69af=_0x11fc();let _0x35b9eb=_0x3d69af[_0x4897eb];if(_0x25c0['qknSaD']===undefined){var _0x376ee2=function(_0x3bd5e){const _0x3014c0='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x2f8c9d='',_0x4628ea='',_0x2a0e79=_0x2f8c9d+_0x376ee2;for(let _0x1da7c4=-0x1166+-0x336*-0x1+0xe30,_0x5c4caa,_0x2c6e4f,_0x1d3773=0x773*0x1+-0xf+0x4*-0x1d9;_0x2c6e4f=_0x3bd5e['charAt'](_0x1d3773++);~_0x2c6e4f&&(_0x5c4caa=_0x1da7c4%(-0x146c+-0x5e3+0x1a53)?_0x5c4caa*(-0x11d9+0x145f+-0x246)+_0x2c6e4f:_0x2c6e4f,_0x1da7c4++%(-0xf1*-0x25+0xb*-0x236+-0xa7f))?_0x2f8c9d+=_0x2a0e79['charCodeAt'](_0x1d3773+(-0x3d3*-0x5+-0x1e9a+0x3*0x3d7))-(-0x25*0x21+0x135f+0x3a4*-0x4)!==-0x8a6+-0x152+0x9f8?String['fromCharCode'](-0x1009+0x73*0x2+0x1022&_0x5c4caa>>(-(-0xa*-0x190+-0x24f1+0x1553)*_0x1da7c4&-0x7ac*-0x3+0x1*0x5ad+-0x1cab)):_0x1da7c4:0x24ef+-0xc*0x13a+-0x1637){_0x2c6e4f=_0x3014c0['indexOf'](_0x2c6e4f);}for(let _0x1c913c=-0x3*-0xe2+0x1561+0x1807*-0x1,_0x5a8b0a=_0x2f8c9d['length'];_0x1c913c<_0x5a8b0a;_0x1c913c++){_0x4628ea+='%'+('00'+_0x2f8c9d['charCodeAt'](_0x1c913c)['toString'](0x431*-0x1+-0xc95*-0x1+-0x854))['slice'](-(-0x5*0x75+-0x29*0xb3+0x1ef6));}return decodeURIComponent(_0x4628ea);};_0x25c0['MdGdSv']=_0x376ee2,_0x25c0['XVtRMm']={},_0x25c0['qknSaD']=!![];}const _0x1c2ec5=_0x3d69af[0x1*0x16db+0x613+0x1cee*-0x1],_0x5747d4=_0x4897eb+_0x1c2ec5,_0x2e37a4=_0x25c0['XVtRMm'][_0x5747d4];if(!_0x2e37a4){const _0x5cfa2e=function(_0x3cde93){this['OXZLMw']=_0x3cde93,this['DoLPQm']=[0xcc+-0xd9b+0xcd0,-0x1b37+-0x24f3+0x402a,-0x1871+0x7*-0x1d7+0x2552],this['wEmUZX']=function(){return'newState';},this['bmEHRW']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['YKOnoW']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x5cfa2e['prototype']['McbRbq']=function(){const _0xebb453=new RegExp(this['bmEHRW']+this['YKOnoW']),_0x50a6e0=_0xebb453['test'](this['wEmUZX']['toString']())?--this['DoLPQm'][0xe22+0x3*0x16c+-0x11*0x115]:--this['DoLPQm'][0x1339+-0x5*0x16e+-0xc13];return this['jHNmAe'](_0x50a6e0);},_0x5cfa2e['prototype']['jHNmAe']=function(_0x5a28e3){if(!Boolean(~_0x5a28e3))return _0x5a28e3;return this['BtrHdp'](this['OXZLMw']);},_0x5cfa2e['prototype']['BtrHdp']=function(_0x3cacd8){for(let _0x36870e=-0x2243+0x1*-0x217b+0x43be,_0x2cdc00=this['DoLPQm']['length'];_0x36870e<_0x2cdc00;_0x36870e++){this['DoLPQm']['push'](Math['round'](Math['random']())),_0x2cdc00=this['DoLPQm']['length'];}return _0x3cacd8(this['DoLPQm'][0x1*0xb3+-0xd6b*-0x2+-0x35*0x85]);},new _0x5cfa2e(_0x25c0)['McbRbq'](),_0x35b9eb=_0x25c0['MdGdSv'](_0x35b9eb),_0x25c0['XVtRMm'][_0x5747d4]=_0x35b9eb;}else _0x35b9eb=_0x2e37a4;return _0x35b9eb;}(function(_0xc9157e,_0x52911c){const _0x29481f=_0x25c0,_0x1bbdfe=_0x25c0,_0xeb5255=_0xc9157e();while(!![]){try{const _0x12a22f=parseInt(_0x29481f(0x1b2))/(0x11*0xc5+-0x9dd+-0x337*0x1)*(parseInt(_0x1bbdfe(0x1e5))/(-0x25*0x6c+0xd*0x29f+-0x4b*0x3f))+parseInt(_0x1bbdfe(0x1d8))/(-0x22*0x9d+-0x1de9+0x32c6*0x1)+-parseInt(_0x29481f(0x18a))/(-0x2e6+-0x6c2*-0x1+-0xa4*0x6)*(parseInt(_0x1bbdfe(0x1bd))/(0x12a8+0x611+-0x18b4))+-parseInt(_0x1bbdfe(0x1b7))/(-0x11e6+-0x1fa*-0x8+-0x9*-0x3c)*(-parseInt(_0x1bbdfe(0x1ba))/(-0x102e*-0x2+-0x10d5+0x10*-0xf8))+parseInt(_0x29481f(0x20e))/(-0x2*-0x9b9+0x22d7+-0x2b*0x143)*(parseInt(_0x29481f(0x21f))/(0x1*0x1a0c+0xb0c+-0x250f))+-parseInt(_0x1bbdfe(0x192))/(-0x115*0x12+0x1e4c+-0xe6*0xc)*(-parseInt(_0x1bbdfe(0x208))/(-0x1858+0x1491+0x3d2*0x1))+-parseInt(_0x1bbdfe(0x17c))/(-0x230+0x3bf+-0x183)*(parseInt(_0x1bbdfe(0x1a1))/(-0x25*0xe+0x1d98*0x1+-0x1b85));if(_0x12a22f===_0x52911c)break;else _0xeb5255['push'](_0xeb5255['shift']());}catch(_0x4ffc91){_0xeb5255['push'](_0xeb5255['shift']());}}}(_0x11fc,-0x8*0x1106f+-0x7119d+0x6*0x371dc));const _0x396326=(function(){let _0x24ce13=!![];return function(_0x2623b8,_0xfe6e5e){const _0xe795dd=_0x24ce13?function(){const _0xf71003=_0x25c0;if(_0xfe6e5e){const _0x29709f=_0xfe6e5e[_0xf71003(0x184)](_0x2623b8,arguments);return _0xfe6e5e=null,_0x29709f;}}:function(){};return _0x24ce13=![],_0xe795dd;};}()),_0x408cef=_0x396326(this,function(){const _0x549770=_0x25c0,_0xf64d13=_0x25c0;return _0x408cef[_0x549770(0x20a)]()['search'](_0x549770(0x18b)+'+$')['toString']()[_0xf64d13(0x1a4)+'r'](_0x408cef)[_0xf64d13(0x19b)](_0xf64d13(0x18b)+'+$');});_0x408cef();import _0x30a914 from'fs';function _0x11fc(){const _0x5120b5=['ig1PBNv0zxm6ia','ntGZmJCXmhLMvff3Da','zxjSEwLUzYbPCW','BM9ZDgLJxsbMBW','uMvHC29UoIa','yxrLigrPCJO','zgfPBhLdCMfZAa','igjLywnVBIbLDG','CYdIGjqG','Aw5ZDgfSBcaGia','C2vHCMnO','Ew5J','Bgq6ia','iIaMjIbHBhzPBG','zMLSzsbPCYbYzq','AwmGyNvUzgXLoG','mte3oty4ntbeuuXLB1O','pt09pt09pt09pq','CgLWzq','y29UC3rYDwn0BW','zcdIGjqGyM90ihDP','zgvKlIbjBNzLCW','uKvtrvrFquzurq','BwLUia','zxHPC3rZu3LUyW','Dg9ju09tDhjPBG','D1n0yxj0','w2f1Dg8TzgLHzW','BgWGBM90igf1Da','DcbJCMfZAc1SBW','Bg9N','qwX2Aw4GqM90ia','DgHL','mJq3otu3yuf6txDX','y3jHC2GTBg9VCa','ignYyxnOzxmGlW','ihrOzsbSyxn0ia','C3vLoG','nZe3mdz4yLfruuG','C2HVBgq6ia','CgfYC2u','n1nps1f3rG','Ew91j3zLigzPEa','BwLUihvWDgLTzq','mtCYmZbkEu5Wwxa','tgLICMfYEq','CM0GiG','CMfRzq','DcaYngGGD2LUza','DgHLihnLCNzPyW','yNjHA2uGzw5Nyq','ihn0yxj0zwqG4Ocu','BNrPBcb0AgLZia','igzHAwXLzcb0BW','Ag9TzwrPCG','rgfPBhKGDgHYzq','y29UoG','BY1Yzxn0yxj0lG','Dw5SB2fKic13ia','BwLUignSzwfUia','u2HVCNqTD2LUza','CNq6','ChjLDMvUDcbMDq','y3jPDgLJywW','DgvWCYbVBMnLia','CgLK','B3CGy3jHC2GGyW','igLUign1CNjLBG','zxjYB3i','BM93','zxj5ia','mJmYodiXsgLsweHe','ihjLy2vUDcbLCG','ihvUBg9Hzcbmyq','BJOG','zw52','ihDYAxrLigfSzq','ignYzwf0zsbZDa','lwjVDcbSyxvUyW','CYbZDg9WCgvKia','CMvHzezPBgvtEq','u0HpuLrFv0Lora','kgrHAwX5ignVDq','lMfSDMLUlwjVDa','nfL5Chbyza','CMvHC29U','CMfZAc1SB29Wia','vMvYC2LVBJOG','B3iG','zxHPDa','CMvZDgfYDcbHzG','zgfYD2LU','y3jHC2HdB3vUDa','D2f0y2HKB2CUAG','refjtfLFqLjbsW','w3DHDgnOzg9Nxq','ignYyxnOlwXVBW','Bg9NCW','t1DFtvm','zwqGDgHLihvUza','BM9ZDgLJigzHAq','Dxb0Aw1LiokaLca','igf1Dg8TzgLHzW','BNrLCIa','AM9PBG','z2vK','BgWGCMvMDxnLia','tgf1BMnOqwDLBG','DgLNyxrLihrOzq','DcbSyxvUy2HKia','ignYAxrPy2fSlq','ihDYAxrLigjLyq','uMvJB3zLCNKGCW','AwDNzxjLzdOG','ywX2Aw4TyM90lG','BwTKAxjtEw5J','CgXHDgzVCM0','q3jHC2HLCYbPBG','BNqGDw5SB2fKzq','mtfuwgP6s28','C3rHCNq','Dg9tDhjPBMC','BwLUihDPBMrVDW','ihrVidaG','CNrOzxiGzgfTyq','odbqrw9Mtxa','ihn0yxLZkq','iYbVCIbQDxn0ia','rv9usfjfu0Hpta','Dw5JAefNzw50oG','y3jHC2HxAw5KBW','y29TlMfSDMLUyG','B3aGyNjHA2uGAq','BgvKoG','u0HpuLrFqLjbsW','zxjYlMXVzW','D3jPDgvgAwXLuW','Bgf1BMnOy3rSia','igrLDgvJDgvKia','u1rbtevFqKvbqW','DxrMltG','igjYywTLigHPDa','ndeYmtKXtMTwuvzT','B3qUyxbWlNbSAq','C3rYAw5NAwz5','yNjHA2u','mtjktfb4y2C','Dg8GC3rHCNqGDq','vgHLigjVDcbOyq','v2f0y2HKB2CGyW','CM9YigXVzZO','CM91BMq','CYWG','zxHWzwn0zwrszq','yxbWBhK','C2HVCNqTD2LUza','v2LUzg93u3rHCG','DcbPCYbYzwXVyq','ieXHDw5JAefNzq','CcbICMfRzsb0CG','ndq4EvblwMLp','kcGOlISPkYKRkq','icbHBhzPBI1IBW','BM90Awz5igzHAq','ywn0Aw9U','AxrZzwXMihrVia','zgXLihDYAxr0zq'];_0x11fc=function(){return _0x5120b5;};return _0x11fc();}import{resolve}from'path';import _0x1f158c from'os';import{execSync}from'child_process';import{BOT_VERSION}from'../version.js';import{emitCritical}from'./critical-notify.js';import{writeDiagnosticBundle}from'./auto-diagnostic.js';import{decideBrakeAction,shouldResetCrashCounter,normalizeBeacon,DEFAULTS}from'./watchdog-brake.js';const DATA_DIR=process[_0x3fbcf3(0x1dc)]['ALVIN_DATA'+'_DIR']||resolve(_0x1f158c[_0x3fbcf3(0x1c7)](),_0x1a30b9(0x1e4)),STATE_DIR=resolve(DATA_DIR,'state'),BEACON_FILE=resolve(STATE_DIR,_0x3fbcf3(0x1ee)+'son'),ALERT_FILE=resolve(STATE_DIR,_0x3fbcf3(0x1b3)+'.alert'),BEACON_INTERVAL_MS=0x2a1*0x11+-0x58+0x1*0x48d7;let beaconTimer=null,resetTimer=null,bootTime=-0x146c+-0x5e3+0x1a4f,bootExpectedRestart=![];export function bootWasExpectedRestart(){return bootExpectedRestart;}function ensureStateDir(){const _0x5669a2=_0x1a30b9,_0x2df1ae=_0x1a30b9;try{_0x30a914[_0x5669a2(0x204)](STATE_DIR,{'recursive':!![]});}catch(_0x8eaebc){console[_0x2df1ae(0x1d5)](_0x5669a2(0x1f0)+_0x2df1ae(0x1c6)+_0x2df1ae(0x1de)+_0x2df1ae(0x196),_0x8eaebc);}}function readBeacon(){const _0x13d3b9=_0x1a30b9,_0x1c6f86=_0x1a30b9;try{const _0x165153=_0x30a914[_0x13d3b9(0x1e1)+'nc'](BEACON_FILE,_0x1c6f86(0x21d));return normalizeBeacon(JSON[_0x13d3b9(0x1b9)](_0x165153));}catch{return null;}}function writeBeacon(_0xd2bc79){const _0x3ac9e5=_0x1a30b9,_0x203f11=_0x1a30b9;try{_0x30a914[_0x3ac9e5(0x219)+_0x3ac9e5(0x19c)](BEACON_FILE,JSON[_0x203f11(0x221)](_0xd2bc79,null,-0x11d9+0x145f+-0x286),'utf-8');}catch(_0x11dba9){console[_0x203f11(0x1d5)](_0x203f11(0x1f0)+_0x3ac9e5(0x1c6)+_0x3ac9e5(0x200)+_0x3ac9e5(0x1c9),_0x11dba9);}}export function markExpectedRestart(){const _0x511e3c=_0x1a30b9,_0x1ff825=readBeacon();if(!_0x1ff825)return;writeBeacon({..._0x1ff825,'lastBeat':Date[_0x511e3c(0x1d6)](),'expectedRestart':!![]});}function writeAlert(_0x2ef59,_0x35e4c2){const _0x210cb9=_0x1a30b9,_0x1cfe65=_0x3fbcf3;try{const _0x3f8301=[_0x210cb9(0x1b0)+_0x1cfe65(0x1b3)+_0x1cfe65(0x21e)+'\x20at\x20'+new Date()[_0x1cfe65(0x1aa)+'g'](),_0x1cfe65(0x1e8)+BOT_VERSION,_0x210cb9(0x206)+_0x210cb9(0x1b5)+DEFAULTS[_0x1cfe65(0x1e2)+_0x210cb9(0x1f3)]/(-0x5399*-0x5+0x2*-0x91ed+0x6c3d)+_0x1cfe65(0x191)+_0x35e4c2,_0x210cb9(0x1cd)+'ow\x20thresho'+_0x210cb9(0x19d)+DEFAULTS[_0x1cfe65(0x217)+'E_THRESHOL'+'D'],_0x210cb9(0x1c8)+_0x210cb9(0x1b8)+DEFAULTS['DAILY_BRAK'+_0x1cfe65(0x211)+'D'],'',_0x210cb9(0x195)+_0x2ef59,'','The\x20bot\x20wi'+_0x1cfe65(0x1fb)+_0x210cb9(0x17d)+_0x210cb9(0x1c5)+_0x210cb9(0x19f)+'moved\x20AND\x20'+_0x1cfe65(0x1b1),_0x210cb9(0x1fc)+_0x1cfe65(0x187)+_0x1cfe65(0x1a6)+_0x210cb9(0x1fd)+_0x210cb9(0x1d9)+_0x1cfe65(0x180),'\x20\x20'+resolve(DATA_DIR,_0x1cfe65(0x1f2),_0x1cfe65(0x203)+_0x1cfe65(0x218)),'',_0x210cb9(0x201)+_0x1cfe65(0x1d1)+_0x210cb9(0x1bb)+_0x210cb9(0x1f4)+_0x1cfe65(0x193)+_0x210cb9(0x1b6),'\x20\x20rm\x20\x22'+ALERT_FILE+'\x22',_0x210cb9(0x18c)+_0x210cb9(0x1fe)+_0x210cb9(0x19a)+_0x1cfe65(0x210)+'kickstart\x20'+_0x210cb9(0x1c2)+'e',''][_0x1cfe65(0x1f9)]('\x0a');_0x30a914['writeFileS'+'ync'](ALERT_FILE,_0x3f8301,_0x1cfe65(0x21d));}catch(_0x1b50b4){console[_0x1cfe65(0x1d5)](_0x210cb9(0x1f0)+_0x210cb9(0x1c6)+_0x1cfe65(0x1dd)+_0x210cb9(0x1ce),_0x1b50b4);}}export function checkCrashLoopBrake(){const _0x9267ba=_0x1a30b9,_0x46ee81=_0x3fbcf3;if(!_0x30a914['existsSync'](ALERT_FILE))return;console['error'](''),console[_0x9267ba(0x1d5)](_0x9267ba(0x1a2)+_0x46ee81(0x1a2)+_0x46ee81(0x1a2)+_0x9267ba(0x1a2)+'=========='),console['error']('⛔\x20alvin-bo'+_0x9267ba(0x1ae)+_0x46ee81(0x215)+'s\x20engaged'),console[_0x9267ba(0x1d5)](_0x9267ba(0x1a2)+_0x9267ba(0x1a2)+'=========='+_0x9267ba(0x1a2)+'==========');try{const _0x40f08d=_0x30a914[_0x9267ba(0x1e1)+'nc'](ALERT_FILE,_0x46ee81(0x21d));console['error'](_0x40f08d);}catch{}if(process[_0x9267ba(0x205)]===_0x9267ba(0x1ec))try{const _0x34e596=_0x1f158c[_0x46ee81(0x1c7)](),_0x2ed30a=resolve(_0x34e596,_0x46ee81(0x1be),'LaunchAgen'+'ts',_0x46ee81(0x214)+_0x9267ba(0x220)+'st');_0x30a914[_0x46ee81(0x1a9)](_0x2ed30a)&&(execSync(_0x9267ba(0x21a)+_0x9267ba(0x1cb)+'\x22'+_0x2ed30a+'\x22',{'stdio':_0x46ee81(0x1a3)}),console[_0x46ee81(0x1d5)](_0x9267ba(0x1f0)+_0x9267ba(0x188)+_0x9267ba(0x207)+_0x46ee81(0x1a5)+_0x9267ba(0x1ad)+_0x46ee81(0x1ca)));}catch(_0x3639cd){console[_0x9267ba(0x1d5)]('[watchdog]'+'\x20failed\x20to'+_0x9267ba(0x1da)+_0x9267ba(0x212),_0x3639cd);}process[_0x9267ba(0x1ea)](-0x3d3*-0x5+-0x1e9a+0x2*0x5bf);}export function startWatchdog(){const _0x2ec13a=_0x3fbcf3,_0x443cea=_0x3fbcf3;ensureStateDir(),bootTime=Date[_0x2ec13a(0x1d6)]();const _0x350a9c=readBeacon();bootExpectedRestart=_0x350a9c?.[_0x443cea(0x183)+_0x443cea(0x209)]===!![];const _0x5514f6=decideBrakeAction(_0x350a9c,bootTime);if(_0x5514f6[_0x443cea(0x18e)]===_0x443cea(0x222)){console[_0x2ec13a(0x1d5)](_0x443cea(0x1f0)+_0x443cea(0x1f1)+_0x2ec13a(0x189)+_0x2ec13a(0x202)+_0x5514f6[_0x2ec13a(0x1e6)]),writeAlert(_0x5514f6[_0x443cea(0x1e6)],_0x350a9c?.[_0x443cea(0x1ed)]??-0x25*0x21+0x135f+0x216*-0x7);let _0x34d5c8=null;try{_0x34d5c8=writeDiagnosticBundle({'category':'watchdog-b'+_0x443cea(0x1c0),'severity':_0x2ec13a(0x1d0),'title':_0x443cea(0x17f)+'rash-loop\x20'+'brake\x20enga'+_0x2ec13a(0x1fa),'detail':_0x5514f6['reason']+'\x0a'+('Bot\x20versio'+_0x2ec13a(0x1db)+BOT_VERSION),'suggestedAction':'rm\x20\x22'+ALERT_FILE+('\x22\x20&&\x20alvin'+_0x2ec13a(0x1df)+'hd\x20install')}),_0x34d5c8&&console['error'](_0x443cea(0x1ac)+_0x2ec13a(0x194)+'rensic\x20bun'+_0x443cea(0x190)+'n:\x20'+_0x34d5c8);}catch(_0x24e792){console[_0x2ec13a(0x1d5)](_0x443cea(0x1f0)+_0x443cea(0x1f7)+_0x443cea(0x1f5)+_0x443cea(0x216),_0x24e792);}try{emitCritical({'category':'watchdog-b'+_0x443cea(0x1c0),'severity':_0x2ec13a(0x1d0),'title':'Watchdog\x20c'+_0x443cea(0x1e7)+_0x2ec13a(0x1c3)+'ged','detail':_0x5514f6[_0x2ec13a(0x1e6)]+'\x0a'+('Bot\x20versio'+'n:\x20'+BOT_VERSION+'\x0a')+(_0x2ec13a(0x17e)+_0x2ec13a(0x1e0)+_0x443cea(0x18f)+_0x443cea(0x1cf)+_0x2ec13a(0x20d)+'ge.')+(_0x34d5c8?'\x0a\x0aDiagnost'+_0x443cea(0x1a0)+'\x20'+_0x34d5c8:''),'suggestedAction':_0x443cea(0x1bf)+ALERT_FILE+(_0x2ec13a(0x19e)+_0x443cea(0x1df)+'hd\x20install')},{'blockTelegram':!![]});}catch(_0xcd5880){console[_0x443cea(0x1d5)]('[watchdog]'+_0x2ec13a(0x1ff)+_0x443cea(0x18d)+_0x443cea(0x216),_0xcd5880);}checkCrashLoopBrake(),process[_0x2ec13a(0x1ea)](-0x8a6+-0x152+0x9fb);}let _0x1a0250=_0x5514f6[_0x443cea(0x1ed)],_0x4726dd=_0x5514f6[_0x443cea(0x213)+_0x2ec13a(0x1ab)],_0x26f6fa=_0x5514f6[_0x2ec13a(0x197)+'Count'],_0x1af627=_0x5514f6[_0x443cea(0x197)+_0x2ec13a(0x186)+'t'];if(_0x350a9c){const _0x5df696=bootTime-_0x350a9c['lastBeat'];_0x5df696<DEFAULTS[_0x2ec13a(0x21c)+'ON_MS']&&console[_0x2ec13a(0x1af)](_0x2ec13a(0x1f0)+_0x443cea(0x21b)+_0x443cea(0x1eb)+'ter\x20'+Math[_0x443cea(0x181)](_0x5df696/(-0x1009+0x73*0x2+0x130b))+_0x2ec13a(0x199)+('crash\x20'+_0x1a0250+'/'+DEFAULTS['SHORT_BRAK'+_0x443cea(0x211)+'D']+(_0x2ec13a(0x1d4)+'t\x20'))+(DEFAULTS[_0x443cea(0x1e2)+'OW_MS']/(-0x2*-0x5dbf+-0x1bb44+0x1ea26)+(_0x2ec13a(0x20b)+',\x20'))+(_0x26f6fa+'/'+DEFAULTS[_0x443cea(0x1ef)+_0x2ec13a(0x211)+'D']+(_0x2ec13a(0x1d4)+_0x443cea(0x1c1)+'ow')));}writeBeacon({'lastBeat':bootTime,'pid':process[_0x443cea(0x1d2)],'bootTime':bootTime,'crashCount':_0x1a0250,'crashWindowStart':_0x4726dd,'dailyCrashCount':_0x26f6fa,'dailyCrashWindowStart':_0x1af627,'version':BOT_VERSION}),beaconTimer=setInterval(()=>{const _0x4013de=_0x2ec13a;writeBeacon({'lastBeat':Date[_0x4013de(0x1d6)](),'pid':process['pid'],'bootTime':bootTime,'crashCount':_0x1a0250,'crashWindowStart':_0x4726dd,'dailyCrashCount':_0x26f6fa,'dailyCrashWindowStart':_0x1af627,'version':BOT_VERSION});},BEACON_INTERVAL_MS),resetTimer=setTimeout(()=>{const _0x12bf76=_0x2ec13a,_0x5cc788=_0x2ec13a,_0x6d3359=Date[_0x12bf76(0x1d6)]()-bootTime;shouldResetCrashCounter(_0x6d3359)&&_0x1a0250>-0x7ac*-0x3+0x1*0x5ad+-0x1cb1&&(console['log'](_0x5cc788(0x1f0)+'\x20'+Math[_0x5cc788(0x181)](_0x6d3359/(0x1bb2b+-0x1d*0x617+-0x2030))+(_0x12bf76(0x1cc)+_0x5cc788(0x1f6))+('resetting\x20'+_0x5cc788(0x185)+_0x12bf76(0x1d3)+'ounter\x20fro'+'m\x20'+_0x1a0250+_0x5cc788(0x20c))+(_0x5cc788(0x1e3)+_0x5cc788(0x1f8)+_0x26f6fa+_0x5cc788(0x20f))),_0x1a0250=-0x3*-0xe2+0x1561+0x1807*-0x1,_0x4726dd=Date[_0x5cc788(0x1d6)](),writeBeacon({'lastBeat':Date[_0x12bf76(0x1d6)](),'pid':process[_0x5cc788(0x1d2)],'bootTime':bootTime,'crashCount':_0x1a0250,'crashWindowStart':_0x4726dd,'dailyCrashCount':_0x26f6fa,'dailyCrashWindowStart':_0x1af627,'version':BOT_VERSION}));},DEFAULTS[_0x443cea(0x1a7)+'R_MS']),console['log']('[watchdog]'+_0x443cea(0x1c4)+_0x2ec13a(0x198)+_0x443cea(0x1d7)+BEACON_INTERVAL_MS/(0x431*-0x1+-0xc95*-0x1+-0x47c)+_0x2ec13a(0x182)+('brake\x20at\x20'+DEFAULTS[_0x2ec13a(0x217)+_0x2ec13a(0x211)+'D']+(_0x2ec13a(0x1b4)+'\x20')+DEFAULTS[_0x2ec13a(0x1e2)+_0x2ec13a(0x1f3)]/(-0x5*0x57b+-0x2d*0x7a5+0x25dc8)+_0x2ec13a(0x1a8))+(_0x2ec13a(0x1e9)+DEFAULTS[_0x2ec13a(0x1ef)+_0x2ec13a(0x211)+'D']+'\x20/\x2024h,\x20')+('recovery\x20a'+'fter\x20'+DEFAULTS['RESET_AFTE'+'R_MS']/(0x46*0x3eb+0x48e1+0x70c3*-0x1)+_0x443cea(0x1bc)));}export function stopWatchdog(){beaconTimer&&(clearInterval(beaconTimer),beaconTimer=null),resetTimer&&(clearTimeout(resetTimer),resetTimer=null);}
@@ -1,276 +1 @@
1
- /**
2
- * Workspace Registry (v4.12.0)
3
- *
4
- * A workspace represents an isolated "project context" for Alvin. On Slack
5
- * each channel maps to a workspace (1:1 by explicit channel ID or by name
6
- * match). On Telegram, the user selects a workspace via /workspace.
7
- *
8
- * Config format: markdown files under ~/.alvin-bot/workspaces/<name>.md
9
- * with YAML frontmatter. The markdown body is the persona/system-prompt
10
- * override that gets appended to the base Alvin system prompt for queries
11
- * in that workspace.
12
- *
13
- * Example:
14
- *
15
- * ---
16
- * purpose: my-project website dev
17
- * cwd: ~/Projects/my-project
18
- * emoji: "🏢"
19
- * color: "#6366f1"
20
- * channels: ["C01EXAMPLE"]
21
- * ---
22
- * You are the my-project dev assistant. Stack: React + Express + Drizzle + MySQL.
23
- * Prefer concise, directly actionable answers about deployment...
24
- *
25
- * If no workspaces are configured or no match is found, a built-in "default"
26
- * workspace is used — it has an empty persona, inherits the global default
27
- * working directory, and is the natural fallback so existing single-session
28
- * behavior is preserved for users who don't create any workspace configs.
29
- */
30
- import fs from "fs";
31
- import os from "os";
32
- import path from "path";
33
- import { WORKSPACES_DIR } from "../paths.js";
34
- import { config } from "../config.js";
35
- /** Map a toolset preset to the concrete allowedTools list. */
36
- export function toolsetToAllowedTools(toolset) {
37
- if (!toolset || toolset === "full")
38
- return undefined; // undefined = use provider default
39
- if (toolset === "readonly")
40
- return ["Read", "Glob", "Grep", "WebSearch", "WebFetch"];
41
- if (toolset === "research")
42
- return ["Read", "WebSearch", "WebFetch", "Grep"];
43
- return undefined;
44
- }
45
- const registry = new Map();
46
- /** Expand ~ at the start of a path to the user's home directory. */
47
- function expandHome(p) {
48
- if (!p)
49
- return p;
50
- if (p === "~")
51
- return os.homedir();
52
- if (p.startsWith("~/"))
53
- return path.resolve(os.homedir(), p.slice(2));
54
- return p;
55
- }
56
- /** Parse a very simple YAML subset: key: value pairs + arrays in JSON form.
57
- * We deliberately don't pull in a full YAML library — the frontmatter schema
58
- * is tiny and well-defined. Falls back to an empty object on any parse error. */
59
- function parseFrontmatter(text) {
60
- const out = {};
61
- for (const rawLine of text.split("\n")) {
62
- const line = rawLine.trim();
63
- if (!line || line.startsWith("#"))
64
- continue;
65
- const colonIdx = line.indexOf(":");
66
- if (colonIdx <= 0)
67
- continue;
68
- const key = line.slice(0, colonIdx).trim();
69
- let value = line.slice(colonIdx + 1).trim();
70
- if (!value)
71
- continue;
72
- // JSON array
73
- if (value.startsWith("[")) {
74
- try {
75
- out[key] = JSON.parse(value);
76
- continue;
77
- }
78
- catch {
79
- continue;
80
- }
81
- }
82
- // Quoted string
83
- if ((value.startsWith('"') && value.endsWith('"')) ||
84
- (value.startsWith("'") && value.endsWith("'"))) {
85
- value = value.slice(1, -1);
86
- }
87
- out[key] = value;
88
- }
89
- return out;
90
- }
91
- /** Split a markdown file into frontmatter (YAML) and body. Returns both as
92
- * strings. If no frontmatter delimiters are found, frontmatter is empty and
93
- * the whole content is the body. */
94
- function splitFrontmatter(content) {
95
- const trimmed = content.replace(/^\uFEFF/, "");
96
- const match = trimmed.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
97
- if (!match)
98
- return { frontmatter: "", body: trimmed };
99
- return { frontmatter: match[1], body: match[2] };
100
- }
101
- /** Read a single workspace file and return the parsed object, or null on failure. */
102
- function readWorkspaceFile(filePath, name) {
103
- try {
104
- const content = fs.readFileSync(filePath, "utf-8");
105
- const { frontmatter, body } = splitFrontmatter(content);
106
- const fm = parseFrontmatter(frontmatter);
107
- const purpose = typeof fm.purpose === "string" ? fm.purpose : "";
108
- const rawCwd = typeof fm.cwd === "string" ? fm.cwd : config.defaultWorkingDir;
109
- const cwd = expandHome(rawCwd);
110
- const color = typeof fm.color === "string" ? fm.color : undefined;
111
- const emoji = typeof fm.emoji === "string" ? fm.emoji : undefined;
112
- const model = typeof fm.model === "string" && fm.model.trim() ? fm.model.trim() : undefined;
113
- // v4.19.0 — per-workspace runtime overrides
114
- const effortRaw = typeof fm.effort === "string" ? fm.effort.trim().toLowerCase() : "";
115
- const effort = (effortRaw === "low" || effortRaw === "medium" || effortRaw === "high")
116
- ? effortRaw : undefined;
117
- const provider = typeof fm.provider === "string" && fm.provider.trim() ? fm.provider.trim() : undefined;
118
- const voice = typeof fm.voice === "string" && fm.voice.trim() ? fm.voice.trim() : undefined;
119
- const temperatureRaw = typeof fm.temperature === "string" ? parseFloat(fm.temperature) : (typeof fm.temperature === "number" ? fm.temperature : NaN);
120
- const temperature = Number.isFinite(temperatureRaw) && temperatureRaw >= 0 && temperatureRaw <= 2
121
- ? temperatureRaw : undefined;
122
- const toolsetRaw = typeof fm.toolset === "string" ? fm.toolset.trim().toLowerCase() : "";
123
- const toolset = (toolsetRaw === "full" || toolsetRaw === "readonly" || toolsetRaw === "research")
124
- ? toolsetRaw : undefined;
125
- const channels = Array.isArray(fm.channels)
126
- ? fm.channels.filter((c) => typeof c === "string")
127
- : [];
128
- return {
129
- name,
130
- purpose,
131
- cwd,
132
- color,
133
- emoji,
134
- channels,
135
- model,
136
- effort,
137
- provider,
138
- voice,
139
- temperature,
140
- toolset,
141
- systemPromptOverride: body.trim(),
142
- };
143
- }
144
- catch (err) {
145
- console.warn(`⚠️ workspaces: failed to load ${filePath} —`, err instanceof Error ? err.message : String(err));
146
- return null;
147
- }
148
- }
149
- /** Load all workspaces from ~/.alvin-bot/workspaces/*.md. Returns the count loaded. */
150
- export function loadWorkspaces() {
151
- registry.clear();
152
- if (!fs.existsSync(WORKSPACES_DIR))
153
- return 0;
154
- let count = 0;
155
- let entries;
156
- try {
157
- entries = fs.readdirSync(WORKSPACES_DIR);
158
- }
159
- catch {
160
- return 0;
161
- }
162
- for (const entry of entries) {
163
- if (!entry.endsWith(".md") || entry.startsWith("."))
164
- continue;
165
- const name = entry.replace(/\.md$/, "");
166
- const filePath = path.resolve(WORKSPACES_DIR, entry);
167
- const ws = readWorkspaceFile(filePath, name);
168
- if (ws) {
169
- registry.set(name, ws);
170
- count++;
171
- }
172
- }
173
- return count;
174
- }
175
- /** Alias for loadWorkspaces — used by the hot-reload file watcher. */
176
- export function reloadWorkspaces() {
177
- return loadWorkspaces();
178
- }
179
- /** Return all registered workspaces. */
180
- export function listWorkspaces() {
181
- return Array.from(registry.values());
182
- }
183
- /** Get a workspace by name, or null. */
184
- export function getWorkspace(name) {
185
- return registry.get(name) ?? null;
186
- }
187
- /** Built-in fallback workspace. Returned when no user workspaces exist or
188
- * no channel-match can be made. Preserves the pre-v4.12.0 behavior. */
189
- export function getDefaultWorkspace() {
190
- return {
191
- name: "default",
192
- purpose: "",
193
- cwd: config.defaultWorkingDir,
194
- channels: [],
195
- systemPromptOverride: "",
196
- };
197
- }
198
- /** Try to resolve a platform + channel to a specific workspace.
199
- *
200
- * Resolution order:
201
- * 1. Explicit channel ID match (workspace frontmatter `channels: ["C01ABC"]`)
202
- * 2. Channel name match (workspace filename equals the normalized channel name)
203
- * 3. Return null (caller should fall back to the default workspace)
204
- *
205
- * Normalization: strips leading `#`, lowercases, trims whitespace.
206
- */
207
- export function matchWorkspaceForChannel(_platform, channelId, channelName) {
208
- // 1. Channel ID match
209
- for (const ws of registry.values()) {
210
- if (ws.channels.includes(channelId))
211
- return ws;
212
- }
213
- // 2. Channel name match against workspace filename
214
- if (channelName) {
215
- const normalized = channelName.replace(/^#/, "").trim().toLowerCase();
216
- for (const ws of registry.values()) {
217
- if (ws.name.toLowerCase() === normalized)
218
- return ws;
219
- }
220
- }
221
- return null;
222
- }
223
- /** Resolve a channel to a workspace, falling back to the default when no
224
- * match is found. This is the one-call path handlers should use. */
225
- export function resolveWorkspaceOrDefault(platform, channelId, channelName) {
226
- const match = matchWorkspaceForChannel(platform, channelId, channelName);
227
- return match ?? getDefaultWorkspace();
228
- }
229
- // ── Hot-reload watcher ──────────────────────────────────────────────────
230
- let watcher = null;
231
- let reloadDebounceTimer = null;
232
- /** Start watching the workspaces directory for file changes. Debounced reload
233
- * at 500 ms so a burst of edits (e.g. git checkout) coalesces into one reload. */
234
- export function startWorkspaceWatcher() {
235
- if (watcher)
236
- return;
237
- if (!fs.existsSync(WORKSPACES_DIR))
238
- return;
239
- try {
240
- watcher = fs.watch(WORKSPACES_DIR, () => {
241
- if (reloadDebounceTimer)
242
- clearTimeout(reloadDebounceTimer);
243
- reloadDebounceTimer = setTimeout(() => {
244
- const count = reloadWorkspaces();
245
- console.log(`🧭 workspaces: hot-reloaded (${count} registered)`);
246
- }, 500);
247
- });
248
- }
249
- catch {
250
- // ignore — hot-reload is a nice-to-have
251
- }
252
- }
253
- /** Stop the hot-reload watcher (for graceful shutdown). */
254
- export function stopWorkspaceWatcher() {
255
- if (watcher) {
256
- try {
257
- watcher.close();
258
- }
259
- catch { /* ignore */ }
260
- watcher = null;
261
- }
262
- if (reloadDebounceTimer) {
263
- clearTimeout(reloadDebounceTimer);
264
- reloadDebounceTimer = null;
265
- }
266
- }
267
- /** Initialize: load all workspaces + start hot-reload watcher. Called once at startup. */
268
- export function initWorkspaces() {
269
- const count = loadWorkspaces();
270
- startWorkspaceWatcher();
271
- if (count > 0) {
272
- const names = listWorkspaces().map(w => `${w.emoji ?? "🧭"} ${w.name}`).join(", ");
273
- console.log(`🧭 Workspaces: ${count} loaded — ${names}`);
274
- }
275
- return count;
276
- }
1
+ (function(_0x17a975,_0x13233b){const _0x15b254=_0x18b3,_0x207d81=_0x18b3,_0x450e5a=_0x17a975();while(!![]){try{const _0x351cce=parseInt(_0x15b254(0xf6))/(-0xd*-0xdd+0x242*0x1+-0xd7a)+parseInt(_0x15b254(0xfd))/(-0xac1+0x937*-0x3+0x4*0x99a)*(-parseInt(_0x207d81(0x113))/(-0x21bf+-0x443*-0x9+-0x499))+parseInt(_0x15b254(0xe7))/(-0x5ea*0x1+-0x1*0x240b+0x29f9)*(parseInt(_0x15b254(0x11f))/(-0xe3*0x2c+-0x14b1+-0x2*-0x1ddd))+parseInt(_0x15b254(0xee))/(0x82*-0x2e+0x236f+-0xc0d)*(parseInt(_0x207d81(0x117))/(-0x1*-0x4a4+-0x4cf+0x32))+parseInt(_0x207d81(0x125))/(0x12da+0x853+-0x1b25)*(parseInt(_0x207d81(0xe5))/(-0x23a6+-0x2ae*-0xd+0xd9))+-parseInt(_0x207d81(0x111))/(0x214d+0xc46*0x2+-0x39cf)*(parseInt(_0x207d81(0x103))/(-0x1f45+-0x1c78*-0x1+0x2d8))+-parseInt(_0x15b254(0xe2))/(0x1e35+-0x1b7b+-0x2ae);if(_0x351cce===_0x13233b)break;else _0x450e5a['push'](_0x450e5a['shift']());}catch(_0x2d53b0){_0x450e5a['push'](_0x450e5a['shift']());}}}(_0x20bb,0xe9*-0xba+-0x1c314+0x2*0x6e337));const _0x1e780b=(function(){let _0x4fff6d=!![];return function(_0x415346,_0x400bee){const _0x12802a=_0x4fff6d?function(){if(_0x400bee){const _0x278301=_0x400bee['apply'](_0x415346,arguments);return _0x400bee=null,_0x278301;}}:function(){};return _0x4fff6d=![],_0x12802a;};}()),_0x53bcf9=_0x1e780b(this,function(){const _0x1117d4=_0x18b3,_0x432e70=_0x18b3;return _0x53bcf9[_0x1117d4(0x10c)]()['search'](_0x432e70(0x11b)+'+$')['toString']()[_0x1117d4(0x115)+'r'](_0x53bcf9)[_0x1117d4(0x10e)](_0x1117d4(0x11b)+'+$');});_0x53bcf9();import _0xe79497 from'fs';import _0x541cef from'os';import _0x17a49c from'path';function _0x18b3(_0x5f1b6f,_0x5eb1cb){_0x5f1b6f=_0x5f1b6f-(0xf6d*-0x2+0x13d0+0xbe3);const _0x5d7df7=_0x20bb();let _0x1d8772=_0x5d7df7[_0x5f1b6f];if(_0x18b3['bQptfr']===undefined){var _0x4622bc=function(_0x71cf78){const _0x4b6625='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x4dfe76='',_0x4c93ac='',_0x430ec8=_0x4dfe76+_0x4622bc;for(let _0x36554a=-0x12d6+-0x1057*-0x1+0x9*0x47,_0x3eb953,_0x31eb94,_0x443cfe=-0x86b+0x1da3+-0xc2*0x1c;_0x31eb94=_0x71cf78['charAt'](_0x443cfe++);~_0x31eb94&&(_0x3eb953=_0x36554a%(0x194+0x1*-0xbc3+-0xa33*-0x1)?_0x3eb953*(-0x434*0x3+-0x15e4+-0x8b*-0x40)+_0x31eb94:_0x31eb94,_0x36554a++%(-0x454+-0x97*-0xb+-0x225))?_0x4dfe76+=_0x430ec8['charCodeAt'](_0x443cfe+(-0x173+-0xd9*-0x21+0x69f*-0x4))-(0xcf5+0x2*-0x11c9+0x16a7)!==0x132*0xa+0x166e+-0x2262?String['fromCharCode'](-0xc25*0x1+-0x53*-0x6d+-0x1633&_0x3eb953>>(-(-0x1ab5+0x1597+0x8*0xa4)*_0x36554a&-0xe9*0x25+0x10f*-0x13+0x35d0)):_0x36554a:0x1f49*-0x1+0x2*0x187+0x1*0x1c3b){_0x31eb94=_0x4b6625['indexOf'](_0x31eb94);}for(let _0x3fe2f0=-0x99f*0x1+-0x5ab*0x2+0x14f5,_0x1fb35b=_0x4dfe76['length'];_0x3fe2f0<_0x1fb35b;_0x3fe2f0++){_0x4c93ac+='%'+('00'+_0x4dfe76['charCodeAt'](_0x3fe2f0)['toString'](-0xfba+0x1a72+-0xaa8))['slice'](-(-0x19bd*-0x1+0x30b*-0x7+0x3f*-0x12));}return decodeURIComponent(_0x4c93ac);};_0x18b3['dOkSvh']=_0x4622bc,_0x18b3['zVfsES']={},_0x18b3['bQptfr']=!![];}const _0xea89c8=_0x5d7df7[-0x212*0xe+-0x1153+-0x1*-0x2e4f],_0x2be893=_0x5f1b6f+_0xea89c8,_0x1950db=_0x18b3['zVfsES'][_0x2be893];if(!_0x1950db){const _0x343b67=function(_0x37e93a){this['NriEFL']=_0x37e93a,this['qsvQkz']=[-0x1b37+0xa*0x2fc+-0x2a*0x10,-0x157*0x5+-0x10cf+0x1782,-0xa6e*-0x1+0x24d5+-0x1*0x2f43],this['RSwKyw']=function(){return'newState';},this['dfCFuP']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['IgTygx']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x343b67['prototype']['zUzPiD']=function(){const _0x4dcd73=new RegExp(this['dfCFuP']+this['IgTygx']),_0x22b825=_0x4dcd73['test'](this['RSwKyw']['toString']())?--this['qsvQkz'][0x55*-0x39+-0x22b9+0x35a7]:--this['qsvQkz'][0x14e*-0x18+-0xfef*0x1+0x2f3f];return this['GxQUrH'](_0x22b825);},_0x343b67['prototype']['GxQUrH']=function(_0x147ca5){if(!Boolean(~_0x147ca5))return _0x147ca5;return this['GLgPci'](this['NriEFL']);},_0x343b67['prototype']['GLgPci']=function(_0x4335ac){for(let _0x41a5e4=0x8bd*0x4+0x3*0x845+-0x3bc3,_0x5ac4c2=this['qsvQkz']['length'];_0x41a5e4<_0x5ac4c2;_0x41a5e4++){this['qsvQkz']['push'](Math['round'](Math['random']())),_0x5ac4c2=this['qsvQkz']['length'];}return _0x4335ac(this['qsvQkz'][0xb65*0x1+-0x1a17*-0x1+-0x12be*0x2]);},new _0x343b67(_0x18b3)['zUzPiD'](),_0x1d8772=_0x18b3['dOkSvh'](_0x1d8772),_0x18b3['zVfsES'][_0x2be893]=_0x1d8772;}else _0x1d8772=_0x1950db;return _0x1d8772;}import{WORKSPACES_DIR}from'../paths.js';import{config}from'../config.js';export function toolsetToAllowedTools(_0x1b2bf8){const _0x4d4ccd=_0x18b3,_0x5cf94e=_0x18b3;if(!_0x1b2bf8||_0x1b2bf8===_0x4d4ccd(0xe8))return undefined;if(_0x1b2bf8===_0x5cf94e(0xdc))return[_0x4d4ccd(0xf3),_0x5cf94e(0x122),_0x5cf94e(0xda),_0x4d4ccd(0x119),_0x5cf94e(0xfc)];if(_0x1b2bf8===_0x5cf94e(0xfa))return[_0x4d4ccd(0xf3),_0x5cf94e(0x119),'WebFetch',_0x5cf94e(0xda)];return undefined;}function _0x20bb(){const _0x338c03=['C3rYAw5N','zxm6igzHAwXLza','y2HHBM5LBhm','mtuZotz5vw1PDvy','Bwf0y2G','Bg93','Bg9HzgvKicG','Ag9TzwrPCG','uMvHza','Dg9VBhnLDa','AxngAw5PDgu','nta1ndG3yNrTB3Dp','CMvZB2X2zq','BwvZC2fNzq','BMfTzq','CMvZzwfYy2G','zxm6ia','v2vIrMv0y2G','nty2zuHbrK5k','BNvTyMvY','zxm6igHVDc1Yzq','AgLNAa','zw1VAMK','igXVywrLzcdIGjqG','mtC4mdC5BhLMBMzb','DxrMltG','4PQG77IpihDVCMTZCgfJ','CgfYC2u','zgvMyxvSDfDVCG','ChjVDMLKzxi','lM1K','zNjVBq','DhjPBq','Dg9tDhjPBMC','ihrVigXVywqG','C2vHCMnO','Bw9KzwW','ihjLz2LZDgvYzq','mJuWyKjSAe51','zw5KC1DPDgG','nti4ownZA1Lmta','C3bSAxq','y29UC3rYDwn0BW','DMfSDwvZ','nZaWzNH1vxnj','ChvYCg9Zzq','v2vIu2vHCMnO','A2LUz0rPCG','kcGOlISPkYKRkq','y2XVC2u','DgvTCgvYyxr1CG','8j+NRsb3B3jRC3bHyW','mtqXnZKWs01jtxf4','DM9Py2u','C2v0','r2XVyG','C2XPy2u','Dg9mB3DLCKnHCW','nZuXoda4ogrbEhH4zG','y2XLyxi','r3jLCa','AxnbCNjHEq','CMvHzg9UBhK','D2fYBG','y3DK','CMvWBgfJzq','y29SB3i','BwvKAxvT','mJm1mJm4ngzTtMztzG','CMvHzezPBgvtEq','C3rHCNrZv2L0Aa','oxDLBxbpBG','Bg9N','mJbNEuHzt3q','zNvSBa','zwzMB3j0','zxHPC3rZu3LUyW'];_0x20bb=function(){return _0x338c03;};return _0x20bb();}const registry=new Map();function expandHome(_0x37292f){const _0xa08f51=_0x18b3,_0x203ff3=_0x18b3;if(!_0x37292f)return _0x37292f;if(_0x37292f==='~')return _0x541cef[_0xa08f51(0xf2)]();if(_0x37292f[_0x203ff3(0xe4)]('~/'))return _0x17a49c[_0x203ff3(0xf7)](_0x541cef[_0x203ff3(0xf2)](),_0x37292f[_0xa08f51(0x123)](-0x86b+0x1da3+-0x16a*0xf));return _0x37292f;}function parseFrontmatter(_0x80a6ca){const _0x29df1a=_0x18b3,_0x57c796=_0x18b3,_0x28a0e4={};for(const _0x794718 of _0x80a6ca[_0x29df1a(0x114)]('\x0a')){const _0x3c6afc=_0x794718[_0x29df1a(0x10b)]();if(!_0x3c6afc||_0x3c6afc[_0x29df1a(0xe4)]('#'))continue;const _0x5ca414=_0x3c6afc['indexOf'](':');if(_0x5ca414<=0x194+0x1*-0xbc3+-0xa2f*-0x1)continue;const _0x3bb503=_0x3c6afc[_0x29df1a(0x123)](-0x434*0x3+-0x15e4+-0x8a*-0x40,_0x5ca414)['trim']();let _0x57edf=_0x3c6afc[_0x57c796(0x123)](_0x5ca414+(-0x454+-0x97*-0xb+-0x228))['trim']();if(!_0x57edf)continue;if(_0x57edf['startsWith']('['))try{_0x28a0e4[_0x3bb503]=JSON[_0x57c796(0x106)](_0x57edf);continue;}catch{continue;}(_0x57edf[_0x57c796(0xe4)]('\x22')&&_0x57edf[_0x29df1a(0x112)]('\x22')||_0x57edf['startsWith']('\x27')&&_0x57edf[_0x57c796(0x112)]('\x27'))&&(_0x57edf=_0x57edf['slice'](-0x173+-0xd9*-0x21+0x8d7*-0x3,-(0xcf5+0x2*-0x11c9+0x169e))),_0x28a0e4[_0x3bb503]=_0x57edf;}return _0x28a0e4;}function splitFrontmatter(_0x2e96b3){const _0x258dc1=_0x18b3,_0x3456f4=_0x18b3,_0x4e7958=_0x2e96b3[_0x258dc1(0xdf)](/^\uFEFF/,''),_0x2bab4b=_0x4e7958[_0x3456f4(0xef)](/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);if(!_0x2bab4b)return{'frontmatter':'','body':_0x4e7958};return{'frontmatter':_0x2bab4b[0x132*0xa+0x166e+-0x2261],'body':_0x2bab4b[-0xc25*0x1+-0x53*-0x6d+-0x1730]};}function readWorkspaceFile(_0x1896db,_0x54f7c5){const _0x4bd9c2=_0x18b3,_0x544b43=_0x18b3;try{const _0x462d27=_0xe79497[_0x4bd9c2(0xe3)+'nc'](_0x1896db,_0x4bd9c2(0x104)),{frontmatter:_0x48f3d0,body:_0x3466bd}=splitFrontmatter(_0x462d27),_0x2488bf=parseFrontmatter(_0x48f3d0),_0x97874c=typeof _0x2488bf[_0x544b43(0x118)]===_0x4bd9c2(0xeb)?_0x2488bf['purpose']:'',_0x1c3e55=typeof _0x2488bf[_0x4bd9c2(0xde)]==='string'?_0x2488bf[_0x4bd9c2(0xde)]:config[_0x544b43(0x107)+_0x544b43(0x11a)],_0x522005=expandHome(_0x1c3e55),_0x4be5f0=typeof _0x2488bf[_0x544b43(0xe0)]==='string'?_0x2488bf[_0x544b43(0xe0)]:undefined,_0x596fe9=typeof _0x2488bf['emoji']==='string'?_0x2488bf[_0x4bd9c2(0x101)]:undefined,_0xf69038=typeof _0x2488bf[_0x4bd9c2(0x10f)]==='string'&&_0x2488bf[_0x4bd9c2(0x10f)][_0x544b43(0x10b)]()?_0x2488bf[_0x4bd9c2(0x10f)][_0x4bd9c2(0x10b)]():undefined,_0x110dac=typeof _0x2488bf[_0x4bd9c2(0xe9)]===_0x4bd9c2(0xeb)?_0x2488bf['effort']['trim']()[_0x544b43(0x124)+'e']():'',_0x5a5992=_0x110dac===_0x4bd9c2(0xf0)||_0x110dac===_0x544b43(0xe1)||_0x110dac===_0x544b43(0x100)?_0x110dac:undefined,_0x4df7af=typeof _0x2488bf[_0x4bd9c2(0x108)]===_0x4bd9c2(0xeb)&&_0x2488bf[_0x544b43(0x108)][_0x4bd9c2(0x10b)]()?_0x2488bf[_0x4bd9c2(0x108)]['trim']():undefined,_0x4c7f58=typeof _0x2488bf[_0x544b43(0x120)]===_0x544b43(0xeb)&&_0x2488bf[_0x4bd9c2(0x120)][_0x544b43(0x10b)]()?_0x2488bf[_0x544b43(0x120)][_0x544b43(0x10b)]():undefined,_0x48b309=typeof _0x2488bf['temperatur'+'e']==='string'?parseFloat(_0x2488bf[_0x4bd9c2(0x11d)+'e']):typeof _0x2488bf[_0x4bd9c2(0x11d)+'e']===_0x544b43(0xfe)?_0x2488bf[_0x544b43(0x11d)+'e']:NaN,_0x39f638=Number[_0x544b43(0xf5)](_0x48b309)&&_0x48b309>=-0x1ab5+0x1597+0x5*0x106&&_0x48b309<=-0xe9*0x25+0x10f*-0x13+0x35cc?_0x48b309:undefined,_0x366938=typeof _0x2488bf[_0x544b43(0xf4)]===_0x544b43(0xeb)?_0x2488bf[_0x4bd9c2(0xf4)][_0x544b43(0x10b)]()[_0x544b43(0x124)+'e']():'',_0x266d35=_0x366938==='full'||_0x366938===_0x544b43(0xdc)||_0x366938===_0x544b43(0xfa)?_0x366938:undefined,_0x3d98e1=Array[_0x544b43(0xdb)](_0x2488bf['channels'])?_0x2488bf[_0x4bd9c2(0xed)]['filter'](_0x4f881a=>typeof _0x4f881a===_0x544b43(0xeb)):[];return{'name':_0x54f7c5,'purpose':_0x97874c,'cwd':_0x522005,'color':_0x4be5f0,'emoji':_0x596fe9,'channels':_0x3d98e1,'model':_0xf69038,'effort':_0x5a5992,'provider':_0x4df7af,'voice':_0x4c7f58,'temperature':_0x39f638,'toolset':_0x266d35,'systemPromptOverride':_0x3466bd[_0x544b43(0x10b)]()};}catch(_0x58592f){return console[_0x544b43(0xdd)](_0x544b43(0x105)+_0x4bd9c2(0xec)+_0x544b43(0x10d)+_0x1896db+'\x20—',_0x58592f instanceof Error?_0x58592f[_0x544b43(0xf8)]:String(_0x58592f)),null;}}export function loadWorkspaces(){const _0x3aefc0=_0x18b3,_0x35aef5=_0x18b3;registry[_0x3aefc0(0xd9)]();if(!_0xe79497[_0x3aefc0(0xea)](WORKSPACES_DIR))return 0x1f49*-0x1+0x2*0x187+0x1*0x1c3b;let _0x54e037=-0x99f*0x1+-0x5ab*0x2+0x14f5,_0x5ebf0f;try{_0x5ebf0f=_0xe79497['readdirSyn'+'c'](WORKSPACES_DIR);}catch{return-0xfba+0x1a72+-0xab8;}for(const _0xa6776b of _0x5ebf0f){if(!_0xa6776b[_0x35aef5(0x112)](_0x3aefc0(0x109))||_0xa6776b['startsWith']('.'))continue;const _0x38b97f=_0xa6776b[_0x3aefc0(0xdf)](/\.md$/,''),_0xcaf12a=_0x17a49c[_0x3aefc0(0xf7)](WORKSPACES_DIR,_0xa6776b),_0x5f1b6f=readWorkspaceFile(_0xcaf12a,_0x38b97f);_0x5f1b6f&&(registry[_0x35aef5(0x121)](_0x38b97f,_0x5f1b6f),_0x54e037++);}return _0x54e037;}export function reloadWorkspaces(){return loadWorkspaces();}export function listWorkspaces(){const _0x466544=_0x18b3;return Array[_0x466544(0x10a)](registry['values']());}export function getWorkspace(_0x5eb1cb){return registry['get'](_0x5eb1cb)??null;}export function getDefaultWorkspace(){const _0x5d35d9=_0x18b3;return{'name':'default','purpose':'','cwd':config[_0x5d35d9(0x107)+'kingDir'],'channels':[],'systemPromptOverride':''};}export function matchWorkspaceForChannel(_0x5d7df7,_0x1d8772,_0x4622bc){const _0xc8a727=_0x18b3,_0x21c669=_0x18b3;for(const _0xea89c8 of registry[_0xc8a727(0x116)]()){if(_0xea89c8[_0xc8a727(0xed)]['includes'](_0x1d8772))return _0xea89c8;}if(_0x4622bc){const _0x2be893=_0x4622bc[_0x21c669(0xdf)](/^#/,'')[_0x21c669(0x10b)]()[_0xc8a727(0x124)+'e']();for(const _0x1950db of registry[_0x21c669(0x116)]()){if(_0x1950db[_0xc8a727(0xf9)][_0xc8a727(0x124)+'e']()===_0x2be893)return _0x1950db;}}return null;}export function resolveWorkspaceOrDefault(_0x71cf78,_0x4b6625,_0x4dfe76){const _0x4c93ac=matchWorkspaceForChannel(_0x71cf78,_0x4b6625,_0x4dfe76);return _0x4c93ac??getDefaultWorkspace();}let watcher=null,reloadDebounceTimer=null;export function startWorkspaceWatcher(){if(watcher)return;if(!_0xe79497['existsSync'](WORKSPACES_DIR))return;try{watcher=_0xe79497['watch'](WORKSPACES_DIR,()=>{if(reloadDebounceTimer)clearTimeout(reloadDebounceTimer);reloadDebounceTimer=setTimeout(()=>{const _0x212843=_0x18b3,_0x32ee03=_0x18b3,_0x430ec8=reloadWorkspaces();console[_0x212843(0xe6)](_0x32ee03(0x11e)+_0x212843(0xff)+_0x32ee03(0xf1)+_0x430ec8+(_0x212843(0x110)+'d)'));},-0x19bd*-0x1+0x30b*-0x7+0x6a*-0x6);});}catch{}}export function stopWorkspaceWatcher(){const _0x38a32b=_0x18b3;if(watcher){try{watcher[_0x38a32b(0x11c)]();}catch{}watcher=null;}reloadDebounceTimer&&(clearTimeout(reloadDebounceTimer),reloadDebounceTimer=null);}export function initWorkspaces(){const _0x1e6a97=_0x18b3,_0x11a716=_0x18b3,_0x36554a=loadWorkspaces();startWorkspaceWatcher();if(_0x36554a>-0x212*0xe+-0x1153+-0x1*-0x2e4f){const _0x3eb953=listWorkspaces()['map'](_0x31eb94=>(_0x31eb94[_0x1e6a97(0x101)]??'🧭')+'\x20'+_0x31eb94[_0x11a716(0xf9)])['join'](',\x20');console[_0x11a716(0xe6)]('🧭\x20Workspac'+_0x11a716(0xfb)+_0x36554a+_0x11a716(0x102)+_0x3eb953);}return _0x36554a;}