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.
- package/CHANGELOG.md +29 -0
- package/README.md +1 -1
- package/dist/claude.js +1 -102
- package/dist/config.js +1 -96
- package/dist/engine.js +1 -90
- package/dist/find-claude-binary.js +1 -98
- package/dist/handlers/async-agent-chunk-handler.js +1 -50
- package/dist/handlers/background-bypass.js +1 -75
- package/dist/handlers/commands.js +1 -2336
- package/dist/handlers/cron-progress.js +1 -52
- package/dist/handlers/document.js +1 -194
- package/dist/handlers/message.js +1 -959
- package/dist/handlers/photo.js +1 -154
- package/dist/handlers/platform-message.js +1 -360
- package/dist/handlers/stuck-timer.js +1 -54
- package/dist/handlers/video.js +1 -237
- package/dist/handlers/voice.js +1 -148
- package/dist/i18n.js +1 -805
- package/dist/index.js +1 -697
- package/dist/init-data-dir.js +1 -98
- package/dist/middleware/auth.js +1 -233
- package/dist/migrate.js +1 -162
- package/dist/paths.js +1 -146
- package/dist/platforms/discord.js +1 -175
- package/dist/platforms/index.js +1 -130
- package/dist/platforms/signal.js +1 -205
- package/dist/platforms/slack-slash-parser.js +1 -32
- package/dist/platforms/slack.js +1 -501
- package/dist/platforms/telegram.js +1 -111
- package/dist/platforms/types.js +1 -8
- package/dist/platforms/whatsapp-auth-helpers.js +1 -53
- package/dist/platforms/whatsapp.js +1 -707
- package/dist/providers/claude-sdk-provider.js +1 -565
- package/dist/providers/codex-cli-provider.js +1 -134
- package/dist/providers/index.js +1 -7
- package/dist/providers/ollama-provider.js +1 -32
- package/dist/providers/openai-compatible.js +1 -406
- package/dist/providers/registry.js +1 -352
- package/dist/providers/runtime-header.js +1 -45
- package/dist/providers/tool-executor.js +1 -475
- package/dist/providers/types.js +1 -227
- package/dist/services/access.js +1 -144
- package/dist/services/allowed-users-gate.js +1 -56
- package/dist/services/alvin-dispatch.js +1 -130
- package/dist/services/alvin-mcp-tools.js +1 -104
- package/dist/services/asset-index.js +1 -224
- package/dist/services/async-agent-parser.js +1 -418
- package/dist/services/async-agent-watcher.js +1 -443
- package/dist/services/auto-diagnostic.js +1 -228
- package/dist/services/broadcast.js +1 -52
- package/dist/services/browser-manager.js +1 -562
- package/dist/services/browser-webfetch.js +1 -127
- package/dist/services/browser.js +1 -121
- package/dist/services/cdp-bootstrap.js +1 -357
- package/dist/services/compaction.js +1 -144
- package/dist/services/critical-notify.js +1 -203
- package/dist/services/cron-resolver.js +1 -58
- package/dist/services/cron-scheduling.js +1 -310
- package/dist/services/cron.js +1 -861
- package/dist/services/custom-tools.js +1 -317
- package/dist/services/delivery-queue.js +1 -173
- package/dist/services/delivery-registry.js +1 -21
- package/dist/services/disk-cleanup.js +1 -203
- package/dist/services/elevenlabs.js +1 -58
- package/dist/services/embeddings/auto-detect.js +1 -74
- package/dist/services/embeddings/fts5.js +1 -108
- package/dist/services/embeddings/gemini.js +1 -65
- package/dist/services/embeddings/index.js +1 -496
- package/dist/services/embeddings/ollama.js +1 -78
- package/dist/services/embeddings/openai.js +1 -49
- package/dist/services/embeddings/provider.js +1 -22
- package/dist/services/embeddings/vector-base.js +1 -113
- package/dist/services/embeddings-migration.js +1 -193
- package/dist/services/embeddings.js +1 -9
- package/dist/services/env-file.js +1 -50
- package/dist/services/exec-guard.js +1 -71
- package/dist/services/fallback-order.js +1 -154
- package/dist/services/file-permissions.js +1 -93
- package/dist/services/heartbeat-file.js +1 -65
- package/dist/services/heartbeat.js +1 -313
- package/dist/services/hooks.js +1 -44
- package/dist/services/imagegen.js +1 -72
- package/dist/services/language-detect.js +1 -154
- package/dist/services/markdown.js +1 -63
- package/dist/services/mcp.js +1 -263
- package/dist/services/memory-extractor.js +1 -178
- package/dist/services/memory-inject-mode.js +1 -43
- package/dist/services/memory-layers.js +1 -156
- package/dist/services/memory.js +1 -146
- package/dist/services/ollama-manager.js +1 -339
- package/dist/services/permissions-wizard.js +1 -291
- package/dist/services/personality.js +1 -376
- package/dist/services/plugins.js +1 -171
- package/dist/services/preflight.js +1 -292
- package/dist/services/process-manager.js +1 -291
- package/dist/services/release-highlights.js +1 -79
- package/dist/services/reminders.js +1 -97
- package/dist/services/restart.js +1 -48
- package/dist/services/security-audit.js +1 -74
- package/dist/services/self-diagnosis.js +1 -272
- package/dist/services/self-search.js +1 -129
- package/dist/services/session-persistence.js +1 -237
- package/dist/services/session.js +1 -282
- package/dist/services/skills.js +1 -290
- package/dist/services/ssrf-guard.js +1 -162
- package/dist/services/standing-orders.js +1 -29
- package/dist/services/steer-channel.js +1 -46
- package/dist/services/stop-controller.js +1 -52
- package/dist/services/subagent-dedup.js +1 -0
- package/dist/services/subagent-delivery.js +1 -452
- package/dist/services/subagent-stats.js +1 -123
- package/dist/services/subagents.js +1 -814
- package/dist/services/sudo.js +1 -329
- package/dist/services/telegram.js +1 -158
- package/dist/services/timing-safe-bearer.js +1 -51
- package/dist/services/tool-discovery.js +1 -214
- package/dist/services/trends.js +1 -580
- package/dist/services/updater.js +1 -291
- package/dist/services/usage-tracker.js +1 -144
- package/dist/services/users.js +1 -271
- package/dist/services/voice.js +1 -104
- package/dist/services/watchdog-brake.js +1 -154
- package/dist/services/watchdog.js +1 -311
- package/dist/services/workspaces.js +1 -276
- package/dist/tui/index.js +1 -667
- package/dist/util/console-formatter.js +1 -109
- package/dist/util/debounce.js +1 -24
- package/dist/util/telegram-error-filter.js +1 -62
- package/dist/version.js +1 -24
- package/dist/web/bind-strategy.js +1 -42
- package/dist/web/canvas.js +1 -30
- package/dist/web/doctor-api.js +1 -604
- package/dist/web/openai-compat.js +1 -252
- package/dist/web/server.js +1 -1831
- package/dist/web/setup-api.js +1 -1101
- package/package.json +5 -2
- package/dist/.metadata_never_index +0 -0
package/dist/services/users.js
CHANGED
|
@@ -1,271 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* User Profiles Service — Multi-user support with per-user settings and memory.
|
|
3
|
-
*
|
|
4
|
-
* Each user gets:
|
|
5
|
-
* - Their own memory directory (docs/users/<userId>/)
|
|
6
|
-
* - A profile with preferences (language, effort, voice, personality)
|
|
7
|
-
* - Separate conversation context
|
|
8
|
-
*
|
|
9
|
-
* The admin/owner user uses the global docs/memory/ and docs/MEMORY.md.
|
|
10
|
-
* Additional users get isolated memory spaces.
|
|
11
|
-
*
|
|
12
|
-
* Performance:
|
|
13
|
-
* Profiles are cached in memory after first read. `touchProfile` — called
|
|
14
|
-
* on every inbound message — writes to cache and schedules a debounced
|
|
15
|
-
* disk flush (2s). This avoids two sync fs operations per message on the
|
|
16
|
-
* hot path. A final flush happens on graceful shutdown so nothing is lost.
|
|
17
|
-
*/
|
|
18
|
-
import fs from "fs";
|
|
19
|
-
import { resolve } from "path";
|
|
20
|
-
import { config } from "../config.js";
|
|
21
|
-
import { LOCALE_NAMES } from "../i18n.js";
|
|
22
|
-
import { killSession } from "./session.js";
|
|
23
|
-
import { USERS_DIR, MEMORY_DIR } from "../paths.js";
|
|
24
|
-
// Ensure users dir exists
|
|
25
|
-
if (!fs.existsSync(USERS_DIR))
|
|
26
|
-
fs.mkdirSync(USERS_DIR, { recursive: true });
|
|
27
|
-
// ── In-memory cache + debounced persistence ─────────────
|
|
28
|
-
const cache = new Map();
|
|
29
|
-
const dirty = new Set();
|
|
30
|
-
let flushTimer = null;
|
|
31
|
-
const FLUSH_DELAY_MS = 2000;
|
|
32
|
-
function schedule_flush() {
|
|
33
|
-
if (flushTimer)
|
|
34
|
-
return;
|
|
35
|
-
flushTimer = setTimeout(() => {
|
|
36
|
-
flushTimer = null;
|
|
37
|
-
flushProfiles();
|
|
38
|
-
}, FLUSH_DELAY_MS);
|
|
39
|
-
flushTimer.unref?.();
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Write every dirty profile to disk synchronously. Called by the debounce
|
|
43
|
-
* timer AND by the graceful-shutdown handler so no in-flight updates are
|
|
44
|
-
* lost even if the bot exits between debounce ticks.
|
|
45
|
-
*/
|
|
46
|
-
export function flushProfiles() {
|
|
47
|
-
if (dirty.size === 0)
|
|
48
|
-
return;
|
|
49
|
-
for (const userId of dirty) {
|
|
50
|
-
const profile = cache.get(userId);
|
|
51
|
-
if (!profile)
|
|
52
|
-
continue;
|
|
53
|
-
try {
|
|
54
|
-
fs.writeFileSync(profilePath(userId), JSON.stringify(profile, null, 2));
|
|
55
|
-
}
|
|
56
|
-
catch (err) {
|
|
57
|
-
// Don't throw — a persistent error would block future flushes.
|
|
58
|
-
console.warn(`[users] flush ${userId} failed: ${err.message}`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
dirty.clear();
|
|
62
|
-
}
|
|
63
|
-
// ── Profile Management ──────────────────────────────────
|
|
64
|
-
function profilePath(userId) {
|
|
65
|
-
return resolve(USERS_DIR, `${userId}.json`);
|
|
66
|
-
}
|
|
67
|
-
function userMemoryDir(userId) {
|
|
68
|
-
return resolve(USERS_DIR, `${userId}`);
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Load a user profile. Returns null if not found. Reads from cache first,
|
|
72
|
-
* falls back to disk on cache miss.
|
|
73
|
-
*/
|
|
74
|
-
export function loadProfile(userId) {
|
|
75
|
-
const cached = cache.get(userId);
|
|
76
|
-
if (cached)
|
|
77
|
-
return cached;
|
|
78
|
-
try {
|
|
79
|
-
const raw = fs.readFileSync(profilePath(userId), "utf-8");
|
|
80
|
-
const profile = JSON.parse(raw);
|
|
81
|
-
cache.set(userId, profile);
|
|
82
|
-
return profile;
|
|
83
|
-
}
|
|
84
|
-
catch {
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Save a user profile — updates cache and schedules a debounced disk flush.
|
|
90
|
-
* For immediate durability (e.g. during shutdown), call flushProfiles()
|
|
91
|
-
* after this.
|
|
92
|
-
*/
|
|
93
|
-
export function saveProfile(profile) {
|
|
94
|
-
cache.set(profile.userId, profile);
|
|
95
|
-
dirty.add(profile.userId);
|
|
96
|
-
schedule_flush();
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Get or create a user profile.
|
|
100
|
-
* Auto-creates on first interaction.
|
|
101
|
-
*/
|
|
102
|
-
export function getOrCreateProfile(userId, name, username) {
|
|
103
|
-
let profile = loadProfile(userId);
|
|
104
|
-
if (!profile) {
|
|
105
|
-
const isOwner = config.allowedUsers.length > 0 && config.allowedUsers[0] === userId;
|
|
106
|
-
profile = {
|
|
107
|
-
userId,
|
|
108
|
-
name: name || `User ${userId}`,
|
|
109
|
-
username,
|
|
110
|
-
firstSeen: Date.now(),
|
|
111
|
-
lastActive: Date.now(),
|
|
112
|
-
totalMessages: 0,
|
|
113
|
-
language: "en",
|
|
114
|
-
isOwner,
|
|
115
|
-
notes: "",
|
|
116
|
-
langStats: { de: 0, en: 0, other: 0 },
|
|
117
|
-
langExplicit: false,
|
|
118
|
-
};
|
|
119
|
-
// Create user memory directory for non-owner users
|
|
120
|
-
if (!isOwner) {
|
|
121
|
-
const memDir = userMemoryDir(userId);
|
|
122
|
-
if (!fs.existsSync(memDir))
|
|
123
|
-
fs.mkdirSync(memDir, { recursive: true });
|
|
124
|
-
}
|
|
125
|
-
saveProfile(profile);
|
|
126
|
-
}
|
|
127
|
-
return profile;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Update a user's activity (call on each message).
|
|
131
|
-
*
|
|
132
|
-
* Previously this did a sync read + write per message. Now it works purely
|
|
133
|
-
* in memory and lets the debounce timer batch writes to disk.
|
|
134
|
-
*/
|
|
135
|
-
export function touchProfile(userId, name, username, platform, messageText) {
|
|
136
|
-
const profile = getOrCreateProfile(userId, name, username);
|
|
137
|
-
profile.lastActive = Date.now();
|
|
138
|
-
profile.totalMessages++;
|
|
139
|
-
if (name)
|
|
140
|
-
profile.name = name;
|
|
141
|
-
if (username)
|
|
142
|
-
profile.username = username;
|
|
143
|
-
if (platform)
|
|
144
|
-
profile.lastPlatform = platform;
|
|
145
|
-
if (messageText) {
|
|
146
|
-
profile.lastMessage = messageText.length > 120 ? messageText.slice(0, 120) + "…" : messageText;
|
|
147
|
-
profile.lastMessageAt = Date.now();
|
|
148
|
-
}
|
|
149
|
-
saveProfile(profile);
|
|
150
|
-
return profile;
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* List all known user profiles. Reads from disk; populates cache for
|
|
154
|
-
* subsequent fast access.
|
|
155
|
-
*/
|
|
156
|
-
export function listProfiles() {
|
|
157
|
-
const profiles = [];
|
|
158
|
-
try {
|
|
159
|
-
const files = fs.readdirSync(USERS_DIR);
|
|
160
|
-
for (const file of files) {
|
|
161
|
-
if (!file.endsWith(".json"))
|
|
162
|
-
continue;
|
|
163
|
-
// Parse user id from filename — skip non-numeric (e.g. stray files)
|
|
164
|
-
const userId = parseInt(file.slice(0, -5), 10);
|
|
165
|
-
if (!Number.isFinite(userId))
|
|
166
|
-
continue;
|
|
167
|
-
// If cached, use that; otherwise read once and cache
|
|
168
|
-
const cached = cache.get(userId);
|
|
169
|
-
if (cached) {
|
|
170
|
-
profiles.push(cached);
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
173
|
-
try {
|
|
174
|
-
const raw = fs.readFileSync(resolve(USERS_DIR, file), "utf-8");
|
|
175
|
-
const p = JSON.parse(raw);
|
|
176
|
-
cache.set(userId, p);
|
|
177
|
-
profiles.push(p);
|
|
178
|
-
}
|
|
179
|
-
catch { /* skip corrupt */ }
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
catch { /* dir doesn't exist */ }
|
|
183
|
-
return profiles.sort((a, b) => b.lastActive - a.lastActive);
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* Get user-specific memory directory.
|
|
187
|
-
* Owner uses global memory, others get isolated dirs.
|
|
188
|
-
*/
|
|
189
|
-
export function getUserMemoryDir(userId) {
|
|
190
|
-
const profile = loadProfile(userId);
|
|
191
|
-
if (profile?.isOwner) {
|
|
192
|
-
return MEMORY_DIR;
|
|
193
|
-
}
|
|
194
|
-
const dir = userMemoryDir(userId);
|
|
195
|
-
if (!fs.existsSync(dir))
|
|
196
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
197
|
-
return dir;
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Add a note to a user's profile (for AI context).
|
|
201
|
-
*/
|
|
202
|
-
export function addUserNote(userId, note) {
|
|
203
|
-
const profile = getOrCreateProfile(userId);
|
|
204
|
-
const timestamp = new Date().toISOString().slice(0, 16);
|
|
205
|
-
profile.notes += `\n[${timestamp}] ${note}`;
|
|
206
|
-
profile.notes = profile.notes.trim();
|
|
207
|
-
saveProfile(profile);
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Delete a user and all their data: profile, session, memory, conversation history.
|
|
211
|
-
* Returns a summary of what was deleted.
|
|
212
|
-
*/
|
|
213
|
-
export function deleteUser(userId) {
|
|
214
|
-
const deleted = [];
|
|
215
|
-
const errors = [];
|
|
216
|
-
// 0. Drop from cache + dirty set so the debounce doesn't re-create the file
|
|
217
|
-
cache.delete(userId);
|
|
218
|
-
dirty.delete(userId);
|
|
219
|
-
// 1. Delete profile JSON
|
|
220
|
-
const pPath = profilePath(userId);
|
|
221
|
-
try {
|
|
222
|
-
if (fs.existsSync(pPath)) {
|
|
223
|
-
fs.unlinkSync(pPath);
|
|
224
|
-
deleted.push("Profile");
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
catch (e) {
|
|
228
|
-
errors.push(`Profile: ${e}`);
|
|
229
|
-
}
|
|
230
|
-
// 2. Delete user memory directory (non-owner only)
|
|
231
|
-
const memDir = userMemoryDir(userId);
|
|
232
|
-
try {
|
|
233
|
-
if (fs.existsSync(memDir) && fs.statSync(memDir).isDirectory()) {
|
|
234
|
-
fs.rmSync(memDir, { recursive: true, force: true });
|
|
235
|
-
deleted.push("Memory directory");
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
catch (e) {
|
|
239
|
-
errors.push(`Memory: ${e}`);
|
|
240
|
-
}
|
|
241
|
-
// 3. Kill active session
|
|
242
|
-
try {
|
|
243
|
-
const result = killSession(userId);
|
|
244
|
-
if (result.hadSession) {
|
|
245
|
-
deleted.push("Session deleted");
|
|
246
|
-
if (result.aborted) {
|
|
247
|
-
deleted.push("Running request aborted");
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
catch (e) {
|
|
252
|
-
errors.push(`Session: ${e}`);
|
|
253
|
-
}
|
|
254
|
-
return { deleted, errors };
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Build user context string for system prompt injection.
|
|
258
|
-
*/
|
|
259
|
-
export function buildUserContext(userId) {
|
|
260
|
-
const profile = loadProfile(userId);
|
|
261
|
-
if (!profile)
|
|
262
|
-
return "";
|
|
263
|
-
const parts = [];
|
|
264
|
-
parts.push(`User: ${profile.name}${profile.username ? ` (@${profile.username})` : ""}`);
|
|
265
|
-
parts.push(`Language: ${LOCALE_NAMES[profile.language] || profile.language}`);
|
|
266
|
-
parts.push(`Messages: ${profile.totalMessages}`);
|
|
267
|
-
if (profile.notes) {
|
|
268
|
-
parts.push(`\nNotes about this user:\n${profile.notes}`);
|
|
269
|
-
}
|
|
270
|
-
return parts.join("\n");
|
|
271
|
-
}
|
|
1
|
+
const _0x4d09e2=_0x3a9a;function _0x3a9a(_0x2b409b,_0x117610){_0x2b409b=_0x2b409b-(0xf98+-0x207a+0x1232);const _0x5b21f5=_0x1db0();let _0x5e2a0c=_0x5b21f5[_0x2b409b];if(_0x3a9a['atYxTy']===undefined){var _0x9cbff0=function(_0x25749a){const _0x25082c='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x40da74='',_0x6723f6='',_0x54280d=_0x40da74+_0x9cbff0;for(let _0x3141d1=-0xebf+0x8f1+-0x2*-0x2e7,_0xfc74b1,_0x1dc15c,_0x7664be=-0x1eb3+-0x252c+0x8b*0x7d;_0x1dc15c=_0x25749a['charAt'](_0x7664be++);~_0x1dc15c&&(_0xfc74b1=_0x3141d1%(0xb92*-0x2+0x258b+-0x1*0xe63)?_0xfc74b1*(-0x11a4+0x5*0x4b2+-0x37*0x1a)+_0x1dc15c:_0x1dc15c,_0x3141d1++%(-0x1*-0x122e+-0x289*0xf+0x153*0xf))?_0x40da74+=_0x54280d['charCodeAt'](_0x7664be+(0x1*-0xcee+-0x12d7+-0x1df*-0x11))-(0x10cb+0xd52+-0x1e13)!==-0x220f+-0x1*0xf1b+0x312a?String['fromCharCode'](0x15cd+0x434+-0x1902&_0xfc74b1>>(-(-0x1*0x771+0xf96+-0x823*0x1)*_0x3141d1&-0x61*0x3a+-0x251e+0x2*0x1d8f)):_0x3141d1:0x1b4c*-0x1+-0x61b+-0x1*-0x2167){_0x1dc15c=_0x25082c['indexOf'](_0x1dc15c);}for(let _0x5800aa=-0x223f+-0xd6*-0x29+-0x1*0x7,_0x12d6b6=_0x40da74['length'];_0x5800aa<_0x12d6b6;_0x5800aa++){_0x6723f6+='%'+('00'+_0x40da74['charCodeAt'](_0x5800aa)['toString'](-0x156a+-0x2654+0x3bce))['slice'](-(0x2657+0x56c+-0x1*0x2bc1));}return decodeURIComponent(_0x6723f6);};_0x3a9a['AtWvCX']=_0x9cbff0,_0x3a9a['VaKWpA']={},_0x3a9a['atYxTy']=!![];}const _0x5b0ec0=_0x5b21f5[0x10+0x1b83+-0x1b93],_0x32a8d9=_0x2b409b+_0x5b0ec0,_0xe35cf1=_0x3a9a['VaKWpA'][_0x32a8d9];if(!_0xe35cf1){const _0x17da48=function(_0x3db29e){this['PKbyfB']=_0x3db29e,this['uXNzGI']=[-0xa2a+-0xb95*-0x3+-0x1894,0x351+-0x47*0x7f+0x8*0x3fd,-0x20ca+-0x2345+0x440f],this['pJshlZ']=function(){return'newState';},this['mTYjKE']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['vgOBsj']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x17da48['prototype']['VVcchj']=function(){const _0x29fa61=new RegExp(this['mTYjKE']+this['vgOBsj']),_0x4c9180=_0x29fa61['test'](this['pJshlZ']['toString']())?--this['uXNzGI'][0x9a0+0x288+-0xc27]:--this['uXNzGI'][0x167*-0xd+0x24a7+-0x126c];return this['fGUJrP'](_0x4c9180);},_0x17da48['prototype']['fGUJrP']=function(_0x247b6b){if(!Boolean(~_0x247b6b))return _0x247b6b;return this['uYnWXS'](this['PKbyfB']);},_0x17da48['prototype']['uYnWXS']=function(_0x337c43){for(let _0x7e38bc=-0x3ae*0x1+-0xf0b*0x1+0x12b9*0x1,_0x2ab71b=this['uXNzGI']['length'];_0x7e38bc<_0x2ab71b;_0x7e38bc++){this['uXNzGI']['push'](Math['round'](Math['random']())),_0x2ab71b=this['uXNzGI']['length'];}return _0x337c43(this['uXNzGI'][0x1*-0xb56+-0x994+0x14ea*0x1]);},new _0x17da48(_0x3a9a)['VVcchj'](),_0x5e2a0c=_0x3a9a['AtWvCX'](_0x5e2a0c),_0x3a9a['VaKWpA'][_0x32a8d9]=_0x5e2a0c;}else _0x5e2a0c=_0xe35cf1;return _0x5e2a0c;}(function(_0x3474db,_0x513814){const _0x303db1=_0x3a9a,_0x5a6724=_0x3a9a,_0x74690b=_0x3474db();while(!![]){try{const _0x3ea500=-parseInt(_0x303db1(0x193))/(-0x1*0x207b+0x1*-0x14ae+0x5*0xaa2)*(parseInt(_0x303db1(0x18a))/(-0x241f+0xfec+-0x7*-0x2e3))+parseInt(_0x5a6724(0x158))/(-0x16ef+0x178+-0x1*-0x157a)*(-parseInt(_0x303db1(0x168))/(0x35c+-0x3b*0x84+0x1b14))+parseInt(_0x5a6724(0x17c))/(-0x19e6+0x1*-0x2f+-0xd0d*-0x2)+-parseInt(_0x303db1(0x181))/(0x126*-0x7+0x137c+-0x2db*0x4)+-parseInt(_0x303db1(0x16d))/(0x73*0x4+0x1*0x1a3c+-0x1*0x1c01)+-parseInt(_0x303db1(0x18c))/(-0xb3*-0x16+-0x75*-0x2e+-0x2460)*(parseInt(_0x303db1(0x17d))/(-0x1df9+0x8eb+-0x1517*-0x1))+parseInt(_0x5a6724(0x197))/(-0x1*-0x10b1+-0xef*-0x13+-0x2264);if(_0x3ea500===_0x513814)break;else _0x74690b['push'](_0x74690b['shift']());}catch(_0x1f5e57){_0x74690b['push'](_0x74690b['shift']());}}}(_0x1db0,-0x11b9*0x31+-0x7*0x1d1a1+0x1*0x1f35b5));const _0x20f16c=(function(){let _0x2e08bf=!![];return function(_0x576570,_0x279411){const _0x2fc347=_0x2e08bf?function(){const _0x536f53=_0x3a9a;if(_0x279411){const _0x5143f1=_0x279411[_0x536f53(0x165)](_0x576570,arguments);return _0x279411=null,_0x5143f1;}}:function(){};return _0x2e08bf=![],_0x2fc347;};}()),_0x96a4d1=_0x20f16c(this,function(){const _0x53434c=_0x3a9a,_0x5dc174=_0x3a9a;return _0x96a4d1[_0x53434c(0x15e)]()['search'](_0x5dc174(0x150)+'+$')['toString']()[_0x53434c(0x183)+'r'](_0x96a4d1)[_0x5dc174(0x166)](_0x53434c(0x150)+'+$');});_0x96a4d1();import _0x2d2564 from'fs';import{resolve}from'path';import{config}from'../config.js';import{LOCALE_NAMES}from'../i18n.js';import{killSession}from'./session.js';import{USERS_DIR,MEMORY_DIR}from'../paths.js';if(!_0x2d2564['existsSync'](USERS_DIR))_0x2d2564[_0x4d09e2(0x17b)](USERS_DIR,{'recursive':!![]});const cache=new Map(),dirty=new Set();let flushTimer=null;const FLUSH_DELAY_MS=0x362*-0x6+-0x106b+0x1*0x2c87;function schedule_flush(){const _0x51d52b=_0x4d09e2;if(flushTimer)return;flushTimer=setTimeout(()=>{flushTimer=null,flushProfiles();},FLUSH_DELAY_MS),flushTimer[_0x51d52b(0x184)]?.();}export function flushProfiles(){const _0x50cde4=_0x4d09e2,_0x582b10=_0x4d09e2;if(dirty[_0x50cde4(0x18d)]===-0x1*-0x1ca0+-0xc3f+-0x1061*0x1)return;for(const _0x28baeb of dirty){const _0x1bf990=cache['get'](_0x28baeb);if(!_0x1bf990)continue;try{_0x2d2564[_0x50cde4(0x16b)+'ync'](profilePath(_0x28baeb),JSON['stringify'](_0x1bf990,null,-0x191*-0x13+-0xaad*-0x1+-0x6*0x6bd));}catch(_0x1ed97c){console[_0x582b10(0x152)]('[users]\x20fl'+_0x582b10(0x191)+_0x28baeb+_0x50cde4(0x161)+_0x1ed97c[_0x50cde4(0x190)]);}}dirty['clear']();}function profilePath(_0x2348f6){const _0x20f198=_0x4d09e2;return resolve(USERS_DIR,_0x2348f6+_0x20f198(0x159));}function userMemoryDir(_0x5a1928){return resolve(USERS_DIR,''+_0x5a1928);}export function loadProfile(_0x2d61cd){const _0x1a4562=_0x4d09e2,_0x4630c1=_0x4d09e2,_0x31d55b=cache[_0x1a4562(0x16e)](_0x2d61cd);if(_0x31d55b)return _0x31d55b;try{const _0x6d057a=_0x2d2564[_0x4630c1(0x182)+'nc'](profilePath(_0x2d61cd),_0x4630c1(0x192)),_0x17b08c=JSON[_0x4630c1(0x17e)](_0x6d057a);return cache[_0x4630c1(0x177)](_0x2d61cd,_0x17b08c),_0x17b08c;}catch{return null;}}export function saveProfile(_0x33bc56){const _0x4da0e5=_0x4d09e2,_0x1301b3=_0x4d09e2;cache['set'](_0x33bc56['userId'],_0x33bc56),dirty[_0x4da0e5(0x157)](_0x33bc56[_0x1301b3(0x196)]),schedule_flush();}export function getOrCreateProfile(_0x4b34e2,_0x136a7d,_0x580c68){const _0x23c94c=_0x4d09e2,_0x3e2f8e=_0x4d09e2;let _0x2304b3=loadProfile(_0x4b34e2);if(!_0x2304b3){const _0x389b4d=config[_0x23c94c(0x164)+'rs'][_0x23c94c(0x189)]>0x115*0x23+-0x1c22+-0x9bd&&config[_0x3e2f8e(0x164)+'rs'][0x2127+-0x20*-0x6+0xb*-0x315]===_0x4b34e2;_0x2304b3={'userId':_0x4b34e2,'name':_0x136a7d||_0x23c94c(0x16f)+_0x4b34e2,'username':_0x580c68,'firstSeen':Date[_0x23c94c(0x155)](),'lastActive':Date[_0x3e2f8e(0x155)](),'totalMessages':0x0,'language':'en','isOwner':_0x389b4d,'notes':'','langStats':{'de':0x0,'en':0x0,'other':0x0},'langExplicit':![]};if(!_0x389b4d){const _0x43450a=userMemoryDir(_0x4b34e2);if(!_0x2d2564['existsSync'](_0x43450a))_0x2d2564[_0x3e2f8e(0x17b)](_0x43450a,{'recursive':!![]});}saveProfile(_0x2304b3);}return _0x2304b3;}export function touchProfile(_0x7aaa65,_0x4a4c4c,_0x2c8e28,_0x25da48,_0x2184a3){const _0x5a21f7=_0x4d09e2,_0x496933=_0x4d09e2,_0x3b7032=getOrCreateProfile(_0x7aaa65,_0x4a4c4c,_0x2c8e28);_0x3b7032[_0x5a21f7(0x169)]=Date[_0x496933(0x155)](),_0x3b7032[_0x496933(0x171)+_0x496933(0x17f)]++;if(_0x4a4c4c)_0x3b7032[_0x5a21f7(0x179)]=_0x4a4c4c;if(_0x2c8e28)_0x3b7032[_0x496933(0x15f)]=_0x2c8e28;if(_0x25da48)_0x3b7032['lastPlatfo'+'rm']=_0x25da48;return _0x2184a3&&(_0x3b7032['lastMessag'+'e']=_0x2184a3[_0x5a21f7(0x189)]>-0x22d6+-0x1a6b+0x3db9?_0x2184a3['slice'](-0x2143+0x7e3+0x4*0x658,-0x2645+-0xec+0xb*0x39b)+'…':_0x2184a3,_0x3b7032[_0x5a21f7(0x187)+_0x5a21f7(0x15c)]=Date[_0x5a21f7(0x155)]()),saveProfile(_0x3b7032),_0x3b7032;}export function listProfiles(){const _0x5ee653=_0x4d09e2,_0x297839=_0x4d09e2,_0x32c73d=[];try{const _0x1958fe=_0x2d2564['readdirSyn'+'c'](USERS_DIR);for(const _0xa1ca32 of _0x1958fe){if(!_0xa1ca32[_0x5ee653(0x167)](_0x297839(0x159)))continue;const _0x11d4e8=parseInt(_0xa1ca32[_0x297839(0x154)](-0xd4*0x1+-0x2043+0x2117,-(0x269e+0x1*-0x178d+-0xf0c)),-0x61b*0x1+-0x1*-0x12d2+-0xcad);if(!Number['isFinite'](_0x11d4e8))continue;const _0x19706b=cache['get'](_0x11d4e8);if(_0x19706b){_0x32c73d[_0x5ee653(0x18f)](_0x19706b);continue;}try{const _0x5c6c7e=_0x2d2564[_0x297839(0x182)+'nc'](resolve(USERS_DIR,_0xa1ca32),_0x297839(0x192)),_0x54a84a=JSON[_0x297839(0x17e)](_0x5c6c7e);cache[_0x297839(0x177)](_0x11d4e8,_0x54a84a),_0x32c73d[_0x5ee653(0x18f)](_0x54a84a);}catch{}}}catch{}return _0x32c73d[_0x5ee653(0x15d)]((_0x4ce8a4,_0x28dbcd)=>_0x28dbcd[_0x5ee653(0x169)]-_0x4ce8a4[_0x5ee653(0x169)]);}export function getUserMemoryDir(_0x259e75){const _0x485d46=_0x4d09e2,_0x5ce3d4=_0x4d09e2,_0x2b3296=loadProfile(_0x259e75);if(_0x2b3296?.[_0x485d46(0x160)])return MEMORY_DIR;const _0x1d53c4=userMemoryDir(_0x259e75);if(!_0x2d2564['existsSync'](_0x1d53c4))_0x2d2564[_0x485d46(0x17b)](_0x1d53c4,{'recursive':!![]});return _0x1d53c4;}export function addUserNote(_0x55c702,_0x3f62dd){const _0x27ec00=_0x4d09e2,_0x266bfc=_0x4d09e2,_0x58727f=getOrCreateProfile(_0x55c702),_0xc61058=new Date()[_0x27ec00(0x18b)+'g']()[_0x266bfc(0x154)](-0xd6*-0x29+-0xd*0x7b+-0x1c07,-0x2654+-0x93f+0x3*0xfe1);_0x58727f[_0x266bfc(0x153)]+='\x0a['+_0xc61058+']\x20'+_0x3f62dd,_0x58727f[_0x27ec00(0x153)]=_0x58727f[_0x27ec00(0x153)][_0x27ec00(0x173)](),saveProfile(_0x58727f);}function _0x1db0(){const _0x1d808e=['zuf0','C29YDa','Dg9tDhjPBMC','DxnLCM5HBwu','AxnpD25LCG','igzHAwXLzdOG','zxi6cG','AM9PBG','ywXSB3DLzfvZzq','yxbWBhK','C2vHCMnO','zw5KC1DPDgG','nJK2nJy4ngzevK5REa','BgfZDefJDgL2zq','DxqGDgHPCYb1CW','D3jPDgvgAwXLuW','cK5VDgvZigfIBW','mJK3mdyWnhfor1bwsq','z2v0','vxnLCIa','zxHPC3rZu3LUyW','Dg90ywXnzxnZyq','u2vZC2LVBJOG','DhjPBq','uNvUBMLUzYbYzq','CM1tEw5J','uhjVzMLSzq','C2v0','zgvSzxrL','BMfTzq','twvTB3j5oIa','BwTKAxjtEw5J','nJe2mdCWzLvxBLLY','ovnLr3vABG','CgfYC2u','z2vZ','uhjVzMLSztOG','odmZmdi1nLjyv295DW','CMvHzezPBgvtEq','y29UC3rYDwn0BW','Dw5Yzwy','u2vZC2LVBIbKzq','twvTB3j5igrPCG','BgfZDe1LC3nHzW','CxvLC3qGywjVCG','BgvUz3rO','mNHYBe93AW','Dg9ju09tDhjPBG','mZuZntq5nMfbwLzXDq','C2L6zq','ywjVCNrLza','ChvZAa','BwvZC2fNzq','DxnOia','DxrMltG','mtu3mtqWmuH3uhrdzq','zwn0B3j5','C3rHDfn5BMm','DxnLCKLK','nJqZmZe4odbcBuresKC','kcGOlISPkYKRkq','DgvK','D2fYBG','BM90zxm','C2XPy2u','BM93','BgfUz3vHz2u','ywrK','m1Dssw50yG','lMPZB24','vxnLCJOG','Dw5SAw5Ru3LUyW'];_0x1db0=function(){return _0x1d808e;};return _0x1db0();}export function deleteUser(_0x34eaac){const _0x30f1e3=_0x4d09e2,_0x2cb58e=_0x4d09e2,_0x4d5dcd=[],_0x21d9cd=[];cache[_0x30f1e3(0x178)](_0x34eaac),dirty[_0x2cb58e(0x178)](_0x34eaac);const _0x23ff02=profilePath(_0x34eaac);try{_0x2d2564[_0x30f1e3(0x170)](_0x23ff02)&&(_0x2d2564[_0x30f1e3(0x15b)](_0x23ff02),_0x4d5dcd['push'](_0x2cb58e(0x176)));}catch(_0x3b1476){_0x21d9cd[_0x30f1e3(0x18f)](_0x2cb58e(0x180)+_0x3b1476);}const _0x5b9534=userMemoryDir(_0x34eaac);try{_0x2d2564[_0x2cb58e(0x170)](_0x5b9534)&&_0x2d2564[_0x30f1e3(0x195)](_0x5b9534)['isDirector'+'y']()&&(_0x2d2564[_0x30f1e3(0x175)](_0x5b9534,{'recursive':!![],'force':!![]}),_0x4d5dcd[_0x30f1e3(0x18f)](_0x30f1e3(0x186)+_0x30f1e3(0x194)));}catch(_0x35f320){_0x21d9cd[_0x30f1e3(0x18f)](_0x2cb58e(0x17a)+_0x35f320);}try{const _0x472dad=killSession(_0x34eaac);_0x472dad['hadSession']&&(_0x4d5dcd[_0x2cb58e(0x18f)](_0x2cb58e(0x185)+'leted'),_0x472dad[_0x30f1e3(0x18e)]&&_0x4d5dcd['push'](_0x2cb58e(0x174)+_0x2cb58e(0x188)+_0x2cb58e(0x151)));}catch(_0x5cdc79){_0x21d9cd['push'](_0x2cb58e(0x172)+_0x5cdc79);}return{'deleted':_0x4d5dcd,'errors':_0x21d9cd};}export function buildUserContext(_0x2b409b){const _0x463d26=_0x4d09e2,_0xfdacd=_0x4d09e2,_0x117610=loadProfile(_0x2b409b);if(!_0x117610)return'';const _0x5b21f5=[];return _0x5b21f5['push'](_0x463d26(0x15a)+_0x117610[_0x463d26(0x179)]+(_0x117610[_0xfdacd(0x15f)]?'\x20(@'+_0x117610[_0x463d26(0x15f)]+')':'')),_0x5b21f5[_0x463d26(0x18f)]('Language:\x20'+(LOCALE_NAMES[_0x117610[_0x463d26(0x156)]]||_0x117610[_0x463d26(0x156)])),_0x5b21f5[_0x463d26(0x18f)]('Messages:\x20'+_0x117610[_0xfdacd(0x171)+_0xfdacd(0x17f)]),_0x117610[_0xfdacd(0x153)]&&_0x5b21f5[_0x463d26(0x18f)](_0xfdacd(0x16c)+_0xfdacd(0x16a)+_0xfdacd(0x162)+_0x117610['notes']),_0x5b21f5[_0xfdacd(0x163)]('\x0a');}
|
package/dist/services/voice.js
CHANGED
|
@@ -1,104 +1 @@
|
|
|
1
|
-
import fs from
|
|
2
|
-
import path from "path";
|
|
3
|
-
import os from "os";
|
|
4
|
-
import https from "https";
|
|
5
|
-
import { EdgeTTS } from "node-edge-tts";
|
|
6
|
-
import { config } from "../config.js";
|
|
7
|
-
const TEMP_DIR = path.join(os.tmpdir(), "alvin-bot");
|
|
8
|
-
if (!fs.existsSync(TEMP_DIR)) {
|
|
9
|
-
fs.mkdirSync(TEMP_DIR, { recursive: true });
|
|
10
|
-
}
|
|
11
|
-
// ── Speech-to-Text (Groq Whisper) ──────────────────────
|
|
12
|
-
export async function transcribeAudio(audioPath) {
|
|
13
|
-
const fileBuffer = fs.readFileSync(audioPath);
|
|
14
|
-
const boundary = "----FormBoundary" + Math.random().toString(36).slice(2);
|
|
15
|
-
const fileName = path.basename(audioPath);
|
|
16
|
-
let body = "";
|
|
17
|
-
body += `--${boundary}\r\n`;
|
|
18
|
-
body += `Content-Disposition: form-data; name="file"; filename="${fileName}"\r\n`;
|
|
19
|
-
body += `Content-Type: audio/ogg\r\n\r\n`;
|
|
20
|
-
const bodyStart = Buffer.from(body, "utf-8");
|
|
21
|
-
const bodyEnd = Buffer.from(`\r\n--${boundary}\r\n` +
|
|
22
|
-
`Content-Disposition: form-data; name="model"\r\n\r\n` +
|
|
23
|
-
`whisper-large-v3-turbo\r\n` +
|
|
24
|
-
`--${boundary}--\r\n`, "utf-8");
|
|
25
|
-
const fullBody = Buffer.concat([bodyStart, fileBuffer, bodyEnd]);
|
|
26
|
-
return new Promise((resolve, reject) => {
|
|
27
|
-
const req = https.request({
|
|
28
|
-
hostname: "api.groq.com",
|
|
29
|
-
path: "/openai/v1/audio/transcriptions",
|
|
30
|
-
method: "POST",
|
|
31
|
-
headers: {
|
|
32
|
-
Authorization: `Bearer ${config.apiKeys.groq}`,
|
|
33
|
-
"Content-Type": `multipart/form-data; boundary=${boundary}`,
|
|
34
|
-
"Content-Length": fullBody.length,
|
|
35
|
-
},
|
|
36
|
-
}, (res) => {
|
|
37
|
-
let data = "";
|
|
38
|
-
res.on("data", (chunk) => (data += chunk));
|
|
39
|
-
res.on("end", () => {
|
|
40
|
-
try {
|
|
41
|
-
const json = JSON.parse(data);
|
|
42
|
-
resolve(json.text || "");
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
reject(new Error(`Groq STT error: ${data}`));
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
req.on("error", reject);
|
|
50
|
-
req.write(fullBody);
|
|
51
|
-
req.end();
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
// ── Text-to-Speech (Edge TTS via node-edge-tts) ────────
|
|
55
|
-
/**
|
|
56
|
-
* Convert text to speech and return path to the MP3 file.
|
|
57
|
-
*
|
|
58
|
-
* @param text The text to synthesize.
|
|
59
|
-
* @param voice Optional voice ID / name override (v4.19.0 — per-workspace).
|
|
60
|
-
* For ElevenLabs this is the Voice ID, for Edge TTS the Voice Name
|
|
61
|
-
* (e.g. "de-DE-ConradNeural", "en-US-JennyNeural"). When undefined,
|
|
62
|
-
* the config default is used.
|
|
63
|
-
*/
|
|
64
|
-
export async function textToSpeech(text, voice) {
|
|
65
|
-
// Strip markdown formatting for cleaner TTS
|
|
66
|
-
let cleanText = text
|
|
67
|
-
.replace(/```[\s\S]*?```/g, " Code block skipped. ")
|
|
68
|
-
.replace(/`([^`]+)`/g, "$1")
|
|
69
|
-
.replace(/\*\*([^*]+)\*\*/g, "$1")
|
|
70
|
-
.replace(/\*([^*]+)\*/g, "$1")
|
|
71
|
-
.replace(/#{1,6}\s/g, "")
|
|
72
|
-
.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
|
|
73
|
-
.replace(/\n{2,}/g, ". ")
|
|
74
|
-
.replace(/\n/g, " ")
|
|
75
|
-
.trim();
|
|
76
|
-
if (!cleanText) {
|
|
77
|
-
throw new Error("No text available for TTS");
|
|
78
|
-
}
|
|
79
|
-
if (cleanText.length > 3000) {
|
|
80
|
-
cleanText = cleanText.slice(0, 3000) + "... Text truncated.";
|
|
81
|
-
}
|
|
82
|
-
// Try ElevenLabs if configured
|
|
83
|
-
if (config.ttsProvider === "elevenlabs" && config.elevenlabs.apiKey) {
|
|
84
|
-
try {
|
|
85
|
-
const { elevenLabsTTS } = await import("./elevenlabs.js");
|
|
86
|
-
// v4.19.0 — per-workspace voice override. When unset, elevenLabsTTS falls
|
|
87
|
-
// back to config.elevenlabs.voiceId.
|
|
88
|
-
return await elevenLabsTTS(cleanText, voice);
|
|
89
|
-
}
|
|
90
|
-
catch (err) {
|
|
91
|
-
console.warn("ElevenLabs TTS failed, falling back to Edge TTS:", err instanceof Error ? err.message : err);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
// Edge TTS (default / fallback)
|
|
95
|
-
const outputPath = path.join(TEMP_DIR, `tts_${Date.now()}.mp3`);
|
|
96
|
-
const tts = new EdgeTTS({
|
|
97
|
-
// v4.19.0 — allow workspace override; default German male.
|
|
98
|
-
voice: voice || "de-DE-ConradNeural",
|
|
99
|
-
lang: voice && voice.match(/^[a-z]{2}-[A-Z]{2}/) ? voice.slice(0, 5) : "de-DE",
|
|
100
|
-
outputFormat: "audio-24khz-48kbitrate-mono-mp3",
|
|
101
|
-
});
|
|
102
|
-
await tts.ttsPromise(cleanText, outputPath);
|
|
103
|
-
return outputPath;
|
|
104
|
-
}
|
|
1
|
+
const _0x27ebef=_0x33b6,_0x3d813f=_0x33b6;(function(_0x12aa1e,_0x3d91da){const _0x51b1f9=_0x33b6,_0x4eb553=_0x33b6,_0x599c97=_0x12aa1e();while(!![]){try{const _0x4b2597=-parseInt(_0x51b1f9(0x12c))/(-0x43*-0x66+0x1*-0x1ac0+0xf)*(parseInt(_0x4eb553(0x126))/(-0xaa9+-0x1*0x25db+0x3086))+-parseInt(_0x4eb553(0x138))/(-0x175f*0x1+-0xdad+0x250f)+-parseInt(_0x4eb553(0x12f))/(-0xd6f*-0x1+-0x1*0x1e7d+0x1112)+parseInt(_0x51b1f9(0x10f))/(-0x4f7+-0x188*0x2+0x67*0x14)*(parseInt(_0x51b1f9(0x12e))/(-0xa9f*-0x2+0x69*0x49+-0x3329))+-parseInt(_0x51b1f9(0x110))/(-0x8fb*-0x1+-0x3ab+-0x549*0x1)*(-parseInt(_0x51b1f9(0x135))/(0x22*0xe5+0x23b6+-0x4218))+parseInt(_0x51b1f9(0x124))/(-0x2*-0xdbd+-0xd1c+-0xe55*0x1)+parseInt(_0x51b1f9(0x131))/(-0x215f+-0x1e06+0x3f6f)*(parseInt(_0x4eb553(0x106))/(0x7*0x147+0x4bb*0x7+-0x2a03));if(_0x4b2597===_0x3d91da)break;else _0x599c97['push'](_0x599c97['shift']());}catch(_0x54666f){_0x599c97['push'](_0x599c97['shift']());}}}(_0x4e7c,-0x4b04*-0x5+0x115689+-0x97a90));const _0x2841fc=(function(){let _0x4ec4f3=!![];return function(_0x2cdd1a,_0xd9a27f){const _0x3e0515=_0x4ec4f3?function(){const _0x469809=_0x33b6;if(_0xd9a27f){const _0x2d6999=_0xd9a27f[_0x469809(0x10a)](_0x2cdd1a,arguments);return _0xd9a27f=null,_0x2d6999;}}:function(){};return _0x4ec4f3=![],_0x3e0515;};}()),_0x1e2ae0=_0x2841fc(this,function(){const _0xa72d68=_0x33b6,_0x33f5aa=_0x33b6;return _0x1e2ae0[_0xa72d68(0x121)]()[_0xa72d68(0x11b)]('(((.+)+)+)'+'+$')[_0xa72d68(0x121)]()[_0x33f5aa(0x10b)+'r'](_0x1e2ae0)[_0x33f5aa(0x11b)](_0xa72d68(0x11f)+'+$');});_0x1e2ae0();import _0x23c7d7 from'fs';import _0x5c7f54 from'path';import _0x462762 from'os';import _0x2d69d1 from'https';import{EdgeTTS}from'node-edge-tts';import{config}from'../config.js';function _0x33b6(_0x2ab468,_0x4afec5){_0x2ab468=_0x2ab468-(-0x1e94+-0x419+0x23b0);const _0x234562=_0x4e7c();let _0x615ec7=_0x234562[_0x2ab468];if(_0x33b6['PIQwjJ']===undefined){var _0xce1cff=function(_0x308cb8){const _0x57d760='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x3be09c='',_0x292180='',_0x4586ba=_0x3be09c+_0xce1cff;for(let _0x557eb5=0x193b+0x34c+-0x1c87,_0x9ecade,_0x4c8d1f,_0x4433f5=-0x79*-0x2f+-0x850+-0x1*0xde7;_0x4c8d1f=_0x308cb8['charAt'](_0x4433f5++);~_0x4c8d1f&&(_0x9ecade=_0x557eb5%(-0x21e*0x5+-0x105*0x1d+0x282b)?_0x9ecade*(0x1ad9+-0x3*-0x487+-0x282e)+_0x4c8d1f:_0x4c8d1f,_0x557eb5++%(-0x13c3+-0x103a+0xd*0x2c5))?_0x3be09c+=_0x4586ba['charCodeAt'](_0x4433f5+(-0x2*-0x41+-0x3*0x82+0x10e))-(-0x14b7+0x11*-0x73+0x1c64)!==0x198d*0x1+-0x598+-0x13f5?String['fromCharCode'](0x47*-0x53+-0x9c2+-0x1*-0x21c6&_0x9ecade>>(-(-0x1bed+0x6*0x1f5+0x1031)*_0x557eb5&-0x24b6+0x5ff+-0xa3f*-0x3)):_0x557eb5:-0x17a0+0x91d*0x2+0x566){_0x4c8d1f=_0x57d760['indexOf'](_0x4c8d1f);}for(let _0x48e86b=0x239*-0x2+-0x1e44+0x22b6,_0x34ca79=_0x3be09c['length'];_0x48e86b<_0x34ca79;_0x48e86b++){_0x292180+='%'+('00'+_0x3be09c['charCodeAt'](_0x48e86b)['toString'](0x1106+0x54e+-0x1644))['slice'](-(0x10b*0x1+0x12f5+-0x13fe));}return decodeURIComponent(_0x292180);};_0x33b6['Uaenro']=_0xce1cff,_0x33b6['kIZEAu']={},_0x33b6['PIQwjJ']=!![];}const _0x55a6c4=_0x234562[0x20b*-0x13+0x25b0+0x121],_0x4f0d82=_0x2ab468+_0x55a6c4,_0x46c57d=_0x33b6['kIZEAu'][_0x4f0d82];if(!_0x46c57d){const _0x48ec19=function(_0x24e54f){this['xKOuUF']=_0x24e54f,this['RdIcMI']=[0x2*0x8e4+0x293+-0x412*0x5,-0x1d51+-0x1*-0x1e9c+0x1*-0x14b,-0x37a*0x4+0x1e02+-0x101a],this['dnxbQL']=function(){return'newState';},this['BKMpmY']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['kQzoht']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x48ec19['prototype']['JfQxNH']=function(){const _0x23559a=new RegExp(this['BKMpmY']+this['kQzoht']),_0x5045b6=_0x23559a['test'](this['dnxbQL']['toString']())?--this['RdIcMI'][-0xe02*-0x1+-0x1*-0x2337+-0x3138]:--this['RdIcMI'][0x1567+-0x21b3+0xc4c];return this['fcDQPQ'](_0x5045b6);},_0x48ec19['prototype']['fcDQPQ']=function(_0xf09aa5){if(!Boolean(~_0xf09aa5))return _0xf09aa5;return this['PWvjGA'](this['xKOuUF']);},_0x48ec19['prototype']['PWvjGA']=function(_0x49872c){for(let _0x18adce=-0x5e*0x24+0x1*-0xdd3+-0x12d*-0x17,_0x52ead0=this['RdIcMI']['length'];_0x18adce<_0x52ead0;_0x18adce++){this['RdIcMI']['push'](Math['round'](Math['random']())),_0x52ead0=this['RdIcMI']['length'];}return _0x49872c(this['RdIcMI'][-0x2171+-0x1*0x1353+0x34c4]);},new _0x48ec19(_0x33b6)['JfQxNH'](),_0x615ec7=_0x33b6['Uaenro'](_0x615ec7),_0x33b6['kIZEAu'][_0x4f0d82]=_0x615ec7;}else _0x615ec7=_0x46c57d;return _0x615ec7;}const TEMP_DIR=_0x5c7f54[_0x27ebef(0x151)](_0x462762[_0x27ebef(0x116)](),'alvin-bot');!_0x23c7d7[_0x3d813f(0x113)](TEMP_DIR)&&_0x23c7d7[_0x27ebef(0x149)](TEMP_DIR,{'recursive':!![]});export async function transcribeAudio(_0x3492d1){const _0x4e987c=_0x3d813f,_0x2e6567=_0x3d813f,_0x3da2bf=_0x23c7d7['readFileSy'+'nc'](_0x3492d1),_0x1bedb6=_0x4e987c(0x103)+_0x2e6567(0x13f)+Math[_0x4e987c(0x142)]()[_0x4e987c(0x121)](-0x9*0x243+-0x2420+0x389f)['slice'](-0x47*-0xe+-0x18bf+0xd*0x19b),_0x2e249b=_0x5c7f54[_0x4e987c(0x111)](_0x3492d1);let _0x3701e1='';_0x3701e1+='--'+_0x1bedb6+'\x0d\x0a',_0x3701e1+=_0x4e987c(0x14f)+_0x4e987c(0x12a)+_0x2e6567(0x105)+_0x4e987c(0x137)+_0x2e6567(0x140)+_0x2e6567(0x147)+_0x2e249b+_0x4e987c(0x118),_0x3701e1+=_0x4e987c(0x122)+_0x2e6567(0x141)+_0x2e6567(0x104);const _0x2569c2=Buffer[_0x2e6567(0x156)](_0x3701e1,_0x4e987c(0x10d)),_0x163cd7=Buffer[_0x2e6567(0x156)]('\x0d\x0a--'+_0x1bedb6+'\x0d\x0a'+(_0x2e6567(0x14f)+_0x4e987c(0x12a)+'\x20form-data'+_0x4e987c(0x152)+_0x4e987c(0x158))+(_0x4e987c(0x10c)+_0x2e6567(0x114)+_0x4e987c(0x14b))+('--'+_0x1bedb6+'--\x0d\x0a'),_0x2e6567(0x10d)),_0x45d4b4=Buffer['concat']([_0x2569c2,_0x3da2bf,_0x163cd7]);return new Promise((_0x611bfd,_0x12daaa)=>{const _0x497002=_0x2e6567,_0x5d115a=_0x2e6567,_0x45eea3=_0x2d69d1[_0x497002(0x129)]({'hostname':_0x497002(0x132)+'om','path':_0x5d115a(0x145)+_0x497002(0x11a)+_0x497002(0x128)+'s','method':_0x497002(0x148),'headers':{'Authorization':_0x497002(0x146)+config[_0x5d115a(0x107)][_0x5d115a(0x13d)],'Content-Type':_0x497002(0x155)+'form-data;'+_0x5d115a(0x120)+_0x1bedb6,'Content-Length':_0x45d4b4[_0x497002(0x10e)]}},_0x21f546=>{const _0x31bba5=_0x497002,_0x5d9db3=_0x5d115a;let _0x30d57d='';_0x21f546['on'](_0x31bba5(0x13a),_0x4eef8d=>_0x30d57d+=_0x4eef8d),_0x21f546['on'](_0x5d9db3(0x13c),()=>{const _0x52ccd6=_0x5d9db3,_0x2470d5=_0x5d9db3;try{const _0x2a53f6=JSON[_0x52ccd6(0x14a)](_0x30d57d);_0x611bfd(_0x2a53f6[_0x2470d5(0x115)]||'');}catch{_0x12daaa(new Error(_0x2470d5(0x139)+_0x52ccd6(0x112)+_0x30d57d));}});});_0x45eea3['on'](_0x497002(0x153),_0x12daaa),_0x45eea3['write'](_0x45d4b4),_0x45eea3[_0x497002(0x13c)]();});}function _0x4e7c(){const _0x53658f=['yw1Lpsi','ue9tva','BwTKAxjtEw5J','CgfYC2u','yM8ncG','D2fYBG','rwXLDMvUtgfICW','AYbZA2LWCgvKlG','q29UDgvUDc1eAq','DguTBw9UBY1TCa','AM9PBG','oYbUyw1LpsjTBW','zxjYB3i','ifruuYbMywLSzq','BxvSDgLWyxj0lW','zNjVBq','tM8GDgv4DcbHDG','zgvSiG0kdqO','zcWGzMfSBgLUzW','ls0TluzVCM1cBW','B2DNdqOncG','igzVCM0Tzgf0yq','mte0nty1otLmtKnoDxq','yxbPs2v5CW','DhjPBq','Bwf0y2G','yxbWBhK','y29UC3rYDwn0BW','D2HPC3bLCI1Syq','DxrMltG','BgvUz3rO','mtvNt2rTzNy','nJm3r2LKBNbn','yMfZzw5HBwu','CNjVCJOG','zxHPC3rZu3LUyW','CMDLlxyZlxr1CG','Dgv4Da','Dg1WzgLY','CIbuvfm','iG0k','CNvUy2f0zwqU','l2f1zgLVl3rYyq','C2vHCMnO','BM93','zgDLifruuZO','DhrZxW','kcGOlISPkYKRkq','igjVDw5Kyxj5pq','Dg9tDhjPBMC','q29UDgvUDc1uEq','yNmUANm','ndi2mdqYowHvuK1bvG','lI9LBgv2zw5Syq','nfv0q3PcrG','lI4UifrLEhqGDa','BNnJCMLWDgLVBG','CMvXDwvZDa','C3bVC2L0Aw9UoG','yxvKAw8TmJrRAa','mZq3ndu1suD3wMHN','zwXLDMvUBgfICW','nJuZntHYCvLSvuu','ndGWntG4nePyr2fbDW','DhrZuhjVBwLZzq','mJbhD0XvzLa','yxbPlMDYB3eUyW','EI00ogTIAxrYyq','ywrozxvYywW','ntiXmZz6z3HpDgq','yxbPs2v5','oYbUyw1LpsjMAq','mJaYmZK3n3fuvwv2AW','r3jVCsbtvfqGzq','zgf0yq','C2XPy2u','zw5K','z3jVCq','igjHy2SGDg8Grq','Dw5Kyxj5','BguIoYbMAwXLBG','Cgu6igf1zgLVlW','CMfUzg9T','zguTreu','CMvWBgfJzq','l29Wzw5HAs92mq','qMvHCMvYia'];_0x4e7c=function(){return _0x53658f;};return _0x4e7c();}export async function textToSpeech(_0x2a43d9,_0xabf406){const _0x4e662f=_0x3d813f,_0xfbfedf=_0x3d813f;let _0x5be4c2=_0x2a43d9[_0x4e662f(0x144)](/```[\s\S]*?```/g,'\x20Code\x20bloc'+_0xfbfedf(0x14e)+'\x20')[_0x4e662f(0x144)](/`([^`]+)`/g,'$1')[_0xfbfedf(0x144)](/\*\*([^*]+)\*\*/g,'$1')[_0xfbfedf(0x144)](/\*([^*]+)\*/g,'$1')[_0xfbfedf(0x144)](/#{1,6}\s/g,'')[_0x4e662f(0x144)](/\[([^\]]+)\]\([^)]+\)/g,'$1')[_0xfbfedf(0x144)](/\n{2,}/g,'.\x20')[_0x4e662f(0x144)](/\n/g,'\x20')[_0x4e662f(0x108)]();if(!_0x5be4c2)throw new Error(_0x4e662f(0x157)+'ailable\x20fo'+_0xfbfedf(0x117));_0x5be4c2[_0xfbfedf(0x10e)]>-0x23c9+0x106+0x2e7b&&(_0x5be4c2=_0x5be4c2[_0xfbfedf(0x13b)](-0x103a+0xc*-0x21d+-0x1*-0x2996,-0x1*-0x1b8e+-0x8e9+-0x6ed)+(_0x4e662f(0x127)+_0x4e662f(0x119)));if(config['ttsProvide'+'r']===_0xfbfedf(0x12d)&&config[_0xfbfedf(0x12d)][_0xfbfedf(0x136)])try{const {elevenLabsTTS:_0x1b3f32}=await import(_0x4e662f(0x125)+_0xfbfedf(0x123));return await _0x1b3f32(_0x5be4c2,_0xabf406);}catch(_0x4477b2){console[_0xfbfedf(0x14c)](_0x4e662f(0x14d)+_0xfbfedf(0x154)+_0xfbfedf(0x159)+_0x4e662f(0x13e)+_0xfbfedf(0x11d),_0x4477b2 instanceof Error?_0x4477b2['message']:_0x4477b2);}const _0x51957b=_0x5c7f54[_0x4e662f(0x151)](TEMP_DIR,_0x4e662f(0x11e)+Date[_0xfbfedf(0x11c)]()+'.mp3'),_0x11dde8=new EdgeTTS({'voice':_0xabf406||'de-DE-Conr'+_0xfbfedf(0x134),'lang':_0xabf406&&_0xabf406[_0x4e662f(0x109)](/^[a-z]{2}-[A-Z]{2}/)?_0xabf406[_0xfbfedf(0x13b)](0x11*-0x73+-0x82f+-0x6*-0x2a3,0x1e3b+0x21be+-0x3ff4):_0xfbfedf(0x143),'outputFormat':_0xfbfedf(0x12b)+_0xfbfedf(0x133)+_0x4e662f(0x150)+'3'});return await _0x11dde8[_0xfbfedf(0x130)](_0x5be4c2,_0x51957b),_0x51957b;}
|
|
@@ -1,154 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Pure crash-loop brake logic, extracted from watchdog.ts so it can be
|
|
3
|
-
* unit-tested without touching the filesystem or launchctl.
|
|
4
|
-
*
|
|
5
|
-
* See test/watchdog-brake.test.ts for the regression this closes:
|
|
6
|
-
* chronic crashes with >5 min of uptime between them used to reset
|
|
7
|
-
* the counter before it could trip the brake, so the bot cycled
|
|
8
|
-
* indefinitely. The new policy enforces TWO thresholds — a fast
|
|
9
|
-
* short-window brake and a hard 24h daily cap — and only resets the
|
|
10
|
-
* counter after a real 1 h of clean uptime.
|
|
11
|
-
*/
|
|
12
|
-
export const DEFAULTS = {
|
|
13
|
-
/** Beacon older than this → previous process exited cleanly (or the
|
|
14
|
-
* machine was rebooted); do not count as a crash. */
|
|
15
|
-
STALE_BEACON_MS: 90_000,
|
|
16
|
-
/** Short-window crash tracking — N crashes in SHORT_WINDOW_MS. */
|
|
17
|
-
SHORT_WINDOW_MS: 10 * 60_000,
|
|
18
|
-
SHORT_BRAKE_THRESHOLD: 10,
|
|
19
|
-
/** Daily crash cap — hard ceiling regardless of gaps. Tripping this
|
|
20
|
-
* means the bot has been restarting >20 times per day, which is
|
|
21
|
-
* almost certainly a chronic issue worth freezing and alerting. */
|
|
22
|
-
DAILY_WINDOW_MS: 24 * 60 * 60 * 1000,
|
|
23
|
-
DAILY_BRAKE_THRESHOLD: 20,
|
|
24
|
-
/** Uptime required before the short-window counter resets. Was 5 min
|
|
25
|
-
* in the buggy version — but 5 min is shorter than the typical
|
|
26
|
-
* sub-agent lifetime (the daily job-alert takes 10+ min), so chronic
|
|
27
|
-
* crashes with ≥5 min gaps sailed right past the brake. 1 h is safer. */
|
|
28
|
-
RESET_AFTER_MS: 60 * 60_000,
|
|
29
|
-
};
|
|
30
|
-
/**
|
|
31
|
-
* Validate + normalize a parsed beacon JSON into a BeaconData (or null
|
|
32
|
-
* if the core fields are missing/wrong-typed). Pure so the read-path
|
|
33
|
-
* field mapping is unit-testable — extracted after v5.1.5 shipped a
|
|
34
|
-
* broken expectedRestart: the old readBeacon() rebuilt the object
|
|
35
|
-
* field-by-field and silently dropped expectedRestart, so the flag
|
|
36
|
-
* never reached decideBrakeAction and intentional restarts were still
|
|
37
|
-
* counted as crashes. Whatever round-trips here is what the brake sees.
|
|
38
|
-
*/
|
|
39
|
-
export function normalizeBeacon(parsed) {
|
|
40
|
-
if (!parsed)
|
|
41
|
-
return null;
|
|
42
|
-
if (typeof parsed.lastBeat === "number" &&
|
|
43
|
-
typeof parsed.pid === "number" &&
|
|
44
|
-
typeof parsed.bootTime === "number" &&
|
|
45
|
-
typeof parsed.crashCount === "number" &&
|
|
46
|
-
typeof parsed.crashWindowStart === "number" &&
|
|
47
|
-
typeof parsed.version === "string") {
|
|
48
|
-
return {
|
|
49
|
-
lastBeat: parsed.lastBeat,
|
|
50
|
-
pid: parsed.pid,
|
|
51
|
-
bootTime: parsed.bootTime,
|
|
52
|
-
crashCount: parsed.crashCount,
|
|
53
|
-
crashWindowStart: parsed.crashWindowStart,
|
|
54
|
-
version: parsed.version,
|
|
55
|
-
// Older beacons don't have daily-counter fields — default them to
|
|
56
|
-
// 0/now so the brake logic treats this run as the start of the
|
|
57
|
-
// first daily window.
|
|
58
|
-
dailyCrashCount: typeof parsed.dailyCrashCount === "number" ? parsed.dailyCrashCount : 0,
|
|
59
|
-
dailyCrashWindowStart: typeof parsed.dailyCrashWindowStart === "number"
|
|
60
|
-
? parsed.dailyCrashWindowStart
|
|
61
|
-
: Date.now(),
|
|
62
|
-
// The whole point of the v5.1.6 fix: propagate expectedRestart so
|
|
63
|
-
// a planned restart is not scored as a crash on the next boot.
|
|
64
|
-
expectedRestart: parsed.expectedRestart === true,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Given the previous beacon (or null on first boot) and the current time,
|
|
71
|
-
* decide whether the bot should proceed with boot or engage the crash-loop
|
|
72
|
-
* brake.
|
|
73
|
-
*
|
|
74
|
-
* PURE: no fs, no launchctl, no clock — `now` is an explicit parameter.
|
|
75
|
-
*/
|
|
76
|
-
export function decideBrakeAction(previous, now, opts = {}) {
|
|
77
|
-
const staleMs = opts.staleBeaconMs ?? DEFAULTS.STALE_BEACON_MS;
|
|
78
|
-
const shortWindow = opts.shortWindowMs ?? DEFAULTS.SHORT_WINDOW_MS;
|
|
79
|
-
const shortBrake = opts.shortBrakeThreshold ?? DEFAULTS.SHORT_BRAKE_THRESHOLD;
|
|
80
|
-
const dailyWindow = opts.dailyWindowMs ?? DEFAULTS.DAILY_WINDOW_MS;
|
|
81
|
-
const dailyBrake = opts.dailyBrakeThreshold ?? DEFAULTS.DAILY_BRAKE_THRESHOLD;
|
|
82
|
-
// First boot or no beacon file → clean start
|
|
83
|
-
if (!previous) {
|
|
84
|
-
return {
|
|
85
|
-
action: "proceed",
|
|
86
|
-
crashCount: 0,
|
|
87
|
-
crashWindowStart: now,
|
|
88
|
-
dailyCrashCount: 0,
|
|
89
|
-
dailyCrashWindowStart: now,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
// Daily window roll-over first — it's independent of short window.
|
|
93
|
-
let dailyCount = previous.dailyCrashCount;
|
|
94
|
-
let dailyStart = previous.dailyCrashWindowStart;
|
|
95
|
-
if (now - dailyStart >= dailyWindow) {
|
|
96
|
-
dailyCount = 0;
|
|
97
|
-
dailyStart = now;
|
|
98
|
-
}
|
|
99
|
-
const timeSinceLastBeat = now - previous.lastBeat;
|
|
100
|
-
const previousExitedRecently = timeSinceLastBeat < staleMs;
|
|
101
|
-
if (!previousExitedRecently || previous.expectedRestart) {
|
|
102
|
-
// Clean exit, intentional restart (auto-update / `/update`), or a
|
|
103
|
-
// machine reboot between runs → short-window counter resets, but the
|
|
104
|
-
// daily counter keeps going unless its own window already expired
|
|
105
|
-
// above. expectedRestart is honored even when the beacon is fresh:
|
|
106
|
-
// a planned process.exit(0) is not a crash.
|
|
107
|
-
return {
|
|
108
|
-
action: "proceed",
|
|
109
|
-
crashCount: 0,
|
|
110
|
-
crashWindowStart: now,
|
|
111
|
-
dailyCrashCount: dailyCount,
|
|
112
|
-
dailyCrashWindowStart: dailyStart,
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
// Short-window logic
|
|
116
|
-
const shortWindowExpired = now - previous.crashWindowStart >= shortWindow;
|
|
117
|
-
let crashCount;
|
|
118
|
-
let crashWindowStart;
|
|
119
|
-
if (shortWindowExpired) {
|
|
120
|
-
crashCount = 1;
|
|
121
|
-
crashWindowStart = now;
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
crashCount = previous.crashCount + 1;
|
|
125
|
-
crashWindowStart = previous.crashWindowStart;
|
|
126
|
-
}
|
|
127
|
-
// Increment daily count since we treat this as a crash
|
|
128
|
-
dailyCount += 1;
|
|
129
|
-
if (crashCount >= shortBrake) {
|
|
130
|
-
return {
|
|
131
|
-
action: "brake",
|
|
132
|
-
reason: `${crashCount} crashes within short window (${Math.round(shortWindow / 60_000)}min) — threshold is ${shortBrake}`,
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
if (dailyCount >= dailyBrake) {
|
|
136
|
-
return {
|
|
137
|
-
action: "brake",
|
|
138
|
-
reason: `${dailyCount} crashes within daily window (${Math.round(dailyWindow / 3_600_000)}h) — threshold is ${dailyBrake}`,
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
return {
|
|
142
|
-
action: "proceed",
|
|
143
|
-
crashCount,
|
|
144
|
-
crashWindowStart,
|
|
145
|
-
dailyCrashCount: dailyCount,
|
|
146
|
-
dailyCrashWindowStart: dailyStart,
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
/** Whether the short-window crash counter should be reset after this
|
|
150
|
-
* much clean uptime. Default: 1 h. */
|
|
151
|
-
export function shouldResetCrashCounter(uptimeMs, opts = {}) {
|
|
152
|
-
const threshold = opts.resetAfterMs ?? DEFAULTS.RESET_AFTER_MS;
|
|
153
|
-
return uptimeMs >= threshold;
|
|
154
|
-
}
|
|
1
|
+
(function(_0x4b01f8,_0x57dd86){const _0xd0a921=_0x2c2c,_0x3ca79c=_0x2c2c,_0x1fc0df=_0x4b01f8();while(!![]){try{const _0x1590d6=-parseInt(_0xd0a921(0x11c))/(0x64*-0x11+0x1d49+0xcf*-0x1c)+parseInt(_0x3ca79c(0x12c))/(-0x1183+-0x1*-0x1f19+-0xd94)+-parseInt(_0xd0a921(0x11b))/(-0xc3e+-0x1acc+0x270d)+-parseInt(_0x3ca79c(0x124))/(0x22a*-0xd+-0x7ae*0x4+0x1d6f*0x2)+-parseInt(_0xd0a921(0x12a))/(-0x2*0x136b+0x3*0xce5+0x2c)*(-parseInt(_0x3ca79c(0x10a))/(-0x1c7b+-0x6*0x31a+0x2f1d))+-parseInt(_0x3ca79c(0x118))/(-0x2631+-0x23da+-0x3e6*-0x13)+-parseInt(_0xd0a921(0x136))/(0x3d*-0x11+0x18*-0x38+0x955)*(-parseInt(_0xd0a921(0x121))/(0x17cc+0x1*0x214c+-0x390f));if(_0x1590d6===_0x57dd86)break;else _0x1fc0df['push'](_0x1fc0df['shift']());}catch(_0x4134ba){_0x1fc0df['push'](_0x1fc0df['shift']());}}}(_0x3be1,0x1*-0x31be3+0x1e1*-0x1d+0x2*0x2b05a));const _0x50c98a=(function(){let _0x2ec69f=!![];return function(_0x366568,_0xd28ad1){const _0x562454=_0x2ec69f?function(){const _0x3ab615=_0x2c2c;if(_0xd28ad1){const _0x5c625a=_0xd28ad1[_0x3ab615(0x115)](_0x366568,arguments);return _0xd28ad1=null,_0x5c625a;}}:function(){};return _0x2ec69f=![],_0x562454;};}()),_0x5401f6=_0x50c98a(this,function(){const _0x19c5ee=_0x2c2c,_0x39b32d=_0x2c2c;return _0x5401f6[_0x19c5ee(0x13b)]()['search'](_0x19c5ee(0x13a)+'+$')['toString']()[_0x39b32d(0x138)+'r'](_0x5401f6)[_0x39b32d(0x122)](_0x19c5ee(0x13a)+'+$');});function _0x2c2c(_0x5e8ea,_0x177e8e){_0x5e8ea=_0x5e8ea-(0xb2b*-0x3+0x2*0x49+0x21f9);const _0x400751=_0x3be1();let _0x13e532=_0x400751[_0x5e8ea];if(_0x2c2c['xTdPgk']===undefined){var _0x1f566d=function(_0x23a561){const _0x2ece7f='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x56eaf4='',_0x4ac903='',_0x201709=_0x56eaf4+_0x1f566d;for(let _0x58fd5a=0x567*-0x4+0x157*0xc+0x588,_0x599e1d,_0x3db4b2,_0x3a5fcf=-0x1958+-0x1ac7+0xb*0x4bd;_0x3db4b2=_0x23a561['charAt'](_0x3a5fcf++);~_0x3db4b2&&(_0x599e1d=_0x58fd5a%(-0x2*-0x395+0x242f+0x1*-0x2b55)?_0x599e1d*(0x109f+0x1462+-0x1*0x24c1)+_0x3db4b2:_0x3db4b2,_0x58fd5a++%(-0xb3a+-0x24f8+0x3036))?_0x56eaf4+=_0x201709['charCodeAt'](_0x3a5fcf+(0x1c4f+0x4af*-0x1+-0x1796))-(-0xa30+0x1fc8+0xac7*-0x2)!==-0xdad+0xf8e+-0x1e1?String['fromCharCode'](0x1167+0x19*-0x65+-0x43*0x19&_0x599e1d>>(-(0x683*-0x1+-0x1*-0x1f4b+-0x18c6)*_0x58fd5a&-0x3*0x707+0x338*0x4+0x83b)):_0x58fd5a:0x9c8+0x1*-0x22dc+0x1914){_0x3db4b2=_0x2ece7f['indexOf'](_0x3db4b2);}for(let _0x579db2=0x73a+0xa*0x301+0x5a*-0x6a,_0x9f3cbe=_0x56eaf4['length'];_0x579db2<_0x9f3cbe;_0x579db2++){_0x4ac903+='%'+('00'+_0x56eaf4['charCodeAt'](_0x579db2)['toString'](0x1e2d+0x1943*-0x1+-0x4da*0x1))['slice'](-(-0x25*0x5c+0x1aa6+0x8*-0x1ab));}return decodeURIComponent(_0x4ac903);};_0x2c2c['Dvgial']=_0x1f566d,_0x2c2c['ONqDEr']={},_0x2c2c['xTdPgk']=!![];}const _0x27d825=_0x400751[-0x67f*0x1+-0x1cf0+0x236f],_0x1648a7=_0x5e8ea+_0x27d825,_0xbfc880=_0x2c2c['ONqDEr'][_0x1648a7];if(!_0xbfc880){const _0x3ec777=function(_0x101ff9){this['gcTRPH']=_0x101ff9,this['ySzIou']=[-0xbf+0x57f*0x1+-0x4bf,-0x392+-0x17*-0xdf+-0x3*0x57d,0x5*0x36b+0x1aa1+0x15dc*-0x2],this['ppAuDq']=function(){return'newState';},this['IPthFj']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['Sqbbky']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x3ec777['prototype']['QeWecb']=function(){const _0x4f52ab=new RegExp(this['IPthFj']+this['Sqbbky']),_0x3710f1=_0x4f52ab['test'](this['ppAuDq']['toString']())?--this['ySzIou'][0x2698+0xf8d+-0x3624]:--this['ySzIou'][-0x172a+0x2164+-0x77*0x16];return this['EnfdEL'](_0x3710f1);},_0x3ec777['prototype']['EnfdEL']=function(_0x3a3ed8){if(!Boolean(~_0x3a3ed8))return _0x3a3ed8;return this['rGVSNE'](this['gcTRPH']);},_0x3ec777['prototype']['rGVSNE']=function(_0x52c52b){for(let _0x53b95c=-0x88d+-0xa00+-0x62f*-0x3,_0x4c1d9e=this['ySzIou']['length'];_0x53b95c<_0x4c1d9e;_0x53b95c++){this['ySzIou']['push'](Math['round'](Math['random']())),_0x4c1d9e=this['ySzIou']['length'];}return _0x52c52b(this['ySzIou'][-0x2133+0x87b+-0x18b8*-0x1]);},new _0x3ec777(_0x2c2c)['QeWecb'](),_0x13e532=_0x2c2c['Dvgial'](_0x13e532),_0x2c2c['ONqDEr'][_0x1648a7]=_0x13e532;}else _0x13e532=_0xbfc880;return _0x13e532;}_0x5401f6();export const DEFAULTS={'STALE_BEACON_MS':0x15f90,'SHORT_WINDOW_MS':(-0x227f+-0x1958+0x3be1)*(0x5e50*0x3+-0x5*-0x2b09+-0x107bd),'SHORT_BRAKE_THRESHOLD':0xa,'DAILY_WINDOW_MS':(0xa9*0x35+0xc5a+-0x2f3f)*(0xff1+-0x82c+-0x789)*(-0x1*0x1dfb+-0x1782+0x35b9*0x1)*(-0x3*0x6dc+-0xa30+0x8ab*0x4),'DAILY_BRAKE_THRESHOLD':0x14,'RESET_AFTER_MS':(-0xdad+0xf8e+-0x1a5)*(0xd0d0+0x1*-0x7655+-0xffd*-0x9)};export function normalizeBeacon(_0x1bea7d){const _0x4afeb3=_0x2c2c,_0x314540=_0x2c2c;if(!_0x1bea7d)return null;if(typeof _0x1bea7d[_0x4afeb3(0x135)]===_0x314540(0x132)&&typeof _0x1bea7d[_0x314540(0x119)]===_0x4afeb3(0x132)&&typeof _0x1bea7d[_0x4afeb3(0x11e)]===_0x4afeb3(0x132)&&typeof _0x1bea7d['crashCount']===_0x4afeb3(0x132)&&typeof _0x1bea7d[_0x314540(0x12d)+'wStart']===_0x4afeb3(0x132)&&typeof _0x1bea7d[_0x4afeb3(0x12f)]==='string')return{'lastBeat':_0x1bea7d[_0x314540(0x135)],'pid':_0x1bea7d[_0x314540(0x119)],'bootTime':_0x1bea7d[_0x4afeb3(0x11e)],'crashCount':_0x1bea7d[_0x4afeb3(0x11f)],'crashWindowStart':_0x1bea7d[_0x314540(0x12d)+_0x314540(0x10e)],'version':_0x1bea7d['version'],'dailyCrashCount':typeof _0x1bea7d[_0x314540(0x139)+_0x4afeb3(0x130)]==='number'?_0x1bea7d[_0x314540(0x139)+_0x4afeb3(0x130)]:0x683*-0x1+-0x1*-0x1f4b+-0x18c8,'dailyCrashWindowStart':typeof _0x1bea7d['dailyCrash'+_0x4afeb3(0x126)+'t']===_0x4afeb3(0x132)?_0x1bea7d[_0x4afeb3(0x139)+_0x314540(0x126)+'t']:Date[_0x314540(0x123)](),'expectedRestart':_0x1bea7d[_0x314540(0x110)+'start']===!![]};return null;}export function decideBrakeAction(_0x2b54f7,_0x4823c5,_0x142ffe={}){const _0x4a26d6=_0x2c2c,_0x3fce37=_0x2c2c,_0x55520a=_0x142ffe['staleBeaco'+_0x4a26d6(0x12e)]??DEFAULTS[_0x3fce37(0x113)+_0x3fce37(0x137)],_0x22c638=_0x142ffe[_0x3fce37(0x12b)+_0x4a26d6(0x10f)]??DEFAULTS['SHORT_WIND'+'OW_MS'],_0x50a54d=_0x142ffe['shortBrake'+'Threshold']??DEFAULTS[_0x3fce37(0x127)+_0x4a26d6(0x134)+'D'],_0x28344b=_0x142ffe['dailyWindo'+_0x4a26d6(0x10f)]??DEFAULTS[_0x3fce37(0x116)+_0x4a26d6(0x11d)],_0x448c1e=_0x142ffe[_0x4a26d6(0x10c)+_0x3fce37(0x111)]??DEFAULTS[_0x4a26d6(0x125)+_0x4a26d6(0x134)+'D'];if(!_0x2b54f7)return{'action':_0x3fce37(0x13c),'crashCount':0x0,'crashWindowStart':_0x4823c5,'dailyCrashCount':0x0,'dailyCrashWindowStart':_0x4823c5};let _0x50311d=_0x2b54f7[_0x4a26d6(0x139)+_0x4a26d6(0x130)],_0x5dbbe7=_0x2b54f7[_0x4a26d6(0x139)+_0x4a26d6(0x126)+'t'];_0x4823c5-_0x5dbbe7>=_0x28344b&&(_0x50311d=-0x3*0x707+0x338*0x4+0x835,_0x5dbbe7=_0x4823c5);const _0x38aa1c=_0x4823c5-_0x2b54f7[_0x4a26d6(0x135)],_0x1c36e4=_0x38aa1c<_0x55520a;if(!_0x1c36e4||_0x2b54f7[_0x3fce37(0x110)+'start'])return{'action':_0x3fce37(0x13c),'crashCount':0x0,'crashWindowStart':_0x4823c5,'dailyCrashCount':_0x50311d,'dailyCrashWindowStart':_0x5dbbe7};const _0x4daf50=_0x4823c5-_0x2b54f7[_0x4a26d6(0x12d)+'wStart']>=_0x22c638;let _0x594f29,_0x5ecb38;_0x4daf50?(_0x594f29=0x9c8+0x1*-0x22dc+0x1915,_0x5ecb38=_0x4823c5):(_0x594f29=_0x2b54f7[_0x4a26d6(0x11f)]+(0x73a+0xa*0x301+0x1*-0x2543),_0x5ecb38=_0x2b54f7[_0x4a26d6(0x12d)+'wStart']);_0x50311d+=0x1e2d+0x1943*-0x1+-0x4e9*0x1;if(_0x594f29>=_0x50a54d)return{'action':'brake','reason':_0x594f29+(_0x3fce37(0x114)+_0x3fce37(0x129)+_0x4a26d6(0x120))+Math[_0x3fce37(0x11a)](_0x22c638/(-0x5c*0x1bc+0x13fc1+0x7*0xa99))+(_0x4a26d6(0x117)+_0x4a26d6(0x131))+_0x50a54d};if(_0x50311d>=_0x448c1e)return{'action':_0x4a26d6(0x10d),'reason':_0x50311d+(_0x3fce37(0x114)+'ithin\x20dail'+_0x4a26d6(0x10b))+Math['round'](_0x28344b/(-0x1244c1*0x1+-0x5160b3+0x9a93f4))+('h)\x20—\x20thres'+_0x4a26d6(0x112))+_0x448c1e};return{'action':'proceed','crashCount':_0x594f29,'crashWindowStart':_0x5ecb38,'dailyCrashCount':_0x50311d,'dailyCrashWindowStart':_0x5dbbe7};}function _0x3be1(){const _0x233e32=['Dg9tDhjPBMC','ChjVy2vLza','mtaYvhvkDxPp','Esb3Aw5KB3CGka','zgfPBhLcCMfRzq','yNjHA2u','D1n0yxj0','D01Z','zxHWzwn0zwrszq','vgHYzxnOB2XK','Ag9SzcbPCYa','u1rbtevFqKvbqW','ignYyxnOzxmGDW','yxbWBhK','refjtfLFv0Lora','BwLUksdIGjqGDgHY','mteYndC2mhfSDKn2tG','CgLK','CM91BMq','ndu1odeXELzpCLDx','mtu5nZG0ELzHyw1j','t1DFtvm','yM9VDfrPBwu','y3jHC2HdB3vUDa','Dcb3Aw5KB3CGka','mtHbD0XZs04','C2vHCMnO','BM93','nJq1nZG4sezwzKLP','refjtfLFqLjbsW','v2LUzg93u3rHCG','u0HpuLrFqLjbsW','uKvtrvrFquzurq','AxrOAw4GC2HVCG','oda0nvjfyLruua','C2HVCNrxAw5KBW','ndyWnZa2A3j2BwD0','y3jHC2HxAw5KBW','BK1Z','DMvYC2LVBG','q291BNq','zxnOB2XKigLZia','BNvTyMvY','CMvZzxrbzNrLCG','rv9usfjfu0Hpta','BgfZDejLyxq','mJa0mZuYogL5rgnnEq','t05Ftvm','y29UC3rYDwn0BW','zgfPBhLdCMfZAa','kcGOlISPkYKRkq'];_0x3be1=function(){return _0x233e32;};return _0x3be1();}export function shouldResetCrashCounter(_0x42ab01,_0x2089e0={}){const _0x1f6397=_0x2c2c,_0x105397=_0x2c2c,_0x202b52=_0x2089e0[_0x1f6397(0x133)+'Ms']??DEFAULTS[_0x105397(0x128)+'R_MS'];return _0x42ab01>=_0x202b52;}
|