alvin-bot 5.7.0 → 5.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +25 -31
- 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 -174
- 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 -583
- 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 -86
- 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 -1902
- 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 _0x134624=_0x2007,_0x348368=_0x2007;(function(_0x20e81a,_0x19794f){const _0x5248be=_0x2007,_0x50926d=_0x2007,_0x522c4d=_0x20e81a();while(!![]){try{const _0x46ae9f=-parseInt(_0x5248be(0x1ae))/(-0x49f*-0x8+-0xea3+-0x2*0xb2a)*(parseInt(_0x5248be(0x185))/(0x1525+0x1512+-0x2a35))+-parseInt(_0x5248be(0x18a))/(-0x6f8+0x5*0x1f2+0x13*-0x25)+-parseInt(_0x50926d(0x1a2))/(-0x22c2+0x5*0x1c9+0x19d9)*(-parseInt(_0x50926d(0x1a6))/(-0x90*0x17+0x1*0x13ab+-0x6b6))+parseInt(_0x5248be(0x1b1))/(0x1392+-0xfbf+-0x3cd*0x1)*(-parseInt(_0x50926d(0x1af))/(-0x867+0x38*0x10+-0x2*-0x277))+-parseInt(_0x5248be(0x191))/(0x2*-0x102b+0x5*-0x7+0x2081*0x1)*(parseInt(_0x50926d(0x1a4))/(-0x239e+-0x2*-0x11b1+-0x45*-0x1))+parseInt(_0x50926d(0x17a))/(-0x3f9+-0xd92*0x1+0x1*0x1195)*(-parseInt(_0x5248be(0x198))/(-0x113b*0x1+0x3*0x44f+-0x459*-0x1))+parseInt(_0x50926d(0x175))/(0x28*0xac+0x17c4+-0x3298);if(_0x46ae9f===_0x19794f)break;else _0x522c4d['push'](_0x522c4d['shift']());}catch(_0x1d7e5a){_0x522c4d['push'](_0x522c4d['shift']());}}}(_0x12a1,0x7c*0x3125+-0x178b4b+0xeda47));const _0x1de8a8=(function(){let _0x3123e3=!![];return function(_0x26648a,_0x3e85ad){const _0x2fa5e2=_0x3123e3?function(){if(_0x3e85ad){const _0x2653bf=_0x3e85ad['apply'](_0x26648a,arguments);return _0x3e85ad=null,_0x2653bf;}}:function(){};return _0x3123e3=![],_0x2fa5e2;};}()),_0x14f83e=_0x1de8a8(this,function(){const _0x551256=_0x2007,_0xec8c30=_0x2007;return _0x14f83e[_0x551256(0x16d)]()['search'](_0xec8c30(0x1a7)+'+$')['toString']()[_0x551256(0x177)+'r'](_0x14f83e)[_0xec8c30(0x17b)](_0x551256(0x1a7)+'+$');});function _0x12a1(){const _0x30b1b5=['AgfKu2vZC2LVBG','ody2z3rIEvfh','n2fXDe9msa','ywXSB3DLzfvZzq','mZy3oti3ohHjA3P6rq','ywrK','DxqGDgHPCYb1CW','Dg9tDhjPBMC','AM9PBG','C3rHDfn5BMm','C2v0','Dg90ywXnzxnZyq','z2v0','u2vZC2LVBIbKzq','ChvZAa','mtK3odC1mJbpq3rVDLi','BgfUz3vHz2u','y29UC3rYDwn0BW','z2vZ','icHa','mZbtDM15CuO','C2vHCMnO','igzHAwXLzdOG','C3rYAw5NAwz5','BM90zxm','Ew5J','w3vZzxjZxsbMBa','C29YDa','CM1tEw5J','DxnLCKLK','BMfTzq','ndaWyNHNBerj','zwn0B3j5','BgfZDefJDgL2zq','DxnLCM5HBwu','AxngAw5PDgu','mZu3mdyWDgDfrvf4','DxrMltG','D3jPDgvgAwXLuW','BgfZDe1LC3nHzW','CMvHzezPBgvtEq','twvTB3j5igrPCG','C2XPy2u','nty4BvPSEuTt','twvZC2fNzxm6ia','y2XLyxi','CgfYC2u','CMvHzgrPCLn5BG','AxnpD25LCG','twvTB3j5oIa','ndCWnda0BK9jD2fL','BgvUz3rO','Dg9ju09tDhjPBG','CxvLC3qGywjVCG','AxneAxjLy3rVCG','BgfZDfbSyxrMBW','BwvZC2fNzq','DxnOia','D2fYBG','lMPZB24','nhPQCNDtBq','BwTKAxjtEw5J','mJG4mJDbq1PNvwG','DhjPBq','mZaXmZa5mfflCLfpDa','kcGOlISPkYKRkq','BM93','zgvSzxrL','vxnLCJOG','C2L6zq','zxHPC3rZu3LUyW'];_0x12a1=function(){return _0x30b1b5;};return _0x12a1();}_0x14f83e();import _0x627473 from'fs';function _0x2007(_0x2a36f9,_0x2c99be){_0x2a36f9=_0x2a36f9-(-0xcc7*0x2+-0x25f4+0x40ef);const _0x46abde=_0x12a1();let _0x151518=_0x46abde[_0x2a36f9];if(_0x2007['lBTfiN']===undefined){var _0x26f995=function(_0x5904a6){const _0x3a94e9='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x1a5d3f='',_0x3a7955='',_0x38e145=_0x1a5d3f+_0x26f995;for(let _0x2d3252=-0xcd5+-0x17ce+0x24a3,_0xb7970b,_0x241b37,_0x26a2fd=0x8b*-0x2e+0x1b4+-0x1*-0x1746;_0x241b37=_0x5904a6['charAt'](_0x26a2fd++);~_0x241b37&&(_0xb7970b=_0x2d3252%(-0x1511+-0x1*0x1a21+0x2f36)?_0xb7970b*(-0x2*0xe75+-0x1d6c+-0x1d4b*-0x2)+_0x241b37:_0x241b37,_0x2d3252++%(0x1*0x13ed+0x1*-0x2252+0x1*0xe69))?_0x1a5d3f+=_0x38e145['charCodeAt'](_0x26a2fd+(0x54*-0x40+-0xd32+0x223c))-(-0xdd5*0x2+-0x1e81+0x1367*0x3)!==0xdb9+0x24aa+-0x3263?String['fromCharCode'](-0x12a8+-0x749+-0xd78*-0x2&_0xb7970b>>(-(0x1ced+-0x1bf5+-0xf6)*_0x2d3252&-0x1134*0x1+0xc1*0x8+0x2*0x599)):_0x2d3252:0xb77+-0xa49+-0x2*0x97){_0x241b37=_0x3a94e9['indexOf'](_0x241b37);}for(let _0x2ca0be=-0x5b*0x2+-0x103*-0x21+0x23*-0xef,_0x4e594d=_0x1a5d3f['length'];_0x2ca0be<_0x4e594d;_0x2ca0be++){_0x3a7955+='%'+('00'+_0x1a5d3f['charCodeAt'](_0x2ca0be)['toString'](0x2*0x5d+-0x16a6*0x1+0x15fc))['slice'](-(-0x2208+-0x1*-0x130+0x20da));}return decodeURIComponent(_0x3a7955);};_0x2007['bSFrMT']=_0x26f995,_0x2007['uojzAY']={},_0x2007['lBTfiN']=!![];}const _0x38db27=_0x46abde[-0x1*-0x1193+0xe4d+-0x1fe0],_0x2f468e=_0x2a36f9+_0x38db27,_0x432bff=_0x2007['uojzAY'][_0x2f468e];if(!_0x432bff){const _0x3ae86c=function(_0x24b3c0){this['knruXb']=_0x24b3c0,this['qQdWfl']=[0x59*-0x4f+-0xb2f*-0x3+0xad*-0x9,-0x11*-0x104+0x11e3*-0x1+0x9f,0x1*-0x2403+-0xf*0xd+0x24c6*0x1],this['HRZwrL']=function(){return'newState';},this['aYlUyb']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['QyyXxx']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x3ae86c['prototype']['hcUOBi']=function(){const _0x2a8b62=new RegExp(this['aYlUyb']+this['QyyXxx']),_0xb6f99b=_0x2a8b62['test'](this['HRZwrL']['toString']())?--this['qQdWfl'][0x2*0x3a+-0xe97+-0x16a*-0xa]:--this['qQdWfl'][-0x118e*0x1+0x12d8+-0x1e*0xb];return this['nyxggq'](_0xb6f99b);},_0x3ae86c['prototype']['nyxggq']=function(_0x15e2a4){if(!Boolean(~_0x15e2a4))return _0x15e2a4;return this['zJYjoY'](this['knruXb']);},_0x3ae86c['prototype']['zJYjoY']=function(_0x358871){for(let _0x3e8210=-0x209+0xbad*0x3+-0x20fe,_0x23907c=this['qQdWfl']['length'];_0x3e8210<_0x23907c;_0x3e8210++){this['qQdWfl']['push'](Math['round'](Math['random']())),_0x23907c=this['qQdWfl']['length'];}return _0x358871(this['qQdWfl'][-0x2593+0x263c+-0x1*0xa9]);},new _0x3ae86c(_0x2007)['hcUOBi'](),_0x151518=_0x2007['bSFrMT'](_0x151518),_0x2007['uojzAY'][_0x2f468e]=_0x151518;}else _0x151518=_0x432bff;return _0x151518;}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(!_0x627473[_0x134624(0x1ac)](USERS_DIR))_0x627473[_0x134624(0x1a3)](USERS_DIR,{'recursive':!![]});const cache=new Map(),dirty=new Set();let flushTimer=null;const FLUSH_DELAY_MS=0x1f79+-0x1*-0x16b3+-0x2e5c;function schedule_flush(){if(flushTimer)return;flushTimer=setTimeout(()=>{flushTimer=null,flushProfiles();},FLUSH_DELAY_MS),flushTimer['unref']?.();}export function flushProfiles(){const _0x253425=_0x348368,_0x540e8e=_0x348368;if(dirty[_0x253425(0x1ab)]===-0x1*0x1a21+-0x2648+0x4069)return;for(const _0x45230b of dirty){const _0x412486=cache[_0x540e8e(0x172)](_0x45230b);if(!_0x412486)continue;try{_0x627473[_0x540e8e(0x18c)+_0x540e8e(0x17f)](profilePath(_0x45230b),JSON[_0x540e8e(0x17d)](_0x412486,null,-0x1d6c+0x75b+-0x1613*-0x1));}catch(_0x4c68d1){console[_0x540e8e(0x1a0)](_0x540e8e(0x180)+_0x540e8e(0x19f)+_0x45230b+_0x540e8e(0x17c)+_0x4c68d1[_0x540e8e(0x19e)]);}}dirty[_0x253425(0x193)]();}function profilePath(_0x28a161){const _0xc8202=_0x348368;return resolve(USERS_DIR,_0x28a161+_0xc8202(0x1a1));}function userMemoryDir(_0x13b149){return resolve(USERS_DIR,''+_0x13b149);}export function loadProfile(_0x1f88ca){const _0x934784=_0x134624,_0x358c66=_0x134624,_0xe2b220=cache['get'](_0x1f88ca);if(_0xe2b220)return _0xe2b220;try{const _0x58a2c0=_0x627473[_0x934784(0x18e)+'nc'](profilePath(_0x1f88ca),_0x934784(0x18b)),_0x3f08cb=JSON[_0x934784(0x194)](_0x58a2c0);return cache[_0x934784(0x170)](_0x1f88ca,_0x3f08cb),_0x3f08cb;}catch{return null;}}export function saveProfile(_0x4c420d){const _0x26a7c1=_0x134624,_0x339d46=_0x134624;cache[_0x26a7c1(0x170)](_0x4c420d['userId'],_0x4c420d),dirty[_0x26a7c1(0x1b2)](_0x4c420d[_0x26a7c1(0x183)]),schedule_flush();}export function getOrCreateProfile(_0x59da4e,_0x916ec4,_0x410e7d){const _0x1e7bbf=_0x348368,_0x389ca1=_0x348368;let _0x4aea21=loadProfile(_0x59da4e);if(!_0x4aea21){const _0x44c387=config[_0x1e7bbf(0x1b0)+'rs'][_0x1e7bbf(0x199)]>0x1*0x13ed+0x1*-0x2252+0x1*0xe65&&config['allowedUse'+'rs'][0x54*-0x40+-0xd32+0x2232]===_0x59da4e;_0x4aea21={'userId':_0x59da4e,'name':_0x916ec4||'User\x20'+_0x59da4e,'username':_0x410e7d,'firstSeen':Date['now'](),'lastActive':Date[_0x389ca1(0x1a8)](),'totalMessages':0x0,'language':'en','isOwner':_0x44c387,'notes':'','langStats':{'de':0x0,'en':0x0,'other':0x0},'langExplicit':![]};if(!_0x44c387){const _0x19dbaf=userMemoryDir(_0x59da4e);if(!_0x627473[_0x389ca1(0x1ac)](_0x19dbaf))_0x627473[_0x1e7bbf(0x1a3)](_0x19dbaf,{'recursive':!![]});}saveProfile(_0x4aea21);}return _0x4aea21;}export function touchProfile(_0x42e6d4,_0x22e153,_0x3153cb,_0x54d65b,_0x424a93){const _0x32a5ab=_0x134624,_0x2ea2b5=_0x348368,_0x3bc5b4=getOrCreateProfile(_0x42e6d4,_0x22e153,_0x3153cb);_0x3bc5b4['lastActive']=Date[_0x32a5ab(0x1a8)](),_0x3bc5b4[_0x32a5ab(0x171)+_0x32a5ab(0x178)]++;if(_0x22e153)_0x3bc5b4[_0x32a5ab(0x184)]=_0x22e153;if(_0x3153cb)_0x3bc5b4[_0x32a5ab(0x188)]=_0x3153cb;if(_0x54d65b)_0x3bc5b4[_0x2ea2b5(0x19d)+'rm']=_0x54d65b;return _0x424a93&&(_0x3bc5b4[_0x2ea2b5(0x18d)+'e']=_0x424a93[_0x2ea2b5(0x199)]>-0xdd5*0x2+-0x1e81+0x373*0x11?_0x424a93[_0x32a5ab(0x190)](0xdb9+0x24aa+-0x3263,-0x12a8+-0x749+-0x1a69*-0x1)+'…':_0x424a93,_0x3bc5b4[_0x2ea2b5(0x18d)+'eAt']=Date[_0x2ea2b5(0x1a8)]()),saveProfile(_0x3bc5b4),_0x3bc5b4;}export function listProfiles(){const _0x36e50f=_0x134624,_0x2d4b9=_0x348368,_0x2ec2be=[];try{const _0x459999=_0x627473[_0x36e50f(0x195)+'c'](USERS_DIR);for(const _0x347d43 of _0x459999){if(!_0x347d43['endsWith'](_0x36e50f(0x1a1)))continue;const _0x31d7ac=parseInt(_0x347d43[_0x36e50f(0x190)](0x1ced+-0x1bf5+-0xf8,-(-0x1134*0x1+0xc1*0x8+0xf*0xbf)),0xb77+-0xa49+-0x4*0x49);if(!Number[_0x36e50f(0x189)](_0x31d7ac))continue;const _0x12bc7c=cache[_0x36e50f(0x172)](_0x31d7ac);if(_0x12bc7c){_0x2ec2be[_0x2d4b9(0x174)](_0x12bc7c);continue;}try{const _0x3212a4=_0x627473['readFileSy'+'nc'](resolve(USERS_DIR,_0x347d43),_0x36e50f(0x18b)),_0x5bc352=JSON[_0x36e50f(0x194)](_0x3212a4);cache['set'](_0x31d7ac,_0x5bc352),_0x2ec2be[_0x36e50f(0x174)](_0x5bc352);}catch{}}}catch{}return _0x2ec2be[_0x2d4b9(0x181)]((_0x303df3,_0x1de1e8)=>_0x1de1e8[_0x36e50f(0x187)]-_0x303df3[_0x2d4b9(0x187)]);}export function getUserMemoryDir(_0x558d84){const _0x37b76a=_0x348368,_0x2f69e6=_0x348368,_0x37cae1=loadProfile(_0x558d84);if(_0x37cae1?.[_0x37b76a(0x196)])return MEMORY_DIR;const _0x24fedd=userMemoryDir(_0x558d84);if(!_0x627473[_0x37b76a(0x1ac)](_0x24fedd))_0x627473[_0x37b76a(0x1a3)](_0x24fedd,{'recursive':!![]});return _0x24fedd;}export function addUserNote(_0x3f9ab9,_0x1256a8){const _0x4b94d1=_0x134624,_0x102391=_0x134624,_0x1a4318=getOrCreateProfile(_0x3f9ab9),_0x46b00e=new Date()[_0x4b94d1(0x19a)+'g']()['slice'](-0x5b*0x2+-0x103*-0x21+0x23*-0xef,0x2*0x5d+-0x16a6*0x1+0x15fc);_0x1a4318[_0x4b94d1(0x17e)]+='\x0a['+_0x46b00e+']\x20'+_0x1256a8,_0x1a4318['notes']=_0x1a4318[_0x4b94d1(0x17e)][_0x102391(0x1a5)](),saveProfile(_0x1a4318);}export function deleteUser(_0x4b4a57){const _0x5da5dc=_0x348368,_0x15c99d=_0x348368,_0x16e186=[],_0x2c5959=[];cache[_0x5da5dc(0x1a9)](_0x4b4a57),dirty[_0x5da5dc(0x1a9)](_0x4b4a57);const _0x3ee26f=profilePath(_0x4b4a57);try{_0x627473[_0x5da5dc(0x1ac)](_0x3ee26f)&&(_0x627473['unlinkSync'](_0x3ee26f),_0x16e186[_0x15c99d(0x174)]('Profile'));}catch(_0x2d3406){_0x2c5959[_0x15c99d(0x174)]('Profile:\x20'+_0x2d3406);}const _0x138c07=userMemoryDir(_0x4b4a57);try{_0x627473['existsSync'](_0x138c07)&&_0x627473[_0x5da5dc(0x16f)](_0x138c07)[_0x5da5dc(0x19c)+'y']()&&(_0x627473[_0x5da5dc(0x182)](_0x138c07,{'recursive':!![],'force':!![]}),_0x16e186[_0x15c99d(0x174)](_0x5da5dc(0x18f)+_0x15c99d(0x186)));}catch(_0x5a7010){_0x2c5959['push'](_0x15c99d(0x197)+_0x5a7010);}try{const _0x709c75=killSession(_0x4b4a57);_0x709c75[_0x5da5dc(0x1ad)]&&(_0x16e186['push'](_0x5da5dc(0x173)+'leted'),_0x709c75['aborted']&&_0x16e186['push']('Running\x20re'+_0x15c99d(0x19b)+'ted'));}catch(_0x3764a9){_0x2c5959[_0x15c99d(0x174)]('Session:\x20'+_0x3764a9);}return{'deleted':_0x16e186,'errors':_0x2c5959};}export function buildUserContext(_0x59a514){const _0x425715=_0x134624,_0x1de394=_0x348368,_0x2d9de5=loadProfile(_0x59a514);if(!_0x2d9de5)return'';const _0x1d4563=[];return _0x1d4563[_0x425715(0x174)](_0x1de394(0x1aa)+_0x2d9de5[_0x425715(0x184)]+(_0x2d9de5['username']?_0x1de394(0x179)+_0x2d9de5[_0x425715(0x188)]+')':'')),_0x1d4563[_0x1de394(0x174)]('Language:\x20'+(LOCALE_NAMES[_0x2d9de5[_0x425715(0x176)]]||_0x2d9de5[_0x425715(0x176)])),_0x1d4563[_0x425715(0x174)](_0x1de394(0x192)+_0x2d9de5[_0x425715(0x171)+_0x425715(0x178)]),_0x2d9de5['notes']&&_0x1d4563[_0x425715(0x174)]('\x0aNotes\x20abo'+_0x425715(0x1b3)+'er:\x0a'+_0x2d9de5[_0x425715(0x17e)]),_0x1d4563[_0x425715(0x16e)]('\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 _0x2027ae=_0x46ed,_0x2693a2=_0x46ed;(function(_0x24427c,_0x44e489){const _0x195439=_0x46ed,_0x279222=_0x46ed,_0x1f2818=_0x24427c();while(!![]){try{const _0x3abdd7=-parseInt(_0x195439(0x1c1))/(0x15f5+-0x55b+-0x1099)+parseInt(_0x279222(0x1d7))/(-0xb6f+-0x1*0x1012+-0x1*-0x1b83)+parseInt(_0x195439(0x1bf))/(0x1*-0x17ad+-0xf84+0x304*0xd)*(-parseInt(_0x195439(0x1c5))/(-0x1*0x2e+-0x1*-0x10b4+0x841*-0x2))+-parseInt(_0x279222(0x1be))/(0x3*0x9+0xc1e+-0x2c*0x47)*(-parseInt(_0x279222(0x1de))/(-0x20c5*-0x1+0x1bdd+-0x3c9c))+-parseInt(_0x195439(0x19d))/(-0x17fc+-0x10fc+0x28ff)*(-parseInt(_0x195439(0x1d4))/(0x10e6+0x1*-0x2093+0xfb5))+-parseInt(_0x279222(0x1e5))/(-0x1*-0x1aa1+0x1*-0x2277+0x7df)*(-parseInt(_0x279222(0x1ca))/(-0xec8+0x18d*-0x10+0x27a2))+-parseInt(_0x279222(0x1cc))/(-0x979+-0x13*-0x158+-0x401*0x4);if(_0x3abdd7===_0x44e489)break;else _0x1f2818['push'](_0x1f2818['shift']());}catch(_0x462b6c){_0x1f2818['push'](_0x1f2818['shift']());}}}(_0x3433,-0x2f9*-0x4f3+-0x223*0x533+0x5*0x2277b));function _0x3433(){const _0x3efe7a=['C2vHCMnO','BgvUz3rO','oYbUyw1LpsjTBW','lI9LBgv2zw5Syq','zguTreuTq29UCG','yNmUANm','igjVDw5Kyxj5pq','y29UC3rYDwn0BW','Dg1WzgLY','ls0ncG','D2HPC3bLCI1Syq','l2f1zgLVl3rYyq','Dg9tDhjPBMC','ywLSywjSzsbMBW','mtqYogThthPksG','CMvHzezPBgvtEq','qMvHCMvYia','l29Wzw5HAs92mq','yMfZzw5HBwu','yxbWBhK','rwXLDMvUtgfICW','yxbPs2v5','zwXLDMvUBgfICW','y29Uy2f0','tM8GDgv4DcbHDG','zgf0yq','C2XPy2u','DguTBw9UBY1TCa','yM8ncG','igzVCM0Tzgf0yq','CgfYC2u','oYbUyw1LpsjMAq','yxbPs2v5CW','DxrMltG','BxvSDgLWyxj0lW','ifruuYbMywLSzq','zM9YBs1KyxrHoW','ls0TluzVCM1cBW','zxjYB3i','z3jVCq','CMDLlxyZlxr1CG','lM1WmW','D3jPDgu','igjHy2SGDg8Grq','DhrZuhjVDMLKzq','yxbPlMDYB3eUyW','zNjVBq','mJbTreH5wLu','mtiZowTvwLDJsa','Cgu6igf1zgLVlW','nZy3mtC5t1fTEuPe','DhrZuhjVBwLZzq','zguTreu','ywrozxvYywW','mta2mJHnAfLeC3a','ue9tva','EI00ogTIAxrYyq','Bwf0y2G','CMvXDwvZDa','ndb6rufQyLy','zcWGzMfSBgLUzW','mtqXotGXntfwtej6C08','AYbZA2LWCgvKlG','CNvUy2f0zwqU','ienVzguGyMXVyW','zw5K','q29UDgvUDc1eAq','BwTKAxjtEw5J','C3bVC2L0Aw9UoG','mZm2mdbgvgzbq1m','AM9PBG','yw1Lpsi','mti2odiWneHfrhP0DG','lI4UifrLEhqGDa','iG0k','Dw5Kyxj5','BM93','zgDLifruuZO','CNjVCJOG','mte0mJq1nezgEMDJqG','BNnJCMLWDgLVBG','BguIoYbMAwXLBG','CMvWBgfJzq','ywX2Aw4TyM90','dqOTlq','kcGOlISPkYKRkq','nde1mdy4m2TRu2jsCW','zgvSiG0kdqO'];_0x3433=function(){return _0x3efe7a;};return _0x3433();}const _0x45807b=(function(){let _0x4065de=!![];return function(_0x5e79bf,_0x5455bd){const _0x3fe10c=_0x4065de?function(){const _0x2d0b50=_0x46ed;if(_0x5455bd){const _0x4f763f=_0x5455bd[_0x2d0b50(0x1a2)](_0x5e79bf,arguments);return _0x5455bd=null,_0x4f763f;}}:function(){};return _0x4065de=![],_0x3fe10c;};}()),_0x222c22=_0x45807b(this,function(){const _0x31fb7d=_0x46ed,_0x3841f2=_0x46ed;return _0x222c22['toString']()[_0x31fb7d(0x1e7)](_0x3841f2(0x1e4)+'+$')[_0x31fb7d(0x19b)]()[_0x3841f2(0x1ee)+'r'](_0x222c22)['search'](_0x31fb7d(0x1e4)+'+$');});_0x222c22();import _0x35bd55 from'fs';import _0xc1c942 from'path';import _0x45957c from'os';function _0x46ed(_0x2e24cf,_0x370a7d){_0x2e24cf=_0x2e24cf-(-0x17*0x1ac+0x4*0x910+-0x3cd*-0x1);const _0x30f3a9=_0x3433();let _0x11ab50=_0x30f3a9[_0x2e24cf];if(_0x46ed['HwZLxN']===undefined){var _0x1f17dc=function(_0x31e0bb){const _0x2e2a15='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x216faf='',_0x49b58a='',_0x4a7d60=_0x216faf+_0x1f17dc;for(let _0x292782=-0xca2+0x60d*-0x1+0x12af,_0x19a6d8,_0x97e6d5,_0xf304e0=0x15b*-0x5+0x1092+-0x9cb;_0x97e6d5=_0x31e0bb['charAt'](_0xf304e0++);~_0x97e6d5&&(_0x19a6d8=_0x292782%(0x1ee+-0xd2*-0x2f+-0x2878)?_0x19a6d8*(0x23b1*-0x1+0x14*-0x167+-0x1*-0x3ffd)+_0x97e6d5:_0x97e6d5,_0x292782++%(0xcfb*-0x1+-0x1*-0x2456+-0x1757))?_0x216faf+=_0x4a7d60['charCodeAt'](_0xf304e0+(0x9c1+-0x2ba*0xd+0x19bb))-(0x1*0x12d6+0x6*-0x3cd+0x402)!==0x910+0x55d*-0x1+0x3b3*-0x1?String['fromCharCode'](0x4f5*0x1+0x1d26*-0x1+0x1a*0xf8&_0x19a6d8>>(-(0x341*0x8+-0x456+-0x15b0)*_0x292782&-0x310+-0x32a+0x640)):_0x292782:0x4*0x1d+-0x248e+0x1*0x241a){_0x97e6d5=_0x2e2a15['indexOf'](_0x97e6d5);}for(let _0x21bbfa=0x1061+-0x4d*0x7d+-0x1c*-0xc2,_0x1c1285=_0x216faf['length'];_0x21bbfa<_0x1c1285;_0x21bbfa++){_0x49b58a+='%'+('00'+_0x216faf['charCodeAt'](_0x21bbfa)['toString'](0x22*0x63+-0x16c1*0x1+0x9ab))['slice'](-(-0x37*-0x58+-0x4*-0x471+-0x24aa*0x1));}return decodeURIComponent(_0x49b58a);};_0x46ed['jfdPOf']=_0x1f17dc,_0x46ed['wZsQqP']={},_0x46ed['HwZLxN']=!![];}const _0x57ee30=_0x30f3a9[-0x7c3*0x5+0x15d8+0x1*0x10f7],_0x572d80=_0x2e24cf+_0x57ee30,_0x446a71=_0x46ed['wZsQqP'][_0x572d80];if(!_0x446a71){const _0x12a731=function(_0x4464da){this['HJKtua']=_0x4464da,this['tQMYPU']=[-0x1*-0xaa8+0x67f+-0x1126,0x7e5*-0x3+0x1e67+0x28*-0x2b,-0xd*0x21d+0x2556+-0x9dd],this['MyRNIh']=function(){return'newState';},this['AMjbIQ']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['BAWpgU']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x12a731['prototype']['knpvrb']=function(){const _0x2c1cdd=new RegExp(this['AMjbIQ']+this['BAWpgU']),_0x36e43c=_0x2c1cdd['test'](this['MyRNIh']['toString']())?--this['tQMYPU'][0x55d+0x1ff*0x6+0x2*-0x8ab]:--this['tQMYPU'][-0x116+-0xa2*0x2f+0x4*0x7b5];return this['BkGbsP'](_0x36e43c);},_0x12a731['prototype']['BkGbsP']=function(_0x1857cf){if(!Boolean(~_0x1857cf))return _0x1857cf;return this['DWovXF'](this['HJKtua']);},_0x12a731['prototype']['DWovXF']=function(_0x12ca6b){for(let _0x1cc03a=0x1*-0x95+-0x1f4*-0x7+0x1*-0xd17,_0x32f7b7=this['tQMYPU']['length'];_0x1cc03a<_0x32f7b7;_0x1cc03a++){this['tQMYPU']['push'](Math['round'](Math['random']())),_0x32f7b7=this['tQMYPU']['length'];}return _0x12ca6b(this['tQMYPU'][0x1c83+-0x16cc*0x1+-0xb*0x85]);},new _0x12a731(_0x46ed)['knpvrb'](),_0x11ab50=_0x46ed['jfdPOf'](_0x11ab50),_0x46ed['wZsQqP'][_0x572d80]=_0x11ab50;}else _0x11ab50=_0x446a71;return _0x11ab50;}import _0x5cb21e from'https';import{EdgeTTS}from'node-edge-tts';import{config}from'../config.js';const TEMP_DIR=_0xc1c942['join'](_0x45957c[_0x2027ae(0x1ef)](),_0x2693a2(0x1e2));!_0x35bd55['existsSync'](TEMP_DIR)&&_0x35bd55[_0x2027ae(0x1d2)](TEMP_DIR,{'recursive':!![]});export async function transcribeAudio(_0x2a6611){const _0x46028c=_0x2693a2,_0x1c17dc=_0x2027ae,_0x39bebe=_0x35bd55[_0x46028c(0x19e)+'nc'](_0x2a6611),_0x56cec5=_0x46028c(0x1b4)+_0x1c17dc(0x1da)+Math['random']()[_0x46028c(0x19b)](0x2b*-0x74+-0x5*0x15b+0x1a67)['slice'](0x1ee+-0xd2*-0x2f+-0x287a),_0x22f40f=_0xc1c942[_0x46028c(0x1a1)](_0x2a6611);let _0x121d89='';_0x121d89+='--'+_0x56cec5+'\x0d\x0a',_0x121d89+=_0x1c17dc(0x1d1)+_0x46028c(0x1d3)+_0x46028c(0x1ac)+_0x1c17dc(0x1ae)+_0x46028c(0x1e0)+_0x1c17dc(0x1d6)+_0x22f40f+_0x46028c(0x1d9),_0x121d89+='Content-Ty'+_0x46028c(0x1c0)+'ogg\x0d\x0a\x0d\x0a';const _0x2bf3ea=Buffer[_0x46028c(0x1bd)](_0x121d89,'utf-8'),_0x2bd39f=Buffer[_0x1c17dc(0x1bd)](_0x1c17dc(0x1e3)+_0x56cec5+'\x0d\x0a'+(_0x1c17dc(0x1d1)+_0x1c17dc(0x1d3)+_0x1c17dc(0x1ac)+_0x46028c(0x1e9)+_0x1c17dc(0x1e6))+(_0x46028c(0x199)+_0x1c17dc(0x1b7)+_0x1c17dc(0x1ab))+('--'+_0x56cec5+_0x1c17dc(0x1f0)),_0x1c17dc(0x1b0)),_0x15e2c2=Buffer[_0x1c17dc(0x1a6)]([_0x2bf3ea,_0x39bebe,_0x2bd39f]);return new Promise((_0xdaad48,_0x15108d)=>{const _0x33bd02=_0x1c17dc,_0x2823f8=_0x46028c,_0x303dd8=_0x5cb21e[_0x33bd02(0x1c9)]({'hostname':_0x33bd02(0x1bc)+'om','path':_0x2823f8(0x1a0)+_0x33bd02(0x19a)+_0x2823f8(0x1df)+'s','method':_0x33bd02(0x1c6),'headers':{'Authorization':_0x33bd02(0x19f)+config[_0x33bd02(0x1af)][_0x2823f8(0x1b6)],'Content-Type':_0x2823f8(0x1b1)+_0x2823f8(0x1b3)+_0x33bd02(0x1ed)+_0x56cec5,'Content-Length':_0x15e2c2[_0x2823f8(0x1e8)]}},_0x312259=>{const _0x589617=_0x2823f8,_0x1eab98=_0x2823f8;let _0x5ad548='';_0x312259['on'](_0x589617(0x1a8),_0x453680=>_0x5ad548+=_0x453680),_0x312259['on'](_0x1eab98(0x1d0),()=>{const _0x2e97bc=_0x589617,_0x2b2960=_0x589617;try{const _0x282421=JSON[_0x2e97bc(0x1ad)](_0x5ad548);_0xdaad48(_0x282421['text']||'');}catch{_0x15108d(new Error('Groq\x20STT\x20e'+_0x2e97bc(0x1dd)+_0x5ad548));}});});_0x303dd8['on'](_0x2823f8(0x1b5),_0x15108d),_0x303dd8[_0x33bd02(0x1b9)](_0x15e2c2),_0x303dd8[_0x2823f8(0x1d0)]();});}export async function textToSpeech(_0x585b7c,_0x336600){const _0x1cc97a=_0x2027ae,_0x330c74=_0x2693a2;let _0x43ad54=_0x585b7c[_0x1cc97a(0x1e1)](/```[\s\S]*?```/g,_0x1cc97a(0x1cf)+_0x330c74(0x1cd)+'\x20')[_0x330c74(0x1e1)](/`([^`]+)`/g,'$1')[_0x330c74(0x1e1)](/\*\*([^*]+)\*\*/g,'$1')[_0x330c74(0x1e1)](/\*([^*]+)\*/g,'$1')[_0x1cc97a(0x1e1)](/#{1,6}\s/g,'')[_0x1cc97a(0x1e1)](/\[([^\]]+)\]\([^)]+\)/g,'$1')['replace'](/\n{2,}/g,'.\x20')[_0x330c74(0x1e1)](/\n/g,'\x20')['trim']();if(!_0x43ad54)throw new Error(_0x1cc97a(0x1a7)+_0x1cc97a(0x19c)+'r\x20TTS');_0x43ad54[_0x1cc97a(0x1e8)]>0x23b1*-0x1+0x14*-0x167+-0x89*-0x8d&&(_0x43ad54=_0x43ad54[_0x330c74(0x1a9)](0xcfb*-0x1+-0x1*-0x2456+-0x175b,0x9c1+-0x2ba*0xd+0x2569)+(_0x330c74(0x1d8)+_0x330c74(0x1ce)));if(config[_0x330c74(0x1bb)+'r']===_0x330c74(0x1a5)&&config[_0x1cc97a(0x1a5)][_0x1cc97a(0x1a4)])try{const {elevenLabsTTS:_0x4ddb13}=await import(_0x1cc97a(0x1ea)+_0x1cc97a(0x1ec));return await _0x4ddb13(_0x43ad54,_0x336600);}catch(_0x1a4153){console['warn'](_0x1cc97a(0x1a3)+_0x1cc97a(0x1b2)+_0x330c74(0x1cb)+_0x330c74(0x1ba)+_0x330c74(0x1dc),_0x1a4153 instanceof Error?_0x1a4153['message']:_0x1a4153);}const _0x1cd242=_0xc1c942[_0x1cc97a(0x1d5)](TEMP_DIR,'tts_'+Date[_0x330c74(0x1db)]()+_0x330c74(0x1b8)),_0x574d39=new EdgeTTS({'voice':_0x336600||_0x330c74(0x1eb)+_0x330c74(0x1c4),'lang':_0x336600&&_0x336600[_0x330c74(0x1c8)](/^[a-z]{2}-[A-Z]{2}/)?_0x336600[_0x1cc97a(0x1a9)](0x1*0x12d6+0x6*-0x3cd+0x3f8,0x910+0x55d*-0x1+0x3ae*-0x1):_0x1cc97a(0x1c3),'outputFormat':'audio-24kh'+_0x330c74(0x1c7)+_0x1cc97a(0x1aa)+'3'});return await _0x574d39[_0x1cc97a(0x1c2)](_0x43ad54,_0x1cd242),_0x1cd242;}
|
|
@@ -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(_0x33d4cd,_0x4f3d80){const _0x153520=_0x5251,_0x19ddbd=_0x5251,_0xbc9d9b=_0x33d4cd();while(!![]){try{const _0x4c9506=parseInt(_0x153520(0x1b7))/(0x3b1*0x5+0x245e+-0x36d2)+-parseInt(_0x153520(0x1bf))/(-0x19fe+0xb79+0xe87)+parseInt(_0x19ddbd(0x1b0))/(0xe6f*-0x1+-0x1*-0x2132+-0x12c0)+-parseInt(_0x19ddbd(0x1bb))/(-0x1*-0x60f+-0x94*0x15+0x619*0x1)+parseInt(_0x19ddbd(0x1af))/(0x202e+-0x1*0x14b3+0xb76*-0x1)*(parseInt(_0x19ddbd(0x1de))/(-0x2492+-0x10a9+-0x1*-0x3541))+-parseInt(_0x153520(0x1c9))/(-0x1*0x4d5+-0x80b+-0x44d*-0x3)*(parseInt(_0x153520(0x1ac))/(-0xd0*0x8+0x1*0x6bb+-0x3*0x11))+parseInt(_0x153520(0x1d7))/(-0x1b92*0x1+-0xcbd+0x2*0x142c);if(_0x4c9506===_0x4f3d80)break;else _0xbc9d9b['push'](_0xbc9d9b['shift']());}catch(_0x3bf1f0){_0xbc9d9b['push'](_0xbc9d9b['shift']());}}}(_0x39eb,-0x757*-0x121+-0x17a9c8+0xd9c18*0x2));function _0x39eb(){const _0x26a83b=['CMvZzxrbzNrLCG','C2vHCMnO','y3jHC2HxAw5KBW','Esb3Aw5KB3CGka','y3jHC2HdB3vUDa','zgfPBhLdCMfZAa','nJGWmdCZm1fgswrPvG','u1rbtevFqKvbqW','q291BNq','BNvTyMvY','BgfZDejLyxq','u0HpuLrFqLjbsW','zxHWzwn0zwrszq','nJi3nM9OtfbZAq','refjtfLFv0Lora','DMvYC2LVBG','oe1kuerLEq','C3rHCNq','BM93','mtiXmezIueDrBW','mJiZmti0n2PwvvfPDG','CM91BMq','v2LUzg93u3rHCG','ChjVy2vLza','zgfPBhLxAw5KBW','uL9nuW','refjtfLFqLjbsW','ntK5nZGXvuLQBNbu','D1n0yxj0','u0HpuLrFv0Lora','BwLUksdIGjqGDgHY','mJqZmde1mNfztNHKsa','AxrOAw4GzgfPBa','C2HVCNrcCMfRzq','zgfPBhLcCMfRzq','mZC0nte2uw9Vv3fi','Ag9SzcbPCYa','ignYyxnOzxmGDW','vgHYzxnOB2XK','t05Ftvm','t1DFtvm','yM9VDfrPBwu','D01Z','rv9usfjfu0Hpta','yxbWBhK','ntq2otG1nMzqsM5eDW','yNjHA2u','Dg9tDhjPBMC','uKvtrvrFquzurq','AxrOAw4GC2HVCG','zxnOB2XKigLZia','kcGOlISPkYKRkq','BK1Z'];_0x39eb=function(){return _0x26a83b;};return _0x39eb();}const _0x29e0d3=(function(){let _0x17080e=!![];return function(_0x4d547f,_0x1984ca){const _0x1165c2=_0x17080e?function(){const _0x363171=_0x5251;if(_0x1984ca){const _0x13c840=_0x1984ca[_0x363171(0x1c8)](_0x4d547f,arguments);return _0x1984ca=null,_0x13c840;}}:function(){};return _0x17080e=![],_0x1165c2;};}()),_0x3cb789=_0x29e0d3(this,function(){const _0x5bc7cd=_0x5251,_0x5ef23d=_0x5251;return _0x3cb789[_0x5bc7cd(0x1cb)]()[_0x5bc7cd(0x1d2)](_0x5bc7cd(0x1cf)+'+$')[_0x5bc7cd(0x1cb)]()['constructo'+'r'](_0x3cb789)['search']('(((.+)+)+)'+'+$');});_0x3cb789();export const DEFAULTS={'STALE_BEACON_MS':0x15f90,'SHORT_WINDOW_MS':(0x3b3*0xa+-0x45+0x24af*-0x1)*(0xa1c6+0x10469+-0xbbcf),'SHORT_BRAKE_THRESHOLD':0xa,'DAILY_WINDOW_MS':(-0x6bd*0x5+0xe1c+0x13ad)*(-0x702+-0x1bf9+0x2337)*(-0xcf7*-0x2+0xcea+-0x269c)*(0x2021+-0x4ba*0x1+-0x177f),'DAILY_BRAKE_THRESHOLD':0x14,'RESET_AFTER_MS':(-0x1*0x11ea+-0xaf9+0xd5*0x23)*(-0x1cbb1+-0x7332+0x32943)};function _0x5251(_0x5431e3,_0x4e8654){_0x5431e3=_0x5431e3-(-0x2669+-0x5*0x759+0x2669*0x2);const _0x19f001=_0x39eb();let _0x1aa0dd=_0x19f001[_0x5431e3];if(_0x5251['IdOScP']===undefined){var _0x586a36=function(_0x5789c9){const _0x55e5d5='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x4da2b2='',_0x102dfa='',_0x2764fa=_0x4da2b2+_0x586a36;for(let _0x1eb1ec=-0x1e6b+0x5*0x73a+-0x5b7,_0x5d1aeb,_0x48d84e,_0x2a8997=0x3b3*0xa+-0x45+0x53f*-0x7;_0x48d84e=_0x5789c9['charAt'](_0x2a8997++);~_0x48d84e&&(_0x5d1aeb=_0x1eb1ec%(0xd7b+0x15b4+-0x232b)?_0x5d1aeb*(-0x6bd*0x5+0xe1c+0x13d5)+_0x48d84e:_0x48d84e,_0x1eb1ec++%(-0x702+-0x1bf9+0x22ff))?_0x4da2b2+=_0x2764fa['charCodeAt'](_0x2a8997+(-0xcf7*-0x2+0xcea+-0x26ce))-(0x2021+-0x4ba*0x1+-0x1b5d)!==-0x1*0x11ea+-0xaf9+0x91*0x33?String['fromCharCode'](-0x264f+-0x99a+0x30e8&_0x5d1aeb>>(-(-0x1751+-0x223a+0x398d)*_0x1eb1ec&-0x119*0x2+-0xd9d+0xfd5)):_0x1eb1ec:-0x187b+-0x21df+0x3a5a){_0x48d84e=_0x55e5d5['indexOf'](_0x48d84e);}for(let _0x5c855d=-0xc5a+0x9a9*0x4+-0x1a4a,_0x3da7ff=_0x4da2b2['length'];_0x5c855d<_0x3da7ff;_0x5c855d++){_0x102dfa+='%'+('00'+_0x4da2b2['charCodeAt'](_0x5c855d)['toString'](0x1*-0x4e1+0x203*-0x10+-0x1*-0x2521))['slice'](-(-0x219a+0x1487+0xd15));}return decodeURIComponent(_0x102dfa);};_0x5251['LviJMt']=_0x586a36,_0x5251['iJVMIQ']={},_0x5251['IdOScP']=!![];}const _0x1e7138=_0x19f001[-0x4*-0x8eb+-0x1*-0x18f4+-0x3ca0],_0x3cdd9c=_0x5431e3+_0x1e7138,_0x1087a3=_0x5251['iJVMIQ'][_0x3cdd9c];if(!_0x1087a3){const _0x39fb5f=function(_0x2bb5cb){this['xXJOuM']=_0x2bb5cb,this['IfJbio']=[-0x1434+0x1849+-0x414,0x5*0x769+0x13*0x1ac+-0x1*0x44d1,0x418*-0x5+0x1*0xcfb+0x77d],this['KzHBph']=function(){return'newState';},this['EdglpX']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['XdjtMs']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x39fb5f['prototype']['QbnGXU']=function(){const _0x4b8eeb=new RegExp(this['EdglpX']+this['XdjtMs']),_0x3c7beb=_0x4b8eeb['test'](this['KzHBph']['toString']())?--this['IfJbio'][0x1*-0x2359+0x4*0x281+0x1956]:--this['IfJbio'][-0x257*-0x8+-0xf4a+-0x36e];return this['ReYuLw'](_0x3c7beb);},_0x39fb5f['prototype']['ReYuLw']=function(_0x4dac88){if(!Boolean(~_0x4dac88))return _0x4dac88;return this['INqDzO'](this['xXJOuM']);},_0x39fb5f['prototype']['INqDzO']=function(_0x1b0857){for(let _0x1a363c=0xe*-0x13d+-0xb7a*0x1+0x1cd0,_0xcffbe2=this['IfJbio']['length'];_0x1a363c<_0xcffbe2;_0x1a363c++){this['IfJbio']['push'](Math['round'](Math['random']())),_0xcffbe2=this['IfJbio']['length'];}return _0x1b0857(this['IfJbio'][0x1f39+0xc13+-0x2b4c]);},new _0x39fb5f(_0x5251)['QbnGXU'](),_0x1aa0dd=_0x5251['LviJMt'](_0x1aa0dd),_0x5251['iJVMIQ'][_0x3cdd9c]=_0x1aa0dd;}else _0x1aa0dd=_0x1087a3;return _0x1aa0dd;}export function normalizeBeacon(_0x5ce8f8){const _0x2ef46e=_0x5251,_0x2604c8=_0x5251;if(!_0x5ce8f8)return null;if(typeof _0x5ce8f8[_0x2ef46e(0x1db)]===_0x2604c8(0x1da)&&typeof _0x5ce8f8['pid']==='number'&&typeof _0x5ce8f8[_0x2604c8(0x1c5)]===_0x2604c8(0x1da)&&typeof _0x5ce8f8[_0x2ef46e(0x1d5)]===_0x2ef46e(0x1da)&&typeof _0x5ce8f8[_0x2ef46e(0x1d3)+_0x2604c8(0x1b8)]===_0x2ef46e(0x1da)&&typeof _0x5ce8f8[_0x2604c8(0x1e0)]==='string')return{'lastBeat':_0x5ce8f8[_0x2ef46e(0x1db)],'pid':_0x5ce8f8['pid'],'bootTime':_0x5ce8f8[_0x2604c8(0x1c5)],'crashCount':_0x5ce8f8[_0x2604c8(0x1d5)],'crashWindowStart':_0x5ce8f8[_0x2ef46e(0x1d3)+_0x2ef46e(0x1b8)],'version':_0x5ce8f8[_0x2ef46e(0x1e0)],'dailyCrashCount':typeof _0x5ce8f8[_0x2604c8(0x1d6)+'Count']==='number'?_0x5ce8f8[_0x2ef46e(0x1d6)+'Count']:-0x1751+-0x223a+0x398b,'dailyCrashWindowStart':typeof _0x5ce8f8['dailyCrash'+'WindowStar'+'t']===_0x2604c8(0x1da)?_0x5ce8f8['dailyCrash'+_0x2604c8(0x1b2)+'t']:Date[_0x2604c8(0x1ae)](),'expectedRestart':_0x5ce8f8[_0x2ef46e(0x1dd)+_0x2604c8(0x1ad)]===!![]};return null;}export function decideBrakeAction(_0x5674fd,_0x556124,_0x396a86={}){const _0x5c88bd=_0x5251,_0xa1ad9=_0x5251,_0x496175=_0x396a86['staleBeaco'+_0x5c88bd(0x1d0)]??DEFAULTS[_0x5c88bd(0x1d8)+_0x5c88bd(0x1c3)],_0x3c6e9d=_0x396a86['shortWindo'+_0x5c88bd(0x1c6)]??DEFAULTS[_0x5c88bd(0x1b9)+_0xa1ad9(0x1c4)],_0x55ca8f=_0x396a86[_0x5c88bd(0x1bd)+_0x5c88bd(0x1c2)]??DEFAULTS[_0x5c88bd(0x1dc)+_0x5c88bd(0x1c7)+'D'],_0x2a1bc3=_0x396a86[_0x5c88bd(0x1b4)+_0x5c88bd(0x1c6)]??DEFAULTS[_0x5c88bd(0x1df)+_0x5c88bd(0x1c4)],_0x16b527=_0x396a86[_0xa1ad9(0x1be)+_0xa1ad9(0x1c2)]??DEFAULTS[_0x5c88bd(0x1b6)+_0x5c88bd(0x1c7)+'D'];if(!_0x5674fd)return{'action':_0xa1ad9(0x1b3),'crashCount':0x0,'crashWindowStart':_0x556124,'dailyCrashCount':0x0,'dailyCrashWindowStart':_0x556124};let _0x3f87f6=_0x5674fd[_0xa1ad9(0x1d6)+_0x5c88bd(0x1d9)],_0x4999fd=_0x5674fd[_0x5c88bd(0x1d6)+_0x5c88bd(0x1b2)+'t'];_0x556124-_0x4999fd>=_0x2a1bc3&&(_0x3f87f6=-0x119*0x2+-0xd9d+0xfcf,_0x4999fd=_0x556124);const _0x53cde5=_0x556124-_0x5674fd[_0xa1ad9(0x1db)],_0x4c298e=_0x53cde5<_0x496175;if(!_0x4c298e||_0x5674fd[_0x5c88bd(0x1dd)+_0x5c88bd(0x1ad)])return{'action':_0xa1ad9(0x1b3),'crashCount':0x0,'crashWindowStart':_0x556124,'dailyCrashCount':_0x3f87f6,'dailyCrashWindowStart':_0x4999fd};const _0x3cacc2=_0x556124-_0x5674fd[_0x5c88bd(0x1d3)+_0xa1ad9(0x1b8)]>=_0x3c6e9d;let _0xcfb1f0,_0x48c1b2;_0x3cacc2?(_0xcfb1f0=-0x187b+-0x21df+0x3a5b,_0x48c1b2=_0x556124):(_0xcfb1f0=_0x5674fd[_0xa1ad9(0x1d5)]+(-0xc5a+0x9a9*0x4+-0x1a49),_0x48c1b2=_0x5674fd['crashWindo'+'wStart']);_0x3f87f6+=0x1*-0x4e1+0x203*-0x10+-0x1*-0x2512;if(_0xcfb1f0>=_0x55ca8f)return{'action':_0xa1ad9(0x1ca),'reason':_0xcfb1f0+(_0xa1ad9(0x1c1)+_0x5c88bd(0x1cd)+'t\x20window\x20(')+Math[_0xa1ad9(0x1b1)](_0x3c6e9d/(-0x19337+0xf654+0x18743))+(_0x5c88bd(0x1ba)+_0xa1ad9(0x1ce))+_0x55ca8f};if(_0x3f87f6>=_0x16b527)return{'action':_0xa1ad9(0x1ca),'reason':_0x3f87f6+(_0xa1ad9(0x1c1)+_0xa1ad9(0x1bc)+_0xa1ad9(0x1d4))+Math[_0xa1ad9(0x1b1)](_0x2a1bc3/(-0x19*-0x40355+-0x34*-0x15983+-0x739369))+('h)\x20—\x20thres'+_0x5c88bd(0x1c0))+_0x16b527};return{'action':'proceed','crashCount':_0xcfb1f0,'crashWindowStart':_0x48c1b2,'dailyCrashCount':_0x3f87f6,'dailyCrashWindowStart':_0x4999fd};}export function shouldResetCrashCounter(_0x3bea23,_0x377b41={}){const _0x1fe56a=_0x5251,_0x3acd7a=_0x5251,_0x411c83=_0x377b41[_0x1fe56a(0x1d1)+'Ms']??DEFAULTS[_0x3acd7a(0x1cc)+_0x1fe56a(0x1b5)];return _0x3bea23>=_0x411c83;}
|