@poolzin/pool-bot 2026.4.37 → 2026.4.39

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2026.4.37",
3
- "commit": "10cf8ee6ea482359cdb4eb35103b39d6e2f10a55",
4
- "builtAt": "2026-04-07T16:52:50.808Z"
2
+ "version": "2026.4.39",
3
+ "commit": "2ad61e6591b10f1337044aba4b549dc434af2593",
4
+ "builtAt": "2026-04-07T18:45:57.845Z"
5
5
  }
@@ -1 +1 @@
1
- {"version":3,"file":"doctor-config-flow.d.ts","sourceRoot":"","sources":["../../src/commands/doctor-config-flow.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAYzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AA4tB1D,wBAAsB,+BAA+B,CAAC,MAAM,EAAE;IAC5D,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,EAAE,CAAC,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9E;;;;;GAmLA"}
1
+ {"version":3,"file":"doctor-config-flow.d.ts","sourceRoot":"","sources":["../../src/commands/doctor-config-flow.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAYzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AA6tB1D,wBAAsB,+BAA+B,CAAC,MAAM,EAAE;IAC5D,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,EAAE,CAAC,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9E;;;;;GAmLA"}
@@ -221,6 +221,7 @@ async function maybeRepairTelegramAllowFromUsernames(cfg) {
221
221
  }
222
222
  const tokens = Array.from(new Set(listTelegramAccountIds(cfg)
223
223
  .map((accountId) => resolveTelegramAccount({ cfg, accountId }))
224
+ .filter((account) => account != null)
224
225
  .map((account) => (account.tokenSource === "none" ? "" : account.token))
225
226
  .map((token) => token.trim())
226
227
  .filter(Boolean)));
@@ -1 +1 @@
1
- {"version":3,"file":"doctor-security.d.ts","sourceRoot":"","sources":["../../src/commands/doctor-security.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAmB,MAAM,qBAAqB,CAAC;AAO1E,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,aAAa,iBAsK5D"}
1
+ {"version":3,"file":"doctor-security.d.ts","sourceRoot":"","sources":["../../src/commands/doctor-security.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAmB,MAAM,qBAAqB,CAAC;AAO1E,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,aAAa,iBAuK5D"}
@@ -100,6 +100,8 @@ export async function noteSecurityWarnings(cfg) {
100
100
  accountIds,
101
101
  });
102
102
  const account = plugin.config.resolveAccount(cfg, defaultAccountId);
103
+ if (!account)
104
+ continue;
103
105
  const enabled = plugin.config.isEnabled ? plugin.config.isEnabled(account, cfg) : true;
104
106
  if (!enabled)
105
107
  continue;
@@ -1 +1 @@
1
- {"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../../../src/gateway/server-methods/channels.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,iCAAiC,CAAC;AAGzC,OAAO,KAAK,EAA0B,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAa5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEhF,KAAK,oBAAoB,GAAG;IAC1B,OAAO,EAAE,SAAS,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,GAAG,EAAE,aAAa,CAAC;IACnB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,MAAM,EAAE,aAAa,CAAC;CACvB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA4BhC;AAED,eAAO,MAAM,gBAAgB,EAAE,sBA2N9B,CAAC"}
1
+ {"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../../../src/gateway/server-methods/channels.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,iCAAiC,CAAC;AAGzC,OAAO,KAAK,EAA0B,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAa5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEhF,KAAK,oBAAoB,GAAG;IAC1B,OAAO,EAAE,SAAS,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,GAAG,EAAE,aAAa,CAAC;IACnB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,MAAM,EAAE,aAAa,CAAC;CACvB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA+BhC;AAED,eAAO,MAAM,gBAAgB,EAAE,sBA6N9B,CAAC"}
@@ -14,6 +14,9 @@ export async function logoutChannelAccount(params) {
14
14
  params.plugin.config.listAccountIds(params.cfg)[0] ||
15
15
  DEFAULT_ACCOUNT_ID;
16
16
  const account = params.plugin.config.resolveAccount(params.cfg, resolvedAccountId);
17
+ if (!account) {
18
+ throw new Error(`Account '${resolvedAccountId}' not found in channel config`);
19
+ }
17
20
  await params.context.stopChannel(params.channelId, resolvedAccountId);
18
21
  const result = await params.plugin.gateway?.logoutAccount?.({
19
22
  cfg: params.cfg,
@@ -82,6 +85,8 @@ export const channelsHandlers = {
82
85
  const resolvedAccounts = {};
83
86
  for (const accountId of accountIds) {
84
87
  const account = plugin.config.resolveAccount(cfg, accountId);
88
+ if (!account)
89
+ continue;
85
90
  const enabled = isAccountEnabled(plugin, account);
86
91
  resolvedAccounts[accountId] = account;
87
92
  let probeResult;
@@ -159,6 +164,8 @@ export const channelsHandlers = {
159
164
  for (const plugin of plugins) {
160
165
  const { accounts, defaultAccountId, defaultAccount, resolvedAccounts } = await buildChannelAccounts(plugin.id);
161
166
  const fallbackAccount = resolvedAccounts[defaultAccountId] ?? plugin.config.resolveAccount(cfg, defaultAccountId);
167
+ if (!fallbackAccount)
168
+ continue;
162
169
  const summary = plugin.status?.buildChannelSummary
163
170
  ? await plugin.status.buildChannelSummary({
164
171
  account: fallbackAccount,
@@ -2,10 +2,10 @@
2
2
  * Heartbeat health monitoring and auto-recovery.
3
3
  * Detects when heartbeat stops running and triggers recovery.
4
4
  */
5
- import { readFileSync, existsSync } from 'node:fs';
6
- import { join } from 'node:path';
7
- import { createSubsystemLogger } from '../logging/subsystem.js';
8
- const log = createSubsystemLogger('heartbeat-monitor');
5
+ import { readFileSync, existsSync } from "node:fs";
6
+ import { join } from "node:path";
7
+ import { createSubsystemLogger } from "../logging/subsystem.js";
8
+ const log = createSubsystemLogger("heartbeat-monitor");
9
9
  const HEARTBEAT_MAX_AGE_MS = 90 * 60 * 1000; // 90 minutes (should run every 30min)
10
10
  const RECOVERY_COOLDOWN_MS = 60 * 60 * 1000; // 1 hour between recovery attempts
11
11
  let monitorState = {
@@ -17,12 +17,12 @@ let monitorState = {
17
17
  * Load heartbeat state file.
18
18
  */
19
19
  function loadHeartbeatState(workspaceDir) {
20
- const statePath = join(workspaceDir, 'memory', 'heartbeat-state.json');
20
+ const statePath = join(workspaceDir, "memory", "heartbeat-state.json");
21
21
  if (!existsSync(statePath)) {
22
22
  return null;
23
23
  }
24
24
  try {
25
- const content = readFileSync(statePath, 'utf-8');
25
+ const content = readFileSync(statePath, "utf-8");
26
26
  return JSON.parse(content);
27
27
  }
28
28
  catch {
@@ -51,7 +51,7 @@ function isHeartbeatStale(state) {
51
51
  * Trigger recovery action.
52
52
  */
53
53
  async function triggerRecovery() {
54
- log.info('[heartbeat-monitor] Triggering recovery action...');
54
+ log.info("[heartbeat-monitor] Triggering recovery action...");
55
55
  // In a full implementation, this would:
56
56
  // 1. Send alert to admin channel
57
57
  // 2. Try to restart heartbeat cron job
@@ -74,7 +74,7 @@ export function monitorHeartbeatHealth(workspaceDir) {
74
74
  const stale = isHeartbeatStale(state);
75
75
  if (stale) {
76
76
  monitorState.consecutiveFailures++;
77
- const lastAudit = state?.lastSecurityAudit || 'never';
77
+ const lastAudit = state?.lastSecurityAudit || "never";
78
78
  log.warn(`[heartbeat-monitor] Heartbeat is STALE! Last audit: ${lastAudit}. Failures: ${monitorState.consecutiveFailures}`);
79
79
  // Trigger recovery if:
80
80
  // 1. Consecutive failures >= 2 (heartbeat missed 2+ cycles)
@@ -85,13 +85,13 @@ export function monitorHeartbeatHealth(workspaceDir) {
85
85
  return {
86
86
  healthy: false,
87
87
  lastAudit,
88
- action: 'recovery_triggered',
88
+ action: "recovery_triggered",
89
89
  };
90
90
  }
91
91
  return {
92
92
  healthy: false,
93
93
  lastAudit,
94
- action: monitorState.consecutiveFailures >= 2 ? 'recovery_pending' : 'monitoring',
94
+ action: monitorState.consecutiveFailures >= 2 ? "recovery_pending" : "monitoring",
95
95
  };
96
96
  }
97
97
  // Heartbeat is healthy
@@ -124,5 +124,5 @@ export function resetMonitorState() {
124
124
  lastRecovery: 0,
125
125
  consecutiveFailures: 0,
126
126
  };
127
- log.info('[heartbeat-monitor] Monitor state reset');
127
+ log.info("[heartbeat-monitor] Monitor state reset");
128
128
  }
@@ -2,7 +2,7 @@
2
2
  * Telegram API retry logic with exponential backoff.
3
3
  * Prevents transient network errors from breaking message delivery.
4
4
  */
5
- import { Context } from 'grammy';
5
+ import { Context } from "grammy";
6
6
  /**
7
7
  * Execute a Telegram API call with retry logic.
8
8
  */
@@ -17,7 +17,7 @@ export declare function sendMessageWithRetry(ctx: Context, text: string, log?: (
17
17
  /**
18
18
  * Send chat action with retry logic.
19
19
  */
20
- export declare function sendChatActionWithRetry(ctx: Context, action: 'typing' | 'upload_photo' | 'record_video' | 'upload_video' | 'record_voice' | 'upload_voice' | 'upload_document' | 'find_location' | 'record_video_note', log?: (msg: string) => void): Promise<void>;
20
+ export declare function sendChatActionWithRetry(ctx: Context, action: "typing" | "upload_photo" | "record_video" | "upload_video" | "record_voice" | "upload_voice" | "upload_document" | "find_location" | "record_video_note", log?: (msg: string) => void): Promise<void>;
21
21
  /**
22
22
  * Edit message with retry logic.
23
23
  */
@@ -1 +1 @@
1
- {"version":3,"file":"retry-logic.d.ts","sourceRoot":"","sources":["../../src/telegram/retry-logic.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAMjC;;GAEG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,EACrD,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,CAAC,CAAC,CA6DZ;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,MAAM,EACZ,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,QAAQ,GAAG,cAAc,GAAG,cAAc,GAAG,cAAc,GAAG,cAAc,GAAG,cAAc,GAAG,iBAAiB,GAAG,eAAe,GAAG,mBAAmB,EACjK,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,OAAO,EACb,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC3B,OAAO,CAAC,IAAI,CAAC,CAGf"}
1
+ {"version":3,"file":"retry-logic.d.ts","sourceRoot":"","sources":["../../src/telegram/retry-logic.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAMjC;;GAEG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,EACrD,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,CAAC,CAAC,CA+DZ;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,MAAM,EACZ,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,OAAO,EACZ,MAAM,EACF,QAAQ,GACR,cAAc,GACd,cAAc,GACd,cAAc,GACd,cAAc,GACd,cAAc,GACd,iBAAiB,GACjB,eAAe,GACf,mBAAmB,EACvB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,OAAO,EACb,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC3B,OAAO,CAAC,IAAI,CAAC,CAGf"}
@@ -18,20 +18,20 @@ export async function withRetry(operation, context, log) {
18
18
  lastError = error instanceof Error ? error : new Error(String(error));
19
19
  const errorMsg = lastError.message.toLowerCase();
20
20
  // Don't retry on certain errors
21
- if (errorMsg.includes('bot was blocked') ||
22
- errorMsg.includes('chat not found') ||
23
- errorMsg.includes('user not found') ||
24
- errorMsg.includes('message not modified')) {
21
+ if (errorMsg.includes("bot was blocked") ||
22
+ errorMsg.includes("chat not found") ||
23
+ errorMsg.includes("user not found") ||
24
+ errorMsg.includes("message not modified")) {
25
25
  throw lastError;
26
26
  }
27
27
  // Network errors, rate limits - retry
28
- const isRetryable = errorMsg.includes('network') ||
29
- errorMsg.includes('fetch') ||
30
- errorMsg.includes('timeout') ||
31
- errorMsg.includes('rate limit') ||
32
- errorMsg.includes('429') ||
33
- errorMsg.includes('50') || // 500, 502, 503, etc.
34
- errorMsg.includes('sendchataction');
28
+ const isRetryable = errorMsg.includes("network") ||
29
+ errorMsg.includes("fetch") ||
30
+ errorMsg.includes("timeout") ||
31
+ errorMsg.includes("rate limit") ||
32
+ errorMsg.includes("429") ||
33
+ errorMsg.includes("50") || // 500, 502, 503, etc.
34
+ errorMsg.includes("sendchataction");
35
35
  if (!isRetryable) {
36
36
  throw lastError;
37
37
  }
@@ -44,7 +44,7 @@ export async function withRetry(operation, context, log) {
44
44
  else {
45
45
  console.warn(logMsg);
46
46
  }
47
- await new Promise(resolve => setTimeout(resolve, delay));
47
+ await new Promise((resolve) => setTimeout(resolve, delay));
48
48
  }
49
49
  }
50
50
  // All retries exhausted
@@ -58,18 +58,18 @@ export async function withRetry(operation, context, log) {
58
58
  * Send message with retry logic.
59
59
  */
60
60
  export async function sendMessageWithRetry(ctx, text, log) {
61
- await withRetry(() => ctx.reply(text), { action: 'sendMessage', chatId: ctx.chat?.id }, log);
61
+ await withRetry(() => ctx.reply(text), { action: "sendMessage", chatId: ctx.chat?.id }, log);
62
62
  }
63
63
  /**
64
64
  * Send chat action with retry logic.
65
65
  */
66
66
  export async function sendChatActionWithRetry(ctx, action, log) {
67
- await withRetry(() => ctx.api.sendChatAction(ctx.chat.id, action), { action: 'sendChatAction', chatId: ctx.chat?.id }, log);
67
+ await withRetry(() => ctx.api.sendChatAction(ctx.chat.id, action), { action: "sendChatAction", chatId: ctx.chat?.id }, log);
68
68
  }
69
69
  /**
70
70
  * Edit message with retry logic.
71
71
  */
72
72
  export async function editMessageWithRetry(_ctx, _messageId, _text, _log) {
73
73
  // Placeholder - implement based on actual API
74
- throw new Error('Not implemented');
74
+ throw new Error("Not implemented");
75
75
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poolzin/pool-bot",
3
- "version": "2026.4.37",
3
+ "version": "2026.4.39",
4
4
  "description": "🎱 Pool Bot - AI assistant with PLCODE integrations",
5
5
  "keywords": [],
6
6
  "license": "MIT",