@poolzin/pool-bot 2026.2.0 → 2026.2.1
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/agents/bash-tools.exec.js +76 -25
- package/dist/agents/cli-runner/helpers.js +9 -11
- package/dist/agents/identity.js +47 -7
- package/dist/agents/memory-search.js +25 -8
- package/dist/agents/model-selection.js +21 -0
- package/dist/agents/pi-embedded-block-chunker.js +117 -42
- package/dist/agents/pi-embedded-helpers/errors.js +183 -78
- package/dist/agents/pi-embedded-helpers.js +1 -1
- package/dist/agents/pi-embedded-runner/compact.js +1 -0
- package/dist/agents/pi-embedded-runner/model.js +61 -2
- package/dist/agents/pi-embedded-runner/run/attempt.js +21 -11
- package/dist/agents/pi-embedded-runner/run.js +199 -46
- package/dist/agents/pi-embedded-runner/system-prompt.js +10 -2
- package/dist/agents/pi-embedded-subscribe.js +118 -29
- package/dist/agents/pi-tools.js +10 -5
- package/dist/agents/poolbot-tools.js +15 -10
- package/dist/agents/sandbox-paths.js +31 -0
- package/dist/agents/session-tool-result-guard.js +94 -15
- package/dist/agents/shell-utils.js +51 -0
- package/dist/agents/skills/bundled-context.js +23 -0
- package/dist/agents/skills/bundled-dir.js +41 -7
- package/dist/agents/skills-install.js +60 -23
- package/dist/agents/subagent-announce.js +79 -34
- package/dist/agents/tool-policy.conformance.js +14 -0
- package/dist/agents/tool-policy.js +24 -0
- package/dist/agents/tools/cron-tool.js +166 -19
- package/dist/agents/tools/discord-actions-presence.js +78 -0
- package/dist/agents/tools/message-tool.js +56 -2
- package/dist/agents/tools/sessions-history-tool.js +69 -1
- package/dist/agents/tools/web-search.js +211 -42
- package/dist/agents/usage.js +23 -1
- package/dist/agents/workspace-run.js +67 -0
- package/dist/agents/workspace-templates.js +44 -0
- package/dist/auto-reply/command-auth.js +121 -6
- package/dist/auto-reply/envelope.js +50 -72
- package/dist/auto-reply/reply/commands-compact.js +1 -0
- package/dist/auto-reply/reply/commands-context-report.js +1 -0
- package/dist/auto-reply/reply/commands-context.js +1 -0
- package/dist/auto-reply/reply/commands-models.js +107 -60
- package/dist/auto-reply/reply/commands-ptt.js +171 -0
- package/dist/auto-reply/reply/get-reply-run.js +2 -1
- package/dist/auto-reply/reply/inbound-context.js +5 -1
- package/dist/auto-reply/reply/model-selection.js +3 -3
- package/dist/auto-reply/thinking.js +88 -43
- package/dist/browser/bridge-server.js +13 -0
- package/dist/browser/cdp.helpers.js +38 -24
- package/dist/browser/client-fetch.js +50 -7
- package/dist/browser/config.js +1 -10
- package/dist/browser/extension-relay.js +101 -40
- package/dist/browser/pw-ai.js +1 -1
- package/dist/browser/pw-session.js +143 -8
- package/dist/browser/pw-tools-core.interactions.js +125 -27
- package/dist/browser/pw-tools-core.responses.js +1 -1
- package/dist/browser/pw-tools-core.state.js +1 -1
- package/dist/browser/routes/agent.act.js +86 -41
- package/dist/browser/routes/dispatcher.js +4 -4
- package/dist/browser/screenshot.js +1 -1
- package/dist/browser/server.js +13 -0
- package/dist/build-info.json +3 -3
- package/dist/channels/reply-prefix.js +8 -1
- package/dist/cli/cron-cli/register.cron-add.js +61 -40
- package/dist/cli/cron-cli/register.cron-edit.js +60 -34
- package/dist/cli/cron-cli/shared.js +56 -41
- package/dist/cli/dns-cli.js +26 -14
- package/dist/cli/gateway-cli/register.js +37 -19
- package/dist/cli/memory-cli.js +5 -5
- package/dist/cli/parse-bytes.js +37 -0
- package/dist/cli/update-cli.js +173 -52
- package/dist/commands/agent.js +1 -0
- package/dist/commands/doctor-config-flow.js +61 -5
- package/dist/commands/doctor-state-migrations.js +1 -1
- package/dist/commands/health.js +1 -1
- package/dist/commands/model-allowlist.js +29 -0
- package/dist/commands/model-picker.js +2 -1
- package/dist/commands/models/list.status-command.js +43 -23
- package/dist/commands/models/shared.js +15 -0
- package/dist/commands/onboard-custom.js +384 -0
- package/dist/commands/onboard-non-interactive/local/auth-choice-inference.js +35 -0
- package/dist/commands/onboard-non-interactive/local/auth-choice.js +6 -3
- package/dist/commands/onboard-skills.js +63 -38
- package/dist/commands/openai-model-default.js +41 -0
- package/dist/config/defaults.js +3 -2
- package/dist/config/paths.js +136 -35
- package/dist/config/plugin-auto-enable.js +21 -5
- package/dist/config/redact-snapshot.js +153 -0
- package/dist/config/schema.field-metadata.js +590 -0
- package/dist/config/schema.js +2 -2
- package/dist/config/sessions/store.js +291 -23
- package/dist/config/zod-schema.agent-defaults.js +3 -0
- package/dist/config/zod-schema.agent-runtime.js +13 -2
- package/dist/config/zod-schema.providers-core.js +142 -0
- package/dist/config/zod-schema.session.js +3 -0
- package/dist/cron/delivery.js +57 -0
- package/dist/cron/isolated-agent/delivery-target.js +18 -3
- package/dist/cron/isolated-agent/helpers.js +22 -5
- package/dist/cron/isolated-agent/run.js +171 -63
- package/dist/cron/isolated-agent/session.js +2 -0
- package/dist/cron/normalize.js +356 -28
- package/dist/cron/parse.js +10 -5
- package/dist/cron/run-log.js +35 -10
- package/dist/cron/schedule.js +41 -6
- package/dist/cron/service/jobs.js +208 -35
- package/dist/cron/service/ops.js +72 -16
- package/dist/cron/service/state.js +2 -0
- package/dist/cron/service/store.js +386 -14
- package/dist/cron/service/timer.js +390 -147
- package/dist/cron/session-reaper.js +86 -0
- package/dist/cron/store.js +23 -8
- package/dist/cron/validate-timestamp.js +43 -0
- package/dist/discord/monitor/agent-components.js +438 -0
- package/dist/discord/monitor/allow-list.js +28 -5
- package/dist/discord/monitor/gateway-registry.js +29 -0
- package/dist/discord/monitor/native-command.js +44 -23
- package/dist/discord/monitor/sender-identity.js +45 -0
- package/dist/discord/pluralkit.js +27 -0
- package/dist/discord/send.outbound.js +92 -5
- package/dist/discord/send.shared.js +60 -23
- package/dist/discord/targets.js +84 -1
- package/dist/entry.js +15 -9
- package/dist/extensionAPI.js +8 -0
- package/dist/gateway/control-ui.js +8 -1
- package/dist/gateway/hooks-mapping.js +3 -0
- package/dist/gateway/hooks.js +65 -0
- package/dist/gateway/net.js +96 -31
- package/dist/gateway/node-command-policy.js +50 -15
- package/dist/gateway/origin-check.js +56 -0
- package/dist/gateway/protocol/client-info.js +9 -0
- package/dist/gateway/protocol/index.js +9 -2
- package/dist/gateway/protocol/schema/agents-models-skills.js +71 -1
- package/dist/gateway/protocol/schema/cron.js +22 -10
- package/dist/gateway/protocol/schema/protocol-schemas.js +16 -2
- package/dist/gateway/protocol/schema/sessions.js +12 -0
- package/dist/gateway/server/hooks.js +1 -1
- package/dist/gateway/server-broadcast.js +26 -9
- package/dist/gateway/server-chat.js +112 -23
- package/dist/gateway/server-discovery-runtime.js +10 -2
- package/dist/gateway/server-http.js +109 -11
- package/dist/gateway/server-methods/agent-timestamp.js +60 -0
- package/dist/gateway/server-methods/agents.js +321 -2
- package/dist/gateway/server-methods/usage.js +559 -16
- package/dist/gateway/server-runtime-state.js +22 -8
- package/dist/gateway/server-startup-memory.js +16 -0
- package/dist/gateway/server.impl.js +5 -1
- package/dist/gateway/session-utils.fs.js +23 -25
- package/dist/gateway/session-utils.js +20 -10
- package/dist/gateway/sessions-patch.js +7 -22
- package/dist/gateway/test-helpers.server.js +35 -2
- package/dist/imessage/constants.js +2 -0
- package/dist/imessage/monitor/deliver.js +4 -1
- package/dist/imessage/monitor/monitor-provider.js +51 -1
- package/dist/infra/bonjour-discovery.js +131 -70
- package/dist/infra/control-ui-assets.js +134 -12
- package/dist/infra/errors.js +12 -0
- package/dist/infra/exec-approvals.js +266 -57
- package/dist/infra/format-time/format-datetime.js +79 -0
- package/dist/infra/format-time/format-duration.js +81 -0
- package/dist/infra/format-time/format-relative.js +80 -0
- package/dist/infra/heartbeat-runner.js +140 -49
- package/dist/infra/home-dir.js +54 -0
- package/dist/infra/net/fetch-guard.js +122 -0
- package/dist/infra/net/ssrf.js +65 -29
- package/dist/infra/outbound/abort.js +14 -0
- package/dist/infra/outbound/message-action-runner.js +77 -13
- package/dist/infra/outbound/outbound-session.js +143 -37
- package/dist/infra/poolbot-root.js +43 -1
- package/dist/infra/session-cost-usage.js +631 -41
- package/dist/infra/state-migrations.js +317 -47
- package/dist/infra/update-global.js +35 -0
- package/dist/infra/update-runner.js +149 -43
- package/dist/infra/warning-filter.js +65 -0
- package/dist/infra/widearea-dns.js +30 -9
- package/dist/logging/redact-identifier.js +12 -0
- package/dist/media/fetch.js +81 -58
- package/dist/media-understanding/apply.js +403 -3
- package/dist/media-understanding/attachments.js +38 -27
- package/dist/media-understanding/defaults.js +16 -0
- package/dist/media-understanding/providers/deepgram/audio.js +22 -14
- package/dist/media-understanding/providers/google/audio.js +24 -17
- package/dist/media-understanding/providers/google/video.js +24 -17
- package/dist/media-understanding/providers/image.js +2 -2
- package/dist/media-understanding/providers/index.js +4 -1
- package/dist/media-understanding/providers/openai/audio.js +22 -14
- package/dist/media-understanding/providers/shared.js +16 -11
- package/dist/media-understanding/providers/zai/index.js +6 -0
- package/dist/media-understanding/runner.js +158 -90
- package/dist/memory/batch-voyage.js +277 -0
- package/dist/memory/embeddings-voyage.js +75 -0
- package/dist/memory/embeddings.js +28 -16
- package/dist/memory/internal.js +101 -18
- package/dist/memory/manager.js +154 -48
- package/dist/memory/search-manager.js +173 -0
- package/dist/memory/session-files.js +9 -3
- package/dist/node-host/runner.js +34 -24
- package/dist/node-host/with-timeout.js +27 -0
- package/dist/plugins/commands.js +5 -1
- package/dist/plugins/config-state.js +86 -7
- package/dist/plugins/source-display.js +51 -0
- package/dist/process/exec.js +20 -2
- package/dist/routing/resolve-route.js +12 -0
- package/dist/routing/session-key.js +15 -0
- package/dist/runtime.js +2 -0
- package/dist/security/audit-extra.async.js +601 -0
- package/dist/security/audit-extra.js +2 -830
- package/dist/security/audit-extra.sync.js +505 -0
- package/dist/security/channel-metadata.js +34 -0
- package/dist/security/external-content.js +88 -6
- package/dist/security/skill-scanner.js +330 -0
- package/dist/sessions/session-key-utils.js +7 -0
- package/dist/signal/monitor/event-handler.js +80 -1
- package/dist/slack/monitor/media.js +85 -15
- package/dist/tailscale/detect.js +1 -2
- package/dist/telegram/bot/helpers.js +109 -28
- package/dist/telegram/bot-handlers.js +144 -3
- package/dist/telegram/bot-message-context.js +37 -10
- package/dist/telegram/bot-message-dispatch.js +48 -15
- package/dist/telegram/bot-native-commands.js +86 -29
- package/dist/telegram/bot.js +30 -29
- package/dist/telegram/model-buttons.js +163 -0
- package/dist/telegram/monitor.js +110 -85
- package/dist/telegram/send.js +129 -47
- package/dist/terminal/restore.js +45 -0
- package/dist/test-helpers/state-dir-env.js +16 -0
- package/dist/tts/tts.js +12 -6
- package/dist/tui/tui-session-actions.js +166 -54
- package/dist/utils/fetch-timeout.js +20 -0
- package/dist/utils/normalize-secret-input.js +19 -0
- package/dist/utils/transcript-tools.js +58 -0
- package/dist/utils.js +45 -14
- package/dist/version.js +42 -5
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ import { resolveAgentConfig, resolveAgentDir, resolveAgentModelFallbacksOverride
|
|
|
2
2
|
import { runCliAgent } from "../../agents/cli-runner.js";
|
|
3
3
|
import { getCliSessionId, setCliSessionId } from "../../agents/cli-session.js";
|
|
4
4
|
import { lookupContextTokens } from "../../agents/context.js";
|
|
5
|
+
import { formatUserTime, resolveUserTimeFormat, resolveUserTimezone, } from "../../agents/date-time.js";
|
|
5
6
|
import { DEFAULT_CONTEXT_TOKENS, DEFAULT_MODEL, DEFAULT_PROVIDER } from "../../agents/defaults.js";
|
|
6
7
|
import { loadModelCatalog } from "../../agents/model-catalog.js";
|
|
7
8
|
import { runWithModelFallback } from "../../agents/model-fallback.js";
|
|
@@ -9,34 +10,46 @@ import { getModelRefStatus, isCliProvider, resolveAllowedModelRef, resolveConfig
|
|
|
9
10
|
import { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
|
|
10
11
|
import { buildWorkspaceSkillSnapshot } from "../../agents/skills.js";
|
|
11
12
|
import { getSkillsSnapshotVersion } from "../../agents/skills/refresh.js";
|
|
13
|
+
import { runSubagentAnnounceFlow } from "../../agents/subagent-announce.js";
|
|
12
14
|
import { resolveAgentTimeoutMs } from "../../agents/timeout.js";
|
|
13
|
-
import { hasNonzeroUsage } from "../../agents/usage.js";
|
|
15
|
+
import { deriveSessionTotalTokens, hasNonzeroUsage } from "../../agents/usage.js";
|
|
14
16
|
import { ensureAgentWorkspace } from "../../agents/workspace.js";
|
|
15
|
-
import {
|
|
16
|
-
import { formatXHighModelHint, normalizeThinkLevel, normalizeVerboseLevel, supportsXHighThinking, } from "../../auto-reply/thinking.js";
|
|
17
|
+
import { normalizeThinkLevel, normalizeVerboseLevel, supportsXHighThinking, } from "../../auto-reply/thinking.js";
|
|
17
18
|
import { createOutboundSendDeps } from "../../cli/outbound-send-deps.js";
|
|
18
|
-
import { resolveSessionTranscriptPath, updateSessionStore } from "../../config/sessions.js";
|
|
19
|
+
import { resolveAgentMainSessionKey, resolveSessionTranscriptPath, updateSessionStore, } from "../../config/sessions.js";
|
|
19
20
|
import { registerAgentRunContext } from "../../infra/agent-events.js";
|
|
20
21
|
import { deliverOutboundPayloads } from "../../infra/outbound/deliver.js";
|
|
21
22
|
import { getRemoteSkillEligibility } from "../../infra/skills-remote.js";
|
|
23
|
+
import { logWarn } from "../../logger.js";
|
|
22
24
|
import { buildAgentMainSessionKey, normalizeAgentId } from "../../routing/session-key.js";
|
|
23
25
|
import { buildSafeExternalPrompt, detectSuspiciousPatterns, getHookType, isExternalHookSession, } from "../../security/external-content.js";
|
|
24
|
-
import {
|
|
26
|
+
import { resolveCronDeliveryPlan } from "../delivery.js";
|
|
25
27
|
import { resolveDeliveryTarget } from "./delivery-target.js";
|
|
26
|
-
import { isHeartbeatOnlyResponse, pickLastNonEmptyTextFromPayloads, pickSummaryFromOutput, pickSummaryFromPayloads, resolveHeartbeatAckMaxChars, } from "./helpers.js";
|
|
28
|
+
import { isHeartbeatOnlyResponse, pickLastDeliverablePayload, pickLastNonEmptyTextFromPayloads, pickSummaryFromOutput, pickSummaryFromPayloads, resolveHeartbeatAckMaxChars, } from "./helpers.js";
|
|
27
29
|
import { resolveCronSession } from "./session.js";
|
|
28
30
|
function matchesMessagingToolDeliveryTarget(target, delivery) {
|
|
29
|
-
if (!delivery.to || !target.to)
|
|
31
|
+
if (!delivery.to || !target.to) {
|
|
30
32
|
return false;
|
|
33
|
+
}
|
|
31
34
|
const channel = delivery.channel.trim().toLowerCase();
|
|
32
35
|
const provider = target.provider?.trim().toLowerCase();
|
|
33
|
-
if (provider && provider !== "message" && provider !== channel)
|
|
36
|
+
if (provider && provider !== "message" && provider !== channel) {
|
|
34
37
|
return false;
|
|
38
|
+
}
|
|
35
39
|
if (target.accountId && delivery.accountId && target.accountId !== delivery.accountId) {
|
|
36
40
|
return false;
|
|
37
41
|
}
|
|
38
42
|
return target.to === delivery.to;
|
|
39
43
|
}
|
|
44
|
+
function resolveCronDeliveryBestEffort(job) {
|
|
45
|
+
if (typeof job.delivery?.bestEffort === "boolean") {
|
|
46
|
+
return job.delivery.bestEffort;
|
|
47
|
+
}
|
|
48
|
+
if (job.payload.kind === "agentTurn" && typeof job.payload.bestEffortDeliver === "boolean") {
|
|
49
|
+
return job.payload.bestEffortDeliver;
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
40
53
|
export async function runCronIsolatedAgentTurn(params) {
|
|
41
54
|
const defaultAgentId = resolveDefaultAgentId(params.cfg);
|
|
42
55
|
const requestedAgentId = typeof params.agentId === "string" && params.agentId.trim()
|
|
@@ -109,14 +122,12 @@ export async function runCronIsolatedAgentTurn(params) {
|
|
|
109
122
|
}
|
|
110
123
|
}
|
|
111
124
|
const modelOverrideRaw = params.job.payload.kind === "agentTurn" ? params.job.payload.model : undefined;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
return { status: "error", error: "invalid model: expected string" };
|
|
115
|
-
}
|
|
125
|
+
const modelOverride = typeof modelOverrideRaw === "string" ? modelOverrideRaw.trim() : undefined;
|
|
126
|
+
if (modelOverride !== undefined && modelOverride.length > 0) {
|
|
116
127
|
const resolvedOverride = resolveAllowedModelRef({
|
|
117
128
|
cfg: cfgWithAgentDefaults,
|
|
118
129
|
catalog: await loadCatalog(),
|
|
119
|
-
raw:
|
|
130
|
+
raw: modelOverride,
|
|
120
131
|
defaultProvider: resolvedDefault.provider,
|
|
121
132
|
defaultModel: resolvedDefault.model,
|
|
122
133
|
});
|
|
@@ -133,6 +144,33 @@ export async function runCronIsolatedAgentTurn(params) {
|
|
|
133
144
|
agentId,
|
|
134
145
|
nowMs: now,
|
|
135
146
|
});
|
|
147
|
+
const runSessionId = cronSession.sessionEntry.sessionId;
|
|
148
|
+
const runSessionKey = baseSessionKey.startsWith("cron:")
|
|
149
|
+
? `${agentSessionKey}:run:${runSessionId}`
|
|
150
|
+
: agentSessionKey;
|
|
151
|
+
const persistSessionEntry = async () => {
|
|
152
|
+
cronSession.store[agentSessionKey] = cronSession.sessionEntry;
|
|
153
|
+
if (runSessionKey !== agentSessionKey) {
|
|
154
|
+
cronSession.store[runSessionKey] = cronSession.sessionEntry;
|
|
155
|
+
}
|
|
156
|
+
await updateSessionStore(cronSession.storePath, (store) => {
|
|
157
|
+
store[agentSessionKey] = cronSession.sessionEntry;
|
|
158
|
+
if (runSessionKey !== agentSessionKey) {
|
|
159
|
+
store[runSessionKey] = cronSession.sessionEntry;
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
};
|
|
163
|
+
const withRunSession = (result) => ({
|
|
164
|
+
...result,
|
|
165
|
+
sessionId: runSessionId,
|
|
166
|
+
sessionKey: runSessionKey,
|
|
167
|
+
});
|
|
168
|
+
if (!cronSession.sessionEntry.label?.trim() && baseSessionKey.startsWith("cron:")) {
|
|
169
|
+
const labelSuffix = typeof params.job.name === "string" && params.job.name.trim()
|
|
170
|
+
? params.job.name.trim()
|
|
171
|
+
: params.job.id;
|
|
172
|
+
cronSession.sessionEntry.label = `Cron: ${labelSuffix}`;
|
|
173
|
+
}
|
|
136
174
|
// Resolve thinking level - job thinking > hooks.gmail.thinking > agent default
|
|
137
175
|
const hooksGmailThinking = isGmailHook
|
|
138
176
|
? normalizeThinkLevel(params.cfg.hooks?.gmail?.thinking)
|
|
@@ -150,20 +188,19 @@ export async function runCronIsolatedAgentTurn(params) {
|
|
|
150
188
|
});
|
|
151
189
|
}
|
|
152
190
|
if (thinkLevel === "xhigh" && !supportsXHighThinking(provider, model)) {
|
|
153
|
-
|
|
191
|
+
logWarn(`[cron:${params.job.id}] Thinking level "xhigh" is not supported for ${provider}/${model}; downgrading to "high".`);
|
|
192
|
+
thinkLevel = "high";
|
|
154
193
|
}
|
|
155
194
|
const timeoutMs = resolveAgentTimeoutMs({
|
|
156
195
|
cfg: cfgWithAgentDefaults,
|
|
157
196
|
overrideSeconds: params.job.payload.kind === "agentTurn" ? params.job.payload.timeoutSeconds : undefined,
|
|
158
197
|
});
|
|
159
198
|
const agentPayload = params.job.payload.kind === "agentTurn" ? params.job.payload : null;
|
|
160
|
-
const
|
|
161
|
-
const
|
|
162
|
-
const deliveryRequested = deliveryMode === "explicit" || (deliveryMode === "auto" && hasExplicitTarget);
|
|
163
|
-
const bestEffortDeliver = agentPayload?.bestEffortDeliver === true;
|
|
199
|
+
const deliveryPlan = resolveCronDeliveryPlan(params.job);
|
|
200
|
+
const deliveryRequested = deliveryPlan.requested;
|
|
164
201
|
const resolvedDelivery = await resolveDeliveryTarget(cfgWithAgentDefaults, agentId, {
|
|
165
|
-
channel:
|
|
166
|
-
to:
|
|
202
|
+
channel: deliveryPlan.channel ?? "last",
|
|
203
|
+
to: deliveryPlan.to,
|
|
167
204
|
});
|
|
168
205
|
const userTimezone = resolveUserTimezone(params.cfg.agents?.defaults?.userTimezone);
|
|
169
206
|
const userTimeFormat = resolveUserTimeFormat(params.cfg.agents?.defaults?.timeFormat);
|
|
@@ -182,8 +219,7 @@ export async function runCronIsolatedAgentTurn(params) {
|
|
|
182
219
|
const suspiciousPatterns = detectSuspiciousPatterns(params.message);
|
|
183
220
|
if (suspiciousPatterns.length > 0) {
|
|
184
221
|
logWarn(`[security] Suspicious patterns detected in external hook content ` +
|
|
185
|
-
`(session=${baseSessionKey}, patterns=${suspiciousPatterns.length}): `
|
|
186
|
-
`${suspiciousPatterns.slice(0, 3).join(", ")}`);
|
|
222
|
+
`(session=${baseSessionKey}, patterns=${suspiciousPatterns.length}): ${suspiciousPatterns.slice(0, 3).join(", ")}`);
|
|
187
223
|
}
|
|
188
224
|
}
|
|
189
225
|
if (shouldWrapExternal) {
|
|
@@ -202,6 +238,10 @@ export async function runCronIsolatedAgentTurn(params) {
|
|
|
202
238
|
// Internal/trusted source - use original format
|
|
203
239
|
commandBody = `${base}\n${timeLine}`.trim();
|
|
204
240
|
}
|
|
241
|
+
if (deliveryRequested) {
|
|
242
|
+
commandBody =
|
|
243
|
+
`${commandBody}\n\nReturn your summary as plain text; it will be delivered automatically. If the task explicitly calls for messaging a specific external recipient, note who/where it should go instead of sending it yourself.`.trim();
|
|
244
|
+
}
|
|
205
245
|
const existingSnapshot = cronSession.sessionEntry.skillsSnapshot;
|
|
206
246
|
const skillsSnapshotVersion = getSkillsSnapshotVersion(workspaceDir);
|
|
207
247
|
const needsSkillsSnapshot = !existingSnapshot || existingSnapshot.version !== skillsSnapshotVersion;
|
|
@@ -218,20 +258,16 @@ export async function runCronIsolatedAgentTurn(params) {
|
|
|
218
258
|
updatedAt: Date.now(),
|
|
219
259
|
skillsSnapshot,
|
|
220
260
|
};
|
|
221
|
-
|
|
222
|
-
await updateSessionStore(cronSession.storePath, (store) => {
|
|
223
|
-
store[agentSessionKey] = cronSession.sessionEntry;
|
|
224
|
-
});
|
|
261
|
+
await persistSessionEntry();
|
|
225
262
|
}
|
|
226
263
|
// Persist systemSent before the run, mirroring the inbound auto-reply behavior.
|
|
227
264
|
cronSession.sessionEntry.systemSent = true;
|
|
228
|
-
|
|
229
|
-
await updateSessionStore(cronSession.storePath, (store) => {
|
|
230
|
-
store[agentSessionKey] = cronSession.sessionEntry;
|
|
231
|
-
});
|
|
265
|
+
await persistSessionEntry();
|
|
232
266
|
let runResult;
|
|
233
267
|
let fallbackProvider = provider;
|
|
234
268
|
let fallbackModel = model;
|
|
269
|
+
const runStartedAt = Date.now();
|
|
270
|
+
let runEndedAt = runStartedAt;
|
|
235
271
|
try {
|
|
236
272
|
const sessionFile = resolveSessionTranscriptPath(cronSession.sessionEntry.sessionId, agentId);
|
|
237
273
|
const resolvedVerboseLevel = normalizeVerboseLevel(cronSession.sessionEntry.verboseLevel) ??
|
|
@@ -289,9 +325,10 @@ export async function runCronIsolatedAgentTurn(params) {
|
|
|
289
325
|
runResult = fallbackResult.result;
|
|
290
326
|
fallbackProvider = fallbackResult.provider;
|
|
291
327
|
fallbackModel = fallbackResult.model;
|
|
328
|
+
runEndedAt = Date.now();
|
|
292
329
|
}
|
|
293
330
|
catch (err) {
|
|
294
|
-
return { status: "error", error: String(err) };
|
|
331
|
+
return withRunSession({ status: "error", error: String(err) });
|
|
295
332
|
}
|
|
296
333
|
const payloads = runResult.payloads ?? [];
|
|
297
334
|
// Update token+model fields in the session store.
|
|
@@ -312,25 +349,34 @@ export async function runCronIsolatedAgentTurn(params) {
|
|
|
312
349
|
if (hasNonzeroUsage(usage)) {
|
|
313
350
|
const input = usage.input ?? 0;
|
|
314
351
|
const output = usage.output ?? 0;
|
|
315
|
-
const promptTokens = input + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
|
|
316
352
|
cronSession.sessionEntry.inputTokens = input;
|
|
317
353
|
cronSession.sessionEntry.outputTokens = output;
|
|
318
354
|
cronSession.sessionEntry.totalTokens =
|
|
319
|
-
|
|
355
|
+
deriveSessionTotalTokens({
|
|
356
|
+
usage,
|
|
357
|
+
contextTokens,
|
|
358
|
+
}) ?? input;
|
|
320
359
|
}
|
|
321
|
-
|
|
322
|
-
await updateSessionStore(cronSession.storePath, (store) => {
|
|
323
|
-
store[agentSessionKey] = cronSession.sessionEntry;
|
|
324
|
-
});
|
|
360
|
+
await persistSessionEntry();
|
|
325
361
|
}
|
|
326
362
|
const firstText = payloads[0]?.text ?? "";
|
|
327
363
|
const summary = pickSummaryFromPayloads(payloads) ?? pickSummaryFromOutput(firstText);
|
|
328
364
|
const outputText = pickLastNonEmptyTextFromPayloads(payloads);
|
|
365
|
+
const synthesizedText = outputText?.trim() || summary?.trim() || undefined;
|
|
366
|
+
const deliveryPayload = pickLastDeliverablePayload(payloads);
|
|
367
|
+
const deliveryPayloads = deliveryPayload !== undefined
|
|
368
|
+
? [deliveryPayload]
|
|
369
|
+
: synthesizedText
|
|
370
|
+
? [{ text: synthesizedText }]
|
|
371
|
+
: [];
|
|
372
|
+
const deliveryPayloadHasStructuredContent = Boolean(deliveryPayload?.mediaUrl) ||
|
|
373
|
+
(deliveryPayload?.mediaUrls?.length ?? 0) > 0 ||
|
|
374
|
+
Object.keys(deliveryPayload?.channelData ?? {}).length > 0;
|
|
375
|
+
const deliveryBestEffort = resolveCronDeliveryBestEffort(params.job);
|
|
329
376
|
// Skip delivery for heartbeat-only responses (HEARTBEAT_OK with no real content).
|
|
330
377
|
const ackMaxChars = resolveHeartbeatAckMaxChars(agentCfg);
|
|
331
378
|
const skipHeartbeatDelivery = deliveryRequested && isHeartbeatOnlyResponse(payloads, ackMaxChars);
|
|
332
379
|
const skipMessagingToolDelivery = deliveryRequested &&
|
|
333
|
-
deliveryMode === "auto" &&
|
|
334
380
|
runResult.didSendViaMessagingTool === true &&
|
|
335
381
|
(runResult.messagingToolSentTargets ?? []).some((target) => matchesMessagingToolDeliveryTarget(target, {
|
|
336
382
|
channel: resolvedDelivery.channel,
|
|
@@ -338,39 +384,101 @@ export async function runCronIsolatedAgentTurn(params) {
|
|
|
338
384
|
accountId: resolvedDelivery.accountId,
|
|
339
385
|
}));
|
|
340
386
|
if (deliveryRequested && !skipHeartbeatDelivery && !skipMessagingToolDelivery) {
|
|
387
|
+
if (resolvedDelivery.error) {
|
|
388
|
+
if (!deliveryBestEffort) {
|
|
389
|
+
return withRunSession({
|
|
390
|
+
status: "error",
|
|
391
|
+
error: resolvedDelivery.error.message,
|
|
392
|
+
summary,
|
|
393
|
+
outputText,
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
logWarn(`[cron:${params.job.id}] ${resolvedDelivery.error.message}`);
|
|
397
|
+
return withRunSession({ status: "ok", summary, outputText });
|
|
398
|
+
}
|
|
341
399
|
if (!resolvedDelivery.to) {
|
|
342
|
-
const
|
|
343
|
-
if (!
|
|
344
|
-
return {
|
|
400
|
+
const message = "cron delivery target is missing";
|
|
401
|
+
if (!deliveryBestEffort) {
|
|
402
|
+
return withRunSession({
|
|
345
403
|
status: "error",
|
|
404
|
+
error: message,
|
|
346
405
|
summary,
|
|
347
406
|
outputText,
|
|
348
|
-
|
|
349
|
-
};
|
|
407
|
+
});
|
|
350
408
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
summary: `Delivery skipped (${reason}).`,
|
|
354
|
-
outputText,
|
|
355
|
-
};
|
|
409
|
+
logWarn(`[cron:${params.job.id}] ${message}`);
|
|
410
|
+
return withRunSession({ status: "ok", summary, outputText });
|
|
356
411
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
412
|
+
// Shared subagent announce flow is text-based; keep direct outbound delivery
|
|
413
|
+
// for media/channel payloads so structured content is preserved.
|
|
414
|
+
if (deliveryPayloadHasStructuredContent) {
|
|
415
|
+
try {
|
|
416
|
+
await deliverOutboundPayloads({
|
|
417
|
+
cfg: cfgWithAgentDefaults,
|
|
418
|
+
channel: resolvedDelivery.channel,
|
|
419
|
+
to: resolvedDelivery.to,
|
|
420
|
+
accountId: resolvedDelivery.accountId,
|
|
421
|
+
threadId: resolvedDelivery.threadId,
|
|
422
|
+
payloads: deliveryPayloads,
|
|
423
|
+
bestEffort: deliveryBestEffort,
|
|
424
|
+
deps: createOutboundSendDeps(params.deps),
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
catch (err) {
|
|
428
|
+
if (!deliveryBestEffort) {
|
|
429
|
+
return withRunSession({ status: "error", summary, outputText, error: String(err) });
|
|
430
|
+
}
|
|
431
|
+
}
|
|
367
432
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
433
|
+
else if (synthesizedText) {
|
|
434
|
+
const announceSessionKey = resolveAgentMainSessionKey({
|
|
435
|
+
cfg: params.cfg,
|
|
436
|
+
agentId,
|
|
437
|
+
});
|
|
438
|
+
const taskLabel = typeof params.job.name === "string" && params.job.name.trim()
|
|
439
|
+
? params.job.name.trim()
|
|
440
|
+
: `cron:${params.job.id}`;
|
|
441
|
+
try {
|
|
442
|
+
const didAnnounce = await runSubagentAnnounceFlow({
|
|
443
|
+
childSessionKey: runSessionKey,
|
|
444
|
+
childRunId: `${params.job.id}:${runSessionId}`,
|
|
445
|
+
requesterSessionKey: announceSessionKey,
|
|
446
|
+
requesterOrigin: {
|
|
447
|
+
channel: resolvedDelivery.channel,
|
|
448
|
+
to: resolvedDelivery.to,
|
|
449
|
+
accountId: resolvedDelivery.accountId,
|
|
450
|
+
threadId: resolvedDelivery.threadId,
|
|
451
|
+
},
|
|
452
|
+
requesterDisplayKey: announceSessionKey,
|
|
453
|
+
task: taskLabel,
|
|
454
|
+
timeoutMs,
|
|
455
|
+
cleanup: "keep",
|
|
456
|
+
roundOneReply: synthesizedText,
|
|
457
|
+
waitForCompletion: false,
|
|
458
|
+
startedAt: runStartedAt,
|
|
459
|
+
endedAt: runEndedAt,
|
|
460
|
+
outcome: { status: "ok" },
|
|
461
|
+
});
|
|
462
|
+
if (!didAnnounce) {
|
|
463
|
+
const message = "cron announce delivery failed";
|
|
464
|
+
if (!deliveryBestEffort) {
|
|
465
|
+
return withRunSession({
|
|
466
|
+
status: "error",
|
|
467
|
+
summary,
|
|
468
|
+
outputText,
|
|
469
|
+
error: message,
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
logWarn(`[cron:${params.job.id}] ${message}`);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
catch (err) {
|
|
476
|
+
if (!deliveryBestEffort) {
|
|
477
|
+
return withRunSession({ status: "error", summary, outputText, error: String(err) });
|
|
478
|
+
}
|
|
479
|
+
logWarn(`[cron:${params.job.id}] ${String(err)}`);
|
|
371
480
|
}
|
|
372
|
-
return { status: "ok", summary, outputText };
|
|
373
481
|
}
|
|
374
482
|
}
|
|
375
|
-
return { status: "ok", summary, outputText };
|
|
483
|
+
return withRunSession({ status: "ok", summary, outputText });
|
|
376
484
|
}
|
|
@@ -21,6 +21,8 @@ export function resolveCronSession(params) {
|
|
|
21
21
|
lastChannel: entry?.lastChannel,
|
|
22
22
|
lastTo: entry?.lastTo,
|
|
23
23
|
lastAccountId: entry?.lastAccountId,
|
|
24
|
+
label: entry?.label,
|
|
25
|
+
displayName: entry?.displayName,
|
|
24
26
|
skillsSnapshot: entry?.skillsSnapshot,
|
|
25
27
|
};
|
|
26
28
|
return { storePath, store, sessionEntry, systemSent, isNewSession: true };
|