@poolzin/pool-bot 2026.2.21 → 2026.2.23
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 +25 -0
- package/dist/agents/api-key-rotation.js +47 -0
- package/dist/agents/apply-patch-update.js +19 -9
- package/dist/agents/apply-patch.js +72 -47
- package/dist/agents/bash-tools.exec.js +141 -559
- package/dist/agents/cli-backends.js +49 -6
- package/dist/agents/cli-runner/helpers.js +69 -152
- package/dist/agents/cli-runner.js +70 -19
- package/dist/agents/identity.js +20 -1
- package/dist/agents/image-sanitization.js +9 -0
- package/dist/agents/live-auth-keys.js +123 -26
- package/dist/agents/live-model-filter.js +13 -4
- package/dist/agents/model-catalog.js +40 -9
- package/dist/agents/model-forward-compat.js +60 -23
- package/dist/agents/model-selection.js +134 -41
- package/dist/agents/pi-auth-json.js +2 -2
- package/dist/agents/pi-embedded-helpers/bootstrap.js +65 -15
- package/dist/agents/pi-embedded-helpers/errors.js +140 -15
- package/dist/agents/pi-embedded-helpers/images.js +22 -12
- package/dist/agents/pi-embedded-helpers.js +2 -2
- package/dist/agents/pi-embedded-runner/abort.js +10 -3
- package/dist/agents/pi-embedded-runner/compact.js +230 -32
- package/dist/agents/pi-embedded-runner/extra-params.js +203 -12
- package/dist/agents/pi-embedded-runner/google.js +109 -19
- package/dist/agents/pi-embedded-runner/history.js +35 -17
- package/dist/agents/pi-embedded-runner/run/attempt.js +386 -95
- package/dist/agents/pi-embedded-runner/run/images.js +81 -55
- package/dist/agents/pi-embedded-runner/run/payloads.js +89 -39
- package/dist/agents/pi-embedded-runner/run.js +193 -25
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +2 -2
- package/dist/agents/pi-embedded-runner/runs.js +17 -8
- package/dist/agents/pi-embedded-runner/tool-result-context-guard.js +262 -0
- package/dist/agents/pi-embedded-runner.js +1 -1
- package/dist/agents/pi-embedded-subscribe.handlers.tools.js +180 -10
- package/dist/agents/pi-embedded-subscribe.js +37 -0
- package/dist/agents/pi-embedded-subscribe.tools.js +127 -30
- package/dist/agents/pi-model-discovery.js +9 -2
- package/dist/agents/pi-tool-definition-adapter.js +60 -8
- package/dist/agents/pi-tools.before-tool-call.js +1 -1
- package/dist/agents/pi-tools.js +113 -94
- package/dist/agents/pi-tools.read.js +337 -38
- package/dist/agents/poolbot-tools.js +14 -5
- package/dist/agents/sandbox/docker.js +10 -5
- package/dist/agents/sandbox/registry.js +96 -46
- package/dist/agents/sandbox/sanitize-env-vars.js +82 -0
- package/dist/agents/sandbox-paths.js +43 -10
- package/dist/agents/session-tool-result-guard-wrapper.js +23 -11
- package/dist/agents/session-tool-result-guard.js +39 -39
- package/dist/agents/session-transcript-repair.js +36 -33
- package/dist/agents/session-write-lock.js +62 -44
- package/dist/agents/skills/frontmatter.js +49 -88
- package/dist/agents/skills/workspace.js +335 -28
- package/dist/agents/subagent-announce.js +508 -174
- package/dist/agents/subagent-registry.js +45 -4
- package/dist/agents/subagent-spawn.js +16 -33
- package/dist/agents/system-prompt-report.js +27 -10
- package/dist/agents/system-prompt.js +26 -32
- package/dist/agents/tool-call-id.js +69 -17
- package/dist/agents/tool-display-common.js +1 -1
- package/dist/agents/tool-images.js +64 -31
- package/dist/agents/tools/canvas-tool.js +17 -11
- package/dist/agents/tools/common.js +37 -19
- package/dist/agents/tools/cron-tool.js +40 -38
- package/dist/agents/tools/gateway.js +70 -2
- package/dist/agents/tools/message-tool.js +181 -40
- package/dist/agents/tools/nodes-tool.js +128 -36
- package/dist/agents/tools/nodes-utils.js +12 -38
- package/dist/agents/tools/session-status-tool.js +24 -71
- package/dist/agents/tools/sessions-helpers.js +38 -210
- package/dist/agents/tools/sessions-spawn-tool.js +28 -198
- package/dist/agents/tools/telegram-actions.js +58 -7
- package/dist/agents/tools/web-fetch-utils.js +112 -7
- package/dist/agents/tools/web-fetch.js +279 -175
- package/dist/agents/tools/web-shared.js +71 -8
- package/dist/agents/usage.js +25 -16
- package/dist/auto-reply/commands-registry.data.js +85 -11
- package/dist/auto-reply/dispatch.js +40 -21
- package/dist/auto-reply/reply/abort.js +102 -33
- package/dist/auto-reply/reply/commands-core.js +82 -33
- package/dist/auto-reply/reply/commands-export-session.js +1 -1
- package/dist/auto-reply/reply/commands-info.js +41 -12
- package/dist/auto-reply/reply/commands-subagents.js +352 -100
- package/dist/auto-reply/reply/commands-system-prompt.js +2 -2
- package/dist/auto-reply/reply/dispatch-from-config.js +100 -29
- package/dist/auto-reply/reply/elevated-unavailable.js +1 -1
- package/dist/auto-reply/reply/inbound-meta.js +12 -1
- package/dist/auto-reply/reply/mentions.js +18 -11
- package/dist/auto-reply/reply/normalize-reply.js +17 -8
- package/dist/auto-reply/reply/reply-dispatcher.js +62 -10
- package/dist/auto-reply/reply/session.js +102 -21
- package/dist/auto-reply/reply/streaming-directives.js +16 -5
- package/dist/auto-reply/status.js +73 -50
- package/dist/browser/extension-relay.js +3 -3
- package/dist/browser/http-auth.js +1 -1
- package/dist/browser/paths.js +2 -2
- package/dist/build-info.json +3 -3
- package/dist/channels/allowlist-match.js +20 -0
- package/dist/channels/allowlists/resolve-utils.js +65 -2
- package/dist/channels/chat-type.js +8 -4
- package/dist/channels/dock.js +127 -35
- package/dist/channels/draft-stream-loop.js +6 -2
- package/dist/channels/plugins/actions/telegram.js +42 -18
- package/dist/channels/plugins/allowlist-match.js +1 -1
- package/dist/channels/plugins/group-mentions.js +51 -41
- package/dist/channels/plugins/message-action-names.js +2 -0
- package/dist/channels/plugins/message-actions.js +24 -5
- package/dist/channels/plugins/normalize/discord.js +26 -4
- package/dist/channels/plugins/normalize/signal.js +35 -22
- package/dist/channels/plugins/onboarding/helpers.js +8 -26
- package/dist/channels/plugins/outbound/imessage.js +15 -14
- package/dist/channels/registry.js +20 -7
- package/dist/cli/acp-cli.js +7 -5
- package/dist/cli/browser-cli-extension.js +25 -12
- package/dist/cli/browser-cli-state.cookies-storage.js +25 -6
- package/dist/cli/browser-cli-state.js +101 -145
- package/dist/cli/command-options.js +28 -0
- package/dist/cli/completion-cli.js +6 -6
- package/dist/cli/cron-cli/register.cron-add.js +25 -1
- package/dist/cli/cron-cli/register.cron-edit.js +44 -0
- package/dist/cli/cron-cli/shared.js +7 -1
- package/dist/cli/daemon-cli/lifecycle-core.js +23 -21
- package/dist/cli/daemon-cli/lifecycle.js +23 -247
- package/dist/cli/daemon-cli/register-service-commands.js +25 -4
- package/dist/cli/daemon-cli.js +1 -0
- package/dist/cli/devices-cli.js +33 -20
- package/dist/cli/gateway-cli/register.js +37 -105
- package/dist/cli/gateway-cli/run.js +49 -11
- package/dist/cli/nodes-camera.js +59 -4
- package/dist/cli/nodes-cli/register.camera.js +27 -24
- package/dist/cli/nodes-cli/rpc.js +21 -38
- package/dist/cli/qr-cli.js +2 -2
- package/dist/cli/skills-cli.format.js +2 -2
- package/dist/cli/update-cli/progress.js +2 -2
- package/dist/cli/update-cli/restart-helper.js +28 -7
- package/dist/cli/update-cli/shared.js +7 -7
- package/dist/cli/update-cli/status.js +1 -1
- package/dist/cli/update-cli/update-command.js +14 -8
- package/dist/cli/update-cli/wizard.js +2 -2
- package/dist/cli/update-cli.js +21 -1027
- package/dist/commands/auth-choice.apply.anthropic.js +10 -2
- package/dist/commands/channels/add-mutators.js +3 -35
- package/dist/commands/channels/add.js +39 -51
- package/dist/commands/config-validation.js +1 -1
- package/dist/commands/configure.gateway-auth.js +52 -15
- package/dist/commands/configure.gateway.js +84 -40
- package/dist/commands/doctor-completion.js +3 -3
- package/dist/commands/doctor-config-flow.js +536 -16
- package/dist/commands/doctor-gateway-services.js +103 -79
- package/dist/commands/doctor-memory-search.js +9 -9
- package/dist/commands/doctor-platform-notes.js +57 -30
- package/dist/commands/doctor-prompter.js +26 -15
- package/dist/commands/doctor-session-locks.js +1 -1
- package/dist/commands/doctor.js +21 -9
- package/dist/commands/model-picker.js +120 -95
- package/dist/commands/models/set.js +2 -21
- package/dist/commands/models/shared.js +65 -37
- package/dist/commands/onboard-helpers.js +81 -39
- package/dist/commands/openai-codex-oauth.js +1 -1
- package/dist/commands/sessions.js +52 -53
- package/dist/commands/status.summary.js +52 -34
- package/dist/commands/test-wizard-helpers.js +2 -2
- package/dist/config/defaults.js +79 -42
- package/dist/config/group-policy.js +50 -18
- package/dist/config/includes.js +37 -10
- package/dist/config/schema.help.js +5 -4
- package/dist/config/schema.hints.js +2 -2
- package/dist/config/schema.labels.js +1 -0
- package/dist/config/sessions/group.js +12 -11
- package/dist/config/sessions/paths.js +137 -11
- package/dist/config/sessions/store.js +185 -65
- package/dist/config/sessions/types.js +15 -1
- package/dist/config/sessions.js +1 -0
- package/dist/config/telegram-custom-commands.js +3 -2
- package/dist/config/types.js +2 -0
- package/dist/config/zod-schema.agent-defaults.js +6 -27
- package/dist/config/zod-schema.agent-runtime.js +171 -79
- package/dist/config/zod-schema.providers-core.js +138 -65
- package/dist/config/zod-schema.session.js +49 -22
- package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
- package/dist/cron/isolated-agent/run.js +224 -57
- package/dist/cron/normalize.js +48 -45
- package/dist/cron/run-log.js +14 -0
- package/dist/cron/service/jobs.js +190 -28
- package/dist/cron/service/normalize.js +29 -11
- package/dist/cron/service/store.js +30 -44
- package/dist/cron/service/timer.js +182 -96
- package/dist/cron/service.js +3 -0
- package/dist/cron/stagger.js +37 -0
- package/dist/daemon/inspect.js +132 -92
- package/dist/daemon/runtime-paths.js +25 -4
- package/dist/daemon/service-audit.js +47 -16
- package/dist/discord/accounts.js +23 -20
- package/dist/discord/monitor/agent-components.js +1115 -219
- package/dist/discord/monitor/allow-list.js +114 -34
- package/dist/discord/monitor/listeners.js +204 -97
- package/dist/discord/monitor/message-handler.js +21 -10
- package/dist/discord/monitor/message-handler.preflight.js +195 -101
- package/dist/discord/monitor/message-handler.process.js +384 -123
- package/dist/discord/monitor/message-utils.js +86 -23
- package/dist/discord/monitor/native-command.js +77 -57
- package/dist/discord/monitor/provider.js +122 -117
- package/dist/discord/monitor/reply-context.js +20 -16
- package/dist/discord/monitor/reply-delivery.js +40 -8
- package/dist/discord/monitor/rest-fetch.js +22 -0
- package/dist/discord/monitor/threading.js +117 -24
- package/dist/discord/send.js +2 -1
- package/dist/discord/send.outbound.js +124 -11
- package/dist/discord/send.shared.js +112 -72
- package/dist/discord/voice-message.js +3 -3
- package/dist/gateway/auth.js +119 -44
- package/dist/gateway/call.js +76 -34
- package/dist/gateway/channel-health-monitor.js +57 -50
- package/dist/gateway/client.js +63 -29
- package/dist/gateway/control-ui-contract.js +1 -1
- package/dist/gateway/gateway-config-prompts.shared.js +2 -2
- package/dist/gateway/net.js +109 -1
- package/dist/gateway/protocol/index.js +5 -8
- package/dist/gateway/protocol/schema/agent.js +19 -1
- package/dist/gateway/protocol/schema/channels.js +21 -0
- package/dist/gateway/protocol/schema/cron.js +43 -30
- package/dist/gateway/protocol/schema/protocol-schemas.js +6 -11
- package/dist/gateway/protocol/schema/sessions.js +5 -1
- package/dist/gateway/protocol/schema.js +0 -1
- package/dist/gateway/server/presence-events.js +12 -0
- package/dist/gateway/server/ws-connection/message-handler.js +203 -212
- package/dist/gateway/server/ws-connection.js +58 -21
- package/dist/gateway/server-broadcast.js +18 -13
- package/dist/gateway/server-cron.js +177 -10
- package/dist/gateway/server-methods/agent-job.js +131 -38
- package/dist/gateway/server-methods/send.js +60 -14
- package/dist/gateway/server-methods/sessions.js +160 -96
- package/dist/gateway/server-methods/system.js +5 -7
- package/dist/gateway/server-methods-list.js +8 -0
- package/dist/gateway/server-methods.js +24 -8
- package/dist/gateway/server-node-events.js +278 -68
- package/dist/gateway/session-utils.fs.js +316 -75
- package/dist/gateway/session-utils.js +224 -70
- package/dist/gateway/sessions-patch.js +63 -20
- package/dist/gateway/test-temp-config.js +1 -1
- package/dist/gateway/tools-invoke-http.js +118 -70
- package/dist/gateway/ws-log.js +135 -107
- package/dist/hooks/frontmatter.js +36 -82
- package/dist/hooks/install.js +149 -139
- package/dist/hooks/internal-hooks.js +29 -4
- package/dist/hooks/plugin-hooks.js +2 -1
- package/dist/imessage/monitor/deliver.js +10 -4
- package/dist/imessage/monitor/monitor-provider.js +138 -375
- package/dist/imessage/monitor/runtime.js +4 -8
- package/dist/imessage/send.js +65 -19
- package/dist/infra/exec-approvals-allowlist.js +7 -0
- package/dist/infra/exec-approvals.js +35 -920
- package/dist/infra/exec-safe-bin-trust.js +64 -0
- package/dist/infra/heartbeat-runner.js +207 -134
- package/dist/infra/heartbeat-wake.js +183 -22
- package/dist/infra/install-source-utils.js +47 -0
- package/dist/infra/net/ssrf.js +170 -36
- package/dist/infra/outbound/deliver.js +224 -58
- package/dist/infra/outbound/message-action-spec.js +12 -5
- package/dist/infra/outbound/outbound-session.js +27 -25
- package/dist/infra/poolbot-root.js +32 -22
- package/dist/infra/ports.js +14 -11
- package/dist/infra/skills-remote.js +48 -37
- package/dist/infra/system-events.js +25 -11
- package/dist/infra/system-presence.js +26 -33
- package/dist/infra/tmp-poolbot-dir.js +81 -2
- package/dist/infra/wsl.js +37 -1
- package/dist/line/bot-message-context.js +163 -191
- package/dist/logging/subsystem.js +59 -22
- package/dist/markdown/ir.js +124 -50
- package/dist/media/store.js +1 -1
- package/dist/media-understanding/runner.entries.js +42 -25
- package/dist/media-understanding/runner.js +53 -488
- package/dist/memory/embeddings-gemini.js +53 -38
- package/dist/memory/manager-embedding-ops.js +48 -69
- package/dist/pairing/pairing-store.js +178 -119
- package/dist/plugin-sdk/index.js +34 -6
- package/dist/plugins/hooks.js +135 -14
- package/dist/plugins/install.js +190 -152
- package/dist/polls.js +11 -0
- package/dist/routing/resolve-route.js +190 -56
- package/dist/routing/session-key.js +38 -22
- package/dist/runtime.js +35 -9
- package/dist/security/audit-channel.js +1 -1
- package/dist/sessions/session-key-utils.js +29 -11
- package/dist/shared/frontmatter.js +5 -5
- package/dist/shared/node-list-types.js +1 -0
- package/dist/shared/string-normalization.js +15 -0
- package/dist/signal/monitor/event-handler.js +68 -36
- package/dist/signal/send.js +29 -37
- package/dist/slack/monitor/allow-list.js +10 -11
- package/dist/slack/monitor/commands.js +14 -3
- package/dist/slack/monitor/events/interactions.js +4 -4
- package/dist/slack/monitor/media.js +224 -16
- package/dist/slack/monitor/message-handler/dispatch.js +247 -13
- package/dist/slack/monitor/message-handler/prepare.js +128 -45
- package/dist/slack/monitor/slash.js +357 -144
- package/dist/slack/streaming.js +77 -0
- package/dist/telegram/accounts.js +40 -13
- package/dist/telegram/allowed-updates.js +3 -0
- package/dist/telegram/bot/delivery.js +129 -66
- package/dist/telegram/bot/helpers.js +136 -122
- package/dist/telegram/bot-handlers.js +600 -339
- package/dist/telegram/bot-message-context.js +115 -73
- package/dist/telegram/bot-message-dispatch.js +235 -104
- package/dist/telegram/bot-native-command-menu.js +3 -1
- package/dist/telegram/bot-native-commands.js +213 -193
- package/dist/telegram/bot.js +24 -132
- package/dist/telegram/draft-stream.js +84 -75
- package/dist/telegram/format.js +150 -6
- package/dist/telegram/send.js +415 -255
- package/dist/telegram/targets.js +21 -2
- package/dist/telegram/update-offset-store.js +19 -3
- package/dist/terminal/restore.js +5 -2
- package/dist/test-utils/fetch-mock.js +5 -0
- package/dist/version.js +18 -5
- package/dist/web/auto-reply/monitor/broadcast.js +7 -3
- package/dist/web/auto-reply/monitor/on-message.js +6 -3
- package/dist/web/inbound/media.js +34 -8
- package/dist/web/inbound/monitor.js +34 -17
- package/dist/web/inbound/send-api.js +18 -17
- package/dist/web/outbound.js +12 -5
- package/dist/wizard/clack-prompter.js +40 -7
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/device-pair/index.ts +2 -2
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/discord/package.json +1 -1
- package/extensions/feishu/package.json +1 -1
- package/extensions/google-antigravity-auth/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/googlechat/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/irc/src/accounts.ts +1 -1
- package/extensions/irc/src/onboarding.ts +4 -4
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +10 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/mattermost/package.json +1 -1
- package/extensions/memory-core/package.json +1 -1
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +10 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +10 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/openai-codex-auth/package.json +1 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/slack/package.json +1 -1
- package/extensions/telegram/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +10 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +10 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +10 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +10 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +1 -1
- package/skills/apple-reminders/SKILL.md +100 -49
- package/skills/coding-agent/SKILL.md +34 -28
- package/skills/github/SKILL.md +131 -16
- package/skills/imsg/SKILL.md +112 -15
- package/skills/openhue/SKILL.md +101 -19
- package/skills/tmux/SKILL.md +111 -79
- package/skills/weather/SKILL.md +88 -25
- package/dist/agents/openclaw-tools.js +0 -151
- package/dist/agents/tool-security.js +0 -96
- package/dist/gateway/url-validation.js +0 -94
- package/dist/infra/openclaw-root.js +0 -109
- package/dist/infra/tmp-openclaw-dir.js +0 -81
- package/dist/media/path-sanitization.js +0 -78
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
|
+
import { getGlobalHookRunner } from "../../plugins/hook-runner-global.js";
|
|
2
3
|
import { enqueueCommandInLane } from "../../process/command-queue.js";
|
|
3
4
|
import { isMarkdownCapableMessageChannel } from "../../utils/message-channel.js";
|
|
4
5
|
import { resolvePoolbotAgentDir } from "../agent-paths.js";
|
|
@@ -9,8 +10,8 @@ import { FailoverError, resolveFailoverStatus } from "../failover-error.js";
|
|
|
9
10
|
import { ensureAuthProfileStore, getApiKeyForModel, resolveAuthProfileOrder, } from "../model-auth.js";
|
|
10
11
|
import { normalizeProviderId } from "../model-selection.js";
|
|
11
12
|
import { ensurePoolbotModelsJson } from "../models-config.js";
|
|
12
|
-
import {
|
|
13
|
-
import { normalizeUsage } from "../usage.js";
|
|
13
|
+
import { formatBillingErrorMessage, classifyFailoverReason, formatAssistantErrorText, isAuthAssistantError, isBillingAssistantError, isCompactionFailureError, isLikelyContextOverflowError, isFailoverAssistantError, isFailoverErrorMessage, parseImageSizeError, parseImageDimensionError, isRateLimitAssistantError, isTimeoutErrorMessage, pickFallbackThinkingLevel, } from "../pi-embedded-helpers.js";
|
|
14
|
+
import { derivePromptTokens, normalizeUsage } from "../usage.js";
|
|
14
15
|
import { redactRunIdentifier, resolveRunWorkspaceDir } from "../workspace-run.js";
|
|
15
16
|
import { compactEmbeddedPiSessionDirect } from "./compact.js";
|
|
16
17
|
import { resolveGlobalLane, resolveSessionLane } from "./lanes.js";
|
|
@@ -24,8 +25,9 @@ import { describeUnknownError } from "./utils.js";
|
|
|
24
25
|
const ANTHROPIC_MAGIC_STRING_TRIGGER_REFUSAL = "ANTHROPIC_MAGIC_STRING_TRIGGER_REFUSAL";
|
|
25
26
|
const ANTHROPIC_MAGIC_STRING_REPLACEMENT = "ANTHROPIC MAGIC STRING TRIGGER REFUSAL (redacted)";
|
|
26
27
|
function scrubAnthropicRefusalMagic(prompt) {
|
|
27
|
-
if (!prompt.includes(ANTHROPIC_MAGIC_STRING_TRIGGER_REFUSAL))
|
|
28
|
+
if (!prompt.includes(ANTHROPIC_MAGIC_STRING_TRIGGER_REFUSAL)) {
|
|
28
29
|
return prompt;
|
|
30
|
+
}
|
|
29
31
|
return prompt.replaceAll(ANTHROPIC_MAGIC_STRING_TRIGGER_REFUSAL, ANTHROPIC_MAGIC_STRING_REPLACEMENT);
|
|
30
32
|
}
|
|
31
33
|
const createUsageAccumulator = () => ({
|
|
@@ -34,7 +36,13 @@ const createUsageAccumulator = () => ({
|
|
|
34
36
|
cacheRead: 0,
|
|
35
37
|
cacheWrite: 0,
|
|
36
38
|
total: 0,
|
|
39
|
+
lastCacheRead: 0,
|
|
40
|
+
lastCacheWrite: 0,
|
|
41
|
+
lastInput: 0,
|
|
37
42
|
});
|
|
43
|
+
function createCompactionDiagId() {
|
|
44
|
+
return `ovf-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
45
|
+
}
|
|
38
46
|
const hasUsageValues = (usage) => !!usage &&
|
|
39
47
|
[usage.input, usage.output, usage.cacheRead, usage.cacheWrite, usage.total].some((value) => typeof value === "number" && Number.isFinite(value) && value > 0);
|
|
40
48
|
const mergeUsageIntoAccumulator = (target, usage) => {
|
|
@@ -48,6 +56,12 @@ const mergeUsageIntoAccumulator = (target, usage) => {
|
|
|
48
56
|
target.total +=
|
|
49
57
|
usage.total ??
|
|
50
58
|
(usage.input ?? 0) + (usage.output ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0);
|
|
59
|
+
// Track the most recent API call's cache fields for accurate context-size reporting.
|
|
60
|
+
// Accumulated cache totals inflate context size when there are multiple tool-call round-trips,
|
|
61
|
+
// since each call reports cacheRead ≈ current_context_size.
|
|
62
|
+
target.lastCacheRead = usage.cacheRead ?? 0;
|
|
63
|
+
target.lastCacheWrite = usage.cacheWrite ?? 0;
|
|
64
|
+
target.lastInput = usage.input ?? 0;
|
|
51
65
|
};
|
|
52
66
|
const toNormalizedUsage = (usage) => {
|
|
53
67
|
const hasUsage = usage.input > 0 ||
|
|
@@ -58,13 +72,21 @@ const toNormalizedUsage = (usage) => {
|
|
|
58
72
|
if (!hasUsage) {
|
|
59
73
|
return undefined;
|
|
60
74
|
}
|
|
61
|
-
|
|
75
|
+
// Use the LAST API call's cache fields for context-size calculation.
|
|
76
|
+
// The accumulated cacheRead/cacheWrite inflate context size because each tool-call
|
|
77
|
+
// round-trip reports cacheRead ≈ current_context_size, and summing N calls gives
|
|
78
|
+
// N × context_size which gets clamped to contextWindow (e.g. 200k).
|
|
79
|
+
// See: https://github.com/poolbot/poolbot/issues/13698
|
|
80
|
+
//
|
|
81
|
+
// We use lastInput/lastCacheRead/lastCacheWrite (from the most recent API call) for
|
|
82
|
+
// cache-related fields, but keep accumulated output (total generated text this turn).
|
|
83
|
+
const lastPromptTokens = usage.lastInput + usage.lastCacheRead + usage.lastCacheWrite;
|
|
62
84
|
return {
|
|
63
|
-
input: usage.
|
|
85
|
+
input: usage.lastInput || undefined,
|
|
64
86
|
output: usage.output || undefined,
|
|
65
|
-
cacheRead: usage.
|
|
66
|
-
cacheWrite: usage.
|
|
67
|
-
total: usage.
|
|
87
|
+
cacheRead: usage.lastCacheRead || undefined,
|
|
88
|
+
cacheWrite: usage.lastCacheWrite || undefined,
|
|
89
|
+
total: lastPromptTokens + usage.output || undefined,
|
|
68
90
|
};
|
|
69
91
|
};
|
|
70
92
|
export async function runEmbeddedPiAgent(params) {
|
|
@@ -85,6 +107,7 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
85
107
|
const workspaceResolution = resolveRunWorkspaceDir({
|
|
86
108
|
workspaceDir: params.workspaceDir,
|
|
87
109
|
sessionKey: params.sessionKey,
|
|
110
|
+
agentId: params.agentId,
|
|
88
111
|
config: params.config,
|
|
89
112
|
});
|
|
90
113
|
const resolvedWorkspace = workspaceResolution.workspaceDir;
|
|
@@ -95,11 +118,53 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
95
118
|
log.warn(`[workspace-fallback] caller=runEmbeddedPiAgent reason=${workspaceResolution.fallbackReason} run=${params.runId} session=${redactedSessionId} sessionKey=${redactedSessionKey} agent=${workspaceResolution.agentId} workspace=${redactedWorkspace}`);
|
|
96
119
|
}
|
|
97
120
|
const prevCwd = process.cwd();
|
|
98
|
-
|
|
99
|
-
|
|
121
|
+
let provider = (params.provider ?? DEFAULT_PROVIDER).trim() || DEFAULT_PROVIDER;
|
|
122
|
+
let modelId = (params.model ?? DEFAULT_MODEL).trim() || DEFAULT_MODEL;
|
|
100
123
|
const agentDir = params.agentDir ?? resolvePoolbotAgentDir();
|
|
101
124
|
const fallbackConfigured = (params.config?.agents?.defaults?.model?.fallbacks?.length ?? 0) > 0;
|
|
102
125
|
await ensurePoolbotModelsJson(params.config, agentDir);
|
|
126
|
+
// Run before_model_resolve hooks early so plugins can override the
|
|
127
|
+
// provider/model before resolveModel().
|
|
128
|
+
//
|
|
129
|
+
// Legacy compatibility: before_agent_start is also checked for override
|
|
130
|
+
// fields if present. New hook takes precedence when both are set.
|
|
131
|
+
let modelResolveOverride;
|
|
132
|
+
const hookRunner = getGlobalHookRunner();
|
|
133
|
+
const hookCtx = {
|
|
134
|
+
agentId: workspaceResolution.agentId,
|
|
135
|
+
sessionKey: params.sessionKey,
|
|
136
|
+
sessionId: params.sessionId,
|
|
137
|
+
workspaceDir: resolvedWorkspace,
|
|
138
|
+
messageProvider: params.messageProvider ?? undefined,
|
|
139
|
+
};
|
|
140
|
+
if (hookRunner?.hasHooks("before_model_resolve")) {
|
|
141
|
+
try {
|
|
142
|
+
modelResolveOverride = await hookRunner.runBeforeModelResolve({ prompt: params.prompt }, hookCtx);
|
|
143
|
+
}
|
|
144
|
+
catch (hookErr) {
|
|
145
|
+
log.warn(`before_model_resolve hook failed: ${String(hookErr)}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (hookRunner?.hasHooks("before_agent_start")) {
|
|
149
|
+
try {
|
|
150
|
+
const legacyResult = await hookRunner.runBeforeAgentStart({ prompt: params.prompt }, hookCtx);
|
|
151
|
+
modelResolveOverride = {
|
|
152
|
+
providerOverride: modelResolveOverride?.providerOverride ?? legacyResult?.providerOverride,
|
|
153
|
+
modelOverride: modelResolveOverride?.modelOverride ?? legacyResult?.modelOverride,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
catch (hookErr) {
|
|
157
|
+
log.warn(`before_agent_start hook (legacy model resolve path) failed: ${String(hookErr)}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (modelResolveOverride?.providerOverride) {
|
|
161
|
+
provider = modelResolveOverride.providerOverride;
|
|
162
|
+
log.info(`[hooks] provider overridden to ${provider}`);
|
|
163
|
+
}
|
|
164
|
+
if (modelResolveOverride?.modelOverride) {
|
|
165
|
+
modelId = modelResolveOverride.modelOverride;
|
|
166
|
+
log.info(`[hooks] model overridden to ${modelId}`);
|
|
167
|
+
}
|
|
103
168
|
const { model, error, authStorage, modelRegistry } = resolveModel(provider, modelId, agentDir, params.config);
|
|
104
169
|
if (!model) {
|
|
105
170
|
throw new Error(error ?? `Unknown model: ${provider}/${modelId}`);
|
|
@@ -154,8 +219,9 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
154
219
|
let apiKeyInfo = null;
|
|
155
220
|
let lastProfileId;
|
|
156
221
|
const resolveAuthProfileFailoverReason = (params) => {
|
|
157
|
-
if (params.allInCooldown)
|
|
222
|
+
if (params.allInCooldown) {
|
|
158
223
|
return "rate_limit";
|
|
224
|
+
}
|
|
159
225
|
const classified = classifyFailoverReason(params.message);
|
|
160
226
|
return classified ?? "auth";
|
|
161
227
|
};
|
|
@@ -177,8 +243,9 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
177
243
|
cause: params.error,
|
|
178
244
|
});
|
|
179
245
|
}
|
|
180
|
-
if (params.error instanceof Error)
|
|
246
|
+
if (params.error instanceof Error) {
|
|
181
247
|
throw params.error;
|
|
248
|
+
}
|
|
182
249
|
throw new Error(message);
|
|
183
250
|
};
|
|
184
251
|
const resolveApiKeyForCandidate = async (candidate) => {
|
|
@@ -213,8 +280,9 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
213
280
|
lastProfileId = apiKeyInfo.profileId;
|
|
214
281
|
};
|
|
215
282
|
const advanceAuthProfile = async () => {
|
|
216
|
-
if (lockedProfileId)
|
|
283
|
+
if (lockedProfileId) {
|
|
217
284
|
return false;
|
|
285
|
+
}
|
|
218
286
|
let nextIndex = profileIndex + 1;
|
|
219
287
|
while (nextIndex < profileCandidates.length) {
|
|
220
288
|
const candidate = profileCandidates[nextIndex];
|
|
@@ -230,8 +298,9 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
230
298
|
return true;
|
|
231
299
|
}
|
|
232
300
|
catch (err) {
|
|
233
|
-
if (candidate && candidate === lockedProfileId)
|
|
301
|
+
if (candidate && candidate === lockedProfileId) {
|
|
234
302
|
throw err;
|
|
303
|
+
}
|
|
235
304
|
nextIndex += 1;
|
|
236
305
|
}
|
|
237
306
|
}
|
|
@@ -254,8 +323,9 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
254
323
|
}
|
|
255
324
|
}
|
|
256
325
|
catch (err) {
|
|
257
|
-
if (err instanceof FailoverError)
|
|
326
|
+
if (err instanceof FailoverError) {
|
|
258
327
|
throw err;
|
|
328
|
+
}
|
|
259
329
|
if (profileCandidates[profileIndex] === lockedProfileId) {
|
|
260
330
|
throwAuthProfileFailover({ allInCooldown: false, error: err });
|
|
261
331
|
}
|
|
@@ -268,6 +338,7 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
268
338
|
let overflowCompactionAttempts = 0;
|
|
269
339
|
let toolResultTruncationAttempted = false;
|
|
270
340
|
const usageAccumulator = createUsageAccumulator();
|
|
341
|
+
let lastRunPromptUsage;
|
|
271
342
|
let autoCompactionCount = 0;
|
|
272
343
|
try {
|
|
273
344
|
while (true) {
|
|
@@ -304,6 +375,7 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
304
375
|
model,
|
|
305
376
|
authStorage,
|
|
306
377
|
modelRegistry,
|
|
378
|
+
agentId: workspaceResolution.agentId,
|
|
307
379
|
thinkLevel,
|
|
308
380
|
verboseLevel: params.verboseLevel,
|
|
309
381
|
reasoningLevel: params.reasoningLevel,
|
|
@@ -322,20 +394,30 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
322
394
|
blockReplyBreak: params.blockReplyBreak,
|
|
323
395
|
blockReplyChunking: params.blockReplyChunking,
|
|
324
396
|
onReasoningStream: params.onReasoningStream,
|
|
397
|
+
onReasoningEnd: params.onReasoningEnd,
|
|
325
398
|
onToolResult: params.onToolResult,
|
|
326
399
|
onAgentEvent: params.onAgentEvent,
|
|
327
400
|
extraSystemPrompt: params.extraSystemPrompt,
|
|
401
|
+
inputProvenance: params.inputProvenance,
|
|
328
402
|
streamParams: params.streamParams,
|
|
329
403
|
ownerNumbers: params.ownerNumbers,
|
|
330
404
|
enforceFinalTag: params.enforceFinalTag,
|
|
331
405
|
});
|
|
332
|
-
const { aborted, promptError, timedOut, sessionIdUsed, lastAssistant } = attempt;
|
|
333
|
-
|
|
334
|
-
|
|
406
|
+
const { aborted, promptError, timedOut, timedOutDuringCompaction, sessionIdUsed, lastAssistant, } = attempt;
|
|
407
|
+
const lastAssistantUsage = normalizeUsage(lastAssistant?.usage);
|
|
408
|
+
const attemptUsage = attempt.attemptUsage ?? lastAssistantUsage;
|
|
409
|
+
mergeUsageIntoAccumulator(usageAccumulator, attemptUsage);
|
|
410
|
+
// Keep prompt size from the latest model call so session totalTokens
|
|
411
|
+
// reflects current context usage, not accumulated tool-loop usage.
|
|
412
|
+
lastRunPromptUsage = lastAssistantUsage ?? attemptUsage;
|
|
413
|
+
const lastTurnTotal = lastAssistantUsage?.total ?? attemptUsage?.total;
|
|
414
|
+
const attemptCompactionCount = Math.max(0, attempt.compactionCount ?? 0);
|
|
415
|
+
autoCompactionCount += attemptCompactionCount;
|
|
335
416
|
const formattedAssistantErrorText = lastAssistant
|
|
336
417
|
? formatAssistantErrorText(lastAssistant, {
|
|
337
418
|
cfg: params.config,
|
|
338
419
|
sessionKey: params.sessionKey ?? params.sessionId,
|
|
420
|
+
provider,
|
|
339
421
|
})
|
|
340
422
|
: undefined;
|
|
341
423
|
const assistantErrorText = lastAssistant?.stopReason === "error"
|
|
@@ -345,30 +427,49 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
345
427
|
? (() => {
|
|
346
428
|
if (promptError) {
|
|
347
429
|
const errorText = describeUnknownError(promptError);
|
|
348
|
-
if (
|
|
430
|
+
if (isLikelyContextOverflowError(errorText)) {
|
|
349
431
|
return { text: errorText, source: "promptError" };
|
|
350
432
|
}
|
|
351
433
|
// Prompt submission failed with a non-overflow error. Do not
|
|
352
434
|
// inspect prior assistant errors from history for this attempt.
|
|
353
435
|
return null;
|
|
354
436
|
}
|
|
355
|
-
if (assistantErrorText &&
|
|
437
|
+
if (assistantErrorText && isLikelyContextOverflowError(assistantErrorText)) {
|
|
356
438
|
return { text: assistantErrorText, source: "assistantError" };
|
|
357
439
|
}
|
|
358
440
|
return null;
|
|
359
441
|
})()
|
|
360
442
|
: null;
|
|
361
443
|
if (contextOverflowError) {
|
|
444
|
+
const overflowDiagId = createCompactionDiagId();
|
|
362
445
|
const errorText = contextOverflowError.text;
|
|
363
446
|
const msgCount = attempt.messagesSnapshot?.length ?? 0;
|
|
364
447
|
log.warn(`[context-overflow-diag] sessionKey=${params.sessionKey ?? params.sessionId} ` +
|
|
365
448
|
`provider=${provider}/${modelId} source=${contextOverflowError.source} ` +
|
|
366
449
|
`messages=${msgCount} sessionFile=${params.sessionFile} ` +
|
|
367
|
-
`
|
|
450
|
+
`diagId=${overflowDiagId} compactionAttempts=${overflowCompactionAttempts} ` +
|
|
451
|
+
`error=${errorText.slice(0, 200)}`);
|
|
368
452
|
const isCompactionFailure = isCompactionFailureError(errorText);
|
|
369
|
-
|
|
453
|
+
const hadAttemptLevelCompaction = attemptCompactionCount > 0;
|
|
454
|
+
// If this attempt already compacted (SDK auto-compaction), avoid immediately
|
|
455
|
+
// running another explicit compaction for the same overflow trigger.
|
|
456
|
+
if (!isCompactionFailure &&
|
|
457
|
+
hadAttemptLevelCompaction &&
|
|
458
|
+
overflowCompactionAttempts < MAX_OVERFLOW_COMPACTION_ATTEMPTS) {
|
|
459
|
+
overflowCompactionAttempts++;
|
|
460
|
+
log.warn(`context overflow persisted after in-attempt compaction (attempt ${overflowCompactionAttempts}/${MAX_OVERFLOW_COMPACTION_ATTEMPTS}); retrying prompt without additional compaction for ${provider}/${modelId}`);
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
// Attempt explicit overflow compaction only when this attempt did not
|
|
464
|
+
// already auto-compact.
|
|
370
465
|
if (!isCompactionFailure &&
|
|
466
|
+
!hadAttemptLevelCompaction &&
|
|
371
467
|
overflowCompactionAttempts < MAX_OVERFLOW_COMPACTION_ATTEMPTS) {
|
|
468
|
+
if (log.isEnabled("debug")) {
|
|
469
|
+
log.debug(`[compaction-diag] decision diagId=${overflowDiagId} branch=compact ` +
|
|
470
|
+
`isCompactionFailure=${isCompactionFailure} hasOversizedToolResults=unknown ` +
|
|
471
|
+
`attempt=${overflowCompactionAttempts + 1} maxAttempts=${MAX_OVERFLOW_COMPACTION_ATTEMPTS}`);
|
|
472
|
+
}
|
|
372
473
|
overflowCompactionAttempts++;
|
|
373
474
|
log.warn(`context overflow detected (attempt ${overflowCompactionAttempts}/${MAX_OVERFLOW_COMPACTION_ATTEMPTS}); attempting auto-compaction for ${provider}/${modelId}`);
|
|
374
475
|
const compactResult = await compactEmbeddedPiSessionDirect({
|
|
@@ -386,11 +487,16 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
386
487
|
senderIsOwner: params.senderIsOwner,
|
|
387
488
|
provider,
|
|
388
489
|
model: modelId,
|
|
490
|
+
runId: params.runId,
|
|
389
491
|
thinkLevel,
|
|
390
492
|
reasoningLevel: params.reasoningLevel,
|
|
391
493
|
bashElevated: params.bashElevated,
|
|
392
494
|
extraSystemPrompt: params.extraSystemPrompt,
|
|
393
495
|
ownerNumbers: params.ownerNumbers,
|
|
496
|
+
trigger: "overflow",
|
|
497
|
+
diagId: overflowDiagId,
|
|
498
|
+
attempt: overflowCompactionAttempts,
|
|
499
|
+
maxAttempts: MAX_OVERFLOW_COMPACTION_ATTEMPTS,
|
|
394
500
|
});
|
|
395
501
|
if (compactResult.compacted) {
|
|
396
502
|
autoCompactionCount += 1;
|
|
@@ -411,6 +517,11 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
411
517
|
})
|
|
412
518
|
: false;
|
|
413
519
|
if (hasOversized) {
|
|
520
|
+
if (log.isEnabled("debug")) {
|
|
521
|
+
log.debug(`[compaction-diag] decision diagId=${overflowDiagId} branch=truncate_tool_results ` +
|
|
522
|
+
`isCompactionFailure=${isCompactionFailure} hasOversizedToolResults=${hasOversized} ` +
|
|
523
|
+
`attempt=${overflowCompactionAttempts} maxAttempts=${MAX_OVERFLOW_COMPACTION_ATTEMPTS}`);
|
|
524
|
+
}
|
|
414
525
|
toolResultTruncationAttempted = true;
|
|
415
526
|
log.warn(`[context-overflow-recovery] Attempting tool result truncation for ${provider}/${modelId} ` +
|
|
416
527
|
`(contextWindow=${contextWindowTokens} tokens)`);
|
|
@@ -428,6 +539,19 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
428
539
|
}
|
|
429
540
|
log.warn(`[context-overflow-recovery] Tool result truncation did not help: ${truncResult.reason ?? "unknown"}`);
|
|
430
541
|
}
|
|
542
|
+
else if (log.isEnabled("debug")) {
|
|
543
|
+
log.debug(`[compaction-diag] decision diagId=${overflowDiagId} branch=give_up ` +
|
|
544
|
+
`isCompactionFailure=${isCompactionFailure} hasOversizedToolResults=${hasOversized} ` +
|
|
545
|
+
`attempt=${overflowCompactionAttempts} maxAttempts=${MAX_OVERFLOW_COMPACTION_ATTEMPTS}`);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
if ((isCompactionFailure ||
|
|
549
|
+
overflowCompactionAttempts >= MAX_OVERFLOW_COMPACTION_ATTEMPTS ||
|
|
550
|
+
toolResultTruncationAttempted) &&
|
|
551
|
+
log.isEnabled("debug")) {
|
|
552
|
+
log.debug(`[compaction-diag] decision diagId=${overflowDiagId} branch=give_up ` +
|
|
553
|
+
`isCompactionFailure=${isCompactionFailure} hasOversizedToolResults=unknown ` +
|
|
554
|
+
`attempt=${overflowCompactionAttempts} maxAttempts=${MAX_OVERFLOW_COMPACTION_ATTEMPTS}`);
|
|
431
555
|
}
|
|
432
556
|
const kind = isCompactionFailure ? "compaction_failure" : "context_overflow";
|
|
433
557
|
return {
|
|
@@ -570,7 +694,8 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
570
694
|
log.warn(`Profile ${lastProfileId} rejected image payload${details ? ` (${details})` : ""}.`);
|
|
571
695
|
}
|
|
572
696
|
// Treat timeout as potential rate limit (Antigravity hangs on rate limit)
|
|
573
|
-
|
|
697
|
+
// But exclude post-prompt compaction timeouts (model succeeded; no profile issue)
|
|
698
|
+
const shouldRotate = (!aborted && failoverFailure) || (timedOut && !timedOutDuringCompaction);
|
|
574
699
|
if (shouldRotate) {
|
|
575
700
|
if (lastProfileId) {
|
|
576
701
|
const reason = timedOut || assistantFailoverReason === "timeout"
|
|
@@ -591,14 +716,16 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
591
716
|
}
|
|
592
717
|
}
|
|
593
718
|
const rotated = await advanceAuthProfile();
|
|
594
|
-
if (rotated)
|
|
719
|
+
if (rotated) {
|
|
595
720
|
continue;
|
|
721
|
+
}
|
|
596
722
|
if (fallbackConfigured) {
|
|
597
723
|
// Prefer formatted error message (user-friendly) over raw errorMessage
|
|
598
724
|
const message = (lastAssistant
|
|
599
725
|
? formatAssistantErrorText(lastAssistant, {
|
|
600
726
|
cfg: params.config,
|
|
601
727
|
sessionKey: params.sessionKey ?? params.sessionId,
|
|
728
|
+
provider,
|
|
602
729
|
})
|
|
603
730
|
: undefined) ||
|
|
604
731
|
lastAssistant?.errorMessage?.trim() ||
|
|
@@ -607,7 +734,7 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
607
734
|
: rateLimitFailure
|
|
608
735
|
? "LLM request rate limited."
|
|
609
736
|
: billingFailure
|
|
610
|
-
?
|
|
737
|
+
? formatBillingErrorMessage(provider)
|
|
611
738
|
: authFailure
|
|
612
739
|
? "LLM request unauthorized."
|
|
613
740
|
: "LLM request failed.");
|
|
@@ -623,11 +750,23 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
623
750
|
}
|
|
624
751
|
}
|
|
625
752
|
const usage = toNormalizedUsage(usageAccumulator);
|
|
753
|
+
if (usage && lastTurnTotal && lastTurnTotal > 0) {
|
|
754
|
+
usage.total = lastTurnTotal;
|
|
755
|
+
}
|
|
756
|
+
// Extract the last individual API call's usage for context-window
|
|
757
|
+
// utilization display. The accumulated `usage` sums input tokens
|
|
758
|
+
// across all calls (tool-use loops, compaction retries), which
|
|
759
|
+
// overstates the actual context size. `lastCallUsage` reflects only
|
|
760
|
+
// the final call, giving an accurate snapshot of current context.
|
|
761
|
+
const lastCallUsage = normalizeUsage(lastAssistant?.usage);
|
|
762
|
+
const promptTokens = derivePromptTokens(lastRunPromptUsage);
|
|
626
763
|
const agentMeta = {
|
|
627
764
|
sessionId: sessionIdUsed,
|
|
628
765
|
provider: lastAssistant?.provider ?? provider,
|
|
629
766
|
model: lastAssistant?.model ?? model.id,
|
|
630
767
|
usage,
|
|
768
|
+
lastCallUsage: lastCallUsage ?? undefined,
|
|
769
|
+
promptTokens,
|
|
631
770
|
compactionCount: autoCompactionCount > 0 ? autoCompactionCount : undefined,
|
|
632
771
|
};
|
|
633
772
|
const payloads = buildEmbeddedRunPayloads({
|
|
@@ -637,11 +776,38 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
637
776
|
lastToolError: attempt.lastToolError,
|
|
638
777
|
config: params.config,
|
|
639
778
|
sessionKey: params.sessionKey ?? params.sessionId,
|
|
779
|
+
provider,
|
|
640
780
|
verboseLevel: params.verboseLevel,
|
|
641
781
|
reasoningLevel: params.reasoningLevel,
|
|
642
782
|
toolResultFormat: resolvedToolResultFormat,
|
|
783
|
+
suppressToolErrorWarnings: params.suppressToolErrorWarnings,
|
|
643
784
|
inlineToolResultsAllowed: false,
|
|
644
785
|
});
|
|
786
|
+
// Timeout aborts can leave the run without any assistant payloads.
|
|
787
|
+
// Emit an explicit timeout error instead of silently completing, so
|
|
788
|
+
// callers do not lose the turn as an orphaned user message.
|
|
789
|
+
if (timedOut && !timedOutDuringCompaction && payloads.length === 0) {
|
|
790
|
+
return {
|
|
791
|
+
payloads: [
|
|
792
|
+
{
|
|
793
|
+
text: "Request timed out before a response was generated. " +
|
|
794
|
+
"Please try again, or increase `agents.defaults.timeoutSeconds` in your config.",
|
|
795
|
+
isError: true,
|
|
796
|
+
},
|
|
797
|
+
],
|
|
798
|
+
meta: {
|
|
799
|
+
durationMs: Date.now() - started,
|
|
800
|
+
agentMeta,
|
|
801
|
+
aborted,
|
|
802
|
+
systemPromptReport: attempt.systemPromptReport,
|
|
803
|
+
},
|
|
804
|
+
didSendViaMessagingTool: attempt.didSendViaMessagingTool,
|
|
805
|
+
messagingToolSentTexts: attempt.messagingToolSentTexts,
|
|
806
|
+
messagingToolSentMediaUrls: attempt.messagingToolSentMediaUrls,
|
|
807
|
+
messagingToolSentTargets: attempt.messagingToolSentTargets,
|
|
808
|
+
successfulCronAdds: attempt.successfulCronAdds,
|
|
809
|
+
};
|
|
810
|
+
}
|
|
645
811
|
log.debug(`embedded run done: runId=${params.runId} sessionId=${params.sessionId} durationMs=${Date.now() - started} aborted=${aborted}`);
|
|
646
812
|
if (lastProfileId) {
|
|
647
813
|
await markAuthProfileGood({
|
|
@@ -677,7 +843,9 @@ export async function runEmbeddedPiAgent(params) {
|
|
|
677
843
|
},
|
|
678
844
|
didSendViaMessagingTool: attempt.didSendViaMessagingTool,
|
|
679
845
|
messagingToolSentTexts: attempt.messagingToolSentTexts,
|
|
846
|
+
messagingToolSentMediaUrls: attempt.messagingToolSentMediaUrls,
|
|
680
847
|
messagingToolSentTargets: attempt.messagingToolSentTargets,
|
|
848
|
+
successfulCronAdds: attempt.successfulCronAdds,
|
|
681
849
|
};
|
|
682
850
|
}
|
|
683
851
|
}
|
|
@@ -78,7 +78,7 @@ vi.mock("../model-auth.js", () => ({
|
|
|
78
78
|
resolveAuthProfileOrder: vi.fn(() => []),
|
|
79
79
|
}));
|
|
80
80
|
vi.mock("../models-config.js", () => ({
|
|
81
|
-
|
|
81
|
+
ensurePoolbotModelsJson: vi.fn(async () => { }),
|
|
82
82
|
}));
|
|
83
83
|
vi.mock("../context-window-guard.js", () => ({
|
|
84
84
|
CONTEXT_WINDOW_HARD_MIN_TOKENS: 1000,
|
|
@@ -101,7 +101,7 @@ vi.mock("../../utils/message-channel.js", () => ({
|
|
|
101
101
|
isMarkdownCapableMessageChannel: vi.fn(() => true),
|
|
102
102
|
}));
|
|
103
103
|
vi.mock("../agent-paths.js", () => ({
|
|
104
|
-
|
|
104
|
+
resolvePoolbotAgentDir: vi.fn(() => "/tmp/agent-dir"),
|
|
105
105
|
}));
|
|
106
106
|
vi.mock("../defaults.js", () => ({
|
|
107
107
|
DEFAULT_CONTEXT_TOKENS: 200000,
|
|
@@ -38,13 +38,18 @@ export function isEmbeddedPiRunActive(sessionId) {
|
|
|
38
38
|
}
|
|
39
39
|
export function isEmbeddedPiRunStreaming(sessionId) {
|
|
40
40
|
const handle = ACTIVE_EMBEDDED_RUNS.get(sessionId);
|
|
41
|
-
if (!handle)
|
|
41
|
+
if (!handle) {
|
|
42
42
|
return false;
|
|
43
|
+
}
|
|
43
44
|
return handle.isStreaming();
|
|
44
45
|
}
|
|
46
|
+
export function getActiveEmbeddedRunCount() {
|
|
47
|
+
return ACTIVE_EMBEDDED_RUNS.size;
|
|
48
|
+
}
|
|
45
49
|
export function waitForEmbeddedPiRunEnd(sessionId, timeoutMs = 15_000) {
|
|
46
|
-
if (!sessionId || !ACTIVE_EMBEDDED_RUNS.has(sessionId))
|
|
50
|
+
if (!sessionId || !ACTIVE_EMBEDDED_RUNS.has(sessionId)) {
|
|
47
51
|
return Promise.resolve(true);
|
|
52
|
+
}
|
|
48
53
|
diag.debug(`waiting for run end: sessionId=${sessionId} timeoutMs=${timeoutMs}`);
|
|
49
54
|
return new Promise((resolve) => {
|
|
50
55
|
const waiters = EMBEDDED_RUN_WAITERS.get(sessionId) ?? new Set();
|
|
@@ -52,8 +57,9 @@ export function waitForEmbeddedPiRunEnd(sessionId, timeoutMs = 15_000) {
|
|
|
52
57
|
resolve,
|
|
53
58
|
timer: setTimeout(() => {
|
|
54
59
|
waiters.delete(waiter);
|
|
55
|
-
if (waiters.size === 0)
|
|
60
|
+
if (waiters.size === 0) {
|
|
56
61
|
EMBEDDED_RUN_WAITERS.delete(sessionId);
|
|
62
|
+
}
|
|
57
63
|
diag.warn(`wait timeout: sessionId=${sessionId} timeoutMs=${timeoutMs}`);
|
|
58
64
|
resolve(false);
|
|
59
65
|
}, Math.max(100, timeoutMs)),
|
|
@@ -62,8 +68,9 @@ export function waitForEmbeddedPiRunEnd(sessionId, timeoutMs = 15_000) {
|
|
|
62
68
|
EMBEDDED_RUN_WAITERS.set(sessionId, waiters);
|
|
63
69
|
if (!ACTIVE_EMBEDDED_RUNS.has(sessionId)) {
|
|
64
70
|
waiters.delete(waiter);
|
|
65
|
-
if (waiters.size === 0)
|
|
71
|
+
if (waiters.size === 0) {
|
|
66
72
|
EMBEDDED_RUN_WAITERS.delete(sessionId);
|
|
73
|
+
}
|
|
67
74
|
clearTimeout(waiter.timer);
|
|
68
75
|
resolve(true);
|
|
69
76
|
}
|
|
@@ -71,8 +78,9 @@ export function waitForEmbeddedPiRunEnd(sessionId, timeoutMs = 15_000) {
|
|
|
71
78
|
}
|
|
72
79
|
function notifyEmbeddedRunEnded(sessionId) {
|
|
73
80
|
const waiters = EMBEDDED_RUN_WAITERS.get(sessionId);
|
|
74
|
-
if (!waiters || waiters.size === 0)
|
|
81
|
+
if (!waiters || waiters.size === 0) {
|
|
75
82
|
return;
|
|
83
|
+
}
|
|
76
84
|
EMBEDDED_RUN_WAITERS.delete(sessionId);
|
|
77
85
|
diag.debug(`notifying waiters: sessionId=${sessionId} waiterCount=${waiters.size}`);
|
|
78
86
|
for (const waiter of waiters) {
|
|
@@ -80,11 +88,12 @@ function notifyEmbeddedRunEnded(sessionId) {
|
|
|
80
88
|
waiter.resolve(true);
|
|
81
89
|
}
|
|
82
90
|
}
|
|
83
|
-
export function setActiveEmbeddedRun(sessionId, handle) {
|
|
91
|
+
export function setActiveEmbeddedRun(sessionId, handle, sessionKey) {
|
|
84
92
|
const wasActive = ACTIVE_EMBEDDED_RUNS.has(sessionId);
|
|
85
93
|
ACTIVE_EMBEDDED_RUNS.set(sessionId, handle);
|
|
86
94
|
logSessionStateChange({
|
|
87
95
|
sessionId,
|
|
96
|
+
sessionKey,
|
|
88
97
|
state: "processing",
|
|
89
98
|
reason: wasActive ? "run_replaced" : "run_started",
|
|
90
99
|
});
|
|
@@ -92,10 +101,10 @@ export function setActiveEmbeddedRun(sessionId, handle) {
|
|
|
92
101
|
diag.debug(`run registered: sessionId=${sessionId} totalActive=${ACTIVE_EMBEDDED_RUNS.size}`);
|
|
93
102
|
}
|
|
94
103
|
}
|
|
95
|
-
export function clearActiveEmbeddedRun(sessionId, handle) {
|
|
104
|
+
export function clearActiveEmbeddedRun(sessionId, handle, sessionKey) {
|
|
96
105
|
if (ACTIVE_EMBEDDED_RUNS.get(sessionId) === handle) {
|
|
97
106
|
ACTIVE_EMBEDDED_RUNS.delete(sessionId);
|
|
98
|
-
logSessionStateChange({ sessionId, state: "idle", reason: "run_completed" });
|
|
107
|
+
logSessionStateChange({ sessionId, sessionKey, state: "idle", reason: "run_completed" });
|
|
99
108
|
if (!sessionId.startsWith("probe-")) {
|
|
100
109
|
diag.debug(`run cleared: sessionId=${sessionId} totalActive=${ACTIVE_EMBEDDED_RUNS.size}`);
|
|
101
110
|
}
|