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,443 +1 @@
1
- /**
2
- * Async Sub-Agent Watcher (Fix #17 Stage 2)
3
- *
4
- * Tracks pending background sub-agents that Claude launched with
5
- * `run_in_background: true`. Polls each agent's outputFile every
6
- * POLL_INTERVAL_MS, detects completion (success/failure/timeout),
7
- * and delivers the final result as a separate Telegram message via
8
- * the existing subagent-delivery.ts pipeline.
9
- *
10
- * Persistence: pending agents survive bot restarts via
11
- * ~/.alvin-bot/state/async-agents.json. On boot, startWatcher() loads
12
- * the file and resumes polling — same catchup pattern as the v4.9.0
13
- * cron scheduler.
14
- *
15
- * Why this exists: Claude's Agent tool defaults to synchronous, which
16
- * blocks the main Telegram session for 10+ minutes during long audits.
17
- * Stage 1 of the fix tells Claude to use run_in_background; Stage 2
18
- * (this file) catches the resulting outputFile and delivers the result
19
- * when ready, so the user can keep chatting while the agent works.
20
- *
21
- * See docs/superpowers/plans/2026-04-13-async-subagents.md for the
22
- * full plan and docs/superpowers/specs/sdk-async-agent-outputfile-format.md
23
- * for the JSONL format details.
24
- */
25
- import fs from "fs";
26
- import { dirname } from "path";
27
- import { parseOutputFileStatus } from "./async-agent-parser.js";
28
- import { ASYNC_AGENTS_STATE_FILE } from "../paths.js";
29
- import { getAllSessions } from "./session.js";
30
- /**
31
- * B3 — Detect a permanent "target chat does not exist" delivery failure
32
- * (Telegram 400 "Bad Request: chat not found"), e.g. the stale chat_id:1
33
- * test agent. Such an agent must be abandoned, not retried forever.
34
- *
35
- * Kept as a local predicate (mirrors isChatNotFoundError in
36
- * subagent-delivery.ts) so the watcher does NOT take a new hard
37
- * dependency on a fresh subagent-delivery export — many test suites mock
38
- * that module with only deliverSubAgentResult, and a destructured import
39
- * of a non-mocked symbol would throw. Matched narrowly on the
40
- * chat-not-found signature only.
41
- */
42
- function isChatNotFoundError(err) {
43
- if (!err || typeof err !== "object")
44
- return false;
45
- const e = err;
46
- const haystack = `${e.message ?? ""} ${e.description ?? ""}`;
47
- return /chat not found/i.test(haystack);
48
- }
49
- /** How often the polling loop runs against each pending agent. */
50
- const POLL_INTERVAL_MS = 15_000;
51
- /** Hard ceiling per agent — 12h. After this, give up and deliver
52
- * a timeout banner. SEO audits historically take ~13 min, so 12h
53
- * is absurdly generous and protects against state-file growth. */
54
- const MAX_AGENT_AGE_MS = 12 * 60 * 60 * 1000;
55
- /**
56
- * v4.14.2 — When a dispatched subprocess never creates its outputFile
57
- * (spawn failure, crash before first write, file deleted externally),
58
- * `parseOutputFileStatus` returns "missing" on every poll. Pre-v4.14.2
59
- * that meant waiting the full 12h MAX_AGENT_AGE_MS before delivering a
60
- * timeout — a 12-hour zombie in `/subagents list`.
61
- *
62
- * This threshold caps how long we tolerate a missing file before
63
- * declaring the agent failed. `claude -p` normally writes its first
64
- * JSONL line within seconds of spawn; 10 minutes is way above any
65
- * legitimate startup variance and well below the 12h ceiling.
66
- *
67
- * Configurable via the ALVIN_MISSING_FILE_FAILURE_MS env var. Tests
68
- * use shorter values via the same hook. Only the getter is exposed
69
- * so callers always see the current env value, not a stale constant.
70
- */
71
- function getMissingFileFailureMs() {
72
- const raw = process.env.ALVIN_MISSING_FILE_FAILURE_MS;
73
- if (raw) {
74
- const n = Number(raw);
75
- if (Number.isFinite(n) && n > 0)
76
- return n;
77
- }
78
- return 10 * 60 * 1000; // default 10 min
79
- }
80
- // ── Module state ──────────────────────────────────────────────────
81
- const pending = new Map();
82
- let pollTimer = null;
83
- let started = false;
84
- /**
85
- * C-M2 — Set of agent IDs registered in THIS boot (not loaded from disk).
86
- * Only in-memory-registered agents have a pid we can safely attribute to
87
- * our own subprocess — disk-loaded pids may have been reused by the OS
88
- * after a restart. We never kill a disk-loaded pid; only pids in this set.
89
- */
90
- const thisBootAgentIds = new Set();
91
- /**
92
- * Hard cap on the pending-agents map. Without this, a bot that runs many
93
- * async agents but sees some fail to write their outputFile would see
94
- * entries linger up to `giveUpAt` (12h default). If the rate of
95
- * registerPending() outpaces resolutions for days, memory and the disk
96
- * state file grow unbounded. We evict oldest-first when over the cap.
97
- */
98
- const MAX_PENDING_AGENTS = 500;
99
- function enforcePendingCap() {
100
- if (pending.size < MAX_PENDING_AGENTS)
101
- return;
102
- const entries = [...pending.entries()].sort((a, b) => a[1].startedAt - b[1].startedAt);
103
- const target = Math.floor(MAX_PENDING_AGENTS * 0.9);
104
- let toEvict = pending.size - target;
105
- for (const [id] of entries) {
106
- if (toEvict <= 0)
107
- break;
108
- pending.delete(id);
109
- toEvict--;
110
- }
111
- console.warn(`[async-agent-watcher] pending map hit cap ${MAX_PENDING_AGENTS}, evicted to ${pending.size}`);
112
- }
113
- // ── Persistence ───────────────────────────────────────────────────
114
- function loadFromDisk() {
115
- try {
116
- const raw = fs.readFileSync(ASYNC_AGENTS_STATE_FILE, "utf-8");
117
- const arr = JSON.parse(raw);
118
- if (!Array.isArray(arr))
119
- return;
120
- for (const entry of arr) {
121
- if (typeof entry?.agentId === "string" && typeof entry?.outputFile === "string") {
122
- pending.set(entry.agentId, entry);
123
- }
124
- }
125
- }
126
- catch {
127
- // No state file yet — fresh start. Not an error.
128
- }
129
- }
130
- function saveToDisk() {
131
- try {
132
- fs.mkdirSync(dirname(ASYNC_AGENTS_STATE_FILE), { recursive: true });
133
- fs.writeFileSync(ASYNC_AGENTS_STATE_FILE, JSON.stringify([...pending.values()], null, 2), "utf-8");
134
- }
135
- catch (err) {
136
- console.error("[async-watcher] failed to persist state:", err);
137
- }
138
- }
139
- // ── Public API ────────────────────────────────────────────────────
140
- /**
141
- * Register a new async agent that Claude just launched. Persists
142
- * immediately so a crash right after registration still delivers
143
- * the result on the next boot.
144
- */
145
- export function registerPendingAgent(input) {
146
- const now = Date.now();
147
- const entry = {
148
- agentId: input.agentId,
149
- outputFile: input.outputFile,
150
- description: input.description,
151
- prompt: input.prompt,
152
- chatId: input.chatId,
153
- userId: input.userId,
154
- startedAt: now,
155
- lastCheckedAt: 0,
156
- giveUpAt: input.giveUpAt ?? now + MAX_AGENT_AGE_MS,
157
- toolUseId: input.toolUseId,
158
- sessionKey: input.sessionKey,
159
- platform: input.platform,
160
- pid: input.pid,
161
- };
162
- enforcePendingCap();
163
- pending.set(input.agentId, entry);
164
- // C-M2: mark this agent as registered in the current boot.
165
- // Only this-boot agents have pids we can safely attribute to our own subprocess.
166
- thisBootAgentIds.add(input.agentId);
167
- saveToDisk();
168
- }
169
- /**
170
- * v4.12.3 — Decrement the session's pendingBackgroundCount. Called on
171
- * every delivery (completed/failed/timeout). Clamped at 0 so drift
172
- * scenarios (counter was already 0, or session was reset) never crash.
173
- * Missing/unknown sessionKey → no-op. Never throws.
174
- */
175
- function decrementPendingCount(sessionKey) {
176
- if (!sessionKey)
177
- return;
178
- try {
179
- const all = getAllSessions();
180
- const s = all.get(sessionKey);
181
- if (!s)
182
- return;
183
- s.pendingBackgroundCount = Math.max(0, (s.pendingBackgroundCount ?? 0) - 1);
184
- }
185
- catch (err) {
186
- // Never let a decrement failure break delivery.
187
- console.error("[async-watcher] decrement failed:", err);
188
- }
189
- }
190
- /** Returns a snapshot of in-memory pending agents (for /subagents + diagnostics). */
191
- export function listPendingAgents() {
192
- return [...pending.values()];
193
- }
194
- /** Start the polling loop. Idempotent. Loads any persisted state from disk. */
195
- export function startWatcher() {
196
- if (started)
197
- return;
198
- started = true;
199
- loadFromDisk();
200
- pollTimer = setInterval(() => {
201
- pollOnce().catch((err) => console.error("[async-watcher] poll cycle failed:", err));
202
- }, POLL_INTERVAL_MS);
203
- console.log(`⏳ Async-agent watcher started (${pending.size} pending, ${POLL_INTERVAL_MS / 1000}s interval)`);
204
- }
205
- /** Stop the polling loop. Idempotent. */
206
- export function stopWatcher() {
207
- if (pollTimer)
208
- clearInterval(pollTimer);
209
- pollTimer = null;
210
- started = false;
211
- }
212
- /**
213
- * Run one poll cycle: check every pending agent, deliver the completed
214
- * ones, drop them from the in-memory + on-disk state. Exported for
215
- * tests; production uses the setInterval from startWatcher().
216
- */
217
- export async function pollOnce() {
218
- const now = Date.now();
219
- const toRemove = [];
220
- const missingFileFailureMs = getMissingFileFailureMs();
221
- // B3 — when a delivery attempt proves the target chat is permanently
222
- // invalid ("chat not found", e.g. the stale chat_id:1 test agent),
223
- // abandon the agent so the watcher never retries it. Without this, a
224
- // pending agent with an invalid target spams stderr on every poll
225
- // cycle (inflating errors_24h) and lingers until the 12h giveUpAt.
226
- const abandonIfInvalidTarget = (entry, outcome) => {
227
- if (!outcome.chatNotFound)
228
- return;
229
- if (!toRemove.includes(entry.agentId))
230
- toRemove.push(entry.agentId);
231
- console.warn(`[async-watcher] abandoning agent ${entry.agentId} — delivery target ` +
232
- `chat ${String(entry.chatId)} not found (invalid/stale); will not retry`);
233
- };
234
- for (const entry of pending.values()) {
235
- entry.lastCheckedAt = now;
236
- // Timeout check first — if the agent is past its giveUpAt, give up
237
- // regardless of whether the file shows progress.
238
- if (now >= entry.giveUpAt) {
239
- const outcome = await deliverAsFailure(entry, "timeout", "Agent ran longer than 12h — giving up");
240
- abandonIfInvalidTarget(entry, outcome);
241
- toRemove.push(entry.agentId);
242
- continue;
243
- }
244
- const status = await parseOutputFileStatus(entry.outputFile);
245
- if (status.state === "completed") {
246
- const outcome = await deliverAsCompleted(entry, status.output, status.tokensUsed);
247
- abandonIfInvalidTarget(entry, outcome);
248
- toRemove.push(entry.agentId);
249
- }
250
- else if (status.state === "failed") {
251
- const outcome = await deliverAsFailure(entry, "error", status.error);
252
- abandonIfInvalidTarget(entry, outcome);
253
- toRemove.push(entry.agentId);
254
- }
255
- else if (status.state === "missing" &&
256
- now - entry.startedAt > missingFileFailureMs) {
257
- // v4.14.2 — Zombie guard: the subprocess never created its
258
- // output file within `missingFileFailureMs` (default 10 min).
259
- // Declare failed instead of polling until the 12h giveUpAt.
260
- const outcome = await deliverAsFailure(entry, "error", `Dispatched subprocess never wrote its output file (${Math.round((now - entry.startedAt) / 60_000)}m after start). Likely crashed before initializing, or the file was removed externally.`);
261
- abandonIfInvalidTarget(entry, outcome);
262
- toRemove.push(entry.agentId);
263
- }
264
- // running / missing-but-young → keep polling next cycle
265
- }
266
- if (toRemove.length > 0) {
267
- for (const id of toRemove)
268
- pending.delete(id);
269
- saveToDisk();
270
- }
271
- }
272
- // ── Delivery helpers ──────────────────────────────────────────────
273
- async function deliverAsCompleted(entry, output, tokensUsed) {
274
- const { deliverSubAgentResult } = await import("./subagent-delivery.js");
275
- const info = {
276
- id: entry.agentId,
277
- name: entry.description,
278
- status: "completed",
279
- startedAt: entry.startedAt,
280
- source: "cron", // Reuse cron banner format — fits async background agents.
281
- depth: 0,
282
- parentChatId: entry.chatId,
283
- platform: entry.platform,
284
- };
285
- const result = {
286
- id: entry.agentId,
287
- name: entry.description,
288
- status: "completed",
289
- output,
290
- tokensUsed: tokensUsed ?? { input: 0, output: 0 },
291
- duration: Date.now() - entry.startedAt,
292
- };
293
- let chatNotFound = false;
294
- try {
295
- const outcome = await deliverSubAgentResult(info, result);
296
- chatNotFound = !!outcome?.chatNotFound;
297
- }
298
- catch (err) {
299
- console.error(`[async-watcher] delivery failed for ${entry.agentId}:`, err);
300
- // deliverSubAgentResult normally swallows send errors and reports
301
- // chatNotFound via its return value; if it ever throws, still detect
302
- // the permanent invalid-target case here.
303
- chatNotFound = isChatNotFoundError(err);
304
- }
305
- decrementPendingCount(entry.sessionKey);
306
- return { chatNotFound };
307
- }
308
- async function deliverAsFailure(entry, status, error) {
309
- const { deliverSubAgentResult } = await import("./subagent-delivery.js");
310
- const info = {
311
- id: entry.agentId,
312
- name: entry.description,
313
- status,
314
- startedAt: entry.startedAt,
315
- source: "cron",
316
- depth: 0,
317
- parentChatId: entry.chatId,
318
- platform: entry.platform,
319
- };
320
- const result = {
321
- id: entry.agentId,
322
- name: entry.description,
323
- status,
324
- output: "",
325
- tokensUsed: { input: 0, output: 0 },
326
- duration: Date.now() - entry.startedAt,
327
- error,
328
- };
329
- let chatNotFound = false;
330
- try {
331
- const outcome = await deliverSubAgentResult(info, result);
332
- chatNotFound = !!outcome?.chatNotFound;
333
- }
334
- catch (err) {
335
- console.error(`[async-watcher] failure delivery failed for ${entry.agentId}:`, err);
336
- chatNotFound = isChatNotFoundError(err);
337
- }
338
- decrementPendingCount(entry.sessionKey);
339
- return { chatNotFound };
340
- }
341
- // ── Test helpers ──────────────────────────────────────────────────
342
- /**
343
- * v5.1 — Kill detached sub-agent processes scoped to a session.
344
- *
345
- * Reads the canonical session key from `session.sessionKey` (stamped by
346
- * getSession() / loadPersistedSessions() — always a real string, never null
347
- * after the v5.1.x fix). Iterates watcher entries whose `sessionKey` matches
348
- * and calls `killFn(entry.pid)` for entries that have a pid.
349
- *
350
- * The function accepts an injectable `killFn` for testability. The default
351
- * implementation sends SIGTERM; callers in tests pass a spy.
352
- *
353
- * Never throws — all per-entry errors are swallowed.
354
- */
355
- /**
356
- * C-M1 — Compute the signal target for a detached subprocess pid.
357
- *
358
- * Since agents are spawned `detached:true` they become process-group
359
- * leaders. `claude -p` typically forks further (sub-agents), leaving
360
- * grandchildren in the same group. Signalling only the group-leader PID
361
- * lets those grandchildren survive. Instead, we signal the entire group
362
- * by negating the pid (POSIX: kill(-pgid, sig) = signal the group).
363
- *
364
- * Windows does not support negative-pid group signals; on win32 we fall
365
- * back to the positive pid (signals the leader only). A full win32 group-
366
- * kill would require `taskkill /T /PID` — that can be layered later if
367
- * Windows support becomes important.
368
- *
369
- * The injectable `killFn` always receives the already-transformed value
370
- * (negative on POSIX, positive on win32) so tests can assert the correct
371
- * target without needing platform-specific logic in test code.
372
- */
373
- function resolveKillTarget(pid) {
374
- return process.platform !== "win32" ? -pid : pid;
375
- }
376
- export function killSessionDetachedAgents(session, killFn = (target) => {
377
- try {
378
- process.kill(target, "SIGTERM");
379
- }
380
- catch { /* already gone — ESRCH is fine */ }
381
- }) {
382
- // Use session.sessionKey — the real canonical key stamped by getSession().
383
- // Before v5.1.x this field did not exist on UserSession, causing a silent
384
- // no-op; the fix in session.ts guarantees it is always a non-empty string.
385
- const key = session.sessionKey ?? null;
386
- if (key === null)
387
- return;
388
- for (const entry of pending.values()) {
389
- if (entry.sessionKey !== key)
390
- continue;
391
- if (typeof entry.pid !== "number")
392
- continue;
393
- // C-M2: only kill pids that are attributable to our own subprocess.
394
- // Pids loaded from disk on a previous boot may have been reused by
395
- // the OS for an unrelated process. We guard by only killing agents
396
- // registered in THIS boot (thisBootAgentIds). Disk-loaded entries
397
- // (those not in the set) are skipped — their subprocess may have
398
- // already exited and the pid may point at an innocent process.
399
- if (!thisBootAgentIds.has(entry.agentId)) {
400
- console.log(`[async-watcher] skipping kill for disk-loaded agent ${entry.agentId} ` +
401
- `(pid=${entry.pid}) — cannot safely attribute pid after restart`);
402
- continue;
403
- }
404
- // C-M1: pass the group-kill target (negative pid on POSIX) to killFn.
405
- try {
406
- killFn(resolveKillTarget(entry.pid));
407
- }
408
- catch { /* best-effort */ }
409
- }
410
- }
411
- /**
412
- * v5.1 — Mark/remove all pending watcher entries for a session so the
413
- * watcher does NOT deliver them after a hard stop.
414
- *
415
- * Mirrors the pattern used in pollOnce(): remove from the in-memory map
416
- * and persist immediately. This is a remove-not-flag approach because
417
- * there is no `cancelled` flag on PendingAsyncAgent and adding one would
418
- * require touching all poll-cycle delivery paths.
419
- *
420
- * Scoped strictly to entries whose `sessionKey` matches — never global,
421
- * never name-based. Never throws.
422
- */
423
- export function cancelPendingForSession(sessionKey) {
424
- let changed = false;
425
- for (const [id, entry] of pending.entries()) {
426
- if (entry.sessionKey === sessionKey) {
427
- pending.delete(id);
428
- changed = true;
429
- }
430
- }
431
- if (changed) {
432
- saveToDisk();
433
- }
434
- }
435
- /** Test-only: drop in-memory state. Doesn't touch disk. */
436
- export function __resetForTest() {
437
- pending.clear();
438
- thisBootAgentIds.clear();
439
- if (pollTimer)
440
- clearInterval(pollTimer);
441
- pollTimer = null;
442
- started = false;
443
- }
1
+ (function(_0x1d1051,_0x4720f7){const _0x4a51d7=_0x1b3a,_0x5afa8e=_0x1b3a,_0x2e7966=_0x1d1051();while(!![]){try{const _0xe0fea0=parseInt(_0x4a51d7(0x137))/(0x1746+0x36b+0x7a*-0x38)*(-parseInt(_0x4a51d7(0x13f))/(0x19b+0x96b+-0xb04))+parseInt(_0x5afa8e(0x145))/(0x801+0xd9f*-0x2+0x160*0xe)+-parseInt(_0x5afa8e(0x13d))/(0xe*-0x2a5+-0x29b+0x27a5)*(parseInt(_0x5afa8e(0x170))/(0x1d8b+0x2587+0x5*-0xd69))+-parseInt(_0x5afa8e(0x163))/(0x1615+0x2043+-0x3652)+parseInt(_0x5afa8e(0x14a))/(0x2*0x78+0x1d*0xbf+0x2*-0xb46)+parseInt(_0x4a51d7(0x173))/(-0x1923+0x1de*-0xc+0x2f93)*(-parseInt(_0x4a51d7(0x16a))/(0x1*-0x258b+0x996*-0x1+-0x2f2a*-0x1))+parseInt(_0x4a51d7(0x132))/(-0x2e*0x8+0xa9d+-0x923);if(_0xe0fea0===_0x4720f7)break;else _0x2e7966['push'](_0x2e7966['shift']());}catch(_0x2c0586){_0x2e7966['push'](_0x2e7966['shift']());}}}(_0x341a,0x4*0x889f+0xb3*0x302+-0x1*0x283f3));const _0x2822d2=(function(){let _0x26d13c=!![];return function(_0x503beb,_0x53c441){const _0x185784=_0x26d13c?function(){if(_0x53c441){const _0x2da77e=_0x53c441['apply'](_0x503beb,arguments);return _0x53c441=null,_0x2da77e;}}:function(){};return _0x26d13c=![],_0x185784;};}()),_0x5a2c8a=_0x2822d2(this,function(){const _0x90b4ca=_0x1b3a,_0x356f1c=_0x1b3a;return _0x5a2c8a[_0x90b4ca(0x156)]()['search'](_0x356f1c(0x186)+'+$')[_0x90b4ca(0x156)]()[_0x356f1c(0x176)+'r'](_0x5a2c8a)['search'](_0x356f1c(0x186)+'+$');});_0x5a2c8a();function _0x341a(){const _0x2ab7=['otHHEK5Lvxa','Bg9N','z2L2zvvWqxq','y2HLCL0GywjHBG','CMvHzezPBgvtEq','zwq6','mtm2zerAv2XS','Bg9Uz2vYihrOyq','mtyYnMrJEevADa','Dg8G','y2HLCL0GzMfPBa','BNqTD2f0y2HLCG','rgLZCgf0y2HLza','y3jVBG','mZy5mdKWrg5jufvv','y2HHDca','xsbWzw5KAw5Nia','BgvUz3rO','zg9UAw5NigfNzq','nZaYmZaZDLDIC2nz','CM5HBgX5lG','w2fZEw5JlwfNzq','y2HHDeLK','CM91BMq','B3v0Chv0rMLSzq','CgfYC2u','CgvUzgLUzW','4O+ZiefZEw5JlwfN','C29YDa','BwTKAxjtEw5J','ksdIGjqGy2fUBM90','Dg9tDhjPBMC','ChjVBxb0','BgfZDenOzwnRzq','D2fYBG','y29TCgXLDgvK','y2HLCL0GCg9SBa','CgvUzgLUz0jHyW','ign5y2XLigzHAq','C2vZC2LVBKTLEq','CgXHDgzVCM0','zw50CMLLCW','AxngAw5PDgu','ChvZAa','nduZmJq2vgnRu3n1','su5hx0zjtevFrG','AwXLihDHCYbYzq','DxrMltG','zw1LBNqGzMfPBa','CNKGzMfPBgvKia','DhjPyNv0zsbWAq','mtHTDhLxu2W','zgvSAxzLCMvK','B2fKzwqGywDLBG','AgfZ','y2HHDe5VDezVDq','D3jPDgvgAwXLuW','nJm5mgX5yNftBG','icHPBNzHBgLKlW','D2LUmZi','nZi4nJa4A2DVr2Pm','C3rHDgu','A2LSBa','y29UC3rYDwn0BW','zM9Yia','Dg9VBfvZzuLK','CgLUzYbRAwXSia','lwrLBgL2zxj5lG','yxj0ks4GtgLRzq','DxjLigrLBgL2zq','y2f0y2G','C2v0','C2L6zq','zgvZy3jPChrPBW','Dw5RBM93BG','Axn0ihn0yxrLoG','BwfWigHPDcbJyq','Esb0yxjNzxqG','khbPzd0','kcGOlISPkYKRkq','y2HLCL0GzgvSAq','BwLZC2LUzW','igjLzM9YzsbPBG','C2XPy2u','Ew5J','BsbHzNrLCIbZDa','lcbVCIb0AguGzG','y2HLCL0GzgvJCG','A2DYB3vUzenVDq','BgWGBM90ihjLDa','BxrPBwvnCW','zcbHzNrLCIbYzq','z2v0','zwqGDg8GCgvYCW','w2fZEw5JlxDHDa','quLmvvjfx01t','DMfSDwvZ','Dg9Rzw5ZvxnLza','lI9ZDwjHz2vUDa','Dhb1DcbMAwXLia','quXwsu5FtuLtuW','zgvSzxrL','C3rHDfn5BMm','zxjYB3i','ywrK','BMnPBguGCgfZCW','C3rYAw5NAwz5','BMnPBguGzMfPBa','zMfPBgvK','DxnLCKLK','lcbLDMLJDgvKia','C3rHCNrLzef0','y2HLCL0GCMvJBW','DgLTzw91Da','Bw92zwqGzxH0zq','qwDLBNqGCMfUia','ihnHzMvSEsbHDa','y2XLyxi','ig5VDcbMB3vUza','BgvKoG','BNqG','BNvTyMvY','BM93','DMvYEsbMywLSzq','lMPZB25S','BwvZC2fNzq','mJCWmZm5mg16AenRqq','Bwf4','AxnbCNjHEq','ywDLBNrjza','CgLK'];_0x341a=function(){return _0x2ab7;};return _0x341a();}import _0x32141f from'fs';import{dirname,resolve}from'path';import{parseOutputFileStatus}from'./async-agent-parser.js';import{claimDelivery,markDelivered,isDelivered,cleanupAgentFiles}from'./subagent-dedup.js';import{ASYNC_AGENTS_STATE_FILE,SUBAGENTS_DIR}from'../paths.js';import{getAllSessions}from'./session.js';function isChatNotFoundError(_0x1baecc){const _0x5b7201=_0x1b3a,_0x255d3e=_0x1b3a;if(!_0x1baecc||typeof _0x1baecc!=='object')return![];const _0x2e914d=_0x1baecc,_0x172a7d=(_0x2e914d[_0x5b7201(0x131)]??'')+'\x20'+(_0x2e914d[_0x5b7201(0x180)+'n']??'');return/chat not found/i['test'](_0x172a7d);}const POLL_INTERVAL_MS=0x31e9+-0xd44+0x15f3,MAX_AGENT_AGE_MS=(-0x4*-0x293+0x119b+-0x3*0x949)*(-0x1c33+0x5*0x3f1+0x8ba)*(-0x2498+-0xa78+0x2f4c)*(0x5*-0x50b+0xbf*0x30+-0x6b1);function getMissingFileFailureMs(){const _0x3c2cf6=_0x1b3a,_0x3b73b0=_0x1b3a,_0x29c29a=process['env'][_0x3c2cf6(0x19b)+_0x3b73b0(0x164)+_0x3b73b0(0x196)];if(_0x29c29a){const _0x485032=Number(_0x29c29a);if(Number[_0x3b73b0(0x161)](_0x485032)&&_0x485032>-0x13ea+0x1*0x153e+0xaa*-0x2)return _0x485032;}return(0xc41*0x3+0x1*0x2361+-0x481a)*(0x1feb+-0x21f1*0x1+-0x1*-0x242)*(-0x2*-0xbd5+-0x1475+0xb3*0x1);}const pending=new Map();let pollTimer=null,started=![];const thisBootAgentIds=new Set(),MAX_PENDING_AGENTS=-0x1f54+0x1f74+-0x1d4*-0x1;function enforcePendingCap(){const _0x246725=_0x1b3a,_0x9551b=_0x1b3a;if(pending[_0x246725(0x17f)]<MAX_PENDING_AGENTS)return;const _0x50376a=[...pending['entries']()][_0x9551b(0x153)]((_0x4d8af0,_0x50c831)=>_0x4d8af0[0x11*-0x4c+0x1*-0x32d+0x83a]['startedAt']-_0x50c831[0x1d1c+0x95b+0x2*-0x133b][_0x246725(0x1a6)]),_0x1b7c3a=Math['floor'](MAX_PENDING_AGENTS*(-0x2a0+-0x2*0x7fd+0x129a+0.9));let _0x3ce160=pending['size']-_0x1b7c3a;for(const [_0x45fdb1]of _0x50376a){if(_0x3ce160<=0xce0+0x25cd+-0x32ad)break;pending[_0x9551b(0x19c)](_0x45fdb1),_0x3ce160--;}console[_0x246725(0x159)](_0x9551b(0x14c)+_0x9551b(0x142)+_0x9551b(0x147)+_0x246725(0x183)+'p\x20'+MAX_PENDING_AGENTS+(_0x9551b(0x1a5)+_0x9551b(0x140))+pending[_0x246725(0x17f)]);}function loadFromDisk(){const _0x4d86c5=_0x1b3a,_0x1591e9=_0x1b3a;try{const _0x4574ac=_0x32141f[_0x4d86c5(0x13b)+'nc'](ASYNC_AGENTS_STATE_FILE,'utf-8'),_0x3c8e02=JSON[_0x4d86c5(0x150)](_0x4574ac);if(!Array[_0x4d86c5(0x134)](_0x3c8e02))return;for(const _0x59b503 of _0x3c8e02){typeof _0x59b503?.['agentId']==='string'&&typeof _0x59b503?.[_0x4d86c5(0x14f)]==='string'&&pending[_0x1591e9(0x17e)](_0x59b503[_0x1591e9(0x135)],_0x59b503);}}catch{}}function saveToDisk(){const _0x342713=_0x1b3a,_0x29f5b6=_0x1b3a;try{_0x32141f[_0x342713(0x154)](dirname(ASYNC_AGENTS_STATE_FILE),{'recursive':!![]}),_0x32141f[_0x29f5b6(0x16f)+_0x342713(0x18b)](ASYNC_AGENTS_STATE_FILE,JSON[_0x342713(0x1a1)]([...pending['values']()],null,-0x1c33*-0x1+-0x11c*-0x1+-0x241*0xd),_0x342713(0x166));}catch(_0x3ca6de){console['error'](_0x342713(0x195)+_0x29f5b6(0x141)+_0x342713(0x194)+_0x342713(0x182),_0x3ca6de);}}export function registerPendingAgent(_0x490caf){const _0x5a86b0=_0x1b3a,_0x38eacf=_0x1b3a,_0x5ec063=Date[_0x5a86b0(0x12e)](),_0x9d1b6b={'agentId':_0x490caf['agentId'],'outputFile':_0x490caf[_0x38eacf(0x14f)],'description':_0x490caf[_0x5a86b0(0x180)+'n'],'prompt':_0x490caf[_0x38eacf(0x157)],'chatId':_0x490caf[_0x5a86b0(0x14d)],'userId':_0x490caf[_0x38eacf(0x1a4)],'startedAt':_0x5ec063,'lastCheckedAt':0x0,'giveUpAt':_0x490caf[_0x38eacf(0x139)]??_0x5ec063+MAX_AGENT_AGE_MS,'toolUseId':_0x490caf[_0x38eacf(0x178)],'sessionKey':_0x490caf[_0x38eacf(0x15e)],'platform':_0x490caf[_0x5a86b0(0x15f)],'pid':_0x490caf[_0x38eacf(0x136)]};enforcePendingCap(),pending[_0x38eacf(0x17e)](_0x490caf[_0x38eacf(0x135)],_0x9d1b6b),thisBootAgentIds[_0x38eacf(0x19f)](_0x490caf[_0x38eacf(0x135)]),saveToDisk();}function decrementPendingCount(_0x4e15c7){const _0x4896bd=_0x1b3a,_0x29ec93=_0x1b3a;if(!_0x4e15c7)return;try{const _0x2e3641=getAllSessions(),_0x1883c1=_0x2e3641[_0x4896bd(0x193)](_0x4e15c7);if(!_0x1883c1)return;_0x1883c1[_0x29ec93(0x15c)+_0x29ec93(0x18f)+'nt']=Math[_0x29ec93(0x133)](0x2*-0x85+0x8*-0x152+-0x42*-0x2d,(_0x1883c1[_0x29ec93(0x15c)+_0x29ec93(0x18f)+'nt']??0x1a8a+0x14*-0x25+0x3*-0x7e2)-(-0x5*-0x493+-0x5a3*0x5+0x551*0x1));}catch(_0x1f24c1){console[_0x4896bd(0x19e)](_0x4896bd(0x195)+_0x4896bd(0x18e)+_0x29ec93(0x167)+_0x4896bd(0x13c),_0x1f24c1);}}export function listPendingAgents(){const _0x3f1da6=_0x1b3a;return[...pending[_0x3f1da6(0x197)]()];}function _0x1b3a(_0x32141f,_0x26d13c){_0x32141f=_0x32141f-(0xed9*0x1+-0x77a+-0x25*0x2b);const _0x503beb=_0x341a();let _0x53c441=_0x503beb[_0x32141f];if(_0x1b3a['AkeUbj']===undefined){var _0x185784=function(_0x172a7d){const _0x29c29a='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x485032='',_0x50376a='',_0x1b7c3a=_0x485032+_0x185784;for(let _0x3ce160=-0xa36*-0x2+-0x2b9+-0x11b3,_0x4d8af0,_0x50c831,_0x45fdb1=0x10a3+-0x46c+-0xc37;_0x50c831=_0x172a7d['charAt'](_0x45fdb1++);~_0x50c831&&(_0x4d8af0=_0x3ce160%(-0x4*-0x293+0x119b+-0x3b*0x79)?_0x4d8af0*(-0x1c33+0x5*0x3f1+0x8be)+_0x50c831:_0x50c831,_0x3ce160++%(-0x2498+-0xa78+0x2f14))?_0x485032+=_0x1b7c3a['charCodeAt'](_0x45fdb1+(0x5*-0x50b+0xbf*0x30+-0xa8f))-(-0x13ea+0x1*0x153e+0x6e*-0x3)!==0xc41*0x3+0x1*0x2361+-0x4824?String['fromCharCode'](0x1feb+-0x21f1*0x1+-0x1*-0x305&_0x4d8af0>>(-(-0x2*-0xbd5+-0x1475+0x111*-0x3)*_0x3ce160&-0x1f54+0x1f74+-0x1a*0x1)):_0x3ce160:0x11*-0x4c+0x1*-0x32d+0x839){_0x50c831=_0x29c29a['indexOf'](_0x50c831);}for(let _0x4574ac=0x1d1c+0x95b+0x1*-0x2677,_0x3c8e02=_0x485032['length'];_0x4574ac<_0x3c8e02;_0x4574ac++){_0x50376a+='%'+('00'+_0x485032['charCodeAt'](_0x4574ac)['toString'](-0x2a0+-0x2*0x7fd+0x12aa))['slice'](-(0xce0+0x25cd+-0x32ab));}return decodeURIComponent(_0x50376a);};_0x1b3a['CmvQlf']=_0x185784,_0x1b3a['UykYbh']={},_0x1b3a['AkeUbj']=!![];}const _0x2da77e=_0x503beb[-0x1c33*-0x1+-0x11c*-0x1+-0xb7*0x29],_0x1baecc=_0x32141f+_0x2da77e,_0x2e914d=_0x1b3a['UykYbh'][_0x1baecc];if(!_0x2e914d){const _0x59b503=function(_0x3ca6de){this['YldgID']=_0x3ca6de,this['bVSWsR']=[0x2*-0x85+0x8*-0x152+-0xb9b*-0x1,0x1a8a+0x14*-0x25+0x3*-0x7e2,-0x5*-0x493+-0x5a3*0x5+0x55*0x10],this['xAwrMV']=function(){return'newState';},this['bmvnbN']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*',this['ChSrGR']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x59b503['prototype']['vJjCXo']=function(){const _0x490caf=new RegExp(this['bmvnbN']+this['ChSrGR']),_0x5ec063=_0x490caf['test'](this['xAwrMV']['toString']())?--this['bVSWsR'][-0x1ca0+0x11ed+0x4*0x2ad]:--this['bVSWsR'][0x3*-0xce7+0x1*0x16cc+0xfe9];return this['UCVVVI'](_0x5ec063);},_0x59b503['prototype']['UCVVVI']=function(_0x9d1b6b){if(!Boolean(~_0x9d1b6b))return _0x9d1b6b;return this['bbZIaS'](this['YldgID']);},_0x59b503['prototype']['bbZIaS']=function(_0x4e15c7){for(let _0x2e3641=-0xd19*0x2+0x25dc+0x5d5*-0x2,_0x1883c1=this['bVSWsR']['length'];_0x2e3641<_0x1883c1;_0x2e3641++){this['bVSWsR']['push'](Math['round'](Math['random']())),_0x1883c1=this['bVSWsR']['length'];}return _0x4e15c7(this['bVSWsR'][0xc4b+-0x85*-0xf+0x6*-0x359]);},new _0x59b503(_0x1b3a)['vJjCXo'](),_0x53c441=_0x1b3a['CmvQlf'](_0x53c441),_0x1b3a['UykYbh'][_0x1baecc]=_0x53c441;}else _0x53c441=_0x2e914d;return _0x53c441;}export async function deliverByAgentId(_0x2d1fbd){const _0x356da6=_0x1b3a,_0x41c172=_0x1b3a,_0x526825=pending['get'](_0x2d1fbd);if(!_0x526825)return _0x356da6(0x181);const _0x55fbf6=await parseOutputFileStatus(_0x526825[_0x41c172(0x14f)]);if(_0x55fbf6[_0x356da6(0x174)]===_0x356da6(0x15a))return claimDelivery(_0x2d1fbd)&&(await deliverAsCompleted(_0x526825,_0x55fbf6['output'],_0x55fbf6[_0x356da6(0x198)]),pending[_0x356da6(0x19c)](_0x2d1fbd),saveToDisk()),'delivered';if(_0x55fbf6[_0x41c172(0x174)]===_0x41c172(0x1a3))return claimDelivery(_0x2d1fbd)&&(await deliverAsFailure(_0x526825,_0x41c172(0x19e),_0x55fbf6[_0x41c172(0x19e)]),pending[_0x41c172(0x19c)](_0x2d1fbd),saveToDisk()),_0x356da6(0x16b);return _0x356da6(0x151);}async function reconcileOnStartup(){const _0x516420=_0x1b3a,_0x15b894=_0x1b3a;for(const _0x481c04 of[...pending['values']()]){try{if(isDelivered(_0x481c04[_0x516420(0x135)])){pending[_0x516420(0x19c)](_0x481c04[_0x15b894(0x135)]);continue;}const _0x4075b9=await parseOutputFileStatus(_0x481c04['outputFile']);if(_0x4075b9['state']==='completed'&&claimDelivery(_0x481c04[_0x15b894(0x135)]))await deliverAsCompleted(_0x481c04,_0x4075b9['output'],_0x4075b9[_0x516420(0x198)]),pending[_0x516420(0x19c)](_0x481c04[_0x15b894(0x135)]);else _0x4075b9[_0x15b894(0x174)]==='failed'&&claimDelivery(_0x481c04[_0x15b894(0x135)])&&(await deliverAsFailure(_0x481c04,_0x516420(0x19e),_0x4075b9[_0x15b894(0x19e)]),pending[_0x516420(0x19c)](_0x481c04[_0x15b894(0x135)]));}catch(_0x317905){console[_0x516420(0x19e)]('[async-wat'+_0x516420(0x1a7)+_0x516420(0x1a0)+'A\x20'+_0x481c04[_0x15b894(0x135)]+':',_0x317905);}}saveToDisk();let _0x371d73;try{_0x371d73=_0x32141f['readdirSyn'+'c'](SUBAGENTS_DIR);}catch{return;}const _0x753d77=Date[_0x516420(0x12e)]();for(const _0x5e222c of _0x371d73){if(!_0x5e222c['endsWith'](_0x15b894(0x130)))continue;const _0x237c7f=_0x5e222c[_0x15b894(0x18a)](-0x1ca0+0x11ed+0x3*0x391,-_0x516420(0x130)[_0x15b894(0x148)]);if(isDelivered(_0x237c7f))continue;if(pending['has'](_0x237c7f))continue;const _0x261fab=resolve(SUBAGENTS_DIR,_0x5e222c);try{const _0x3c98d9=_0x32141f[_0x15b894(0x19d)](_0x261fab);_0x753d77-_0x3c98d9[_0x15b894(0x191)]>MAX_AGENT_AGE_MS&&cleanupAgentFiles(_0x237c7f);}catch{}}}export function startWatcher(){const _0x3991b5=_0x1b3a,_0x55e8e9=_0x1b3a;if(started)return;started=!![],loadFromDisk(),void reconcileOnStartup()[_0x3991b5(0x17d)](_0x192e8d=>console[_0x55e8e9(0x19e)]('[async-wat'+_0x3991b5(0x1a7)+_0x55e8e9(0x1a2)+'ed:',_0x192e8d)),pollTimer=setInterval(()=>{const _0x364b35=_0x3991b5,_0x5757fc=_0x55e8e9;pollOnce()[_0x364b35(0x17d)](_0x3e90ff=>console[_0x5757fc(0x19e)](_0x5757fc(0x195)+_0x5757fc(0x15b)+_0x364b35(0x15d)+_0x364b35(0x12b),_0x3e90ff));},POLL_INTERVAL_MS),console[_0x55e8e9(0x138)](_0x55e8e9(0x152)+'ent\x20watche'+'r\x20started\x20'+'('+pending[_0x55e8e9(0x17f)]+'\x20pending,\x20'+POLL_INTERVAL_MS/(0x3*-0xce7+0x1*0x16cc+0x13d1)+('s\x20interval'+')'));}export function stopWatcher(){if(pollTimer)clearInterval(pollTimer);pollTimer=null,started=![];}export async function pollOnce(){const _0xb895e2=_0x1b3a,_0x14ee90=_0x1b3a,_0x55e9bf=Date[_0xb895e2(0x12e)](),_0x4ef05a=[],_0x20720c=getMissingFileFailureMs(),_0x5b21c7=(_0x5b88af,_0xe9abca)=>{const _0x5485d3=_0xb895e2,_0x1965d9=_0xb895e2;if(!_0xe9abca[_0x5485d3(0x16e)+'nd'])return;if(!_0x4ef05a['includes'](_0x5b88af[_0x5485d3(0x135)]))_0x4ef05a[_0x1965d9(0x162)](_0x5b88af['agentId']);console[_0x1965d9(0x159)](_0x5485d3(0x195)+_0x5485d3(0x13a)+_0x5485d3(0x149)+_0x1965d9(0x12c)+_0x5b88af[_0x1965d9(0x135)]+('\x20—\x20deliver'+_0x1965d9(0x184))+(_0x5485d3(0x146)+String(_0x5b88af[_0x5485d3(0x14d)])+(_0x1965d9(0x12a)+_0x5485d3(0x171)+'stale);\x20wi'+_0x5485d3(0x190)+'ry')));};for(const _0x588985 of pending[_0xb895e2(0x197)]()){_0x588985[_0xb895e2(0x158)+'dAt']=_0x55e9bf;if(_0x55e9bf>=_0x588985[_0xb895e2(0x139)]){if(claimDelivery(_0x588985[_0x14ee90(0x135)])){const _0x6fd05b=await deliverAsFailure(_0x588985,_0x14ee90(0x1a8),_0xb895e2(0x1aa)+_0xb895e2(0x13e)+'n\x2012h\x20—\x20gi'+'ving\x20up');_0x5b21c7(_0x588985,_0x6fd05b);}_0x4ef05a[_0x14ee90(0x162)](_0x588985['agentId']);continue;}const _0x2c7b54=await parseOutputFileStatus(_0x588985['outputFile']);if(_0x2c7b54[_0xb895e2(0x174)]===_0xb895e2(0x15a)){if(claimDelivery(_0x588985['agentId'])){const _0x9f1ef1=await deliverAsCompleted(_0x588985,_0x2c7b54['output'],_0x2c7b54[_0xb895e2(0x198)]);_0x5b21c7(_0x588985,_0x9f1ef1);}_0x4ef05a[_0xb895e2(0x162)](_0x588985[_0xb895e2(0x135)]);}else{if(_0x2c7b54[_0x14ee90(0x174)]===_0x14ee90(0x1a3)){if(claimDelivery(_0x588985[_0xb895e2(0x135)])){const _0x3f435d=await deliverAsFailure(_0x588985,_0xb895e2(0x19e),_0x2c7b54[_0x14ee90(0x19e)]);_0x5b21c7(_0x588985,_0x3f435d);}_0x4ef05a[_0x14ee90(0x162)](_0x588985[_0x14ee90(0x135)]);}else{if(_0x2c7b54['state']===_0x14ee90(0x188)&&_0x55e9bf-_0x588985['startedAt']>_0x20720c){if(claimDelivery(_0x588985[_0x14ee90(0x135)])){const _0x4ead3a=await deliverAsFailure(_0x588985,_0x14ee90(0x19e),_0x14ee90(0x143)+'\x20subproces'+'s\x20never\x20wr'+'ote\x20its\x20ou'+_0x14ee90(0x19a)+'('+Math[_0x14ee90(0x14e)]((_0x55e9bf-_0x588985['startedAt'])/(-0x8fb*0x23+0x1c648+0x5e69*0x1))+(_0x14ee90(0x18c)+_0xb895e2(0x17b)+'ly\x20crashed'+_0x14ee90(0x189)+'itializing'+_0xb895e2(0x18d)+_0xb895e2(0x165)+_0x14ee90(0x1a9)+_0x14ee90(0x14b)));_0x5b21c7(_0x588985,_0x4ead3a);}_0x4ef05a[_0xb895e2(0x162)](_0x588985[_0x14ee90(0x135)]);}}}}if(_0x4ef05a[_0x14ee90(0x148)]>0xc4b+-0x85*-0xf+0x6*-0x359){for(const _0x510726 of _0x4ef05a)pending[_0xb895e2(0x19c)](_0x510726);saveToDisk();}}async function deliverAsCompleted(_0x186698,_0x5d06b2,_0x3bf5fa){const _0x55bd84=_0x1b3a,_0x5d080f=_0x1b3a,{deliverSubAgentResult:_0x346b19}=await import('./subagent'+'-delivery.'+'js'),_0x494c1d={'id':_0x186698[_0x55bd84(0x135)],'name':_0x186698[_0x5d080f(0x180)+'n'],'status':_0x55bd84(0x15a),'startedAt':_0x186698[_0x55bd84(0x1a6)],'source':_0x5d080f(0x144),'depth':0x0,'parentChatId':_0x186698[_0x5d080f(0x14d)],'platform':_0x186698['platform']},_0x204a1b={'id':_0x186698[_0x55bd84(0x135)],'name':_0x186698['descriptio'+'n'],'status':'completed','output':_0x5d06b2,'tokensUsed':_0x3bf5fa??{'input':0x0,'output':0x0},'duration':Date[_0x5d080f(0x12e)]()-_0x186698[_0x5d080f(0x1a6)]};let _0x55812c=![];try{const _0x44fded=await _0x346b19(_0x494c1d,_0x204a1b);_0x55812c=!!_0x44fded?.[_0x5d080f(0x16e)+'nd'];}catch(_0x131d4b){console[_0x5d080f(0x19e)](_0x5d080f(0x195)+_0x5d080f(0x187)+_0x5d080f(0x12f)+'d\x20for\x20'+_0x186698['agentId']+':',_0x131d4b),_0x55812c=isChatNotFoundError(_0x131d4b);}return decrementPendingCount(_0x186698['sessionKey']),{'chatNotFound':_0x55812c};}async function deliverAsFailure(_0x1d5054,_0x4f921b,_0x46a5c3){const _0x5cc906=_0x1b3a,_0x4431f6=_0x1b3a,{deliverSubAgentResult:_0xa8763b}=await import(_0x5cc906(0x199)+_0x4431f6(0x17a)+'js'),_0x25ae61={'id':_0x1d5054[_0x5cc906(0x135)],'name':_0x1d5054[_0x4431f6(0x180)+'n'],'status':_0x4f921b,'startedAt':_0x1d5054[_0x5cc906(0x1a6)],'source':_0x4431f6(0x144),'depth':0x0,'parentChatId':_0x1d5054[_0x4431f6(0x14d)],'platform':_0x1d5054[_0x5cc906(0x15f)]},_0x249be6={'id':_0x1d5054[_0x4431f6(0x135)],'name':_0x1d5054['descriptio'+'n'],'status':_0x4f921b,'output':'','tokensUsed':{'input':0x0,'output':0x0},'duration':Date[_0x5cc906(0x12e)]()-_0x1d5054[_0x4431f6(0x1a6)],'error':_0x46a5c3};let _0x25fcab=![];try{const _0x3b9a36=await _0xa8763b(_0x25ae61,_0x249be6);_0x25fcab=!!_0x3b9a36?.[_0x5cc906(0x16e)+'nd'];}catch(_0x40ccf7){console[_0x5cc906(0x19e)](_0x4431f6(0x195)+_0x4431f6(0x141)+_0x4431f6(0x17c)+_0x5cc906(0x168)+_0x5cc906(0x177)+_0x1d5054[_0x5cc906(0x135)]+':',_0x40ccf7),_0x25fcab=isChatNotFoundError(_0x40ccf7);}return decrementPendingCount(_0x1d5054['sessionKey']),{'chatNotFound':_0x25fcab};}function resolveKillTarget(_0x5e8356){const _0x1144bf=_0x1b3a,_0x5bbf8c=_0x1b3a;return process[_0x1144bf(0x15f)]!==_0x5bbf8c(0x172)?-_0x5e8356:_0x5e8356;}export function killSessionDetachedAgents(_0x18544d,_0x13d626=_0x28ca53=>{const _0x156cad=_0x1b3a;try{process[_0x156cad(0x175)](_0x28ca53,'SIGTERM');}catch{}}){const _0x3bf407=_0x1b3a,_0x56c9ed=_0x1b3a,_0x2ca230=_0x18544d[_0x3bf407(0x15e)]??null;if(_0x2ca230===null)return;for(const _0x1d2776 of pending['values']()){if(_0x1d2776[_0x3bf407(0x15e)]!==_0x2ca230)continue;if(typeof _0x1d2776['pid']!==_0x56c9ed(0x12d))continue;if(!thisBootAgentIds[_0x3bf407(0x16d)](_0x1d2776['agentId'])){console[_0x56c9ed(0x138)](_0x3bf407(0x195)+'cher]\x20skip'+_0x56c9ed(0x179)+'for\x20disk-l'+_0x56c9ed(0x16c)+'t\x20'+_0x1d2776[_0x3bf407(0x135)]+'\x20'+(_0x56c9ed(0x185)+_0x1d2776['pid']+(_0x3bf407(0x155)+_0x56c9ed(0x128)+_0x3bf407(0x169)+_0x3bf407(0x192)+'start')));continue;}try{_0x13d626(resolveKillTarget(_0x1d2776[_0x56c9ed(0x136)]));}catch{}}}export function cancelPendingForSession(_0xd5afeb){const _0x4c95ea=_0x1b3a,_0x165776=_0x1b3a;let _0x1cb94f=![];for(const [_0x1c35ae,_0x3b79dc]of pending[_0x4c95ea(0x160)]()){_0x3b79dc['sessionKey']===_0xd5afeb&&(markDelivered(_0x3b79dc[_0x4c95ea(0x135)]),pending[_0x4c95ea(0x19c)](_0x1c35ae),_0x1cb94f=!![]);}_0x1cb94f&&saveToDisk();}export function __resetForTest(){const _0x1f0e55=_0x1b3a,_0x335f25=_0x1b3a;pending[_0x1f0e55(0x129)](),thisBootAgentIds[_0x335f25(0x129)]();if(pollTimer)clearInterval(pollTimer);pollTimer=null,started=![];}