@poolzin/pool-bot 2026.2.20 → 2026.2.22
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-auth.js +12 -0
- package/dist/agents/model-catalog.js +40 -9
- package/dist/agents/model-fallback.js +24 -0
- 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 -80
- 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/provider/config-loader.js +76 -0
- package/dist/agents/provider/index.js +15 -0
- package/dist/agents/provider/integration.js +136 -0
- package/dist/agents/provider/models-dev.js +129 -0
- package/dist/agents/provider/rate-limits.js +458 -0
- package/dist/agents/provider/request-monitor.js +449 -0
- package/dist/agents/provider/session-binding.js +376 -0
- package/dist/agents/provider/token-pool.js +541 -0
- 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/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/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 +5 -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 +5 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +5 -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 +5 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +5 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +5 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +5 -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/plcode-controller/SKILL.md +156 -0
- package/skills/plcode-controller/assets/operator-prompts.md +65 -0
- package/skills/plcode-controller/references/command-cheatsheet.md +53 -0
- package/skills/plcode-controller/references/failure-handling.md +60 -0
- package/skills/plcode-controller/references/model-selection.md +57 -0
- package/skills/plcode-controller/references/plan-vs-build.md +52 -0
- package/skills/plcode-controller/references/question-handling.md +40 -0
- package/skills/plcode-controller/references/session-management.md +63 -0
- package/skills/plcode-controller/references/workflow.md +35 -0
- package/skills/tmux/SKILL.md +111 -79
- package/skills/weather/SKILL.md +88 -25
|
@@ -1,14 +1,19 @@
|
|
|
1
|
+
import { CLI_FRESH_WATCHDOG_DEFAULTS, CLI_RESUME_WATCHDOG_DEFAULTS, } from "./cli-watchdog-defaults.js";
|
|
1
2
|
import { normalizeProviderId } from "./model-selection.js";
|
|
2
3
|
const CLAUDE_MODEL_ALIASES = {
|
|
3
4
|
opus: "opus",
|
|
5
|
+
"opus-4.6": "opus",
|
|
4
6
|
"opus-4.5": "opus",
|
|
5
7
|
"opus-4": "opus",
|
|
8
|
+
"claude-opus-4-6": "opus",
|
|
6
9
|
"claude-opus-4-5": "opus",
|
|
7
10
|
"claude-opus-4": "opus",
|
|
8
11
|
sonnet: "sonnet",
|
|
12
|
+
"sonnet-4.6": "sonnet",
|
|
9
13
|
"sonnet-4.5": "sonnet",
|
|
10
14
|
"sonnet-4.1": "sonnet",
|
|
11
15
|
"sonnet-4.0": "sonnet",
|
|
16
|
+
"claude-sonnet-4-6": "sonnet",
|
|
12
17
|
"claude-sonnet-4-5": "sonnet",
|
|
13
18
|
"claude-sonnet-4-1": "sonnet",
|
|
14
19
|
"claude-sonnet-4-0": "sonnet",
|
|
@@ -38,6 +43,12 @@ const DEFAULT_CLAUDE_BACKEND = {
|
|
|
38
43
|
systemPromptMode: "append",
|
|
39
44
|
systemPromptWhen: "first",
|
|
40
45
|
clearEnv: ["ANTHROPIC_API_KEY", "ANTHROPIC_API_KEY_OLD"],
|
|
46
|
+
reliability: {
|
|
47
|
+
watchdog: {
|
|
48
|
+
fresh: { ...CLI_FRESH_WATCHDOG_DEFAULTS },
|
|
49
|
+
resume: { ...CLI_RESUME_WATCHDOG_DEFAULTS },
|
|
50
|
+
},
|
|
51
|
+
},
|
|
41
52
|
serialize: true,
|
|
42
53
|
};
|
|
43
54
|
const DEFAULT_CODEX_BACKEND = {
|
|
@@ -61,6 +72,12 @@ const DEFAULT_CODEX_BACKEND = {
|
|
|
61
72
|
sessionMode: "existing",
|
|
62
73
|
imageArg: "--image",
|
|
63
74
|
imageMode: "repeat",
|
|
75
|
+
reliability: {
|
|
76
|
+
watchdog: {
|
|
77
|
+
fresh: { ...CLI_FRESH_WATCHDOG_DEFAULTS },
|
|
78
|
+
resume: { ...CLI_RESUME_WATCHDOG_DEFAULTS },
|
|
79
|
+
},
|
|
80
|
+
},
|
|
64
81
|
serialize: true,
|
|
65
82
|
};
|
|
66
83
|
function normalizeBackendKey(key) {
|
|
@@ -68,14 +85,20 @@ function normalizeBackendKey(key) {
|
|
|
68
85
|
}
|
|
69
86
|
function pickBackendConfig(config, normalizedId) {
|
|
70
87
|
for (const [key, entry] of Object.entries(config)) {
|
|
71
|
-
if (normalizeBackendKey(key) === normalizedId)
|
|
88
|
+
if (normalizeBackendKey(key) === normalizedId) {
|
|
72
89
|
return entry;
|
|
90
|
+
}
|
|
73
91
|
}
|
|
74
92
|
return undefined;
|
|
75
93
|
}
|
|
76
94
|
function mergeBackendConfig(base, override) {
|
|
77
|
-
if (!override)
|
|
95
|
+
if (!override) {
|
|
78
96
|
return { ...base };
|
|
97
|
+
}
|
|
98
|
+
const baseFresh = base.reliability?.watchdog?.fresh ?? {};
|
|
99
|
+
const baseResume = base.reliability?.watchdog?.resume ?? {};
|
|
100
|
+
const overrideFresh = override.reliability?.watchdog?.fresh ?? {};
|
|
101
|
+
const overrideResume = override.reliability?.watchdog?.resume ?? {};
|
|
79
102
|
return {
|
|
80
103
|
...base,
|
|
81
104
|
...override,
|
|
@@ -86,6 +109,22 @@ function mergeBackendConfig(base, override) {
|
|
|
86
109
|
sessionIdFields: override.sessionIdFields ?? base.sessionIdFields,
|
|
87
110
|
sessionArgs: override.sessionArgs ?? base.sessionArgs,
|
|
88
111
|
resumeArgs: override.resumeArgs ?? base.resumeArgs,
|
|
112
|
+
reliability: {
|
|
113
|
+
...base.reliability,
|
|
114
|
+
...override.reliability,
|
|
115
|
+
watchdog: {
|
|
116
|
+
...base.reliability?.watchdog,
|
|
117
|
+
...override.reliability?.watchdog,
|
|
118
|
+
fresh: {
|
|
119
|
+
...baseFresh,
|
|
120
|
+
...overrideFresh,
|
|
121
|
+
},
|
|
122
|
+
resume: {
|
|
123
|
+
...baseResume,
|
|
124
|
+
...overrideResume,
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
},
|
|
89
128
|
};
|
|
90
129
|
}
|
|
91
130
|
export function resolveCliBackendIds(cfg) {
|
|
@@ -106,21 +145,25 @@ export function resolveCliBackendConfig(provider, cfg) {
|
|
|
106
145
|
if (normalized === "claude-cli") {
|
|
107
146
|
const merged = mergeBackendConfig(DEFAULT_CLAUDE_BACKEND, override);
|
|
108
147
|
const command = merged.command?.trim();
|
|
109
|
-
if (!command)
|
|
148
|
+
if (!command) {
|
|
110
149
|
return null;
|
|
150
|
+
}
|
|
111
151
|
return { id: normalized, config: { ...merged, command } };
|
|
112
152
|
}
|
|
113
153
|
if (normalized === "codex-cli") {
|
|
114
154
|
const merged = mergeBackendConfig(DEFAULT_CODEX_BACKEND, override);
|
|
115
155
|
const command = merged.command?.trim();
|
|
116
|
-
if (!command)
|
|
156
|
+
if (!command) {
|
|
117
157
|
return null;
|
|
158
|
+
}
|
|
118
159
|
return { id: normalized, config: { ...merged, command } };
|
|
119
160
|
}
|
|
120
|
-
if (!override)
|
|
161
|
+
if (!override) {
|
|
121
162
|
return null;
|
|
163
|
+
}
|
|
122
164
|
const command = override.command?.trim();
|
|
123
|
-
if (!command)
|
|
165
|
+
if (!command) {
|
|
124
166
|
return null;
|
|
167
|
+
}
|
|
125
168
|
return { id: normalized, config: { ...override, command } };
|
|
126
169
|
}
|
|
@@ -2,120 +2,22 @@ import crypto from "node:crypto";
|
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
|
-
import { runExec } from "../../process/exec.js";
|
|
6
5
|
import { buildTtsSystemPromptHint } from "../../tts/tts.js";
|
|
7
|
-
import {
|
|
6
|
+
import { isRecord } from "../../utils.js";
|
|
7
|
+
import { buildModelAliasLines } from "../model-alias-lines.js";
|
|
8
8
|
import { resolveDefaultModelForAgent } from "../model-selection.js";
|
|
9
9
|
import { detectRuntimeShell } from "../shell-utils.js";
|
|
10
10
|
import { buildSystemPromptParams } from "../system-prompt-params.js";
|
|
11
11
|
import { buildAgentSystemPrompt } from "../system-prompt.js";
|
|
12
|
+
export { buildCliSupervisorScopeKey, resolveCliNoOutputTimeoutMs } from "./reliability.js";
|
|
12
13
|
const CLI_RUN_QUEUE = new Map();
|
|
13
|
-
export async function cleanupResumeProcesses(backend, sessionId) {
|
|
14
|
-
if (process.platform === "win32")
|
|
15
|
-
return;
|
|
16
|
-
const resumeArgs = backend.resumeArgs ?? [];
|
|
17
|
-
if (resumeArgs.length === 0)
|
|
18
|
-
return;
|
|
19
|
-
if (!resumeArgs.some((arg) => arg.includes("{sessionId}")))
|
|
20
|
-
return;
|
|
21
|
-
const commandToken = path.basename(backend.command ?? "").trim();
|
|
22
|
-
if (!commandToken)
|
|
23
|
-
return;
|
|
24
|
-
const resumeTokens = resumeArgs.map((arg) => arg.replaceAll("{sessionId}", sessionId));
|
|
25
|
-
const pattern = [commandToken, ...resumeTokens]
|
|
26
|
-
.filter(Boolean)
|
|
27
|
-
.map((token) => escapeRegExp(token))
|
|
28
|
-
.join(".*");
|
|
29
|
-
if (!pattern)
|
|
30
|
-
return;
|
|
31
|
-
try {
|
|
32
|
-
await runExec("pkill", ["-f", pattern]);
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
// ignore missing pkill or no matches
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
function buildSessionMatchers(backend) {
|
|
39
|
-
const commandToken = path.basename(backend.command ?? "").trim();
|
|
40
|
-
if (!commandToken)
|
|
41
|
-
return [];
|
|
42
|
-
const matchers = [];
|
|
43
|
-
const sessionArg = backend.sessionArg?.trim();
|
|
44
|
-
const sessionArgs = backend.sessionArgs ?? [];
|
|
45
|
-
const resumeArgs = backend.resumeArgs ?? [];
|
|
46
|
-
const addMatcher = (args) => {
|
|
47
|
-
if (args.length === 0)
|
|
48
|
-
return;
|
|
49
|
-
const tokens = [commandToken, ...args];
|
|
50
|
-
const pattern = tokens
|
|
51
|
-
.map((token, index) => {
|
|
52
|
-
const tokenPattern = tokenToRegex(token);
|
|
53
|
-
return index === 0 ? `(?:^|\\s)${tokenPattern}` : `\\s+${tokenPattern}`;
|
|
54
|
-
})
|
|
55
|
-
.join("");
|
|
56
|
-
matchers.push(new RegExp(pattern));
|
|
57
|
-
};
|
|
58
|
-
if (sessionArgs.some((arg) => arg.includes("{sessionId}"))) {
|
|
59
|
-
addMatcher(sessionArgs);
|
|
60
|
-
}
|
|
61
|
-
else if (sessionArg) {
|
|
62
|
-
addMatcher([sessionArg, "{sessionId}"]);
|
|
63
|
-
}
|
|
64
|
-
if (resumeArgs.some((arg) => arg.includes("{sessionId}"))) {
|
|
65
|
-
addMatcher(resumeArgs);
|
|
66
|
-
}
|
|
67
|
-
return matchers;
|
|
68
|
-
}
|
|
69
|
-
function tokenToRegex(token) {
|
|
70
|
-
if (!token.includes("{sessionId}"))
|
|
71
|
-
return escapeRegExp(token);
|
|
72
|
-
const parts = token.split("{sessionId}").map((part) => escapeRegExp(part));
|
|
73
|
-
return parts.join("\\S+");
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Cleanup suspended Poolbot CLI processes that have accumulated.
|
|
77
|
-
* Only cleans up if there are more than the threshold (default: 10).
|
|
78
|
-
*/
|
|
79
|
-
export async function cleanupSuspendedCliProcesses(backend, threshold = 10) {
|
|
80
|
-
if (process.platform === "win32")
|
|
81
|
-
return;
|
|
82
|
-
const matchers = buildSessionMatchers(backend);
|
|
83
|
-
if (matchers.length === 0)
|
|
84
|
-
return;
|
|
85
|
-
try {
|
|
86
|
-
const { stdout } = await runExec("ps", ["-ax", "-o", "pid=,stat=,command="]);
|
|
87
|
-
const suspended = [];
|
|
88
|
-
for (const line of stdout.split("\n")) {
|
|
89
|
-
const trimmed = line.trim();
|
|
90
|
-
if (!trimmed)
|
|
91
|
-
continue;
|
|
92
|
-
const match = /^(\d+)\s+(\S+)\s+(.*)$/.exec(trimmed);
|
|
93
|
-
if (!match)
|
|
94
|
-
continue;
|
|
95
|
-
const pid = Number(match[1]);
|
|
96
|
-
const stat = match[2] ?? "";
|
|
97
|
-
const command = match[3] ?? "";
|
|
98
|
-
if (!Number.isFinite(pid))
|
|
99
|
-
continue;
|
|
100
|
-
if (!stat.includes("T"))
|
|
101
|
-
continue;
|
|
102
|
-
if (!matchers.some((matcher) => matcher.test(command)))
|
|
103
|
-
continue;
|
|
104
|
-
suspended.push(pid);
|
|
105
|
-
}
|
|
106
|
-
if (suspended.length > threshold) {
|
|
107
|
-
// Verified locally: stopped (T) processes ignore SIGTERM, so use SIGKILL.
|
|
108
|
-
await runExec("kill", ["-9", ...suspended.map((pid) => String(pid))]);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
catch {
|
|
112
|
-
// ignore errors - best effort cleanup
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
14
|
export function enqueueCliRun(key, task) {
|
|
116
15
|
const prior = CLI_RUN_QUEUE.get(key) ?? Promise.resolve();
|
|
117
16
|
const chained = prior.catch(() => undefined).then(task);
|
|
118
|
-
|
|
17
|
+
// Keep queue continuity even when a run rejects, without emitting unhandled rejections.
|
|
18
|
+
const tracked = chained
|
|
19
|
+
.catch(() => undefined)
|
|
20
|
+
.finally(() => {
|
|
119
21
|
if (CLI_RUN_QUEUE.get(key) === tracked) {
|
|
120
22
|
CLI_RUN_QUEUE.delete(key);
|
|
121
23
|
}
|
|
@@ -123,22 +25,6 @@ export function enqueueCliRun(key, task) {
|
|
|
123
25
|
CLI_RUN_QUEUE.set(key, tracked);
|
|
124
26
|
return chained;
|
|
125
27
|
}
|
|
126
|
-
function buildModelAliasLines(cfg) {
|
|
127
|
-
const models = cfg?.agents?.defaults?.models ?? {};
|
|
128
|
-
const entries = [];
|
|
129
|
-
for (const [keyRaw, entryRaw] of Object.entries(models)) {
|
|
130
|
-
const model = String(keyRaw ?? "").trim();
|
|
131
|
-
if (!model)
|
|
132
|
-
continue;
|
|
133
|
-
const alias = String(entryRaw?.alias ?? "").trim();
|
|
134
|
-
if (!alias)
|
|
135
|
-
continue;
|
|
136
|
-
entries.push({ alias, model });
|
|
137
|
-
}
|
|
138
|
-
return entries
|
|
139
|
-
.sort((a, b) => a.alias.localeCompare(b.alias))
|
|
140
|
-
.map((entry) => `- ${entry.alias}: ${entry.model}`);
|
|
141
|
-
}
|
|
142
28
|
export function buildSystemPrompt(params) {
|
|
143
29
|
const defaultModelRef = resolveDefaultModelForAgent({
|
|
144
30
|
cfg: params.config ?? {},
|
|
@@ -182,15 +68,18 @@ export function buildSystemPrompt(params) {
|
|
|
182
68
|
}
|
|
183
69
|
export function normalizeCliModel(modelId, backend) {
|
|
184
70
|
const trimmed = modelId.trim();
|
|
185
|
-
if (!trimmed)
|
|
71
|
+
if (!trimmed) {
|
|
186
72
|
return trimmed;
|
|
73
|
+
}
|
|
187
74
|
const direct = backend.modelAliases?.[trimmed];
|
|
188
|
-
if (direct)
|
|
75
|
+
if (direct) {
|
|
189
76
|
return direct;
|
|
77
|
+
}
|
|
190
78
|
const lower = trimmed.toLowerCase();
|
|
191
79
|
const mapped = backend.modelAliases?.[lower];
|
|
192
|
-
if (mapped)
|
|
80
|
+
if (mapped) {
|
|
193
81
|
return mapped;
|
|
82
|
+
}
|
|
194
83
|
return trimmed;
|
|
195
84
|
}
|
|
196
85
|
function toUsage(raw) {
|
|
@@ -200,27 +89,36 @@ function toUsage(raw) {
|
|
|
200
89
|
const cacheRead = pick("cache_read_input_tokens") ?? pick("cached_input_tokens") ?? pick("cacheRead");
|
|
201
90
|
const cacheWrite = pick("cache_write_input_tokens") ?? pick("cacheWrite");
|
|
202
91
|
const total = pick("total_tokens") ?? pick("total");
|
|
203
|
-
if (!input && !output && !cacheRead && !cacheWrite && !total)
|
|
92
|
+
if (!input && !output && !cacheRead && !cacheWrite && !total) {
|
|
204
93
|
return undefined;
|
|
94
|
+
}
|
|
205
95
|
return { input, output, cacheRead, cacheWrite, total };
|
|
206
96
|
}
|
|
207
97
|
function collectText(value) {
|
|
208
|
-
if (!value)
|
|
98
|
+
if (!value) {
|
|
209
99
|
return "";
|
|
210
|
-
|
|
100
|
+
}
|
|
101
|
+
if (typeof value === "string") {
|
|
211
102
|
return value;
|
|
212
|
-
|
|
103
|
+
}
|
|
104
|
+
if (Array.isArray(value)) {
|
|
213
105
|
return value.map((entry) => collectText(entry)).join("");
|
|
214
|
-
|
|
106
|
+
}
|
|
107
|
+
if (!isRecord(value)) {
|
|
215
108
|
return "";
|
|
216
|
-
|
|
109
|
+
}
|
|
110
|
+
if (typeof value.text === "string") {
|
|
217
111
|
return value.text;
|
|
218
|
-
|
|
112
|
+
}
|
|
113
|
+
if (typeof value.content === "string") {
|
|
219
114
|
return value.content;
|
|
220
|
-
|
|
115
|
+
}
|
|
116
|
+
if (Array.isArray(value.content)) {
|
|
221
117
|
return value.content.map((entry) => collectText(entry)).join("");
|
|
222
|
-
|
|
118
|
+
}
|
|
119
|
+
if (isRecord(value.message)) {
|
|
223
120
|
return collectText(value.message);
|
|
121
|
+
}
|
|
224
122
|
return "";
|
|
225
123
|
}
|
|
226
124
|
function pickSessionId(parsed, backend) {
|
|
@@ -232,15 +130,17 @@ function pickSessionId(parsed, backend) {
|
|
|
232
130
|
];
|
|
233
131
|
for (const field of fields) {
|
|
234
132
|
const value = parsed[field];
|
|
235
|
-
if (typeof value === "string" && value.trim())
|
|
133
|
+
if (typeof value === "string" && value.trim()) {
|
|
236
134
|
return value.trim();
|
|
135
|
+
}
|
|
237
136
|
}
|
|
238
137
|
return undefined;
|
|
239
138
|
}
|
|
240
139
|
export function parseCliJson(raw, backend) {
|
|
241
140
|
const trimmed = raw.trim();
|
|
242
|
-
if (!trimmed)
|
|
141
|
+
if (!trimmed) {
|
|
243
142
|
return null;
|
|
143
|
+
}
|
|
244
144
|
let parsed;
|
|
245
145
|
try {
|
|
246
146
|
parsed = JSON.parse(trimmed);
|
|
@@ -248,8 +148,9 @@ export function parseCliJson(raw, backend) {
|
|
|
248
148
|
catch {
|
|
249
149
|
return null;
|
|
250
150
|
}
|
|
251
|
-
if (!isRecord(parsed))
|
|
151
|
+
if (!isRecord(parsed)) {
|
|
252
152
|
return null;
|
|
153
|
+
}
|
|
253
154
|
const sessionId = pickSessionId(parsed, backend);
|
|
254
155
|
const usage = isRecord(parsed.usage) ? toUsage(parsed.usage) : undefined;
|
|
255
156
|
const text = collectText(parsed.message) ||
|
|
@@ -263,8 +164,9 @@ export function parseCliJsonl(raw, backend) {
|
|
|
263
164
|
.split(/\r?\n/g)
|
|
264
165
|
.map((line) => line.trim())
|
|
265
166
|
.filter(Boolean);
|
|
266
|
-
if (lines.length === 0)
|
|
167
|
+
if (lines.length === 0) {
|
|
267
168
|
return null;
|
|
169
|
+
}
|
|
268
170
|
let sessionId;
|
|
269
171
|
let usage;
|
|
270
172
|
const texts = [];
|
|
@@ -276,10 +178,12 @@ export function parseCliJsonl(raw, backend) {
|
|
|
276
178
|
catch {
|
|
277
179
|
continue;
|
|
278
180
|
}
|
|
279
|
-
if (!isRecord(parsed))
|
|
181
|
+
if (!isRecord(parsed)) {
|
|
280
182
|
continue;
|
|
281
|
-
|
|
183
|
+
}
|
|
184
|
+
if (!sessionId) {
|
|
282
185
|
sessionId = pickSessionId(parsed, backend);
|
|
186
|
+
}
|
|
283
187
|
if (!sessionId && typeof parsed.thread_id === "string") {
|
|
284
188
|
sessionId = parsed.thread_id.trim();
|
|
285
189
|
}
|
|
@@ -295,32 +199,40 @@ export function parseCliJsonl(raw, backend) {
|
|
|
295
199
|
}
|
|
296
200
|
}
|
|
297
201
|
const text = texts.join("\n").trim();
|
|
298
|
-
if (!text)
|
|
202
|
+
if (!text) {
|
|
299
203
|
return null;
|
|
204
|
+
}
|
|
300
205
|
return { text, sessionId, usage };
|
|
301
206
|
}
|
|
302
207
|
export function resolveSystemPromptUsage(params) {
|
|
303
208
|
const systemPrompt = params.systemPrompt?.trim();
|
|
304
|
-
if (!systemPrompt)
|
|
209
|
+
if (!systemPrompt) {
|
|
305
210
|
return null;
|
|
211
|
+
}
|
|
306
212
|
const when = params.backend.systemPromptWhen ?? "first";
|
|
307
|
-
if (when === "never")
|
|
213
|
+
if (when === "never") {
|
|
308
214
|
return null;
|
|
309
|
-
|
|
215
|
+
}
|
|
216
|
+
if (when === "first" && !params.isNewSession) {
|
|
310
217
|
return null;
|
|
311
|
-
|
|
218
|
+
}
|
|
219
|
+
if (!params.backend.systemPromptArg?.trim()) {
|
|
312
220
|
return null;
|
|
221
|
+
}
|
|
313
222
|
return systemPrompt;
|
|
314
223
|
}
|
|
315
224
|
export function resolveSessionIdToSend(params) {
|
|
316
225
|
const mode = params.backend.sessionMode ?? "always";
|
|
317
226
|
const existing = params.cliSessionId?.trim();
|
|
318
|
-
if (mode === "none")
|
|
227
|
+
if (mode === "none") {
|
|
319
228
|
return { sessionId: undefined, isNew: !existing };
|
|
320
|
-
|
|
229
|
+
}
|
|
230
|
+
if (mode === "existing") {
|
|
321
231
|
return { sessionId: existing, isNew: !existing };
|
|
322
|
-
|
|
232
|
+
}
|
|
233
|
+
if (existing) {
|
|
323
234
|
return { sessionId: existing, isNew: false };
|
|
235
|
+
}
|
|
324
236
|
return { sessionId: crypto.randomUUID(), isNew: true };
|
|
325
237
|
}
|
|
326
238
|
export function resolvePromptInput(params) {
|
|
@@ -335,19 +247,24 @@ export function resolvePromptInput(params) {
|
|
|
335
247
|
}
|
|
336
248
|
function resolveImageExtension(mimeType) {
|
|
337
249
|
const normalized = mimeType.toLowerCase();
|
|
338
|
-
if (normalized.includes("png"))
|
|
250
|
+
if (normalized.includes("png")) {
|
|
339
251
|
return "png";
|
|
340
|
-
|
|
252
|
+
}
|
|
253
|
+
if (normalized.includes("jpeg") || normalized.includes("jpg")) {
|
|
341
254
|
return "jpg";
|
|
342
|
-
|
|
255
|
+
}
|
|
256
|
+
if (normalized.includes("gif")) {
|
|
343
257
|
return "gif";
|
|
344
|
-
|
|
258
|
+
}
|
|
259
|
+
if (normalized.includes("webp")) {
|
|
345
260
|
return "webp";
|
|
261
|
+
}
|
|
346
262
|
return "bin";
|
|
347
263
|
}
|
|
348
264
|
export function appendImagePathsToPrompt(prompt, paths) {
|
|
349
|
-
if (!paths.length)
|
|
265
|
+
if (!paths.length) {
|
|
350
266
|
return prompt;
|
|
267
|
+
}
|
|
351
268
|
const trimmed = prompt.trimEnd();
|
|
352
269
|
const separator = trimmed ? "\n\n" : "";
|
|
353
270
|
return `${trimmed}${separator}${paths.join("\n")}`;
|
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
import { resolveHeartbeatPrompt } from "../auto-reply/heartbeat.js";
|
|
2
|
-
import { isTruthyEnvValue } from "../infra/env.js";
|
|
3
2
|
import { shouldLogVerbose } from "../globals.js";
|
|
3
|
+
import { isTruthyEnvValue } from "../infra/env.js";
|
|
4
4
|
import { createSubsystemLogger } from "../logging/subsystem.js";
|
|
5
|
-
import {
|
|
6
|
-
import { resolveUserPath } from "../utils.js";
|
|
7
|
-
import { resolvePoolbotDocsPath } from "./docs-path.js";
|
|
5
|
+
import { getProcessSupervisor } from "../process/supervisor/index.js";
|
|
8
6
|
import { resolveSessionAgentIds } from "./agent-scope.js";
|
|
9
7
|
import { makeBootstrapWarn, resolveBootstrapContextForRun } from "./bootstrap-files.js";
|
|
10
8
|
import { resolveCliBackendConfig } from "./cli-backends.js";
|
|
11
|
-
import { appendImagePathsToPrompt, buildCliArgs, buildSystemPrompt,
|
|
9
|
+
import { appendImagePathsToPrompt, buildCliSupervisorScopeKey, buildCliArgs, buildSystemPrompt, enqueueCliRun, normalizeCliModel, parseCliJson, parseCliJsonl, resolveCliNoOutputTimeoutMs, resolvePromptInput, resolveSessionIdToSend, resolveSystemPromptUsage, writeCliImages, } from "./cli-runner/helpers.js";
|
|
10
|
+
import { resolvePoolbotDocsPath } from "./docs-path.js";
|
|
12
11
|
import { FailoverError, resolveFailoverStatus } from "./failover-error.js";
|
|
13
12
|
import { classifyFailoverReason, isFailoverErrorMessage } from "./pi-embedded-helpers.js";
|
|
13
|
+
import { redactRunIdentifier, resolveRunWorkspaceDir } from "./workspace-run.js";
|
|
14
14
|
const log = createSubsystemLogger("agent/claude-cli");
|
|
15
15
|
export async function runCliAgent(params) {
|
|
16
16
|
const started = Date.now();
|
|
17
|
-
const
|
|
17
|
+
const workspaceResolution = resolveRunWorkspaceDir({
|
|
18
|
+
workspaceDir: params.workspaceDir,
|
|
19
|
+
sessionKey: params.sessionKey,
|
|
20
|
+
agentId: params.agentId,
|
|
21
|
+
config: params.config,
|
|
22
|
+
});
|
|
23
|
+
const resolvedWorkspace = workspaceResolution.workspaceDir;
|
|
24
|
+
const redactedSessionId = redactRunIdentifier(params.sessionId);
|
|
25
|
+
const redactedSessionKey = redactRunIdentifier(params.sessionKey);
|
|
26
|
+
const redactedWorkspace = redactRunIdentifier(resolvedWorkspace);
|
|
27
|
+
if (workspaceResolution.usedFallback) {
|
|
28
|
+
log.warn(`[workspace-fallback] caller=runCliAgent reason=${workspaceResolution.fallbackReason} run=${params.runId} session=${redactedSessionId} sessionKey=${redactedSessionKey} agent=${workspaceResolution.agentId} workspace=${redactedWorkspace}`);
|
|
29
|
+
}
|
|
18
30
|
const workspaceDir = resolvedWorkspace;
|
|
19
31
|
const backendResolved = resolveCliBackendConfig(params.provider, params.config);
|
|
20
32
|
if (!backendResolved) {
|
|
@@ -117,7 +129,7 @@ export async function runCliAgent(params) {
|
|
|
117
129
|
try {
|
|
118
130
|
const output = await enqueueCliRun(queueKey, async () => {
|
|
119
131
|
log.info(`cli exec: provider=${params.provider} model=${normalizedModel} promptChars=${params.prompt.length}`);
|
|
120
|
-
const logOutputText = isTruthyEnvValue(process.env.POOLBOT_CLAUDE_CLI_LOG_OUTPUT
|
|
132
|
+
const logOutputText = isTruthyEnvValue(process.env.POOLBOT_CLAUDE_CLI_LOG_OUTPUT);
|
|
121
133
|
if (logOutputText) {
|
|
122
134
|
const logArgs = [];
|
|
123
135
|
for (let i = 0; i < args.length; i += 1) {
|
|
@@ -160,32 +172,69 @@ export async function runCliAgent(params) {
|
|
|
160
172
|
}
|
|
161
173
|
return next;
|
|
162
174
|
})();
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if (useResume && cliSessionIdToSend) {
|
|
166
|
-
await cleanupResumeProcesses(backend, cliSessionIdToSend);
|
|
167
|
-
}
|
|
168
|
-
const result = await runCommandWithTimeout([backend.command, ...args], {
|
|
175
|
+
const noOutputTimeoutMs = resolveCliNoOutputTimeoutMs({
|
|
176
|
+
backend,
|
|
169
177
|
timeoutMs: params.timeoutMs,
|
|
178
|
+
useResume,
|
|
179
|
+
});
|
|
180
|
+
const supervisor = getProcessSupervisor();
|
|
181
|
+
const scopeKey = buildCliSupervisorScopeKey({
|
|
182
|
+
backend,
|
|
183
|
+
backendId: backendResolved.id,
|
|
184
|
+
cliSessionId: useResume ? cliSessionIdToSend : undefined,
|
|
185
|
+
});
|
|
186
|
+
const managedRun = await supervisor.spawn({
|
|
187
|
+
sessionId: params.sessionId,
|
|
188
|
+
backendId: backendResolved.id,
|
|
189
|
+
scopeKey,
|
|
190
|
+
replaceExistingScope: Boolean(useResume && scopeKey),
|
|
191
|
+
mode: "child",
|
|
192
|
+
argv: [backend.command, ...args],
|
|
193
|
+
timeoutMs: params.timeoutMs,
|
|
194
|
+
noOutputTimeoutMs,
|
|
170
195
|
cwd: workspaceDir,
|
|
171
196
|
env,
|
|
172
197
|
input: stdinPayload,
|
|
173
198
|
});
|
|
199
|
+
const result = await managedRun.wait();
|
|
174
200
|
const stdout = result.stdout.trim();
|
|
175
201
|
const stderr = result.stderr.trim();
|
|
176
202
|
if (logOutputText) {
|
|
177
|
-
if (stdout)
|
|
203
|
+
if (stdout) {
|
|
178
204
|
log.info(`cli stdout:\n${stdout}`);
|
|
179
|
-
|
|
205
|
+
}
|
|
206
|
+
if (stderr) {
|
|
180
207
|
log.info(`cli stderr:\n${stderr}`);
|
|
208
|
+
}
|
|
181
209
|
}
|
|
182
210
|
if (shouldLogVerbose()) {
|
|
183
|
-
if (stdout)
|
|
211
|
+
if (stdout) {
|
|
184
212
|
log.debug(`cli stdout:\n${stdout}`);
|
|
185
|
-
|
|
213
|
+
}
|
|
214
|
+
if (stderr) {
|
|
186
215
|
log.debug(`cli stderr:\n${stderr}`);
|
|
216
|
+
}
|
|
187
217
|
}
|
|
188
|
-
if (result.
|
|
218
|
+
if (result.exitCode !== 0 || result.reason !== "exit") {
|
|
219
|
+
if (result.reason === "no-output-timeout" || result.noOutputTimedOut) {
|
|
220
|
+
const timeoutReason = `CLI produced no output for ${Math.round(noOutputTimeoutMs / 1000)}s and was terminated.`;
|
|
221
|
+
log.warn(`cli watchdog timeout: provider=${params.provider} model=${modelId} session=${cliSessionIdToSend ?? params.sessionId} noOutputTimeoutMs=${noOutputTimeoutMs} pid=${managedRun.pid ?? "unknown"}`);
|
|
222
|
+
throw new FailoverError(timeoutReason, {
|
|
223
|
+
reason: "timeout",
|
|
224
|
+
provider: params.provider,
|
|
225
|
+
model: modelId,
|
|
226
|
+
status: resolveFailoverStatus("timeout"),
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
if (result.reason === "overall-timeout") {
|
|
230
|
+
const timeoutReason = `CLI exceeded timeout (${Math.round(params.timeoutMs / 1000)}s) and was terminated.`;
|
|
231
|
+
throw new FailoverError(timeoutReason, {
|
|
232
|
+
reason: "timeout",
|
|
233
|
+
provider: params.provider,
|
|
234
|
+
model: modelId,
|
|
235
|
+
status: resolveFailoverStatus("timeout"),
|
|
236
|
+
});
|
|
237
|
+
}
|
|
189
238
|
const err = stderr || stdout || "CLI failed.";
|
|
190
239
|
const reason = classifyFailoverReason(err) ?? "unknown";
|
|
191
240
|
const status = resolveFailoverStatus(reason);
|
|
@@ -223,8 +272,9 @@ export async function runCliAgent(params) {
|
|
|
223
272
|
};
|
|
224
273
|
}
|
|
225
274
|
catch (err) {
|
|
226
|
-
if (err instanceof FailoverError)
|
|
275
|
+
if (err instanceof FailoverError) {
|
|
227
276
|
throw err;
|
|
277
|
+
}
|
|
228
278
|
const message = err instanceof Error ? err.message : String(err);
|
|
229
279
|
if (isFailoverErrorMessage(message)) {
|
|
230
280
|
const reason = classifyFailoverReason(message) ?? "unknown";
|
|
@@ -248,6 +298,7 @@ export async function runClaudeCliAgent(params) {
|
|
|
248
298
|
return runCliAgent({
|
|
249
299
|
sessionId: params.sessionId,
|
|
250
300
|
sessionKey: params.sessionKey,
|
|
301
|
+
agentId: params.agentId,
|
|
251
302
|
sessionFile: params.sessionFile,
|
|
252
303
|
workspaceDir: params.workspaceDir,
|
|
253
304
|
config: params.config,
|
package/dist/agents/identity.js
CHANGED
|
@@ -3,11 +3,30 @@ const DEFAULT_ACK_REACTION = "👀";
|
|
|
3
3
|
export function resolveAgentIdentity(cfg, agentId) {
|
|
4
4
|
return resolveAgentConfig(cfg, agentId)?.identity;
|
|
5
5
|
}
|
|
6
|
-
export function resolveAckReaction(cfg, agentId) {
|
|
6
|
+
export function resolveAckReaction(cfg, agentId, opts) {
|
|
7
|
+
// L1: Channel account level
|
|
8
|
+
if (opts?.channel && opts?.accountId) {
|
|
9
|
+
const channelCfg = getChannelConfig(cfg, opts.channel);
|
|
10
|
+
const accounts = channelCfg?.accounts;
|
|
11
|
+
const accountReaction = accounts?.[opts.accountId]?.ackReaction;
|
|
12
|
+
if (accountReaction !== undefined) {
|
|
13
|
+
return accountReaction.trim();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
// L2: Channel level
|
|
17
|
+
if (opts?.channel) {
|
|
18
|
+
const channelCfg = getChannelConfig(cfg, opts.channel);
|
|
19
|
+
const channelReaction = channelCfg?.ackReaction;
|
|
20
|
+
if (channelReaction !== undefined) {
|
|
21
|
+
return channelReaction.trim();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// L3: Global messages level
|
|
7
25
|
const configured = cfg.messages?.ackReaction;
|
|
8
26
|
if (configured !== undefined) {
|
|
9
27
|
return configured.trim();
|
|
10
28
|
}
|
|
29
|
+
// L4: Agent identity emoji fallback
|
|
11
30
|
const emoji = resolveAgentIdentity(cfg, agentId)?.emoji?.trim();
|
|
12
31
|
return emoji || DEFAULT_ACK_REACTION;
|
|
13
32
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const DEFAULT_IMAGE_MAX_DIMENSION_PX = 1200;
|
|
2
|
+
export const DEFAULT_IMAGE_MAX_BYTES = 5 * 1024 * 1024;
|
|
3
|
+
export function resolveImageSanitizationLimits(cfg) {
|
|
4
|
+
const configured = cfg?.agents?.defaults?.imageMaxDimensionPx;
|
|
5
|
+
if (typeof configured !== "number" || !Number.isFinite(configured)) {
|
|
6
|
+
return {};
|
|
7
|
+
}
|
|
8
|
+
return { maxDimensionPx: Math.max(1, Math.floor(configured)) };
|
|
9
|
+
}
|