@poolzin/pool-bot 2026.4.18 → 2026.4.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-info.json +2 -2
- package/dist/config/types.cron.d.ts +6 -0
- package/dist/config/types.cron.d.ts.map +1 -1
- package/dist/cron/delivery.d.ts.map +1 -1
- package/dist/cron/delivery.js +6 -4
- package/dist/cron/isolated-agent/session.d.ts +9 -6
- package/dist/cron/isolated-agent/session.d.ts.map +1 -1
- package/dist/cron/isolated-agent/session.js +20 -0
- package/dist/cron/isolated-agent/subagent-followup.d.ts +5 -0
- package/dist/cron/isolated-agent/subagent-followup.d.ts.map +1 -1
- package/dist/cron/isolated-agent/subagent-followup.js +14 -3
- package/dist/cron/service/timer.d.ts.map +1 -1
- package/dist/cron/service/timer.js +8 -2
- package/package.json +1 -1
package/dist/build-info.json
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/cron/delivery.js
CHANGED
|
@@ -25,9 +25,11 @@ export function resolveCronDeliveryPlan(job) {
|
|
|
25
25
|
? "announce"
|
|
26
26
|
: normalizedMode === "none"
|
|
27
27
|
? "none"
|
|
28
|
-
: normalizedMode === "
|
|
29
|
-
? "
|
|
30
|
-
:
|
|
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
|
|
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;
|
|
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":"
|
|
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
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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 =
|
|
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
|
-
:
|
|
216
|
+
: effectiveDefaultMs;
|
|
211
217
|
try {
|
|
212
218
|
const result = typeof jobTimeoutMs === "number"
|
|
213
219
|
? await (async () => {
|