@poolzin/pool-bot 2026.4.18 → 2026.4.20

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.
@@ -162,7 +162,7 @@ export function buildAgentSystemPrompt(params) {
162
162
  browser: "Control web browser",
163
163
  canvas: "Present/eval/snapshot the Canvas",
164
164
  nodes: "List/describe/notify/camera/screen on paired nodes",
165
- cron: "Manage cron jobs and wake events (use for reminders; when scheduling a reminder, write the systemEvent text as something that will read like a reminder when it fires, and mention that it is a reminder depending on the time gap between setting and firing; include recent context in reminder text if appropriate)",
165
+ cron: "Manage cron jobs and wake events. SCHEDULING MODES: (1) Reminders — use systemEvent payload to inject text into your session when it fires; write the text as something that reads like a reminder. (2) Background tasks — use agentTurn payload with a message describing the work; results auto-deliver back to the originating chat. CRITICAL: When the user asks you to do something 'later', 'tonight', 'overnight', 'tomorrow morning', 'when I wake up', or any future time IMMEDIATELY schedule a cron job with schedule.kind='at' at the appropriate time and payload.kind='agentTurn' with a descriptive message. Do NOT just say you'll do it. Actually schedule it. Use delivery.mode='announce' (default) to deliver results back to the user's chat.",
166
166
  message: "Send messages and channel actions",
167
167
  gateway: "Restart, apply config, or run updates on the running Pool Bot process",
168
168
  agents_list: "List agent ids allowed for sessions_spawn",
@@ -326,7 +326,7 @@ export function buildAgentSystemPrompt(params) {
326
326
  "- browser: control Pool Bot's dedicated browser",
327
327
  "- canvas: present/eval/snapshot the Canvas",
328
328
  "- nodes: list/describe/notify/camera/screen on paired nodes",
329
- "- cron: manage cron jobs and wake events (use for reminders; when scheduling a reminder, write the systemEvent text as something that will read like a reminder when it fires, and mention that it is a reminder depending on the time gap between setting and firing; include recent context in reminder text if appropriate)",
329
+ "- cron: manage cron jobs and wake events (use systemEvent for reminders, agentTurn for background tasks; when user asks for future work 'later', 'tonight', 'tomorrow' schedule an agentTurn cron job with schedule.kind='at')",
330
330
  "- sessions_list: list sessions",
331
331
  "- sessions_history: fetch session history",
332
332
  "- sessions_send: send to another session",
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2026.4.18",
2
+ "version": "2026.4.20",
3
3
  "commit": "4e1f8d4b27c26618d3a69049dbe44698929a6ba8",
4
- "builtAt": "2026-03-27T01:18:30.781Z"
4
+ "builtAt": "2026-03-27T04:37:21.576Z"
5
5
  }
@@ -15,5 +15,11 @@ export type CronConfig = {
15
15
  * Default: "24h".
16
16
  */
17
17
  sessionRetention?: string | false;
18
+ /**
19
+ * Default timeout for cron jobs in seconds.
20
+ * Per-job `timeoutSeconds` overrides this. Set to 0 to disable timeout (not recommended).
21
+ * Default: 7200 (2 hours).
22
+ */
23
+ defaultJobTimeoutSeconds?: number;
18
24
  };
19
25
  //# sourceMappingURL=types.cron.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.cron.d.ts","sourceRoot":"","sources":["../../src/config/types.cron.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CACnC,CAAC"}
1
+ {"version":3,"file":"types.cron.d.ts","sourceRoot":"","sources":["../../src/config/types.cron.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAClC;;;;OAIG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../src/cron/delivery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAqBF,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CA+CtE"}
1
+ {"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../src/cron/delivery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAqBF,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAiDtE"}
@@ -25,9 +25,11 @@ export function resolveCronDeliveryPlan(job) {
25
25
  ? "announce"
26
26
  : normalizedMode === "none"
27
27
  ? "none"
28
- : normalizedMode === "deliver"
29
- ? "announce"
30
- : undefined;
28
+ : normalizedMode === "webhook"
29
+ ? "webhook"
30
+ : normalizedMode === "deliver"
31
+ ? "announce"
32
+ : undefined;
31
33
  const payloadChannel = normalizeChannel(payload?.channel);
32
34
  const payloadTo = normalizeTo(payload?.to);
33
35
  const deliveryChannel = normalizeChannel(delivery?.channel);
@@ -41,7 +43,7 @@ export function resolveCronDeliveryPlan(job) {
41
43
  channel,
42
44
  to,
43
45
  source: "delivery",
44
- requested: resolvedMode === "announce",
46
+ requested: resolvedMode === "announce" || resolvedMode === "webhook",
45
47
  };
46
48
  }
47
49
  const legacyMode = payload?.deliver === true ? "explicit" : payload?.deliver === false ? "off" : "auto";
@@ -1,15 +1,18 @@
1
1
  import type { PoolBotConfig } from "../../config/config.js";
2
2
  import { type SessionEntry } from "../../config/sessions.js";
3
- export declare function resolveCronSession(params: {
4
- cfg: PoolBotConfig;
5
- sessionKey: string;
6
- nowMs: number;
7
- agentId: string;
8
- }): {
3
+ export type CronSessionResult = {
9
4
  storePath: string;
10
5
  store: Record<string, SessionEntry>;
11
6
  sessionEntry: SessionEntry;
12
7
  systemSent: boolean;
13
8
  isNewSession: boolean;
9
+ reusedSessionId?: string;
14
10
  };
11
+ export declare function resolveCronSession(params: {
12
+ cfg: PoolBotConfig;
13
+ sessionKey: string;
14
+ nowMs: number;
15
+ agentId: string;
16
+ forceNew?: boolean;
17
+ }): CronSessionResult;
15
18
  //# sourceMappingURL=session.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/cron/isolated-agent/session.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAsC,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAEjG,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,GAAG,EAAE,aAAa,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;;;;;;EA0BA"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/cron/isolated-agent/session.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAsC,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAIjG,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACpC,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE;IACzC,GAAG,EAAE,aAAa,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,iBAAiB,CAgDpB"}
@@ -1,5 +1,6 @@
1
1
  import crypto from "node:crypto";
2
2
  import { loadSessionStore, resolveStorePath } from "../../config/sessions.js";
3
+ const SESSION_FRESHNESS_MS = 10 * 60_000; // 10 minutes
3
4
  export function resolveCronSession(params) {
4
5
  const sessionCfg = params.cfg.session;
5
6
  const storePath = resolveStorePath(sessionCfg?.store, {
@@ -7,6 +8,25 @@ export function resolveCronSession(params) {
7
8
  });
8
9
  const store = loadSessionStore(storePath);
9
10
  const entry = store[params.sessionKey];
11
+ // Check if we can reuse the existing session (fresh and forceNew is not set)
12
+ const forceNew = params.forceNew !== false;
13
+ const isFresh = entry?.updatedAt && params.nowMs - entry.updatedAt < SESSION_FRESHNESS_MS;
14
+ if (!forceNew && isFresh && entry) {
15
+ // Reuse existing session — preserve context continuity
16
+ const sessionEntry = {
17
+ ...entry,
18
+ updatedAt: params.nowMs,
19
+ };
20
+ return {
21
+ storePath,
22
+ store,
23
+ sessionEntry,
24
+ systemSent: entry.systemSent ?? false,
25
+ isNewSession: false,
26
+ reusedSessionId: entry.sessionId,
27
+ };
28
+ }
29
+ // Create fresh session
10
30
  const sessionId = crypto.randomUUID();
11
31
  const systemSent = false;
12
32
  const sessionEntry = {
@@ -4,6 +4,11 @@ export declare function readDescendantSubagentFallbackReply(params: {
4
4
  sessionKey: string;
5
5
  runStartedAt: number;
6
6
  }): Promise<string | undefined>;
7
+ /**
8
+ * Wait for descendant subagents with exponential backoff.
9
+ * Starts at 500ms, doubles up to 10s between polls.
10
+ * This dramatically reduces CPU usage for long-running overnight tasks.
11
+ */
7
12
  export declare function waitForDescendantSubagentSummary(params: {
8
13
  sessionKey: string;
9
14
  initialReply?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"subagent-followup.d.ts","sourceRoot":"","sources":["../../../src/cron/isolated-agent/subagent-followup.ts"],"names":[],"mappings":"AAWA,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CA6BjE;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAa9D;AAED,wBAAsB,mCAAmC,CAAC,MAAM,EAAE;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA2C9B;AAED,wBAAsB,gCAAgC,CAAC,MAAM,EAAE;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAyC9B"}
1
+ {"version":3,"file":"subagent-followup.d.ts","sourceRoot":"","sources":["../../../src/cron/isolated-agent/subagent-followup.ts"],"names":[],"mappings":"AAYA,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CA6BjE;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAa9D;AAED,wBAAsB,mCAAmC,CAAC,MAAM,EAAE;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA2C9B;AAED;;;;GAIG;AACH,wBAAsB,gCAAgC,CAAC,MAAM,EAAE;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAiD9B"}
@@ -1,7 +1,8 @@
1
1
  import { countActiveDescendantRuns, listDescendantRunsForRequester, } from "../../agents/subagent-registry.js";
2
2
  import { readLatestAssistantReply } from "../../agents/tools/agent-step.js";
3
3
  import { SILENT_REPLY_TOKEN } from "../../auto-reply/tokens.js";
4
- const CRON_SUBAGENT_WAIT_POLL_MS = 500;
4
+ const CRON_SUBAGENT_WAIT_INITIAL_POLL_MS = 500;
5
+ const CRON_SUBAGENT_WAIT_MAX_POLL_MS = 10_000;
5
6
  const CRON_SUBAGENT_WAIT_MIN_MS = 30_000;
6
7
  const CRON_SUBAGENT_FINAL_REPLY_GRACE_MS = 5_000;
7
8
  export function isLikelyInterimCronMessage(value) {
@@ -87,19 +88,29 @@ export async function readDescendantSubagentFallbackReply(params) {
87
88
  }
88
89
  return replies.join("\n\n");
89
90
  }
91
+ /**
92
+ * Wait for descendant subagents with exponential backoff.
93
+ * Starts at 500ms, doubles up to 10s between polls.
94
+ * This dramatically reduces CPU usage for long-running overnight tasks.
95
+ */
90
96
  export async function waitForDescendantSubagentSummary(params) {
91
97
  const initialReply = params.initialReply?.trim();
92
98
  const deadline = Date.now() + Math.max(CRON_SUBAGENT_WAIT_MIN_MS, Math.floor(params.timeoutMs));
93
99
  let sawActiveDescendants = params.observedActiveDescendants === true;
94
100
  let drainedAtMs;
101
+ let pollInterval = CRON_SUBAGENT_WAIT_INITIAL_POLL_MS;
95
102
  while (Date.now() < deadline) {
96
103
  const activeDescendants = countActiveDescendantRuns(params.sessionKey);
97
104
  if (activeDescendants > 0) {
98
105
  sawActiveDescendants = true;
99
106
  drainedAtMs = undefined;
100
- await new Promise((resolve) => setTimeout(resolve, CRON_SUBAGENT_WAIT_POLL_MS));
107
+ // Exponential backoff: 500ms → 1s → 2s → 4s → 8s → 10s (cap)
108
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
109
+ pollInterval = Math.min(pollInterval * 2, CRON_SUBAGENT_WAIT_MAX_POLL_MS);
101
110
  continue;
102
111
  }
112
+ // Reset poll interval when descendants drain
113
+ pollInterval = CRON_SUBAGENT_WAIT_INITIAL_POLL_MS;
103
114
  if (!sawActiveDescendants) {
104
115
  return initialReply;
105
116
  }
@@ -115,7 +126,7 @@ export async function waitForDescendantSubagentSummary(params) {
115
126
  if (Date.now() - drainedAtMs >= CRON_SUBAGENT_FINAL_REPLY_GRACE_MS) {
116
127
  return undefined;
117
128
  }
118
- await new Promise((resolve) => setTimeout(resolve, CRON_SUBAGENT_WAIT_POLL_MS));
129
+ await new Promise((resolve) => setTimeout(resolve, CRON_SUBAGENT_WAIT_INITIAL_POLL_MS));
119
130
  }
120
131
  const latest = (await readLatestAssistantReply({ sessionKey: params.sessionKey }))?.trim();
121
132
  if (latest &&
@@ -1 +1 @@
1
- {"version":3,"file":"timer.d.ts","sourceRoot":"","sources":["../../../src/cron/service/timer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAmD,MAAM,aAAa,CAAC;AAQ5F,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA+I9D,wBAAgB,QAAQ,CAAC,KAAK,EAAE,gBAAgB,QAuC/C;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE,gBAAgB,iBA2MpD;AAyDD,wBAAsB,aAAa,CACjC,KAAK,EAAE,gBAAgB,EACvB,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAAE,iBA6F5C;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,gBAAgB,iBASvD;AAuHD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,gBAAgB,EACvB,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,iBAoC3B;AAmDD,wBAAgB,IAAI,CAClB,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE;IAAE,IAAI,EAAE,KAAK,GAAG,gBAAgB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;;;;EAWvD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,gBAAgB,QAKhD;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,SAAS,QAM3D"}
1
+ {"version":3,"file":"timer.d.ts","sourceRoot":"","sources":["../../../src/cron/service/timer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAmD,MAAM,aAAa,CAAC;AAQ5F,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA+I9D,wBAAgB,QAAQ,CAAC,KAAK,EAAE,gBAAgB,QAuC/C;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE,gBAAgB,iBAkNpD;AAyDD,wBAAsB,aAAa,CACjC,KAAK,EAAE,gBAAgB,EACvB,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAAE,iBA6F5C;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,gBAAgB,iBASvD;AAuHD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,gBAAgB,EACvB,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,iBAoC3B;AAmDD,wBAAgB,IAAI,CAClB,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE;IAAE,IAAI,EAAE,KAAK,GAAG,gBAAgB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;;;;EAWvD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,gBAAgB,QAKhD;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,SAAS,QAM3D"}
@@ -18,7 +18,7 @@ const MIN_REFIRE_GAP_MS = 2_000;
18
18
  * on top of the per-provider / per-agent timeouts to prevent one stuck job
19
19
  * from wedging the entire cron lane.
20
20
  */
21
- const DEFAULT_JOB_TIMEOUT_MS = 10 * 60_000; // 10 minutes
21
+ const DEFAULT_JOB_TIMEOUT_MS = 2 * 60 * 60_000; // 2 hours (allows overnight/long-running tasks)
22
22
  function resolveRunConcurrency(state) {
23
23
  const raw = state.deps.cronConfig?.maxConcurrentRuns;
24
24
  if (typeof raw !== "number" || !Number.isFinite(raw)) {
@@ -203,11 +203,17 @@ export async function onTimer(state) {
203
203
  const configuredTimeoutMs = job.payload.kind === "agentTurn" && typeof job.payload.timeoutSeconds === "number"
204
204
  ? Math.floor(job.payload.timeoutSeconds * 1_000)
205
205
  : undefined;
206
+ const cronDefaultTimeoutMs = typeof state.deps.cronConfig?.defaultJobTimeoutSeconds === "number"
207
+ ? state.deps.cronConfig.defaultJobTimeoutSeconds <= 0
208
+ ? undefined
209
+ : Math.floor(state.deps.cronConfig.defaultJobTimeoutSeconds * 1_000)
210
+ : undefined;
211
+ const effectiveDefaultMs = cronDefaultTimeoutMs ?? DEFAULT_JOB_TIMEOUT_MS;
206
212
  const jobTimeoutMs = configuredTimeoutMs !== undefined
207
213
  ? configuredTimeoutMs <= 0
208
214
  ? undefined
209
215
  : configuredTimeoutMs
210
- : DEFAULT_JOB_TIMEOUT_MS;
216
+ : effectiveDefaultMs;
211
217
  try {
212
218
  const result = typeof jobTimeoutMs === "number"
213
219
  ? await (async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poolzin/pool-bot",
3
- "version": "2026.4.18",
3
+ "version": "2026.4.20",
4
4
  "description": "🎱 Pool Bot - AI assistant with PLCODE integrations",
5
5
  "keywords": [],
6
6
  "license": "MIT",