alvin-bot 5.7.0 → 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 (136) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/claude.js +1 -102
  3. package/dist/config.js +1 -96
  4. package/dist/engine.js +1 -90
  5. package/dist/find-claude-binary.js +1 -98
  6. package/dist/handlers/async-agent-chunk-handler.js +1 -50
  7. package/dist/handlers/background-bypass.js +1 -75
  8. package/dist/handlers/commands.js +1 -2336
  9. package/dist/handlers/cron-progress.js +1 -52
  10. package/dist/handlers/document.js +1 -194
  11. package/dist/handlers/message.js +1 -959
  12. package/dist/handlers/photo.js +1 -154
  13. package/dist/handlers/platform-message.js +1 -360
  14. package/dist/handlers/stuck-timer.js +1 -54
  15. package/dist/handlers/video.js +1 -237
  16. package/dist/handlers/voice.js +1 -148
  17. package/dist/i18n.js +1 -805
  18. package/dist/index.js +1 -697
  19. package/dist/init-data-dir.js +1 -98
  20. package/dist/middleware/auth.js +1 -233
  21. package/dist/migrate.js +1 -162
  22. package/dist/paths.js +1 -146
  23. package/dist/platforms/discord.js +1 -175
  24. package/dist/platforms/index.js +1 -130
  25. package/dist/platforms/signal.js +1 -205
  26. package/dist/platforms/slack-slash-parser.js +1 -32
  27. package/dist/platforms/slack.js +1 -501
  28. package/dist/platforms/telegram.js +1 -111
  29. package/dist/platforms/types.js +1 -8
  30. package/dist/platforms/whatsapp-auth-helpers.js +1 -53
  31. package/dist/platforms/whatsapp.js +1 -707
  32. package/dist/providers/claude-sdk-provider.js +1 -565
  33. package/dist/providers/codex-cli-provider.js +1 -134
  34. package/dist/providers/index.js +1 -7
  35. package/dist/providers/ollama-provider.js +1 -32
  36. package/dist/providers/openai-compatible.js +1 -406
  37. package/dist/providers/registry.js +1 -352
  38. package/dist/providers/runtime-header.js +1 -45
  39. package/dist/providers/tool-executor.js +1 -475
  40. package/dist/providers/types.js +1 -227
  41. package/dist/services/access.js +1 -144
  42. package/dist/services/allowed-users-gate.js +1 -56
  43. package/dist/services/alvin-dispatch.js +1 -174
  44. package/dist/services/alvin-mcp-tools.js +1 -104
  45. package/dist/services/asset-index.js +1 -224
  46. package/dist/services/async-agent-parser.js +1 -418
  47. package/dist/services/async-agent-watcher.js +1 -583
  48. package/dist/services/auto-diagnostic.js +1 -228
  49. package/dist/services/broadcast.js +1 -52
  50. package/dist/services/browser-manager.js +1 -562
  51. package/dist/services/browser-webfetch.js +1 -127
  52. package/dist/services/browser.js +1 -121
  53. package/dist/services/cdp-bootstrap.js +1 -357
  54. package/dist/services/compaction.js +1 -144
  55. package/dist/services/critical-notify.js +1 -203
  56. package/dist/services/cron-resolver.js +1 -58
  57. package/dist/services/cron-scheduling.js +1 -310
  58. package/dist/services/cron.js +1 -861
  59. package/dist/services/custom-tools.js +1 -317
  60. package/dist/services/delivery-queue.js +1 -173
  61. package/dist/services/delivery-registry.js +1 -21
  62. package/dist/services/disk-cleanup.js +1 -203
  63. package/dist/services/elevenlabs.js +1 -58
  64. package/dist/services/embeddings/auto-detect.js +1 -74
  65. package/dist/services/embeddings/fts5.js +1 -108
  66. package/dist/services/embeddings/gemini.js +1 -65
  67. package/dist/services/embeddings/index.js +1 -496
  68. package/dist/services/embeddings/ollama.js +1 -78
  69. package/dist/services/embeddings/openai.js +1 -49
  70. package/dist/services/embeddings/provider.js +1 -22
  71. package/dist/services/embeddings/vector-base.js +1 -113
  72. package/dist/services/embeddings-migration.js +1 -193
  73. package/dist/services/embeddings.js +1 -9
  74. package/dist/services/env-file.js +1 -50
  75. package/dist/services/exec-guard.js +1 -71
  76. package/dist/services/fallback-order.js +1 -154
  77. package/dist/services/file-permissions.js +1 -93
  78. package/dist/services/heartbeat-file.js +1 -65
  79. package/dist/services/heartbeat.js +1 -313
  80. package/dist/services/hooks.js +1 -44
  81. package/dist/services/imagegen.js +1 -72
  82. package/dist/services/language-detect.js +1 -154
  83. package/dist/services/markdown.js +1 -63
  84. package/dist/services/mcp.js +1 -263
  85. package/dist/services/memory-extractor.js +1 -178
  86. package/dist/services/memory-inject-mode.js +1 -43
  87. package/dist/services/memory-layers.js +1 -156
  88. package/dist/services/memory.js +1 -146
  89. package/dist/services/ollama-manager.js +1 -339
  90. package/dist/services/permissions-wizard.js +1 -291
  91. package/dist/services/personality.js +1 -376
  92. package/dist/services/plugins.js +1 -171
  93. package/dist/services/preflight.js +1 -292
  94. package/dist/services/process-manager.js +1 -291
  95. package/dist/services/release-highlights.js +1 -79
  96. package/dist/services/reminders.js +1 -97
  97. package/dist/services/restart.js +1 -48
  98. package/dist/services/security-audit.js +1 -74
  99. package/dist/services/self-diagnosis.js +1 -272
  100. package/dist/services/self-search.js +1 -129
  101. package/dist/services/session-persistence.js +1 -237
  102. package/dist/services/session.js +1 -282
  103. package/dist/services/skills.js +1 -290
  104. package/dist/services/ssrf-guard.js +1 -162
  105. package/dist/services/standing-orders.js +1 -29
  106. package/dist/services/steer-channel.js +1 -46
  107. package/dist/services/stop-controller.js +1 -52
  108. package/dist/services/subagent-dedup.js +1 -86
  109. package/dist/services/subagent-delivery.js +1 -452
  110. package/dist/services/subagent-stats.js +1 -123
  111. package/dist/services/subagents.js +1 -814
  112. package/dist/services/sudo.js +1 -329
  113. package/dist/services/telegram.js +1 -158
  114. package/dist/services/timing-safe-bearer.js +1 -51
  115. package/dist/services/tool-discovery.js +1 -214
  116. package/dist/services/trends.js +1 -580
  117. package/dist/services/updater.js +1 -291
  118. package/dist/services/usage-tracker.js +1 -144
  119. package/dist/services/users.js +1 -271
  120. package/dist/services/voice.js +1 -104
  121. package/dist/services/watchdog-brake.js +1 -154
  122. package/dist/services/watchdog.js +1 -311
  123. package/dist/services/workspaces.js +1 -276
  124. package/dist/tui/index.js +1 -667
  125. package/dist/util/console-formatter.js +1 -109
  126. package/dist/util/debounce.js +1 -24
  127. package/dist/util/telegram-error-filter.js +1 -62
  128. package/dist/version.js +1 -24
  129. package/dist/web/bind-strategy.js +1 -42
  130. package/dist/web/canvas.js +1 -30
  131. package/dist/web/doctor-api.js +1 -604
  132. package/dist/web/openai-compat.js +1 -252
  133. package/dist/web/server.js +1 -1902
  134. package/dist/web/setup-api.js +1 -1101
  135. package/package.json +5 -2
  136. package/dist/.metadata_never_index +0 -0
@@ -1,339 +1 @@
1
- /**
2
- * Ollama Manager — on-demand daemon lifecycle for fallback use.
3
- *
4
- * The bot uses Ollama as a local fallback when the primary provider is down.
5
- * Historically the user had to run `ollama serve` themselves — if they forgot,
6
- * the fallback silently failed. This service spawns the daemon on demand,
7
- * preloads the target model into VRAM, and tears it all down once the primary
8
- * provider is healthy again.
9
- *
10
- * Key invariants:
11
- * • Only kills instances the bot started itself (tracked via PID file).
12
- * An externally-managed ollama is left alone.
13
- * • Preload uses Ollama's native /api/generate endpoint with an empty
14
- * prompt and keep_alive=30m, so the first real query is not cold.
15
- * • Unload sets keep_alive=0 to flush the model from VRAM immediately.
16
- * • All spawns are detached with stdio=ignore, so the child survives the
17
- * bot crashing but still gets cleaned up on graceful shutdown.
18
- */
19
- import { spawn, execFile } from "child_process";
20
- import { promisify } from "util";
21
- import fs from "fs";
22
- import { resolve, dirname } from "path";
23
- import os from "os";
24
- const execFileAsync = promisify(execFile);
25
- const DATA_DIR = process.env.ALVIN_DATA_DIR || resolve(os.homedir(), ".alvin-bot");
26
- const PID_FILE = resolve(DATA_DIR, "ollama.pid");
27
- const MODEL_FILE = resolve(DATA_DIR, "ollama.model");
28
- const OLLAMA_API_BASE = "http://localhost:11434";
29
- const DAEMON_READY_TIMEOUT_MS = 15_000;
30
- const PRELOAD_TIMEOUT_MS = 60_000;
31
- const KEEP_ALIVE = "30m";
32
- let managedProcess = null;
33
- let managedModel = null;
34
- // ── PID / Process verification ─────────────────────────────────────────────
35
- /**
36
- * Verify that `pid` is actually an ollama process by inspecting its command
37
- * via `ps`. This prevents the classic PID-reuse bug where we'd kill a
38
- * random process after a bot crash left a stale pid file pointing at
39
- * something the OS has since re-assigned.
40
- */
41
- async function verifyPidIsOllama(pid) {
42
- try {
43
- const { stdout } = await execFileAsync("ps", ["-p", String(pid), "-o", "command="], {
44
- timeout: 3_000,
45
- });
46
- return stdout.toLowerCase().includes("ollama");
47
- }
48
- catch {
49
- // ps exits non-zero if pid doesn't exist — treat as "not ollama"
50
- return false;
51
- }
52
- }
53
- function loadManagedModelFromDisk() {
54
- try {
55
- if (fs.existsSync(MODEL_FILE)) {
56
- return fs.readFileSync(MODEL_FILE, "utf-8").trim() || null;
57
- }
58
- }
59
- catch { /* ignore */ }
60
- return null;
61
- }
62
- function persistManagedModel(model) {
63
- try {
64
- fs.mkdirSync(dirname(MODEL_FILE), { recursive: true });
65
- if (model) {
66
- fs.writeFileSync(MODEL_FILE, model, "utf-8");
67
- }
68
- else if (fs.existsSync(MODEL_FILE)) {
69
- fs.unlinkSync(MODEL_FILE);
70
- }
71
- }
72
- catch (err) {
73
- console.warn(`[ollama] failed to persist model file: ${err}`);
74
- }
75
- }
76
- /**
77
- * Reconcile stale state left behind from a previous bot run.
78
- * If the PID file points at a process that is no longer ollama (crashed,
79
- * PID reused, never existed), remove the file so we don't try to kill
80
- * the wrong process later. Called lazily from ensureRunning / ensureStopped.
81
- */
82
- async function reconcileStalePidFile() {
83
- if (!fs.existsSync(PID_FILE))
84
- return;
85
- try {
86
- const raw = fs.readFileSync(PID_FILE, "utf-8").trim();
87
- const pid = parseInt(raw, 10);
88
- if (isNaN(pid) || pid <= 0) {
89
- fs.unlinkSync(PID_FILE);
90
- return;
91
- }
92
- const isOllama = await verifyPidIsOllama(pid);
93
- if (!isOllama) {
94
- console.log(`[ollama] stale pid file (pid=${pid} is no longer ollama) — removing`);
95
- fs.unlinkSync(PID_FILE);
96
- persistManagedModel(null);
97
- }
98
- }
99
- catch {
100
- // If we can't read/parse it, drop it
101
- try {
102
- fs.unlinkSync(PID_FILE);
103
- }
104
- catch { /* ignore */ }
105
- }
106
- }
107
- export async function isDaemonRunning() {
108
- try {
109
- const res = await fetch(`${OLLAMA_API_BASE}/api/tags`, {
110
- signal: AbortSignal.timeout(2_000),
111
- });
112
- return res.ok;
113
- }
114
- catch {
115
- return false;
116
- }
117
- }
118
- async function findOllamaBinary() {
119
- // Common install paths — macOS Homebrew, Linux, /usr/local
120
- const candidates = [
121
- "/opt/homebrew/bin/ollama",
122
- "/usr/local/bin/ollama",
123
- "/usr/bin/ollama",
124
- ];
125
- for (const p of candidates) {
126
- if (fs.existsSync(p))
127
- return p;
128
- }
129
- // Fallback: `which ollama` (async, no event-loop block)
130
- try {
131
- const { stdout } = await execFileAsync("which", ["ollama"], { timeout: 3_000 });
132
- return stdout.trim() || null;
133
- }
134
- catch {
135
- return null;
136
- }
137
- }
138
- async function waitForDaemon(timeoutMs = DAEMON_READY_TIMEOUT_MS) {
139
- const start = Date.now();
140
- while (Date.now() - start < timeoutMs) {
141
- if (await isDaemonRunning())
142
- return true;
143
- await new Promise(r => setTimeout(r, 500));
144
- }
145
- return false;
146
- }
147
- async function preloadModel(model) {
148
- try {
149
- await fetch(`${OLLAMA_API_BASE}/api/generate`, {
150
- method: "POST",
151
- headers: { "Content-Type": "application/json" },
152
- body: JSON.stringify({
153
- model,
154
- prompt: "",
155
- keep_alive: KEEP_ALIVE,
156
- }),
157
- signal: AbortSignal.timeout(PRELOAD_TIMEOUT_MS),
158
- });
159
- }
160
- catch (err) {
161
- const msg = err instanceof Error ? err.message : String(err);
162
- console.warn(`[ollama] preload warning (model=${model}): ${msg}`);
163
- }
164
- }
165
- async function unloadModel(model) {
166
- try {
167
- await fetch(`${OLLAMA_API_BASE}/api/generate`, {
168
- method: "POST",
169
- headers: { "Content-Type": "application/json" },
170
- body: JSON.stringify({
171
- model,
172
- keep_alive: 0, // immediate VRAM unload
173
- }),
174
- signal: AbortSignal.timeout(5_000),
175
- });
176
- }
177
- catch {
178
- // ignore — daemon may already be stopping
179
- }
180
- }
181
- /**
182
- * Ensure the Ollama daemon is running and the specified model is loaded.
183
- * Idempotent. If an externally-managed daemon is already running, we use
184
- * it and just preload the model, but leave it for ensureStopped() to decide
185
- * whether to kill it (it won't — only bot-spawned daemons get killed).
186
- */
187
- export async function ensureRunning(model) {
188
- // Drop any stale pid file from a previous run before deciding anything.
189
- await reconcileStalePidFile();
190
- if (await isDaemonRunning()) {
191
- // Daemon is already up — either we started it in a previous bot run
192
- // (pid file still valid) or user started it externally (no pid file).
193
- // In both cases we preload the target model so the first query is warm.
194
- await preloadModel(model);
195
- managedModel = model;
196
- // If a valid pid file exists, we inherit ownership of that daemon
197
- // (it was bot-managed before a crash/restart). Update the model file.
198
- if (fs.existsSync(PID_FILE)) {
199
- persistManagedModel(model);
200
- }
201
- return true;
202
- }
203
- const binary = await findOllamaBinary();
204
- if (!binary) {
205
- console.error("[ollama] binary not found — install ollama first (brew install ollama)");
206
- return false;
207
- }
208
- console.log(`[ollama] starting daemon: ${binary} serve`);
209
- const proc = spawn(binary, ["serve"], {
210
- detached: true,
211
- stdio: "ignore",
212
- env: process.env,
213
- });
214
- proc.unref();
215
- if (!proc.pid) {
216
- console.error("[ollama] spawn failed — no pid");
217
- return false;
218
- }
219
- // Persist the PID + model so we can kill/unload correctly on cleanup,
220
- // even after a bot restart loses the in-memory references.
221
- try {
222
- fs.mkdirSync(dirname(PID_FILE), { recursive: true });
223
- fs.writeFileSync(PID_FILE, String(proc.pid), "utf-8");
224
- persistManagedModel(model);
225
- }
226
- catch (err) {
227
- console.warn(`[ollama] failed to write state files: ${err}`);
228
- }
229
- managedProcess = proc;
230
- managedModel = model;
231
- const ready = await waitForDaemon();
232
- if (!ready) {
233
- console.error("[ollama] daemon did not become ready within 15s");
234
- // Clean up: we spawned something that didn't come up. Best effort kill.
235
- try {
236
- process.kill(proc.pid, "SIGTERM");
237
- }
238
- catch { /* ignore */ }
239
- try {
240
- fs.unlinkSync(PID_FILE);
241
- }
242
- catch { /* ignore */ }
243
- persistManagedModel(null);
244
- return false;
245
- }
246
- console.log(`[ollama] daemon ready — preloading model: ${model}`);
247
- await preloadModel(model);
248
- return true;
249
- }
250
- /**
251
- * Stop the daemon if we started it, unload the model from VRAM.
252
- * Does nothing if the daemon was started externally (no PID file).
253
- */
254
- export async function ensureStopped() {
255
- if (!fs.existsSync(PID_FILE)) {
256
- // No PID file = externally managed daemon. Don't touch it.
257
- return;
258
- }
259
- let pid = null;
260
- try {
261
- const raw = fs.readFileSync(PID_FILE, "utf-8").trim();
262
- const parsed = parseInt(raw, 10);
263
- if (!isNaN(parsed) && parsed > 0)
264
- pid = parsed;
265
- }
266
- catch {
267
- // ignore
268
- }
269
- // Verify the PID actually points at an ollama process before SIGTERM.
270
- // Prevents the classic PID-reuse bug where we'd kill a random process
271
- // after a bot crash/restart left a stale pid file.
272
- const pidIsOllama = pid ? await verifyPidIsOllama(pid) : false;
273
- if (!pidIsOllama) {
274
- console.log(`[ollama] pid file points to pid=${pid} which is no longer ollama — cleaning up`);
275
- try {
276
- fs.unlinkSync(PID_FILE);
277
- }
278
- catch { /* ignore */ }
279
- persistManagedModel(null);
280
- managedProcess = null;
281
- managedModel = null;
282
- return;
283
- }
284
- // Unload the model first so VRAM is freed even if the kill races.
285
- // Model name might be in memory (current run) or on disk (survived a restart).
286
- const modelToUnload = managedModel || loadManagedModelFromDisk();
287
- if (modelToUnload) {
288
- await unloadModel(modelToUnload);
289
- }
290
- try {
291
- process.kill(pid, "SIGTERM");
292
- console.log(`[ollama] stopped daemon pid=${pid}`);
293
- }
294
- catch (err) {
295
- const msg = err instanceof Error ? err.message : String(err);
296
- console.warn(`[ollama] failed to kill pid=${pid}: ${msg}`);
297
- }
298
- // Clean up state
299
- try {
300
- fs.unlinkSync(PID_FILE);
301
- }
302
- catch { /* ignore */ }
303
- persistManagedModel(null);
304
- managedProcess = null;
305
- managedModel = null;
306
- }
307
- /** Whether the current daemon was spawned by the bot (via PID file). */
308
- export function isBotManaged() {
309
- return fs.existsSync(PID_FILE);
310
- }
311
- /** Currently loaded model name, if any. */
312
- export function getManagedModel() {
313
- return managedModel || loadManagedModelFromDisk();
314
- }
315
- // ── Module-load side effects ──────────────────────────────────────────────
316
- //
317
- // On first import (bot startup), reconcile any stale pid file from a previous
318
- // crashed run AND restore the in-memory managedModel if the daemon is still
319
- // alive. Best-effort — failures are logged but not fatal.
320
- //
321
- // NOTE: SIGTERM/SIGINT handling lives in src/index.ts (the bot's shutdown()
322
- // function). That function calls ensureStopped() directly — we deliberately
323
- // do NOT install our own signal handler here, to avoid racing with the
324
- // bot's own cleanup path.
325
- void (async () => {
326
- try {
327
- await reconcileStalePidFile();
328
- if (fs.existsSync(PID_FILE)) {
329
- const diskModel = loadManagedModelFromDisk();
330
- if (diskModel) {
331
- managedModel = diskModel;
332
- console.log(`[ollama] restored managed state from previous run (model=${diskModel})`);
333
- }
334
- }
335
- }
336
- catch (err) {
337
- console.warn(`[ollama] startup reconciliation failed: ${err}`);
338
- }
339
- })();
1
+ const _0x49b55b=_0xb91f,_0x5d2f5a=_0xb91f;(function(_0x1a9252,_0x15f86b){const _0x2a5b3e=_0xb91f,_0x57619b=_0xb91f,_0x2196ae=_0x1a9252();while(!![]){try{const _0x334adb=parseInt(_0x2a5b3e(0x198))/(-0x2330+-0xa2f+-0x58*-0x84)+parseInt(_0x57619b(0x151))/(-0x87b*-0x1+0x1*0x2581+-0x16fd*0x2)*(parseInt(_0x2a5b3e(0x15d))/(0x4b0*-0x2+0x1a0e+-0x10ab))+parseInt(_0x2a5b3e(0x16e))/(0x731+-0x4c*0xf+-0x2b9*0x1)+-parseInt(_0x2a5b3e(0x188))/(-0x8a3+0x1f79+0x1*-0x16d1)*(-parseInt(_0x2a5b3e(0x17f))/(0x2075+-0x1dae+0x8d*-0x5))+-parseInt(_0x57619b(0x17b))/(0x1c0a+-0x851*0x2+-0xb61)*(-parseInt(_0x57619b(0x179))/(-0x70*0x31+-0xa82+-0x1ffa*-0x1))+parseInt(_0x57619b(0x14f))/(-0x1d*0x4b+0x1*0x1d68+0x2*-0xa70)+-parseInt(_0x2a5b3e(0x191))/(0x26af+-0x1e09+-0x4*0x227)*(parseInt(_0x57619b(0x195))/(-0x1*-0x37b+-0x9d*-0x19+-0x12c5));if(_0x334adb===_0x15f86b)break;else _0x2196ae['push'](_0x2196ae['shift']());}catch(_0x1cfbc8){_0x2196ae['push'](_0x2196ae['shift']());}}}(_0x5e9c,0x12fca+0x17e722+0x2*-0x53283));const _0x6c385=(function(){let _0x231008=!![];return function(_0x29e6d3,_0x25dbb5){const _0x51b09b=_0x231008?function(){if(_0x25dbb5){const _0x4eda7d=_0x25dbb5['apply'](_0x29e6d3,arguments);return _0x25dbb5=null,_0x4eda7d;}}:function(){};return _0x231008=![],_0x51b09b;};}()),_0x59bd9c=_0x6c385(this,function(){const _0x5c6114=_0xb91f,_0x195c10=_0xb91f;return _0x59bd9c[_0x5c6114(0x164)]()[_0x195c10(0x16a)](_0x5c6114(0x186)+'+$')[_0x195c10(0x164)]()[_0x5c6114(0x1a4)+'r'](_0x59bd9c)['search'](_0x5c6114(0x186)+'+$');});_0x59bd9c();import{spawn,execFile}from'child_process';import{promisify}from'util';import _0x2e39b5 from'fs';import{resolve,dirname}from'path';import _0x20a69b from'os';const execFileAsync=promisify(execFile),DATA_DIR=process[_0x49b55b(0x19e)][_0x5d2f5a(0x187)+_0x49b55b(0x158)]||resolve(_0x20a69b[_0x5d2f5a(0x190)](),'.alvin-bot'),PID_FILE=resolve(DATA_DIR,_0x5d2f5a(0x166)),MODEL_FILE=resolve(DATA_DIR,_0x5d2f5a(0x162)+'el'),OLLAMA_API_BASE=_0x5d2f5a(0x173)+_0x5d2f5a(0x18f)+'34',DAEMON_READY_TIMEOUT_MS=0x5e94+0x681b+-0x8c17,PRELOAD_TIMEOUT_MS=0x8baf+-0x13858+0x19709,KEEP_ALIVE=_0x49b55b(0x168);let managedProcess=null,managedModel=null;function _0x5e9c(){const _0xbcb9d4=['DgfSzsbWAwqGzG','y29UC3rYDwn0BW','D2fYBG','ywvTB24GzgLKia','zxHPC3rZu3LUyW','igLZig5VigXVBG','AgLUide1CW','Aw5JBhvKzxm','BgvHBMLUzYb1Ca','C2vYDMu','BIbMywLSzwq6ia','l2fWAs90ywDZ','yxbWBgLJyxrPBW','mti4ota4odLkAenytfm','CMvHzezPBgvtEq','mtuYt1HlrKPJ','y29TBwfUzd0','w29SBgfTyv0GCa','w29SBgfTyv0GCG','CgLK','z2vYig9SBgfTyq','ywLSzwqGDg8GAW','x0rjuG','DgfYDhvWihjLyW','BwvZC2fNzq','l2fWAs9Nzw5LCG','BM93','ndC1mJLJzurNy3C','zsbMCM9TihbYzq','CML0zsbZDgf0zq','yNjLDYbPBNn0yq','BwTKAxjtEw5J','B2XSyw1HlM1Vza','DgLTzw91Da','Dg9tDhjPBMC','BMLUzYaOBw9Kzq','B2XSyw1HlNbPza','BI9QC29U','mZbT','ktOG','C2vHCMnO','DhjPBq','BM8GBg9Uz2vYia','yxrL','nti3ndq2menlu2TKvq','ywLSzwqGDg8GCa','zw1VBJOG','AwqGzMLSzsbWBW','A2LSBa','Ahr0CdOVl2XVyW','igzPBgvZoIa','kg1VzgvSpq','EsdIGjqGChjLBg9H','C3rYAw5NAwz5','w29SBgfTyv0GzG','ntK5ndGWoevtBgHgua','Aw5HCNKGBM90ia','mtrbwMf3Dei','w29SBgfTyv0GyG','zgLUzYbTB2rLBa','DxrMltG','nLHhyuPAtW','ywLSzwqGDg8GDW','BweGzMLYC3qGka','w29SBgfTyv0Gza','BMfNzwqGC3rHDa','Bw9UihbPzd0','u0Lhvevstq','kcGOlISPkYKRkq','quXwsu5Frefuqq','nJaYnZuZmfbxsvrNCG','ywvTB24GCMvHza','w29SBgfTyv0GCW','ihjLywr5ihDPDa','Ew5J','CMv3l2jPBI9VBa','B2XSyw1H','ywXOB3n0oJeXna','Ag9TzwrPCG','nZaXntq4mZbRuuzXswK','zwWGzMLSztOG','ihnLCNzL','DgfYDgLUzYbKyq','mtflD1DkAKS','l2jPBI9VBgXHBq','Dw5Yzwy','mtmXotmXn3n6s2HezW','zxjYB3i','DMLVDxmGCNvUia','D3jPDgvgAwXLuW','Bg9N','l3vZCI9SB2nHBa','zw52','l3vZCI9IAw4VBW','AwXLicHWAwq9','AwDUB3jL','Dw5SAw5Ru3LUyW'];_0x5e9c=function(){return _0xbcb9d4;};return _0x5e9c();}async function verifyPidIsOllama(_0x3cb166){const _0x49e494=_0x49b55b,_0x1570d3=_0x49b55b;try{const {stdout:_0x26a710}=await execFileAsync('ps',['-p',String(_0x3cb166),'-o',_0x49e494(0x152)],{'timeout':0xbb8});return _0x26a710['toLowerCas'+'e']()[_0x49e494(0x149)](_0x1570d3(0x18e));}catch{return![];}}function loadManagedModelFromDisk(){const _0x4c1273=_0x5d2f5a,_0x69cc42=_0x5d2f5a;try{if(_0x2e39b5[_0x4c1273(0x1a7)](MODEL_FILE))return _0x2e39b5[_0x69cc42(0x150)+'nc'](MODEL_FILE,'utf-8')[_0x4c1273(0x16b)]()||null;}catch{}return null;}function persistManagedModel(_0x586c7c){const _0x3377e7=_0x49b55b,_0x25a2bc=_0x49b55b;try{_0x2e39b5[_0x3377e7(0x161)](dirname(MODEL_FILE),{'recursive':!![]});if(_0x586c7c)_0x2e39b5[_0x3377e7(0x19b)+_0x3377e7(0x18c)](MODEL_FILE,_0x586c7c,'utf-8');else _0x2e39b5[_0x3377e7(0x1a7)](MODEL_FILE)&&_0x2e39b5[_0x25a2bc(0x1a2)](MODEL_FILE);}catch(_0x1d8a45){console['warn'](_0x3377e7(0x178)+_0x25a2bc(0x16f)+'ersist\x20mod'+_0x25a2bc(0x192)+_0x1d8a45);}}function _0xb91f(_0x53d05e,_0xb47279){_0x53d05e=_0x53d05e-(0x196a*0x1+0xf48+-0x276b*0x1);const _0x207280=_0x5e9c();let _0x5a162e=_0x207280[_0x53d05e];if(_0xb91f['KTrkML']===undefined){var _0x3b8ff4=function(_0x49feb6){const _0x2ff3f2='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x5e1c92='',_0x1b7e34='',_0x28b1c8=_0x5e1c92+_0x3b8ff4;for(let _0x246b07=-0x4f1+-0x1ffa*0x1+0x24eb,_0x321096,_0x37a923,_0x52797c=0x1f87+0x22b4+-0x423b;_0x37a923=_0x49feb6['charAt'](_0x52797c++);~_0x37a923&&(_0x321096=_0x246b07%(0xba4+-0x1a08+0xe68)?_0x321096*(0x1e*0x59+-0x14e6+0x2*0x55c)+_0x37a923:_0x37a923,_0x246b07++%(0xbc8+-0x1d46+0x1182))?_0x5e1c92+=_0x28b1c8['charCodeAt'](_0x52797c+(-0x3*0x876+-0xe40+-0x13d6*-0x2))-(-0xb7*-0xf+0x1e46+-0x28f5)!==0x143+0x1*-0x1950+0x180d?String['fromCharCode'](-0x93*-0x7+0x29*-0xe+0x28*-0x5&_0x321096>>(-(-0x1*-0x1b05+-0x160+-0x19a3*0x1)*_0x246b07&-0x133+-0xc52+0xd8b)):_0x246b07:-0x2*-0xdee+-0x3*-0x883+-0x3565){_0x37a923=_0x2ff3f2['indexOf'](_0x37a923);}for(let _0x159769=0x26e4+-0x3*-0x241+0xd*-0x383,_0xe42f4a=_0x5e1c92['length'];_0x159769<_0xe42f4a;_0x159769++){_0x1b7e34+='%'+('00'+_0x5e1c92['charCodeAt'](_0x159769)['toString'](0x167c+0x3ac*0x7+-0xc08*0x4))['slice'](-(0x16*0x2+0x203c+-0x2066));}return decodeURIComponent(_0x1b7e34);};_0xb91f['QOcvYw']=_0x3b8ff4,_0xb91f['nZBhZx']={},_0xb91f['KTrkML']=!![];}const _0xf9656=_0x207280[0x2362+-0x34+-0x232e],_0x4176eb=_0x53d05e+_0xf9656,_0x5dd2ae=_0xb91f['nZBhZx'][_0x4176eb];if(!_0x5dd2ae){const _0x3a7561=function(_0x4c9cc1){this['rDYRog']=_0x4c9cc1,this['CfvOHE']=[0x355*-0x2+0x67*-0x1d+0x1256*0x1,0x43*0x6f+-0x205a+-0x34d*-0x1,0x2278+-0xee1*0x1+-0x1397],this['womNjT']=function(){return'newState';},this['GcQEUi']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['xtBPkP']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x3a7561['prototype']['rGBkYs']=function(){const _0x414474=new RegExp(this['GcQEUi']+this['xtBPkP']),_0xe79990=_0x414474['test'](this['womNjT']['toString']())?--this['CfvOHE'][-0x106+-0x833*-0x2+0xf5f*-0x1]:--this['CfvOHE'][-0xf7a*-0x1+0x878+-0x17f2];return this['nmlhdh'](_0xe79990);},_0x3a7561['prototype']['nmlhdh']=function(_0x34ae3b){if(!Boolean(~_0x34ae3b))return _0x34ae3b;return this['yUIYwq'](this['rDYRog']);},_0x3a7561['prototype']['yUIYwq']=function(_0x5aee88){for(let _0x43f69d=0x5c6+-0x1dd5+0x3*0x805,_0x518e35=this['CfvOHE']['length'];_0x43f69d<_0x518e35;_0x43f69d++){this['CfvOHE']['push'](Math['round'](Math['random']())),_0x518e35=this['CfvOHE']['length'];}return _0x5aee88(this['CfvOHE'][0x1bc5+0xa1*-0x25+0xc*-0x60]);},new _0x3a7561(_0xb91f)['rGBkYs'](),_0x5a162e=_0xb91f['QOcvYw'](_0x5a162e),_0xb91f['nZBhZx'][_0x4176eb]=_0x5a162e;}else _0x5a162e=_0x5dd2ae;return _0x5a162e;}async function reconcileStalePidFile(){const _0xf76b2c=_0x49b55b,_0x1d5e8e=_0x5d2f5a;if(!_0x2e39b5[_0xf76b2c(0x1a7)](PID_FILE))return;try{const _0x2c8e9a=_0x2e39b5['readFileSy'+'nc'](PID_FILE,_0xf76b2c(0x17e))[_0x1d5e8e(0x16b)](),_0x5f27a7=parseInt(_0x2c8e9a,0x1e*0x59+-0x14e6+0x1*0xa82);if(isNaN(_0x5f27a7)||_0x5f27a7<=0xbc8+-0x1d46+0x117e){_0x2e39b5[_0x1d5e8e(0x1a2)](PID_FILE);return;}const _0x37f078=await verifyPidIsOllama(_0x5f27a7);!_0x37f078&&(console[_0x1d5e8e(0x19c)](_0x1d5e8e(0x18a)+_0x1d5e8e(0x1a3)+_0x1d5e8e(0x1a0)+_0x5f27a7+(_0x1d5e8e(0x147)+_0x1d5e8e(0x156)+')\x20—\x20removi'+'ng')),_0x2e39b5[_0xf76b2c(0x1a2)](PID_FILE),persistManagedModel(null));}catch{try{_0x2e39b5['unlinkSync'](PID_FILE);}catch{}}}export async function isDaemonRunning(){const _0x347128=_0x49b55b,_0x2b8799=_0x5d2f5a;try{const _0x14496d=await fetch(OLLAMA_API_BASE+_0x347128(0x14d),{'signal':AbortSignal[_0x2b8799(0x163)](-0x3*0x876+-0xe40+-0x17b9*-0x2)});return _0x14496d['ok'];}catch{return![];}}async function findOllamaBinary(){const _0x4803d1=_0x5d2f5a,_0x3e94ae=_0x5d2f5a,_0x34d9bd=['/opt/homeb'+_0x4803d1(0x18d)+'lama',_0x3e94ae(0x19d)+_0x3e94ae(0x196)+'a',_0x3e94ae(0x19f)+'llama'];for(const _0x22acb5 of _0x34d9bd){if(_0x2e39b5[_0x3e94ae(0x1a7)](_0x22acb5))return _0x22acb5;}try{const {stdout:_0x37407c}=await execFileAsync('which',[_0x4803d1(0x18e)],{'timeout':0xbb8});return _0x37407c[_0x4803d1(0x16b)]()||null;}catch{return null;}}async function waitForDaemon(_0x3ac6a7=DAEMON_READY_TIMEOUT_MS){const _0x25778b=_0x5d2f5a,_0x4c37fc=_0x5d2f5a,_0x4b21e5=Date[_0x25778b(0x15c)]();while(Date[_0x25778b(0x15c)]()-_0x4b21e5<_0x3ac6a7){if(await isDaemonRunning())return!![];await new Promise(_0x4f0ecd=>setTimeout(_0x4f0ecd,-0xb7*-0xf+0x1e46+-0x270b));}return![];}async function preloadModel(_0x231626){const _0x4b6993=_0x49b55b,_0x3843cc=_0x5d2f5a;try{await fetch(OLLAMA_API_BASE+('/api/gener'+_0x4b6993(0x16d)),{'method':'POST','headers':{'Content-Type':'applicatio'+'n/json'},'body':JSON['stringify']({'model':_0x231626,'prompt':'','keep_alive':KEEP_ALIVE}),'signal':AbortSignal[_0x3843cc(0x163)](PRELOAD_TIMEOUT_MS)});}catch(_0x51a098){const _0x56879d=_0x51a098 instanceof Error?_0x51a098[_0x3843cc(0x15a)]:String(_0x51a098);console[_0x3843cc(0x1a5)](_0x4b6993(0x153)+'reload\x20war'+_0x4b6993(0x165)+'l='+_0x231626+_0x3843cc(0x169)+_0x56879d);}}async function unloadModel(_0x4461e8){const _0x29d311=_0x5d2f5a,_0x327290=_0x5d2f5a;try{await fetch(OLLAMA_API_BASE+(_0x29d311(0x15b)+_0x327290(0x16d)),{'method':'POST','headers':{'Content-Type':_0x327290(0x14e)+_0x327290(0x167)},'body':JSON[_0x29d311(0x177)]({'model':_0x4461e8,'keep_alive':0x0}),'signal':AbortSignal[_0x327290(0x163)](0x143+0x1*-0x1950+0x2b95)});}catch{}}export async function ensureRunning(_0x2f0a33){const _0x21cc49=_0x49b55b,_0x136afb=_0x49b55b;await reconcileStalePidFile();if(await isDaemonRunning())return await preloadModel(_0x2f0a33),managedModel=_0x2f0a33,_0x2e39b5[_0x21cc49(0x1a7)](PID_FILE)&&persistManagedModel(_0x2f0a33),!![];const _0x2fe66a=await findOllamaBinary();if(!_0x2fe66a)return console['error'](_0x136afb(0x17c)+_0x21cc49(0x17a)+'found\x20—\x20in'+'stall\x20olla'+_0x136afb(0x181)+_0x136afb(0x160)+'ll\x20ollama)'),![];console[_0x136afb(0x19c)](_0x136afb(0x18a)+_0x136afb(0x194)+_0x136afb(0x170)+_0x2fe66a+_0x21cc49(0x193));const _0x570839=spawn(_0x2fe66a,[_0x21cc49(0x14b)],{'detached':!![],'stdio':_0x136afb(0x1a1),'env':process[_0x136afb(0x19e)]});_0x570839[_0x136afb(0x197)]();if(!_0x570839[_0x21cc49(0x155)])return console[_0x136afb(0x199)](_0x136afb(0x18a)+'pawn\x20faile'+'d\x20—\x20no\x20pid'),![];try{_0x2e39b5[_0x136afb(0x161)](dirname(PID_FILE),{'recursive':!![]}),_0x2e39b5[_0x21cc49(0x19b)+'ync'](PID_FILE,String(_0x570839[_0x136afb(0x155)]),'utf-8'),persistManagedModel(_0x2f0a33);}catch(_0x53f716){console[_0x21cc49(0x1a5)](_0x136afb(0x178)+_0x136afb(0x180)+_0x21cc49(0x15f)+_0x136afb(0x174)+_0x53f716);}managedProcess=_0x570839,managedModel=_0x2f0a33;const _0x4d155e=await waitForDaemon();if(!_0x4d155e){console[_0x136afb(0x199)](_0x136afb(0x182)+_0x21cc49(0x1a6)+'not\x20become'+_0x21cc49(0x18b)+_0x21cc49(0x148));try{process[_0x21cc49(0x172)](_0x570839[_0x136afb(0x155)],_0x136afb(0x185));}catch{}try{_0x2e39b5[_0x21cc49(0x1a2)](PID_FILE);}catch{}return persistManagedModel(null),![];}return console[_0x136afb(0x19c)]('[ollama]\x20d'+_0x136afb(0x189)+_0x21cc49(0x176)+_0x21cc49(0x17d)+':\x20'+_0x2f0a33),await preloadModel(_0x2f0a33),!![];}export async function ensureStopped(){const _0x24d8e3=_0x49b55b,_0x603fa8=_0x5d2f5a;if(!_0x2e39b5[_0x24d8e3(0x1a7)](PID_FILE))return;let _0x19079c=null;try{const _0x2f70e3=_0x2e39b5[_0x603fa8(0x150)+'nc'](PID_FILE,_0x603fa8(0x17e))[_0x24d8e3(0x16b)](),_0x2601ab=parseInt(_0x2f70e3,-0x93*-0x7+0x29*-0xe+0x59*-0x5);if(!isNaN(_0x2601ab)&&_0x2601ab>-0x1*-0x1b05+-0x160+-0x65*0x41)_0x19079c=_0x2601ab;}catch{}const _0x11d354=_0x19079c?await verifyPidIsOllama(_0x19079c):![];if(!_0x11d354){console[_0x24d8e3(0x19c)](_0x24d8e3(0x153)+_0x603fa8(0x171)+'ints\x20to\x20pi'+'d='+_0x19079c+('\x20which\x20is\x20'+_0x24d8e3(0x16c)+'ollama\x20—\x20c'+_0x603fa8(0x14a)));try{_0x2e39b5[_0x603fa8(0x1a2)](PID_FILE);}catch{}persistManagedModel(null),managedProcess=null,managedModel=null;return;}const _0x5ae033=managedModel||loadManagedModelFromDisk();_0x5ae033&&await unloadModel(_0x5ae033);try{process[_0x603fa8(0x172)](_0x19079c,'SIGTERM'),console[_0x24d8e3(0x19c)](_0x24d8e3(0x18a)+'topped\x20dae'+_0x603fa8(0x184)+_0x19079c);}catch(_0x2c08ee){const _0x12e081=_0x2c08ee instanceof Error?_0x2c08ee['message']:String(_0x2c08ee);console[_0x603fa8(0x1a5)](_0x603fa8(0x178)+_0x603fa8(0x157)+'ill\x20pid='+_0x19079c+':\x20'+_0x12e081);}try{_0x2e39b5[_0x24d8e3(0x1a2)](PID_FILE);}catch{}persistManagedModel(null),managedProcess=null,managedModel=null;}export function isBotManaged(){const _0x3a6510=_0x49b55b;return _0x2e39b5[_0x3a6510(0x1a7)](PID_FILE);}export function getManagedModel(){return managedModel||loadManagedModelFromDisk();}void((async()=>{const _0x37baf8=_0x5d2f5a,_0x4a4e50=_0x49b55b;try{await reconcileStalePidFile();if(_0x2e39b5[_0x37baf8(0x1a7)](PID_FILE)){const _0x278e8f=loadManagedModelFromDisk();_0x278e8f&&(managedModel=_0x278e8f,console['log'](_0x37baf8(0x154)+'estored\x20ma'+_0x4a4e50(0x183)+_0x4a4e50(0x15e)+_0x37baf8(0x19a)+_0x4a4e50(0x175)+_0x278e8f+')'));}}catch(_0x21732a){console[_0x4a4e50(0x1a5)](_0x37baf8(0x18a)+_0x37baf8(0x159)+'onciliatio'+_0x4a4e50(0x14c)+_0x21732a);}})());