@poolzin/pool-bot 2026.2.0 → 2026.2.2
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/CHANGELOG.md +118 -0
- package/README-header.png +0 -0
- package/dist/agents/bash-tools.exec.js +76 -25
- package/dist/agents/cli-runner/helpers.js +9 -11
- package/dist/agents/context.js +1 -1
- package/dist/agents/identity.js +47 -7
- package/dist/agents/memory-search.js +25 -8
- package/dist/agents/model-catalog.js +1 -1
- 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 +8 -10
- package/dist/agents/pi-embedded-runner/model.js +62 -3
- 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/image-tool.js +1 -1
- 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 +74 -82
- 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/mentions.js +1 -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/canvas-host/a2ui/index.html +28 -28
- 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/auth-choice.apply.oauth.js +1 -1
- 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.registry.js +1 -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/compat/legacy-names.js +2 -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/control-ui/assets/{index-CIRDm-Lu.css → index-CSfXd2LO.css} +1 -1
- package/dist/control-ui/assets/{index-CmNMuoem.js → index-HRr1grwl.js} +446 -413
- package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -0
- package/dist/control-ui/index.html +4 -4
- 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 +172 -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.mocks.js +11 -7
- 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/store.js +2 -0
- 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 +3 -3
- 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 +54 -17
- 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/dist/wizard/clack-prompter.js +9 -6
- package/extensions/googlechat/node_modules/.bin/poolbot +21 -0
- package/extensions/googlechat/package.json +2 -2
- package/extensions/line/node_modules/.bin/poolbot +21 -0
- package/extensions/line/package.json +1 -1
- package/extensions/matrix/node_modules/.bin/poolbot +21 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/memory-core/node_modules/.bin/poolbot +21 -0
- package/extensions/memory-core/package.json +4 -1
- package/extensions/twitch/node_modules/.bin/poolbot +21 -0
- package/extensions/twitch/package.json +1 -1
- package/package.json +183 -24
- package/dist/control-ui/assets/index-CmNMuoem.js.map +0 -1
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>
|
|
6
|
+
<title>Poolbot Control</title>
|
|
7
7
|
<meta name="color-scheme" content="dark light" />
|
|
8
8
|
<link rel="icon" href="./favicon.ico" sizes="any" />
|
|
9
|
-
<script type="module" crossorigin src="./assets/index-
|
|
10
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
9
|
+
<script type="module" crossorigin src="./assets/index-HRr1grwl.js"></script>
|
|
10
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CSfXd2LO.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
13
|
-
<
|
|
13
|
+
<poolbot-app></poolbot-app>
|
|
14
14
|
</body>
|
|
15
15
|
</html>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
function normalizeChannel(value) {
|
|
2
|
+
if (typeof value !== "string") {
|
|
3
|
+
return undefined;
|
|
4
|
+
}
|
|
5
|
+
const trimmed = value.trim().toLowerCase();
|
|
6
|
+
if (!trimmed) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
return trimmed;
|
|
10
|
+
}
|
|
11
|
+
function normalizeTo(value) {
|
|
12
|
+
if (typeof value !== "string") {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
const trimmed = value.trim();
|
|
16
|
+
return trimmed ? trimmed : undefined;
|
|
17
|
+
}
|
|
18
|
+
export function resolveCronDeliveryPlan(job) {
|
|
19
|
+
const payload = job.payload.kind === "agentTurn" ? job.payload : null;
|
|
20
|
+
const delivery = job.delivery;
|
|
21
|
+
const hasDelivery = delivery && typeof delivery === "object";
|
|
22
|
+
const rawMode = hasDelivery ? delivery.mode : undefined;
|
|
23
|
+
const normalizedMode = typeof rawMode === "string" ? rawMode.trim().toLowerCase() : rawMode;
|
|
24
|
+
const mode = normalizedMode === "announce"
|
|
25
|
+
? "announce"
|
|
26
|
+
: normalizedMode === "none"
|
|
27
|
+
? "none"
|
|
28
|
+
: normalizedMode === "deliver"
|
|
29
|
+
? "announce"
|
|
30
|
+
: undefined;
|
|
31
|
+
const payloadChannel = normalizeChannel(payload?.channel);
|
|
32
|
+
const payloadTo = normalizeTo(payload?.to);
|
|
33
|
+
const deliveryChannel = normalizeChannel(delivery?.channel);
|
|
34
|
+
const deliveryTo = normalizeTo(delivery?.to);
|
|
35
|
+
const channel = deliveryChannel ?? payloadChannel ?? "last";
|
|
36
|
+
const to = deliveryTo ?? payloadTo;
|
|
37
|
+
if (hasDelivery) {
|
|
38
|
+
const resolvedMode = mode ?? "announce";
|
|
39
|
+
return {
|
|
40
|
+
mode: resolvedMode,
|
|
41
|
+
channel,
|
|
42
|
+
to,
|
|
43
|
+
source: "delivery",
|
|
44
|
+
requested: resolvedMode === "announce",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const legacyMode = payload?.deliver === true ? "explicit" : payload?.deliver === false ? "off" : "auto";
|
|
48
|
+
const hasExplicitTarget = Boolean(to);
|
|
49
|
+
const requested = legacyMode === "explicit" || (legacyMode === "auto" && hasExplicitTarget);
|
|
50
|
+
return {
|
|
51
|
+
mode: requested ? "announce" : "none",
|
|
52
|
+
channel,
|
|
53
|
+
to,
|
|
54
|
+
source: "payload",
|
|
55
|
+
requested,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -5,6 +5,7 @@ import { resolveOutboundTarget, resolveSessionDeliveryTarget, } from "../../infr
|
|
|
5
5
|
export async function resolveDeliveryTarget(cfg, agentId, jobPayload) {
|
|
6
6
|
const requestedChannel = typeof jobPayload.channel === "string" ? jobPayload.channel : "last";
|
|
7
7
|
const explicitTo = typeof jobPayload.to === "string" ? jobPayload.to : undefined;
|
|
8
|
+
const allowMismatchedLastTo = requestedChannel === "last";
|
|
8
9
|
const sessionCfg = cfg.session;
|
|
9
10
|
const mainSessionKey = resolveAgentMainSessionKey({ cfg, agentId });
|
|
10
11
|
const storePath = resolveStorePath(sessionCfg?.store, { agentId });
|
|
@@ -14,7 +15,7 @@ export async function resolveDeliveryTarget(cfg, agentId, jobPayload) {
|
|
|
14
15
|
entry: main,
|
|
15
16
|
requestedChannel,
|
|
16
17
|
explicitTo,
|
|
17
|
-
allowMismatchedLastTo
|
|
18
|
+
allowMismatchedLastTo,
|
|
18
19
|
});
|
|
19
20
|
let fallbackChannel;
|
|
20
21
|
if (!preliminary.channel) {
|
|
@@ -32,15 +33,28 @@ export async function resolveDeliveryTarget(cfg, agentId, jobPayload) {
|
|
|
32
33
|
requestedChannel,
|
|
33
34
|
explicitTo,
|
|
34
35
|
fallbackChannel,
|
|
35
|
-
allowMismatchedLastTo
|
|
36
|
+
allowMismatchedLastTo,
|
|
36
37
|
mode: preliminary.mode,
|
|
37
38
|
})
|
|
38
39
|
: preliminary;
|
|
39
40
|
const channel = resolved.channel ?? fallbackChannel ?? DEFAULT_CHAT_CHANNEL;
|
|
40
41
|
const mode = resolved.mode;
|
|
41
42
|
const toCandidate = resolved.to;
|
|
43
|
+
// Only carry threadId when delivering to the same recipient as the session's
|
|
44
|
+
// last conversation. This prevents stale thread IDs (e.g. from a Telegram
|
|
45
|
+
// supergroup topic) from being sent to a different target (e.g. a private
|
|
46
|
+
// chat) where they would cause API errors.
|
|
47
|
+
const threadId = resolved.threadId && resolved.to && resolved.to === resolved.lastTo
|
|
48
|
+
? resolved.threadId
|
|
49
|
+
: undefined;
|
|
42
50
|
if (!toCandidate) {
|
|
43
|
-
return {
|
|
51
|
+
return {
|
|
52
|
+
channel,
|
|
53
|
+
to: undefined,
|
|
54
|
+
accountId: resolved.accountId,
|
|
55
|
+
threadId,
|
|
56
|
+
mode,
|
|
57
|
+
};
|
|
44
58
|
}
|
|
45
59
|
const docked = resolveOutboundTarget({
|
|
46
60
|
channel,
|
|
@@ -53,6 +67,7 @@ export async function resolveDeliveryTarget(cfg, agentId, jobPayload) {
|
|
|
53
67
|
channel,
|
|
54
68
|
to: docked.ok ? docked.to : undefined,
|
|
55
69
|
accountId: resolved.accountId,
|
|
70
|
+
threadId,
|
|
56
71
|
mode,
|
|
57
72
|
error: docked.ok ? undefined : docked.error,
|
|
58
73
|
};
|
|
@@ -2,24 +2,39 @@ import { DEFAULT_HEARTBEAT_ACK_MAX_CHARS, stripHeartbeatToken, } from "../../aut
|
|
|
2
2
|
import { truncateUtf16Safe } from "../../utils.js";
|
|
3
3
|
export function pickSummaryFromOutput(text) {
|
|
4
4
|
const clean = (text ?? "").trim();
|
|
5
|
-
if (!clean)
|
|
5
|
+
if (!clean) {
|
|
6
6
|
return undefined;
|
|
7
|
+
}
|
|
7
8
|
const limit = 2000;
|
|
8
9
|
return clean.length > limit ? `${truncateUtf16Safe(clean, limit)}…` : clean;
|
|
9
10
|
}
|
|
10
11
|
export function pickSummaryFromPayloads(payloads) {
|
|
11
12
|
for (let i = payloads.length - 1; i >= 0; i--) {
|
|
12
13
|
const summary = pickSummaryFromOutput(payloads[i]?.text);
|
|
13
|
-
if (summary)
|
|
14
|
+
if (summary) {
|
|
14
15
|
return summary;
|
|
16
|
+
}
|
|
15
17
|
}
|
|
16
18
|
return undefined;
|
|
17
19
|
}
|
|
18
20
|
export function pickLastNonEmptyTextFromPayloads(payloads) {
|
|
19
21
|
for (let i = payloads.length - 1; i >= 0; i--) {
|
|
20
22
|
const clean = (payloads[i]?.text ?? "").trim();
|
|
21
|
-
if (clean)
|
|
23
|
+
if (clean) {
|
|
22
24
|
return clean;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
export function pickLastDeliverablePayload(payloads) {
|
|
30
|
+
for (let i = payloads.length - 1; i >= 0; i--) {
|
|
31
|
+
const payload = payloads[i];
|
|
32
|
+
const text = (payload?.text ?? "").trim();
|
|
33
|
+
const hasMedia = Boolean(payload?.mediaUrl) || (payload?.mediaUrls?.length ?? 0) > 0;
|
|
34
|
+
const hasChannelData = Object.keys(payload?.channelData ?? {}).length > 0;
|
|
35
|
+
if (text || hasMedia || hasChannelData) {
|
|
36
|
+
return payload;
|
|
37
|
+
}
|
|
23
38
|
}
|
|
24
39
|
return undefined;
|
|
25
40
|
}
|
|
@@ -28,13 +43,15 @@ export function pickLastNonEmptyTextFromPayloads(payloads) {
|
|
|
28
43
|
* Returns true if delivery should be skipped because there's no real content.
|
|
29
44
|
*/
|
|
30
45
|
export function isHeartbeatOnlyResponse(payloads, ackMaxChars) {
|
|
31
|
-
if (payloads.length === 0)
|
|
46
|
+
if (payloads.length === 0) {
|
|
32
47
|
return true;
|
|
48
|
+
}
|
|
33
49
|
return payloads.every((payload) => {
|
|
34
50
|
// If there's media, we should deliver regardless of text content.
|
|
35
51
|
const hasMedia = (payload.mediaUrls?.length ?? 0) > 0 || Boolean(payload.mediaUrl);
|
|
36
|
-
if (hasMedia)
|
|
52
|
+
if (hasMedia) {
|
|
37
53
|
return false;
|
|
54
|
+
}
|
|
38
55
|
// Use heartbeat mode to check if text is just HEARTBEAT_OK or short ack.
|
|
39
56
|
const result = stripHeartbeatToken(payload.text, {
|
|
40
57
|
mode: "heartbeat",
|
|
@@ -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,102 @@ 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
|
+
announceType: "cron job",
|
|
462
|
+
});
|
|
463
|
+
if (!didAnnounce) {
|
|
464
|
+
const message = "cron announce delivery failed";
|
|
465
|
+
if (!deliveryBestEffort) {
|
|
466
|
+
return withRunSession({
|
|
467
|
+
status: "error",
|
|
468
|
+
summary,
|
|
469
|
+
outputText,
|
|
470
|
+
error: message,
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
logWarn(`[cron:${params.job.id}] ${message}`);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
catch (err) {
|
|
477
|
+
if (!deliveryBestEffort) {
|
|
478
|
+
return withRunSession({ status: "error", summary, outputText, error: String(err) });
|
|
479
|
+
}
|
|
480
|
+
logWarn(`[cron:${params.job.id}] ${String(err)}`);
|
|
371
481
|
}
|
|
372
|
-
return { status: "ok", summary, outputText };
|
|
373
482
|
}
|
|
374
483
|
}
|
|
375
|
-
return { status: "ok", summary, outputText };
|
|
484
|
+
return withRunSession({ status: "ok", summary, outputText });
|
|
376
485
|
}
|
|
@@ -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 };
|