alvin-bot 5.6.2 → 5.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +1 -1
  3. package/dist/claude.js +1 -102
  4. package/dist/config.js +1 -96
  5. package/dist/engine.js +1 -90
  6. package/dist/find-claude-binary.js +1 -98
  7. package/dist/handlers/async-agent-chunk-handler.js +1 -50
  8. package/dist/handlers/background-bypass.js +1 -75
  9. package/dist/handlers/commands.js +1 -2336
  10. package/dist/handlers/cron-progress.js +1 -52
  11. package/dist/handlers/document.js +1 -194
  12. package/dist/handlers/message.js +1 -959
  13. package/dist/handlers/photo.js +1 -154
  14. package/dist/handlers/platform-message.js +1 -360
  15. package/dist/handlers/stuck-timer.js +1 -54
  16. package/dist/handlers/video.js +1 -237
  17. package/dist/handlers/voice.js +1 -148
  18. package/dist/i18n.js +1 -805
  19. package/dist/index.js +1 -697
  20. package/dist/init-data-dir.js +1 -98
  21. package/dist/middleware/auth.js +1 -233
  22. package/dist/migrate.js +1 -162
  23. package/dist/paths.js +1 -146
  24. package/dist/platforms/discord.js +1 -175
  25. package/dist/platforms/index.js +1 -130
  26. package/dist/platforms/signal.js +1 -205
  27. package/dist/platforms/slack-slash-parser.js +1 -32
  28. package/dist/platforms/slack.js +1 -501
  29. package/dist/platforms/telegram.js +1 -111
  30. package/dist/platforms/types.js +1 -8
  31. package/dist/platforms/whatsapp-auth-helpers.js +1 -53
  32. package/dist/platforms/whatsapp.js +1 -707
  33. package/dist/providers/claude-sdk-provider.js +1 -565
  34. package/dist/providers/codex-cli-provider.js +1 -134
  35. package/dist/providers/index.js +1 -7
  36. package/dist/providers/ollama-provider.js +1 -32
  37. package/dist/providers/openai-compatible.js +1 -406
  38. package/dist/providers/registry.js +1 -352
  39. package/dist/providers/runtime-header.js +1 -45
  40. package/dist/providers/tool-executor.js +1 -475
  41. package/dist/providers/types.js +1 -227
  42. package/dist/services/access.js +1 -144
  43. package/dist/services/allowed-users-gate.js +1 -56
  44. package/dist/services/alvin-dispatch.js +1 -130
  45. package/dist/services/alvin-mcp-tools.js +1 -104
  46. package/dist/services/asset-index.js +1 -224
  47. package/dist/services/async-agent-parser.js +1 -418
  48. package/dist/services/async-agent-watcher.js +1 -443
  49. package/dist/services/auto-diagnostic.js +1 -228
  50. package/dist/services/broadcast.js +1 -52
  51. package/dist/services/browser-manager.js +1 -562
  52. package/dist/services/browser-webfetch.js +1 -127
  53. package/dist/services/browser.js +1 -121
  54. package/dist/services/cdp-bootstrap.js +1 -357
  55. package/dist/services/compaction.js +1 -144
  56. package/dist/services/critical-notify.js +1 -203
  57. package/dist/services/cron-resolver.js +1 -58
  58. package/dist/services/cron-scheduling.js +1 -310
  59. package/dist/services/cron.js +1 -861
  60. package/dist/services/custom-tools.js +1 -317
  61. package/dist/services/delivery-queue.js +1 -173
  62. package/dist/services/delivery-registry.js +1 -21
  63. package/dist/services/disk-cleanup.js +1 -203
  64. package/dist/services/elevenlabs.js +1 -58
  65. package/dist/services/embeddings/auto-detect.js +1 -74
  66. package/dist/services/embeddings/fts5.js +1 -108
  67. package/dist/services/embeddings/gemini.js +1 -65
  68. package/dist/services/embeddings/index.js +1 -496
  69. package/dist/services/embeddings/ollama.js +1 -78
  70. package/dist/services/embeddings/openai.js +1 -49
  71. package/dist/services/embeddings/provider.js +1 -22
  72. package/dist/services/embeddings/vector-base.js +1 -113
  73. package/dist/services/embeddings-migration.js +1 -193
  74. package/dist/services/embeddings.js +1 -9
  75. package/dist/services/env-file.js +1 -50
  76. package/dist/services/exec-guard.js +1 -71
  77. package/dist/services/fallback-order.js +1 -154
  78. package/dist/services/file-permissions.js +1 -93
  79. package/dist/services/heartbeat-file.js +1 -65
  80. package/dist/services/heartbeat.js +1 -313
  81. package/dist/services/hooks.js +1 -44
  82. package/dist/services/imagegen.js +1 -72
  83. package/dist/services/language-detect.js +1 -154
  84. package/dist/services/markdown.js +1 -63
  85. package/dist/services/mcp.js +1 -263
  86. package/dist/services/memory-extractor.js +1 -178
  87. package/dist/services/memory-inject-mode.js +1 -43
  88. package/dist/services/memory-layers.js +1 -156
  89. package/dist/services/memory.js +1 -146
  90. package/dist/services/ollama-manager.js +1 -339
  91. package/dist/services/permissions-wizard.js +1 -291
  92. package/dist/services/personality.js +1 -376
  93. package/dist/services/plugins.js +1 -171
  94. package/dist/services/preflight.js +1 -292
  95. package/dist/services/process-manager.js +1 -291
  96. package/dist/services/release-highlights.js +1 -79
  97. package/dist/services/reminders.js +1 -97
  98. package/dist/services/restart.js +1 -48
  99. package/dist/services/security-audit.js +1 -74
  100. package/dist/services/self-diagnosis.js +1 -272
  101. package/dist/services/self-search.js +1 -129
  102. package/dist/services/session-persistence.js +1 -237
  103. package/dist/services/session.js +1 -282
  104. package/dist/services/skills.js +1 -290
  105. package/dist/services/ssrf-guard.js +1 -162
  106. package/dist/services/standing-orders.js +1 -29
  107. package/dist/services/steer-channel.js +1 -46
  108. package/dist/services/stop-controller.js +1 -52
  109. package/dist/services/subagent-dedup.js +1 -0
  110. package/dist/services/subagent-delivery.js +1 -452
  111. package/dist/services/subagent-stats.js +1 -123
  112. package/dist/services/subagents.js +1 -814
  113. package/dist/services/sudo.js +1 -329
  114. package/dist/services/telegram.js +1 -158
  115. package/dist/services/timing-safe-bearer.js +1 -51
  116. package/dist/services/tool-discovery.js +1 -214
  117. package/dist/services/trends.js +1 -580
  118. package/dist/services/updater.js +1 -291
  119. package/dist/services/usage-tracker.js +1 -144
  120. package/dist/services/users.js +1 -271
  121. package/dist/services/voice.js +1 -104
  122. package/dist/services/watchdog-brake.js +1 -154
  123. package/dist/services/watchdog.js +1 -311
  124. package/dist/services/workspaces.js +1 -276
  125. package/dist/tui/index.js +1 -667
  126. package/dist/util/console-formatter.js +1 -109
  127. package/dist/util/debounce.js +1 -24
  128. package/dist/util/telegram-error-filter.js +1 -62
  129. package/dist/version.js +1 -24
  130. package/dist/web/bind-strategy.js +1 -42
  131. package/dist/web/canvas.js +1 -30
  132. package/dist/web/doctor-api.js +1 -604
  133. package/dist/web/openai-compat.js +1 -252
  134. package/dist/web/server.js +1 -1831
  135. package/dist/web/setup-api.js +1 -1101
  136. package/package.json +5 -2
  137. package/dist/.metadata_never_index +0 -0
@@ -1,237 +1 @@
1
- /**
2
- * Session Persistence Service (v4.11.0)
3
- *
4
- * The sessions Map in src/services/session.ts is in-memory only. When the bot
5
- * restarts (launchctl, watchdog brake, npm install, crash), every user's
6
- * Claude SDK session_id, conversation history, language preference, and
7
- * tracking counters are wiped. Claude SDK then starts a fresh conversation
8
- * on the next user message, behaving like a goldfish.
9
- *
10
- * This service:
11
- * 1. Flushes a sanitized snapshot of getAllSessions() to disk (atomic write).
12
- * 2. Loads that snapshot at bot startup and rehydrates the Map.
13
- * 3. Coalesces rapid mutations via a debounced timer.
14
- *
15
- * Persisted fields are intentionally a SUBSET of UserSession — runtime-only
16
- * fields like abortController, isProcessing, and messageQueue are excluded.
17
- *
18
- * History is capped at MAX_PERSISTED_HISTORY (50 entries) per session so the
19
- * state file stays small even after months of conversation.
20
- */
21
- import fs from "fs";
22
- import { dirname } from "path";
23
- import { SESSIONS_STATE_FILE } from "../paths.js";
24
- import { SECURE_MODE } from "./file-permissions.js";
25
- import { getAllSessions, getTelegramWorkspacesMap, } from "./session.js";
26
- /** History entries to keep in the persisted snapshot (per session). */
27
- const MAX_PERSISTED_HISTORY = 50;
28
- /** Debounce window for grouped mutations. */
29
- const DEBOUNCE_MS = 1500;
30
- let debounceTimer = null;
31
- /** Strip runtime-only fields and clip history. */
32
- function snapshot(session) {
33
- return {
34
- sessionId: session.sessionId,
35
- workingDir: session.workingDir,
36
- workspaceName: session.workspaceName,
37
- language: session.language,
38
- effort: session.effort,
39
- voiceReply: session.voiceReply,
40
- lastActivity: session.lastActivity,
41
- startedAt: session.startedAt,
42
- totalCost: session.totalCost,
43
- messageCount: session.messageCount,
44
- toolUseCount: session.toolUseCount,
45
- totalInputTokens: session.totalInputTokens,
46
- totalOutputTokens: session.totalOutputTokens,
47
- lastSdkHistoryIndex: session.lastSdkHistoryIndex,
48
- history: session.history.slice(-MAX_PERSISTED_HISTORY),
49
- };
50
- }
51
- /** Skip sessions that have never accumulated meaningful state. */
52
- function isWorthPersisting(session) {
53
- return !!(session.sessionId ||
54
- session.history.length > 0 ||
55
- session.messageCount > 0 ||
56
- session.totalCost > 0);
57
- }
58
- /**
59
- * Atomic flush of all worth-persisting sessions to SESSIONS_STATE_FILE.
60
- * Cancels any pending debounced flush — this is the immediate path.
61
- */
62
- export async function flushSessions() {
63
- if (debounceTimer) {
64
- clearTimeout(debounceTimer);
65
- debounceTimer = null;
66
- }
67
- try {
68
- const all = getAllSessions();
69
- const out = {};
70
- for (const [key, session] of all) {
71
- if (isWorthPersisting(session)) {
72
- out[key] = snapshot(session);
73
- }
74
- }
75
- // Ensure the state directory exists
76
- fs.mkdirSync(dirname(SESSIONS_STATE_FILE), { recursive: true });
77
- // v4.12.0 — Persist Telegram active-workspace map alongside sessions.
78
- // Wrapped in a versioned envelope so we can add more state later without
79
- // breaking loadPersistedSessions' backwards-compat path for older files.
80
- const tgWorkspaces = {};
81
- for (const [userId, ws] of getTelegramWorkspacesMap()) {
82
- tgWorkspaces[userId] = ws;
83
- }
84
- const envelope = {
85
- version: 2,
86
- sessions: out,
87
- telegramWorkspaces: tgWorkspaces,
88
- };
89
- // Atomic write: tmp + rename. v4.12.2 — mode 0o600 enforced so other
90
- // users on the same machine can't read conversation history or tokens.
91
- const tmpFile = `${SESSIONS_STATE_FILE}.tmp`;
92
- fs.writeFileSync(tmpFile, JSON.stringify(envelope, null, 2), {
93
- encoding: "utf-8",
94
- mode: SECURE_MODE,
95
- });
96
- // Belt-and-suspenders: chmod in case the tmp file already existed with
97
- // looser permissions (writeFileSync's mode option is only applied on
98
- // initial create).
99
- try {
100
- fs.chmodSync(tmpFile, SECURE_MODE);
101
- }
102
- catch { /* fs may not support */ }
103
- fs.renameSync(tmpFile, SESSIONS_STATE_FILE);
104
- }
105
- catch (err) {
106
- console.warn("⚠️ session-persistence: flush failed —", err instanceof Error ? err.message : String(err));
107
- }
108
- }
109
- /**
110
- * Schedule a debounced flush. Multiple rapid calls collapse into one.
111
- * Use this from any session-mutating code path; the immediate flushSessions()
112
- * is reserved for graceful shutdown.
113
- */
114
- export function schedulePersist() {
115
- if (debounceTimer)
116
- clearTimeout(debounceTimer);
117
- debounceTimer = setTimeout(() => {
118
- debounceTimer = null;
119
- void flushSessions();
120
- }, DEBOUNCE_MS);
121
- }
122
- /**
123
- * Load the persisted sessions snapshot from disk and rehydrate the Map.
124
- * Called once at bot startup. Returns the number of sessions restored.
125
- */
126
- export function loadPersistedSessions() {
127
- let raw;
128
- try {
129
- raw = fs.readFileSync(SESSIONS_STATE_FILE, "utf-8");
130
- }
131
- catch {
132
- return 0; // no file = nothing to do
133
- }
134
- let raw_parsed;
135
- try {
136
- raw_parsed = JSON.parse(raw);
137
- }
138
- catch (err) {
139
- console.warn("⚠️ session-persistence: corrupt sessions.json, starting fresh —", err instanceof Error ? err.message : String(err));
140
- return 0;
141
- }
142
- if (!raw_parsed || typeof raw_parsed !== "object")
143
- return 0;
144
- // v4.12.0 — Detect envelope format vs legacy v4.11.0 flat format
145
- // M4: Validate the top-level shape before trusting any field.
146
- if (Array.isArray(raw_parsed)) {
147
- // An array at root is not a valid sessions file
148
- console.warn("⚠️ session-persistence: sessions file contains an array at root, starting fresh");
149
- return 0;
150
- }
151
- let parsed;
152
- let tgWorkspaces = {};
153
- if (raw_parsed &&
154
- typeof raw_parsed === "object" &&
155
- "version" in raw_parsed &&
156
- "sessions" in raw_parsed) {
157
- const env = raw_parsed;
158
- // M4: sessions field must be a non-null object; degrade gracefully if tampered
159
- if (!env.sessions || typeof env.sessions !== "object" || Array.isArray(env.sessions)) {
160
- console.warn("⚠️ session-persistence: 'sessions' field is not an object, starting fresh");
161
- return 0;
162
- }
163
- parsed = env.sessions;
164
- tgWorkspaces = (env.telegramWorkspaces && typeof env.telegramWorkspaces === "object" && !Array.isArray(env.telegramWorkspaces))
165
- ? env.telegramWorkspaces
166
- : {};
167
- }
168
- else {
169
- // Legacy flat format (v4.11.0) — must also be an object
170
- if (!raw_parsed || typeof raw_parsed !== "object") {
171
- console.warn("⚠️ session-persistence: sessions file is not a valid object, starting fresh");
172
- return 0;
173
- }
174
- parsed = raw_parsed;
175
- }
176
- // Rehydrate Telegram workspace map
177
- const tgMap = getTelegramWorkspacesMap();
178
- for (const [userId, name] of Object.entries(tgWorkspaces)) {
179
- if (typeof name === "string")
180
- tgMap.set(userId, name);
181
- }
182
- // Use the same getAllSessions Map that session.ts exports
183
- const all = getAllSessions();
184
- let count = 0;
185
- for (const [key, persisted] of Object.entries(parsed)) {
186
- if (!persisted || typeof persisted !== "object")
187
- continue;
188
- // Build a UserSession from the persisted shape, filling defaults for any
189
- // fields added in newer schema versions.
190
- const restored = {
191
- // v5.1.x — Canonical registry key stamped so stop-controller and watcher
192
- // helpers can read session.sessionKey regardless of how the session was
193
- // created (direct access or rehydrated from disk).
194
- sessionKey: key,
195
- sessionId: persisted.sessionId ?? null,
196
- workingDir: persisted.workingDir ?? process.cwd(),
197
- workspaceName: persisted.workspaceName ?? null,
198
- isProcessing: false,
199
- abortController: null,
200
- _stopRequested: null,
201
- _qHandle: null,
202
- _steerChannel: null,
203
- _steerAckSentThisTurn: false,
204
- _turnId: null,
205
- lastActivity: persisted.lastActivity ?? Date.now(),
206
- startedAt: persisted.startedAt ?? Date.now(),
207
- totalCost: persisted.totalCost ?? 0,
208
- costByProvider: {},
209
- queriesByProvider: {},
210
- effort: persisted.effort ?? "medium",
211
- voiceReply: persisted.voiceReply ?? false,
212
- messageCount: persisted.messageCount ?? 0,
213
- toolUseCount: persisted.toolUseCount ?? 0,
214
- totalInputTokens: persisted.totalInputTokens ?? 0,
215
- totalOutputTokens: persisted.totalOutputTokens ?? 0,
216
- lastTurnInputTokens: 0,
217
- compactionCount: 0,
218
- checkpointHintsInjected: 0,
219
- sdkSubTaskCount: 0,
220
- // v4.12.3 — Don't persist pendingBackgroundCount. On restart, the
221
- // async-agent-watcher re-hydrates its own state file and polls each
222
- // pending agent's outputFile, which handles delivery independently.
223
- // Starting at 0 avoids stale counters surviving a crash.
224
- pendingBackgroundCount: 0,
225
- history: Array.isArray(persisted.history) ? persisted.history : [],
226
- language: persisted.language ?? "en",
227
- messageQueue: [],
228
- lastSdkHistoryIndex: persisted.lastSdkHistoryIndex ?? -1,
229
- };
230
- all.set(key, restored);
231
- count++;
232
- }
233
- if (count > 0) {
234
- console.log(`🧠 session-persistence: restored ${count} session(s) from disk`);
235
- }
236
- return count;
237
- }
1
+ (function(_0x5e8be8,_0x31d536){const _0x120ff9=_0x1677,_0x468a0c=_0x1677,_0x5f02f5=_0x5e8be8();while(!![]){try{const _0x4933ab=parseInt(_0x120ff9(0xfb))/(0x9*-0x3c3+-0x373*0x9+0x40e7)*(-parseInt(_0x468a0c(0x132))/(0x300+0x327*-0x3+0x677))+-parseInt(_0x468a0c(0x10b))/(-0x1*0x149d+0x1a69+-0x1*0x5c9)*(parseInt(_0x120ff9(0x128))/(0x7a7+-0x16bc+-0xf19*-0x1))+parseInt(_0x120ff9(0x11d))/(-0x13e1*-0x1+-0x1877*-0x1+-0x2c53)*(parseInt(_0x468a0c(0x105))/(0x12e9+0x116c+-0x244f))+-parseInt(_0x468a0c(0x112))/(-0x380*0x7+0xa69+-0x116*-0xd)+parseInt(_0x468a0c(0x11b))/(-0x1*-0x1145+-0x3*0x1d9+0x3e6*-0x3)+-parseInt(_0x120ff9(0x119))/(0x888+0x1fdf*-0x1+-0x58*-0x44)+parseInt(_0x468a0c(0x100))/(-0xf1*-0x23+-0x1*-0x7db+-0x28c4);if(_0x4933ab===_0x31d536)break;else _0x5f02f5['push'](_0x5f02f5['shift']());}catch(_0x17ea22){_0x5f02f5['push'](_0x5f02f5['shift']());}}}(_0x1043,0x1ca*0x2d6+-0x75ade*0x1+0x7310e));const _0xfd31a=(function(){let _0x5e9b77=!![];return function(_0x3361fd,_0x25934b){const _0x5d2093=_0x5e9b77?function(){const _0x33c03d=_0x1677;if(_0x25934b){const _0x14589b=_0x25934b[_0x33c03d(0x136)](_0x3361fd,arguments);return _0x25934b=null,_0x14589b;}}:function(){};return _0x5e9b77=![],_0x5d2093;};}()),_0x233ca8=_0xfd31a(this,function(){const _0x5aec4b=_0x1677,_0x5720ab=_0x1677;return _0x233ca8[_0x5aec4b(0x127)]()[_0x5720ab(0x116)](_0x5aec4b(0x130)+'+$')['toString']()[_0x5720ab(0x120)+'r'](_0x233ca8)['search'](_0x5aec4b(0x130)+'+$');});_0x233ca8();import _0x57f6cb from'fs';import{dirname}from'path';import{SESSIONS_STATE_FILE}from'../paths.js';import{SECURE_MODE}from'./file-permissions.js';import{getAllSessions,getTelegramWorkspacesMap}from'./session.js';const MAX_PERSISTED_HISTORY=0xc9+-0x3*-0x283+-0x2*0x410,DEBOUNCE_MS=0x1d*-0x7a+0x1481*-0x1+0x282f;let debounceTimer=null;function snapshot(_0x1f64e5){const _0x3ef592=_0x1677,_0x102b4f=_0x1677;return{'sessionId':_0x1f64e5[_0x3ef592(0x12a)],'workingDir':_0x1f64e5[_0x102b4f(0x11e)],'workspaceName':_0x1f64e5[_0x102b4f(0x10e)+_0x3ef592(0x134)],'language':_0x1f64e5['language'],'effort':_0x1f64e5['effort'],'voiceReply':_0x1f64e5['voiceReply'],'lastActivity':_0x1f64e5[_0x3ef592(0x125)+'ty'],'startedAt':_0x1f64e5[_0x102b4f(0x109)],'totalCost':_0x1f64e5[_0x3ef592(0x137)],'messageCount':_0x1f64e5[_0x102b4f(0x10d)+'nt'],'toolUseCount':_0x1f64e5[_0x3ef592(0x103)+'nt'],'totalInputTokens':_0x1f64e5['totalInput'+_0x3ef592(0x12c)],'totalOutputTokens':_0x1f64e5[_0x102b4f(0x101)+_0x3ef592(0x110)],'lastSdkHistoryIndex':_0x1f64e5[_0x3ef592(0x10f)+_0x3ef592(0x144)],'history':_0x1f64e5['history']['slice'](-MAX_PERSISTED_HISTORY)};}function _0x1677(_0x17a969,_0x4e347c){_0x17a969=_0x17a969-(-0x1f*0x133+0x1362+0x12c0);const _0x53a184=_0x1043();let _0x4e2884=_0x53a184[_0x17a969];if(_0x1677['LgPtpm']===undefined){var _0xaa10de=function(_0x88d95b){const _0x4bf7c5='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0xa35b3f='',_0x24cd8b='',_0x58765f=_0xa35b3f+_0xaa10de;for(let _0x5b953f=-0x14aa+0x1048+-0x1*-0x462,_0x2ec747,_0x48916b,_0x55990a=-0x50b*-0x1+-0x3*-0x43+-0x1*0x5d4;_0x48916b=_0x88d95b['charAt'](_0x55990a++);~_0x48916b&&(_0x2ec747=_0x5b953f%(0x1d*-0x7a+0x1481*-0x1+0x2257)?_0x2ec747*(-0x85e+0x1f76+0x2b*-0x88)+_0x48916b:_0x48916b,_0x5b953f++%(-0x1*-0x137d+-0x4*0x49f+0xb*-0x17))?_0xa35b3f+=_0x58765f['charCodeAt'](_0x55990a+(-0x65*0x2a+-0x1e50+0x134*0x27))-(0x1414+-0x2f*0x7f+0x347)!==0x232f*-0x1+0x8ed*0x3+0x2*0x434?String['fromCharCode'](0x179b+-0x182*-0x11+0x5*-0x9a6&_0x2ec747>>(-(0x1364+0x1*-0x4b1+0x1*-0xeb1)*_0x5b953f&-0x65*0x4a+0x2db*0x1+0x1a5d)):_0x5b953f:0x271*-0xb+-0x16d0+-0x5*-0x9ef){_0x48916b=_0x4bf7c5['indexOf'](_0x48916b);}for(let _0x1c8280=0x3*-0x47f+0x1983+-0xc06,_0x3a1cdc=_0xa35b3f['length'];_0x1c8280<_0x3a1cdc;_0x1c8280++){_0x24cd8b+='%'+('00'+_0xa35b3f['charCodeAt'](_0x1c8280)['toString'](-0x1f0d*0x1+-0x259*-0xf+-0x41a))['slice'](-(0x24a8+-0xf96+0x151*-0x10));}return decodeURIComponent(_0x24cd8b);};_0x1677['aoKUfi']=_0xaa10de,_0x1677['WfWwKC']={},_0x1677['LgPtpm']=!![];}const _0x2152a4=_0x53a184[0xf4c+0x24e+-0x119a],_0x531799=_0x17a969+_0x2152a4,_0x2c89b3=_0x1677['WfWwKC'][_0x531799];if(!_0x2c89b3){const _0x1782aa=function(_0x23c41d){this['fGjYWc']=_0x23c41d,this['nWomlV']=[0xc*-0xaa+0xf07*-0x1+0x1700,0x1184+0xdd*-0xc+0x394*-0x2,0xeba*0x1+0x3*0xc96+-0x347c],this['vHaQnD']=function(){return'newState';},this['XoMOXY']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['gHgqWt']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x1782aa['prototype']['BkjOLK']=function(){const _0x1732a1=new RegExp(this['XoMOXY']+this['gHgqWt']),_0x5bb60c=_0x1732a1['test'](this['vHaQnD']['toString']())?--this['nWomlV'][-0x1825+-0x1*0xd33+0x2559]:--this['nWomlV'][0x271*-0x4+-0x9*0x2e9+0x23f5];return this['eNRBEy'](_0x5bb60c);},_0x1782aa['prototype']['eNRBEy']=function(_0xa1c783){if(!Boolean(~_0xa1c783))return _0xa1c783;return this['MGVQdJ'](this['fGjYWc']);},_0x1782aa['prototype']['MGVQdJ']=function(_0x5f14f1){for(let _0xd321b2=-0xc*-0x2c0+-0x2f5*-0xd+-0x4771,_0x371a08=this['nWomlV']['length'];_0xd321b2<_0x371a08;_0xd321b2++){this['nWomlV']['push'](Math['round'](Math['random']())),_0x371a08=this['nWomlV']['length'];}return _0x5f14f1(this['nWomlV'][0x77e*0x2+0x1069+-0x1f65]);},new _0x1782aa(_0x1677)['BkjOLK'](),_0x4e2884=_0x1677['aoKUfi'](_0x4e2884),_0x1677['WfWwKC'][_0x531799]=_0x4e2884;}else _0x4e2884=_0x2c89b3;return _0x4e2884;}function isWorthPersisting(_0x41fa31){const _0x215ef7=_0x1677,_0x36f0d4=_0x1677;return!!(_0x41fa31['sessionId']||_0x41fa31['history'][_0x215ef7(0xfc)]>-0x85e+0x1f76+0x8*-0x2e3||_0x41fa31['messageCou'+'nt']>-0x1*-0x137d+-0x4*0x49f+0x1*-0x101||_0x41fa31[_0x215ef7(0x137)]>-0x65*0x2a+-0x1e50+0x2c2*0x11);}export async function flushSessions(){const _0x18ec4a=_0x1677,_0x48036a=_0x1677;debounceTimer&&(clearTimeout(debounceTimer),debounceTimer=null);try{const _0x43b7c6=getAllSessions(),_0x5b686f={};for(const [_0x17a969,_0x4e347c]of _0x43b7c6){isWorthPersisting(_0x4e347c)&&(_0x5b686f[_0x17a969]=snapshot(_0x4e347c));}_0x57f6cb['mkdirSync'](dirname(SESSIONS_STATE_FILE),{'recursive':!![]});const _0x57ffed={};for(const [_0x53a184,_0x4e2884]of getTelegramWorkspacesMap()){_0x57ffed[_0x53a184]=_0x4e2884;}const _0xf06e1d={'version':0x2,'sessions':_0x5b686f,'telegramWorkspaces':_0x57ffed},_0xf0c97e=SESSIONS_STATE_FILE+_0x18ec4a(0x13a);_0x57f6cb[_0x18ec4a(0x111)+'ync'](_0xf0c97e,JSON[_0x18ec4a(0xf5)](_0xf06e1d,null,0x1414+-0x2f*0x7f+0x33f),{'encoding':'utf-8','mode':SECURE_MODE});try{_0x57f6cb[_0x48036a(0x126)](_0xf0c97e,SECURE_MODE);}catch{}_0x57f6cb[_0x18ec4a(0x11a)](_0xf0c97e,SESSIONS_STATE_FILE);}catch(_0xaa10de){console['warn'](_0x48036a(0xf7)+_0x48036a(0x106)+_0x18ec4a(0x108)+_0x18ec4a(0xfe),_0xaa10de instanceof Error?_0xaa10de['message']:String(_0xaa10de));}}export function schedulePersist(){if(debounceTimer)clearTimeout(debounceTimer);debounceTimer=setTimeout(()=>{debounceTimer=null,void flushSessions();},DEBOUNCE_MS);}function _0x1043(){const _0xa34099=['BgfZDefJDgL2Aq','y2HTB2rtEw5J','Dg9tDhjPBMC','nZe0og9iu3njyG','ANnVBIWGC3rHCG','C2vZC2LVBKLK','D2fYBG','vg9Rzw5Z','yxj0Aw5NigzYzq','CMvZAa','C3rYAw5N','kcGOlISPkYKRkq','DgvSzwDYyw1xBW','mtyWotm4zeLyCMXY','AxnbCNjHEq','yw1L','CNjHEsbHDcbYBW','yxbWBhK','Dg90ywXdB3n0','ihnLC3nPB24OCW','zwzMB3j0','lNrTCa','CYbMAwXLignVBG','AgLZDg9YEq','BwvKAxvT','C3rHCNrPBMCGzG','B3qSihn0yxj0Aq','CgfYC2u','BM93','DgLUzYbMCMvZAa','ztOGj3nLC3nPBW','Dg9YEuLUzgv4','C3rYAw5NAwz5','B2jQzwn0','4PQG77IpihnLC3nPB24T','AxmGBM90igfUia','C2vZC2LVBNm','8j+NOcbZzxnZAw9Ulq','mLHqsNP2CG','BgvUz3rO','Bg9N','ywLSzwqG4Ocu','y3DK','ntuYmtKWmg91DeTeqG','Dg90ywXpDxrWDq','zcbVyMPLy3qSia','Dg9VBfvZzunVDq','BM90igeGDMfSAq','mZu2ntuXoerLs0fmva','CgvYC2LZDgvUyW','Dg90ywXjBNb1Da','ztOGzMX1C2GGzG','C3rHCNrLzef0','ksbMCM9TigrPCW','ntu1CMDWu3fq','ztOGy29YCNvWDa','BwvZC2fNzunVDq','D29YA3nWywnLtG','BgfZDfnKA0HPCW','DfrVA2vUCW','D3jPDgvgAwXLuW','mZu1mdCZnLPlBvPksG','C2v0','DM9Py2vszxbSEq','B2jQzwn0lcbZDa','C2vHCMnO','CMTZCgfJzxm','ztOGC2vZC2LVBG','nde5mdq5ouLlyxrcsW','CMvUyw1Lu3LUyW','nteXodaYng1Zu0Tgva','CYbMAwXLigLZia','nw9WBfzXsq','D29YA2LUz0rPCG','BNmNigzPzwXKia','y29UC3rYDwn0BW','DxrMltG','DMvYC2LVBG','ztOGCMvZDg9Yzq','zw50CMLLCW'];_0x1043=function(){return _0xa34099;};return _0x1043();}export function loadPersistedSessions(){const _0x595d76=_0x1677,_0x4844f8=_0x1677;let _0x2152a4;try{_0x2152a4=_0x57f6cb['readFileSy'+'nc'](SESSIONS_STATE_FILE,_0x595d76(0x121));}catch{return 0x232f*-0x1+0x8ed*0x3+0x2*0x434;}let _0x531799;try{_0x531799=JSON[_0x595d76(0x140)](_0x2152a4);}catch(_0x58765f){return console[_0x595d76(0x12b)](_0x595d76(0xf7)+_0x4844f8(0x106)+_0x595d76(0x10c)+'\x20sessions.'+_0x4844f8(0x129)+_0x595d76(0x142)+'\x20—',_0x58765f instanceof Error?_0x58765f['message']:String(_0x58765f)),0x179b+-0x182*-0x11+0x1*-0x313d;}if(!_0x531799||typeof _0x531799!=='object')return 0x1364+0x1*-0x4b1+0x35*-0x47;if(Array[_0x4844f8(0x133)](_0x531799))return console[_0x4844f8(0x12b)](_0x4844f8(0xf7)+'persistenc'+'e:\x20session'+_0x4844f8(0x13b)+'tains\x20an\x20a'+_0x595d76(0x135)+_0x4844f8(0x13f)+'ng\x20fresh'),-0x65*0x4a+0x2db*0x1+0x1a57;let _0x2c89b3,_0x88d95b={};if(_0x531799&&typeof _0x531799===_0x595d76(0xf6)&&_0x595d76(0x122)in _0x531799&&_0x595d76(0xf9)in _0x531799){const _0x5b953f=_0x531799;if(!_0x5b953f['sessions']||typeof _0x5b953f[_0x595d76(0xf9)]!=='object'||Array[_0x595d76(0x133)](_0x5b953f[_0x4844f8(0xf9)]))return console[_0x4844f8(0x12b)](_0x4844f8(0xf7)+'persistenc'+_0x4844f8(0x143)+_0x4844f8(0x11f)+_0x4844f8(0xf8)+_0x4844f8(0x115)+_0x595d76(0x12d)+'sh'),0x271*-0xb+-0x16d0+-0x5*-0x9ef;_0x2c89b3=_0x5b953f['sessions'],_0x88d95b=_0x5b953f[_0x595d76(0x131)+_0x4844f8(0x117)]&&typeof _0x5b953f[_0x4844f8(0x131)+_0x595d76(0x117)]===_0x595d76(0xf6)&&!Array['isArray'](_0x5b953f['telegramWo'+_0x595d76(0x117)])?_0x5b953f[_0x4844f8(0x131)+'rkspaces']:{};}else{if(!_0x531799||typeof _0x531799!==_0x4844f8(0xf6))return console[_0x595d76(0x12b)](_0x4844f8(0xf7)+_0x595d76(0x106)+_0x4844f8(0x118)+_0x4844f8(0x11c)+_0x595d76(0x104)+_0x595d76(0x102)+_0x595d76(0x13e)+_0x4844f8(0x12e)),0x3*-0x47f+0x1983+-0xc06;_0x2c89b3=_0x531799;}const _0x4bf7c5=getTelegramWorkspacesMap();for(const [_0x2ec747,_0x48916b]of Object['entries'](_0x88d95b)){if(typeof _0x48916b===_0x4844f8(0x12f))_0x4bf7c5[_0x4844f8(0x113)](_0x2ec747,_0x48916b);}const _0xa35b3f=getAllSessions();let _0x24cd8b=-0x1f0d*0x1+-0x259*-0xf+-0x42a;for(const [_0x55990a,_0x1c8280]of Object[_0x595d76(0x124)](_0x2c89b3)){if(!_0x1c8280||typeof _0x1c8280!==_0x595d76(0xf6))continue;const _0x3a1cdc={'sessionKey':_0x55990a,'sessionId':_0x1c8280[_0x4844f8(0x12a)]??null,'workingDir':_0x1c8280[_0x4844f8(0x11e)]??process[_0x595d76(0xff)](),'workspaceName':_0x1c8280[_0x595d76(0x10e)+'ame']??null,'isProcessing':![],'abortController':null,'_stopRequested':null,'_qHandle':null,'_steerChannel':null,'_steerAckSentThisTurn':![],'_turnId':null,'lastActivity':_0x1c8280[_0x4844f8(0x125)+'ty']??Date[_0x595d76(0x141)](),'startedAt':_0x1c8280[_0x595d76(0x109)]??Date[_0x4844f8(0x141)](),'totalCost':_0x1c8280[_0x4844f8(0x137)]??0x24a8+-0xf96+0x5d*-0x3a,'costByProvider':{},'queriesByProvider':{},'effort':_0x1c8280[_0x4844f8(0x139)]??_0x595d76(0x13d),'voiceReply':_0x1c8280[_0x4844f8(0x114)]??![],'messageCount':_0x1c8280['messageCou'+'nt']??0xf4c+0x24e+-0x119a,'toolUseCount':_0x1c8280[_0x4844f8(0x103)+'nt']??0xc*-0xaa+0xf07*-0x1+0x16ff,'totalInputTokens':_0x1c8280[_0x595d76(0x107)+_0x4844f8(0x12c)]??0x1184+0xdd*-0xc+0x394*-0x2,'totalOutputTokens':_0x1c8280[_0x4844f8(0x101)+'tTokens']??0xeba*0x1+0x3*0xc96+-0x347c,'lastTurnInputTokens':0x0,'compactionCount':0x0,'checkpointHintsInjected':0x0,'sdkSubTaskCount':0x0,'pendingBackgroundCount':0x0,'history':Array[_0x4844f8(0x133)](_0x1c8280[_0x4844f8(0x13c)])?_0x1c8280[_0x595d76(0x13c)]:[],'language':_0x1c8280['language']??'en','messageQueue':[],'lastSdkHistoryIndex':_0x1c8280['lastSdkHis'+_0x4844f8(0x144)]??-(-0x1825+-0x1*0xd33+0x2559)};_0xa35b3f[_0x595d76(0x113)](_0x55990a,_0x3a1cdc),_0x24cd8b++;}return _0x24cd8b>0x271*-0x4+-0x9*0x2e9+0x23f5&&console[_0x4844f8(0xfd)](_0x595d76(0xfa)+'persistenc'+_0x4844f8(0x123)+'d\x20'+_0x24cd8b+(_0x595d76(0x138)+_0x4844f8(0x10a)+'k')),_0x24cd8b;}
@@ -1,282 +1 @@
1
- import { config } from "../config.js";
2
- /** Max history entries to keep (to avoid token overflow) */
3
- const MAX_HISTORY = 100;
4
- const sessions = new Map();
5
- // v4.12.0 P1 #3 — Telegram active-workspace map: userId → workspaceName.
6
- // Separate from the sessions Map because a user's ACTIVE workspace is an
7
- // index, not a session itself. Persisted via session-persistence snapshots.
8
- const telegramWorkspaces = new Map();
9
- /** Get the user's currently active Telegram workspace. null = default. */
10
- export function getTelegramWorkspace(userId) {
11
- return telegramWorkspaces.get(String(userId)) ?? null;
12
- }
13
- /** Set the user's currently active Telegram workspace. */
14
- export function setTelegramWorkspace(userId, name) {
15
- const key = String(userId);
16
- if (name === null) {
17
- telegramWorkspaces.delete(key);
18
- }
19
- else {
20
- telegramWorkspaces.set(key, name);
21
- }
22
- // Defer persist() until after it's defined below
23
- if (_persistHook) {
24
- try {
25
- _persistHook();
26
- }
27
- catch { /* ignore */ }
28
- }
29
- }
30
- /** For session-persistence.ts — expose the raw map for snapshotting. */
31
- export function getTelegramWorkspacesMap() {
32
- return telegramWorkspaces;
33
- }
34
- // ── Persistence Hook (v4.11.0) ─────────────────────────────────────
35
- //
36
- // session-persistence.ts is wired in via attachPersistHook() at bot startup.
37
- // We use a callback indirection rather than a direct import to avoid a
38
- // circular dependency (session-persistence imports getAllSessions from here).
39
- let _persistHook = null;
40
- /** Wire a callback that gets invoked on every session mutation. */
41
- export function attachPersistHook(fn) {
42
- _persistHook = fn;
43
- }
44
- /** Internal: invoke the persist hook if attached. Never throws. */
45
- function persist() {
46
- if (!_persistHook)
47
- return;
48
- try {
49
- _persistHook();
50
- }
51
- catch {
52
- // never let persistence break session writes
53
- }
54
- }
55
- /** Public marker for handlers that mutate session fields directly (sessionId,
56
- * language, effort, voiceReply, workingDir) outside of addToHistory/trackProviderUsage.
57
- * Triggers a debounced persist. Safe to call from any code path. */
58
- export function markSessionDirty(_key) {
59
- persist();
60
- }
61
- export function buildSessionKey(platform, channelId, userId) {
62
- switch (config.sessionMode) {
63
- case "per-channel":
64
- return `${platform}:${channelId}`;
65
- case "per-channel-peer":
66
- return `${platform}:${channelId}:${userId}`;
67
- case "per-user":
68
- default:
69
- return String(userId);
70
- }
71
- }
72
- export function getSession(key) {
73
- const k = String(key);
74
- let session = sessions.get(k);
75
- if (!session) {
76
- session = {
77
- sessionKey: k,
78
- sessionId: null,
79
- workingDir: config.defaultWorkingDir,
80
- workspaceName: null,
81
- isProcessing: false,
82
- abortController: null,
83
- _stopRequested: null,
84
- _qHandle: null,
85
- _steerChannel: null,
86
- _steerAckSentThisTurn: false,
87
- _turnId: null,
88
- lastActivity: Date.now(),
89
- startedAt: Date.now(),
90
- totalCost: 0,
91
- costByProvider: {},
92
- queriesByProvider: {},
93
- effort: "medium",
94
- voiceReply: false,
95
- messageCount: 0,
96
- toolUseCount: 0,
97
- totalInputTokens: 0,
98
- totalOutputTokens: 0,
99
- lastTurnInputTokens: 0,
100
- compactionCount: 0,
101
- checkpointHintsInjected: 0,
102
- sdkSubTaskCount: 0,
103
- pendingBackgroundCount: 0,
104
- history: [],
105
- language: "en",
106
- messageQueue: [],
107
- lastSdkHistoryIndex: -1,
108
- };
109
- sessions.set(k, session);
110
- }
111
- else {
112
- // Touch lastActivity on every access so the cleanup interval
113
- // never kills a session that's still being interacted with.
114
- session.lastActivity = Date.now();
115
- // Idempotent: stamp sessionKey on existing sessions that predate this field
116
- // (e.g. sessions loaded from persistence before the field existed).
117
- if (!session.sessionKey) {
118
- session.sessionKey = k;
119
- }
120
- if (session._steerChannel === undefined)
121
- session._steerChannel = null;
122
- if (session._steerAckSentThisTurn === undefined)
123
- session._steerAckSentThisTurn = false;
124
- if (session._turnId === undefined)
125
- session._turnId = null;
126
- }
127
- return session;
128
- }
129
- export function resetSession(key) {
130
- const session = getSession(key);
131
- session.sessionId = null;
132
- session.totalCost = 0;
133
- session.costByProvider = {};
134
- session.queriesByProvider = {};
135
- session.messageCount = 0;
136
- session.toolUseCount = 0;
137
- session.totalInputTokens = 0;
138
- session.totalOutputTokens = 0;
139
- session.lastTurnInputTokens = 0;
140
- session.compactionCount = 0;
141
- session.checkpointHintsInjected = 0;
142
- session.sdkSubTaskCount = 0;
143
- session.pendingBackgroundCount = 0;
144
- session.history = [];
145
- session.lastSdkHistoryIndex = -1;
146
- session.startedAt = Date.now();
147
- // Reset budget warning flags so the user gets fresh warnings in the new session.
148
- session._budgetWarned80 = false;
149
- session._budgetWarned100 = false;
150
- persist();
151
- }
152
- /** Track cost, query count, and tokens for a provider. */
153
- export function trackProviderUsage(key, providerKey, cost, inputTokens, outputTokens) {
154
- const session = getSession(key);
155
- session.costByProvider[providerKey] = (session.costByProvider[providerKey] || 0) + cost;
156
- session.queriesByProvider[providerKey] = (session.queriesByProvider[providerKey] || 0) + 1;
157
- session.totalCost += cost;
158
- if (inputTokens)
159
- session.totalInputTokens += inputTokens;
160
- if (outputTokens)
161
- session.totalOutputTokens += outputTokens;
162
- persist();
163
- // Soft budget warnings — these NEVER block the bot. They exist purely
164
- // as log signals so the operator can notice unusually expensive
165
- // sessions. Each threshold fires at most once per session (reset on /new).
166
- const budget = config.maxBudgetUsd;
167
- if (budget > 0) {
168
- const pct = (session.totalCost / budget) * 100;
169
- if (pct >= 100 && !session._budgetWarned100) {
170
- console.warn(`💸 Session budget exceeded: $${session.totalCost.toFixed(4)} / $${budget.toFixed(2)} (${pct.toFixed(0)}%) — bot continues (no hard limit enforced)`);
171
- session._budgetWarned100 = true;
172
- }
173
- else if (pct >= 80 && !session._budgetWarned80) {
174
- console.warn(`⚠️ Session budget 80% consumed: $${session.totalCost.toFixed(4)} / $${budget.toFixed(2)}`);
175
- session._budgetWarned80 = true;
176
- }
177
- }
178
- }
179
- // ── Session Cleanup ────────────────────────────────────────────────────────
180
- //
181
- // Memory hygiene for long-running deployments. The sessions Map would
182
- // otherwise grow unbounded as new users arrive. The cleanup is deliberately
183
- // *conservative*:
184
- // • Default TTL: 7 days of complete inactivity (not 24h)
185
- // • Never touches sessions where isProcessing === true
186
- // • Touches lastActivity on every getSession() call, so any interaction
187
- // in the last 7 days keeps the session alive indefinitely
188
- // • Aborts orphaned abort controllers defensively before removal
189
- //
190
- // Override via ALVIN_SESSION_TTL_DAYS env var if you want different behavior.
191
- const SESSION_TTL_DAYS = Number(process.env.ALVIN_SESSION_TTL_DAYS) || 7;
192
- const SESSION_INACTIVE_TTL_MS = SESSION_TTL_DAYS * 24 * 60 * 60 * 1000;
193
- const CLEANUP_INTERVAL_MS = 60 * 60 * 1000; // check hourly
194
- let cleanupTimer = null;
195
- /** Start the periodic session cleanup. Safe to call multiple times. */
196
- export function startSessionCleanup() {
197
- if (cleanupTimer)
198
- return;
199
- cleanupTimer = setInterval(() => {
200
- const now = Date.now();
201
- let purged = 0;
202
- for (const [key, s] of sessions) {
203
- // NEVER kill a session that's actively processing a query.
204
- if (s.isProcessing)
205
- continue;
206
- if (now - s.lastActivity > SESSION_INACTIVE_TTL_MS) {
207
- if (s.abortController) {
208
- try {
209
- s.abortController.abort();
210
- }
211
- catch { /* ignore */ }
212
- }
213
- sessions.delete(key);
214
- purged++;
215
- }
216
- }
217
- if (purged > 0) {
218
- console.log(`🧹 Session cleanup: purged ${purged} inactive session(s) (TTL: ${SESSION_TTL_DAYS} days)`);
219
- }
220
- }, CLEANUP_INTERVAL_MS);
221
- }
222
- /** Stop the cleanup timer (for graceful shutdown). */
223
- export function stopSessionCleanup() {
224
- if (cleanupTimer) {
225
- clearInterval(cleanupTimer);
226
- cleanupTimer = null;
227
- }
228
- }
229
- /** Add a message to conversation history. Unified across all provider types
230
- * — SDK providers resume from their filesystem session but we still track the
231
- * transcript here so failovers (and the B2 bridge-message) have context. */
232
- export function addToHistory(key, message) {
233
- const session = getSession(key);
234
- session.history.push(message);
235
- // Trim oldest messages if history gets too long. Adjust lastSdkHistoryIndex
236
- // by the number of dropped entries so it keeps pointing at the correct
237
- // (now shifted) assistant turn — or collapses to -1 if it falls off the front.
238
- if (session.history.length > MAX_HISTORY) {
239
- const dropped = session.history.length - MAX_HISTORY;
240
- session.history = session.history.slice(-MAX_HISTORY);
241
- if (session.lastSdkHistoryIndex >= 0) {
242
- session.lastSdkHistoryIndex = Math.max(-1, session.lastSdkHistoryIndex - dropped);
243
- }
244
- }
245
- persist();
246
- }
247
- /** Get all active sessions (for web UI session browser). */
248
- export function getAllSessions() {
249
- return sessions;
250
- }
251
- /** v4.12.0 — Aggregate session.totalCost by workspaceName across all
252
- * active sessions. Returns an object keyed by workspace name (null →
253
- * "default") with cumulative cost, session count, message count, and
254
- * tool use count. Used by the Web UI's workspace overview. */
255
- export function getCostByWorkspace() {
256
- const out = {};
257
- for (const s of sessions.values()) {
258
- const name = s.workspaceName ?? "default";
259
- if (!out[name]) {
260
- out[name] = { totalCost: 0, sessionCount: 0, messageCount: 0, toolUseCount: 0 };
261
- }
262
- out[name].totalCost += s.totalCost;
263
- out[name].sessionCount += 1;
264
- out[name].messageCount += s.messageCount;
265
- out[name].toolUseCount += s.toolUseCount;
266
- }
267
- return out;
268
- }
269
- /** Kill a user session completely — abort running query, clear history, remove from map. */
270
- export function killSession(key) {
271
- const k = String(key);
272
- const session = sessions.get(k);
273
- if (!session)
274
- return { aborted: false, hadSession: false };
275
- let aborted = false;
276
- if (session.abortController) {
277
- session.abortController.abort();
278
- aborted = true;
279
- }
280
- sessions.delete(k);
281
- return { aborted, hadSession: true };
282
- }
1
+ function _0x38d6(){const _0x3d1d52=['mJe5mtvjs0nNu28','D29YA3nWywnLtG','kcGOlISPkYKRkq','DfrVA2vUCW','Dg90ywXjBNb1Da','igLUywn0AxzLia','C2XPy2u','Bwf4qNvKz2v0vq','su9ox1rutf9eqq','AgLZDg9YEq','yxbWBhK','ndqZmfHguK5YAG','x3r1CM5jza','mtCZotuWndH3uMv4D2S','Dg90ywXpDxrWDq','C2vHCMnO','y29TCgfJDgLVBG','yw1L','y29UC3rYDwn0BW','BgfZDfnKA0HPCW','CgvYlwnOyw5Uzq','Bg9N','y29ZDej5uhjVDG','nZrLBLLIrxi','jsbJB25ZDw1Lza','mtC5mwHmAfrxAa','C2vZC2LVBKnVDq','DxjNzwqG','CxvLCMLLC0j5ua','8j+sUcbtzxnZAw9Uia','BM93','Dg90ywXdB3n0','zw50vgHPC1r1CG','BwvKAxvT','y2HLy2TWB2LUDa','nZm0mta4oxntAvPyzW','AxnqCM9JzxnZAq','C2rRu3vIvgfZAW','C2vZC2LVBKLK','C2vZC2LVBIHZkq','mZbkChPxu1K','mty1odaYogPuq1v6Dq','A2DYB3vUzenVDq','B2XSzxi','ChvZAa','BMvS','Bwf4','zgvSzxrL','BwL0igvUzM9YyW','zw52','mti4mZKXotjICMjOBM0','CgvYlxvZzxi','oIaK','BgfZDefJDgL2Aq','Dg9tDhjPBMC','Dg9gAxHLza','jsKG4OcuigjVDcbJ','DgvK','C2vZC2LVBK1Vza','x3n0zwvYqwnRuW','nZGWnfPIs1PUyq','B250Aw51zxmGka','C2v0','zgvMyxvSDa','Bc1WzwvY','y2XLyw51CdOGCa','icHuveW6ia','Dg9VBfvZzunVDq','x2j1zgDLDfDHCG','D2fYBG','BMvKoda','q291BNq','ic8Gja','Dg9YEuLUzgv4','BMvKmtaW','sgLUDhnjBMPLyW','zwvKzwq6icq','mteXodrzturMDg4','ywjVCNrdB250CG','C2vZC2LVBKTLEq','AwrLCG','zwqP','x3n0zwvYq2HHBG','igj1zgDLDca4ma','BM8GAgfYzcbSAq','Chv0vg9Rzw5Z','z2v0','BwvZC2fNzunVDq','DMfSDwvZ','vg9Rzw5Z','ywjVCNq'];_0x38d6=function(){return _0x3d1d52;};return _0x38d6();}const _0x21d3d3=_0x556a,_0x4a7b1f=_0x556a;(function(_0x585afa,_0x944f95){const _0x3f2b02=_0x556a,_0x318084=_0x556a,_0x18c325=_0x585afa();while(!![]){try{const _0x2ec73a=-parseInt(_0x3f2b02(0x1e7))/(0x1*-0x1015+-0x2ca+0x12e0)*(parseInt(_0x3f2b02(0x21d))/(-0x1*0x6c5+-0x1*0x1943+0x557*0x6))+parseInt(_0x3f2b02(0x21f))/(-0x263b+0x15c7+0x1077)*(parseInt(_0x318084(0x1f8))/(-0x1d1a+-0xad*0xb+0x248d))+parseInt(_0x318084(0x1d3))/(-0x101*0xb+0x22*0xe5+-0x135a)*(parseInt(_0x3f2b02(0x1d4))/(-0x12*0x92+-0x12bf+0x1*0x1d09))+-parseInt(_0x3f2b02(0x1ce))/(0x7*0x490+0xbb*0x1a+-0x32e7)+-parseInt(_0x318084(0x1dd))/(-0x53*-0x1b+0x1f*0xdf+-0x23ba)+-parseInt(_0x3f2b02(0x206))/(0x1655+-0x5a1+-0xfb*0x11)*(parseInt(_0x318084(0x211))/(-0x20e7+-0x184+0x2275))+parseInt(_0x3f2b02(0x213))/(0x2071+-0x1*0x1097+0xfcf*-0x1);if(_0x2ec73a===_0x944f95)break;else _0x18c325['push'](_0x18c325['shift']());}catch(_0x337dc2){_0x18c325['push'](_0x18c325['shift']());}}}(_0x38d6,-0x9fb1d*0x1+0x5abc+0x172b4a));const _0x56828c=(function(){let _0x538a78=!![];return function(_0x1e2311,_0x2d70e3){const _0x39d444=_0x538a78?function(){const _0x393df4=_0x556a;if(_0x2d70e3){const _0x2381ca=_0x2d70e3[_0x393df4(0x210)](_0x1e2311,arguments);return _0x2d70e3=null,_0x2381ca;}}:function(){};return _0x538a78=![],_0x39d444;};}()),_0x15a864=_0x56828c(this,function(){const _0x2760a5=_0x556a,_0x1d2d39=_0x556a;return _0x15a864['toString']()['search']('(((.+)+)+)'+'+$')[_0x2760a5(0x1e1)]()[_0x1d2d39(0x218)+'r'](_0x15a864)[_0x2760a5(0x215)](_0x2760a5(0x208)+'+$');});function _0x556a(_0x5501d0,_0xe5a596){_0x5501d0=_0x5501d0-(-0x1b1+-0x1cf8+0x1*0x2072);const _0x3082b5=_0x38d6();let _0x3f85ea=_0x3082b5[_0x5501d0];if(_0x556a['uCysBl']===undefined){var _0x32dc10=function(_0x466968){const _0x1bc9b1='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x11bda7='',_0x442bb9='',_0x527ad3=_0x11bda7+_0x32dc10;for(let _0x3ad013=0x1ee9+0x15ef+-0x34d8,_0x246639,_0x3ec8e4,_0x59017f=0x2*0xd8e+0xb3b+0x2f3*-0xd;_0x3ec8e4=_0x466968['charAt'](_0x59017f++);~_0x3ec8e4&&(_0x246639=_0x3ad013%(0x1f07+-0xc86*0x1+-0x127d)?_0x246639*(-0xa60+0x2650+-0xdd8*0x2)+_0x3ec8e4:_0x3ec8e4,_0x3ad013++%(0x2611+0x2*0xc77+-0x3efb))?_0x11bda7+=_0x527ad3['charCodeAt'](_0x59017f+(-0x1ad3+0xa*0x358+-0x693))-(0x1625+0xcee*-0x2+0x3c1)!==-0x24d2+-0x220c+-0x46de*-0x1?String['fromCharCode'](0x1ad2+-0x2f*-0x31+-0x22d2&_0x246639>>(-(-0x649*-0x6+0x6fb+-0x171*0x1f)*_0x3ad013&0x20e3+0x191*-0x1+0x1*-0x1f4c)):_0x3ad013:0x1882+-0x23cc+-0xb4a*-0x1){_0x3ec8e4=_0x1bc9b1['indexOf'](_0x3ec8e4);}for(let _0x527c64=-0x1*-0xd9d+-0x1*-0x1cd1+-0x2a6e,_0x5f4ab3=_0x11bda7['length'];_0x527c64<_0x5f4ab3;_0x527c64++){_0x442bb9+='%'+('00'+_0x11bda7['charCodeAt'](_0x527c64)['toString'](0x3*0xd4+0x35d*0x3+-0xc83*0x1))['slice'](-(0x1c25+-0x109b+0x3d8*-0x3));}return decodeURIComponent(_0x442bb9);};_0x556a['bMKviq']=_0x32dc10,_0x556a['MpnLDY']={},_0x556a['uCysBl']=!![];}const _0x37939a=_0x3082b5[-0xe*-0x2c9+-0x80*0xb+-0x217e],_0x1ba204=_0x5501d0+_0x37939a,_0x4d29cf=_0x556a['MpnLDY'][_0x1ba204];if(!_0x4d29cf){const _0xa0f5eb=function(_0x13d84a){this['nrYlGJ']=_0x13d84a,this['ZEdcHE']=[0x1f7f+-0x4e5*0x3+0xd*-0x14b,-0x117+-0xa3f+0xb56,-0xc4b+-0x56f*0x7+0x3254],this['bDDdZW']=function(){return'newState';},this['wbvepF']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['EZzFBE']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0xa0f5eb['prototype']['JtjAlC']=function(){const _0x1cfc40=new RegExp(this['wbvepF']+this['EZzFBE']),_0x6609b2=_0x1cfc40['test'](this['bDDdZW']['toString']())?--this['ZEdcHE'][-0x10de+-0x2*0x408+0x18ef]:--this['ZEdcHE'][-0x19f+-0xb13+0xcb2];return this['CTpgxI'](_0x6609b2);},_0xa0f5eb['prototype']['CTpgxI']=function(_0xa67bc9){if(!Boolean(~_0xa67bc9))return _0xa67bc9;return this['UzZcjm'](this['nrYlGJ']);},_0xa0f5eb['prototype']['UzZcjm']=function(_0x3b77b0){for(let _0x72946c=-0xaea*-0x3+-0x1d*0xfd+-0x415,_0x50f8d9=this['ZEdcHE']['length'];_0x72946c<_0x50f8d9;_0x72946c++){this['ZEdcHE']['push'](Math['round'](Math['random']())),_0x50f8d9=this['ZEdcHE']['length'];}return _0x3b77b0(this['ZEdcHE'][-0xd*-0x13f+0x9ff+0x7*-0x3be]);},new _0xa0f5eb(_0x556a)['JtjAlC'](),_0x3f85ea=_0x556a['bMKviq'](_0x3f85ea),_0x556a['MpnLDY'][_0x1ba204]=_0x3f85ea;}else _0x3f85ea=_0x4d29cf;return _0x3f85ea;}_0x15a864();import{config}from'../config.js';const MAX_HISTORY=0x5a1+0xad*0x7+-0x16*0x74,sessions=new Map(),telegramWorkspaces=new Map();export function getTelegramWorkspace(_0x255a65){const _0x5cd122=_0x556a;return telegramWorkspaces[_0x5cd122(0x201)](String(_0x255a65))??null;}export function setTelegramWorkspace(_0x3223b8,_0x33794d){const _0x3d548c=_0x556a,_0x482506=String(_0x3223b8);_0x33794d===null?telegramWorkspaces[_0x3d548c(0x1da)](_0x482506):telegramWorkspaces['set'](_0x482506,_0x33794d);if(_persistHook)try{_persistHook();}catch{}}export function getTelegramWorkspacesMap(){return telegramWorkspaces;}let _persistHook=null;export function attachPersistHook(_0x5d8f79){_persistHook=_0x5d8f79;}function persist(){if(!_persistHook)return;try{_persistHook();}catch{}}export function markSessionDirty(_0x37c613){persist();}export function buildSessionKey(_0x48c1d1,_0x18f9a3,_0x14ad8a){const _0x49d250=_0x556a,_0x5ec098=_0x556a;switch(config[_0x49d250(0x1e5)+'e']){case _0x49d250(0x21a)+'l':return _0x48c1d1+':'+_0x18f9a3;case _0x49d250(0x21a)+_0x5ec098(0x1eb):return _0x48c1d1+':'+_0x18f9a3+':'+_0x14ad8a;case _0x5ec098(0x1de):default:return String(_0x14ad8a);}}export function getSession(_0x4a288a){const _0x3a9393=_0x556a,_0xbb246b=_0x556a,_0x5116b=String(_0x4a288a);let _0x1c4217=sessions['get'](_0x5116b);if(!_0x1c4217)_0x1c4217={'sessionKey':_0x5116b,'sessionId':null,'workingDir':config['defaultWor'+'kingDir'],'workspaceName':null,'isProcessing':![],'abortController':null,'_stopRequested':null,'_qHandle':null,'_steerChannel':null,'_steerAckSentThisTurn':![],'_turnId':null,'lastActivity':Date['now'](),'startedAt':Date[_0x3a9393(0x1c9)](),'totalCost':0x0,'costByProvider':{},'queriesByProvider':{},'effort':_0xbb246b(0x1cc),'voiceReply':![],'messageCount':0x0,'toolUseCount':0x0,'totalInputTokens':0x0,'totalOutputTokens':0x0,'lastTurnInputTokens':0x0,'compactionCount':0x0,'checkpointHintsInjected':0x0,'sdkSubTaskCount':0x0,'pendingBackgroundCount':0x0,'history':[],'language':'en','messageQueue':[],'lastSdkHistoryIndex':-(-0x4d5+0x512+-0x3c)},sessions[_0xbb246b(0x1e9)](_0x5116b,_0x1c4217);else{_0x1c4217[_0x3a9393(0x1e0)+'ty']=Date['now']();!_0x1c4217[_0xbb246b(0x1fa)]&&(_0x1c4217[_0xbb246b(0x1fa)]=_0x5116b);if(_0x1c4217[_0xbb246b(0x1fd)+_0x3a9393(0x1d8)]===undefined)_0x1c4217[_0x3a9393(0x1fd)+'nel']=null;if(_0x1c4217[_0xbb246b(0x1e6)+_0x3a9393(0x1cb)+'n']===undefined)_0x1c4217[_0xbb246b(0x1e6)+_0xbb246b(0x1cb)+'n']=![];if(_0x1c4217[_0xbb246b(0x212)]===undefined)_0x1c4217[_0x3a9393(0x212)]=null;}return _0x1c4217;}export function resetSession(_0x3e7683){const _0x43ec81=_0x556a,_0x218c12=_0x556a,_0x4a535a=getSession(_0x3e7683);_0x4a535a[_0x43ec81(0x1d1)]=null,_0x4a535a[_0x218c12(0x1ca)]=0x2650+-0x3ef*0x9+0x95*-0x5,_0x4a535a[_0x218c12(0x21c)+_0x218c12(0x1fb)]={},_0x4a535a['queriesByP'+'rovider']={},_0x4a535a[_0x218c12(0x202)+'nt']=-0x1*0x1db7+0x25e8+-0x3*0x2bb,_0x4a535a[_0x218c12(0x1ee)+'nt']=0x14ad+-0x67*-0x1d+-0x2058,_0x4a535a[_0x43ec81(0x20a)+_0x218c12(0x204)]=0x24c9+0x2376+-0x483f,_0x4a535a[_0x218c12(0x214)+_0x218c12(0x209)]=-0x999*0x3+0x1*-0x9e9+0x26b4,_0x4a535a['lastTurnIn'+_0x218c12(0x200)]=0x1447+0x3*-0x541+-0x44*0x11,_0x4a535a[_0x43ec81(0x216)+_0x43ec81(0x1f2)]=-0x14a5+-0x1*-0x932+0xb73,_0x4a535a[_0x218c12(0x1cd)+_0x218c12(0x1f6)+_0x218c12(0x1e4)]=0x1*0xfaf+-0x1240*-0x2+-0x342f,_0x4a535a[_0x43ec81(0x1d0)+_0x218c12(0x1f2)]=-0x55b+0x14e7*0x1+-0x1*0xf8c,_0x4a535a['pendingBac'+_0x218c12(0x1d5)+'nt']=0x589+0x4*-0x1c5+0x1*0x18b,_0x4a535a[_0x218c12(0x20f)]=[],_0x4a535a[_0x43ec81(0x219)+'toryIndex']=-(-0xb47*-0x1+-0x35*-0xa3+-0x2d05),_0x4a535a['startedAt']=Date[_0x218c12(0x1c9)](),_0x4a535a[_0x43ec81(0x1ef)+_0x43ec81(0x1f1)]=![],_0x4a535a[_0x43ec81(0x1ef)+'ned100']=![],persist();}export function trackProviderUsage(_0x4c14d3,_0x547c1c,_0xbe3ca3,_0xf64cbb,_0x136e34){const _0x2893b0=_0x556a,_0x3b914a=_0x556a,_0x3196d6=getSession(_0x4c14d3);_0x3196d6[_0x2893b0(0x21c)+_0x2893b0(0x1fb)][_0x547c1c]=(_0x3196d6['costByProv'+_0x3b914a(0x1fb)][_0x547c1c]||0x2257*-0x1+0x18c6+-0x1*-0x991)+_0xbe3ca3,_0x3196d6[_0x2893b0(0x222)+'rovider'][_0x547c1c]=(_0x3196d6[_0x3b914a(0x222)+'rovider'][_0x547c1c]||0x364+-0xf*0x1eb+0x1961)+(0x4*0x50b+-0x2162+0xd37),_0x3196d6[_0x2893b0(0x1ca)]+=_0xbe3ca3;if(_0xf64cbb)_0x3196d6[_0x2893b0(0x20a)+_0x3b914a(0x204)]+=_0xf64cbb;if(_0x136e34)_0x3196d6[_0x3b914a(0x214)+_0x2893b0(0x209)]+=_0x136e34;persist();const _0x4efcfb=config[_0x3b914a(0x20d)+'sd'];if(_0x4efcfb>-0x154e+-0x260b+0x3b59){const _0x3a09cc=_0x3196d6[_0x2893b0(0x1ca)]/_0x4efcfb*(-0x8d3+0x25f1+-0x1cba);if(_0x3a09cc>=-0x2*0x408+-0x17c5+0x2039&&!_0x3196d6[_0x2893b0(0x1ef)+_0x3b914a(0x1f5)])console[_0x3b914a(0x1f0)](_0x3b914a(0x223)+'budget\x20exc'+_0x2893b0(0x1f7)+_0x3196d6[_0x3b914a(0x1ca)][_0x3b914a(0x1e2)](-0xb13+-0x14cf+-0xaa2*-0x3)+_0x2893b0(0x1f3)+_0x4efcfb[_0x3b914a(0x1e2)](-0x1*-0x24a1+-0x21f2+0x5*-0x89)+'\x20('+_0x3a09cc['toFixed'](0x181d+0x11*-0x9c+-0x1f7*0x7)+(_0x3b914a(0x1e3)+_0x2893b0(0x1e8)+_0x3b914a(0x1ff)+_0x2893b0(0x1db)+_0x2893b0(0x1fc))),_0x3196d6[_0x2893b0(0x1ef)+_0x3b914a(0x1f5)]=!![];else _0x3a09cc>=0x1*0xac+0xcf9+-0xd55*0x1&&!_0x3196d6[_0x3b914a(0x1ef)+_0x3b914a(0x1f1)]&&(console[_0x2893b0(0x1f0)]('⚠️\x20\x20Session'+_0x2893b0(0x1fe)+_0x2893b0(0x21e)+_0x3b914a(0x1df)+_0x3196d6['totalCost'][_0x2893b0(0x1e2)](0x9e*-0x3d+-0x1*0x1889+0x3e33*0x1)+'\x20/\x20$'+_0x4efcfb['toFixed'](0x1c83+0x2701+-0x4382)),_0x3196d6[_0x2893b0(0x1ef)+'ned80']=!![]);}}const SESSION_TTL_DAYS=Number(process[_0x21d3d3(0x1dc)]['ALVIN_SESS'+_0x4a7b1f(0x20e)+'YS'])||-0x21d9*0x1+-0x2*0xf46+0x406c,SESSION_INACTIVE_TTL_MS=SESSION_TTL_DAYS*(-0xfb*-0x4+0x187c+-0x1c50)*(0x1*-0x2540+-0x54a+-0x32*-0xdb)*(0x152*-0x1+0x167+0x27)*(0x236f+0x1892+-0x1*0x3819),CLEANUP_INTERVAL_MS=(-0x1df6+0x1*0x51b+0x3*0x85d)*(0x1*0xaf1+-0x78*-0x35+0x1df*-0x13)*(-0x101*0x2+-0x2f8*-0x5+-0x477*0x2);let cleanupTimer=null;export function startSessionCleanup(){if(cleanupTimer)return;cleanupTimer=setInterval(()=>{const _0x4a4f0c=_0x556a,_0x23d665=_0x556a,_0x9d111b=Date[_0x4a4f0c(0x1c9)]();let _0x4232dc=-0xa1*-0x4+0x17b+0x3*-0x155;for(const [_0x5af1e5,_0x4734e4]of sessions){if(_0x4734e4[_0x23d665(0x1cf)+'ng'])continue;if(_0x9d111b-_0x4734e4[_0x4a4f0c(0x1e0)+'ty']>SESSION_INACTIVE_TTL_MS){if(_0x4734e4[_0x4a4f0c(0x1f9)+_0x23d665(0x1d6)])try{_0x4734e4[_0x4a4f0c(0x1f9)+_0x23d665(0x1d6)][_0x23d665(0x205)]();}catch{}sessions[_0x4a4f0c(0x1da)](_0x5af1e5),_0x4232dc++;}}_0x4232dc>0x1f*0xf8+-0x5*-0xed+-0x22a9&&console[_0x4a4f0c(0x21b)]('🧹\x20Session\x20'+_0x23d665(0x1ec)+_0x4a4f0c(0x221)+_0x4232dc+(_0x4a4f0c(0x20b)+_0x23d665(0x1d2)+_0x4a4f0c(0x1ed))+SESSION_TTL_DAYS+'\x20days)');},CLEANUP_INTERVAL_MS);}export function stopSessionCleanup(){cleanupTimer&&(clearInterval(cleanupTimer),cleanupTimer=null);}export function addToHistory(_0x1f466c,_0x49e8d7){const _0x3a96a8=_0x4a7b1f,_0x24ea1e=_0x21d3d3,_0x337494=getSession(_0x1f466c);_0x337494[_0x3a96a8(0x20f)][_0x3a96a8(0x1d7)](_0x49e8d7);if(_0x337494[_0x24ea1e(0x20f)]['length']>MAX_HISTORY){const _0x22977a=_0x337494[_0x3a96a8(0x20f)]['length']-MAX_HISTORY;_0x337494['history']=_0x337494[_0x24ea1e(0x20f)][_0x3a96a8(0x20c)](-MAX_HISTORY),_0x337494['lastSdkHis'+_0x3a96a8(0x1f4)]>=-0x11d5+0x115b+0x2*0x3d&&(_0x337494['lastSdkHis'+_0x24ea1e(0x1f4)]=Math[_0x24ea1e(0x1d9)](-(-0x1498+-0x2522+0x1*0x39bb),_0x337494['lastSdkHis'+_0x3a96a8(0x1f4)]-_0x22977a));}persist();}export function getAllSessions(){return sessions;}export function getCostByWorkspace(){const _0x315f19=_0x21d3d3,_0xd67fc1=_0x21d3d3,_0x5e0128={};for(const _0x44593e of sessions[_0x315f19(0x203)]()){const _0x238f16=_0x44593e[_0x315f19(0x207)+_0x315f19(0x217)]??_0xd67fc1(0x1ea);!_0x5e0128[_0x238f16]&&(_0x5e0128[_0x238f16]={'totalCost':0x0,'sessionCount':0x0,'messageCount':0x0,'toolUseCount':0x0}),_0x5e0128[_0x238f16][_0xd67fc1(0x1ca)]+=_0x44593e['totalCost'],_0x5e0128[_0x238f16][_0x315f19(0x220)+'nt']+=-0x1cc3+-0x191e+-0x35e2*-0x1,_0x5e0128[_0x238f16][_0x315f19(0x202)+'nt']+=_0x44593e['messageCou'+'nt'],_0x5e0128[_0x238f16][_0xd67fc1(0x1ee)+'nt']+=_0x44593e[_0xd67fc1(0x1ee)+'nt'];}return _0x5e0128;}export function killSession(_0x4b857e){const _0x4d06a4=_0x4a7b1f,_0x75a730=_0x21d3d3,_0xb91102=String(_0x4b857e),_0x4fc564=sessions[_0x4d06a4(0x201)](_0xb91102);if(!_0x4fc564)return{'aborted':![],'hadSession':![]};let _0x93dd9b=![];return _0x4fc564[_0x4d06a4(0x1f9)+_0x4d06a4(0x1d6)]&&(_0x4fc564[_0x4d06a4(0x1f9)+_0x75a730(0x1d6)][_0x4d06a4(0x205)](),_0x93dd9b=!![]),sessions[_0x75a730(0x1da)](_0xb91102),{'aborted':_0x93dd9b,'hadSession':!![]};}