@poolzin/pool-bot 2026.2.21 → 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 +17 -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/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/tmux/SKILL.md +111 -79
- package/skills/weather/SKILL.md +88 -25
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
## v2026.2.22 (2026-02-18)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
- **Upstream Sync (openclaw 639d0221):** major sync with upstream — 402 files updated covering agents, auto-reply, gateway, channels, infra, and cron
|
|
5
|
+
- **Agent tooling:** API key rotation, image sanitization, tool-result context guard, sandbox env var sanitization
|
|
6
|
+
- **Auto-reply:** reply dispatcher reservation pattern, abort memory tracking with cascade support, subagent info 30-minute recency window, `compact` as native command
|
|
7
|
+
- **Gateway:** presence events, protocol schema updates, mesh removal
|
|
8
|
+
- **Channels:** Telegram replyToMode defaults to off, Discord REST fetch helper, Slack streaming support
|
|
9
|
+
- **Infra:** exec-safe binary trust, install-source utilities, string normalization
|
|
10
|
+
- **Cron:** stagger scheduling for distributed job execution
|
|
11
|
+
- **Markdown:** nested list rendering now uses proper newline+indentation (blockquote style support)
|
|
12
|
+
|
|
13
|
+
### Fixes
|
|
14
|
+
- **Slack format:** updated nested list test expectation to match upstream markdown IR changes
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
1
18
|
## v2026.2.21 (2026-02-18)
|
|
2
19
|
|
|
3
20
|
### Features
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { formatErrorMessage } from "../infra/errors.js";
|
|
2
|
+
import { collectProviderApiKeys, isApiKeyRateLimitError } from "./live-auth-keys.js";
|
|
3
|
+
function dedupeApiKeys(raw) {
|
|
4
|
+
const seen = new Set();
|
|
5
|
+
const keys = [];
|
|
6
|
+
for (const value of raw) {
|
|
7
|
+
const apiKey = value.trim();
|
|
8
|
+
if (!apiKey || seen.has(apiKey)) {
|
|
9
|
+
continue;
|
|
10
|
+
}
|
|
11
|
+
seen.add(apiKey);
|
|
12
|
+
keys.push(apiKey);
|
|
13
|
+
}
|
|
14
|
+
return keys;
|
|
15
|
+
}
|
|
16
|
+
export function collectProviderApiKeysForExecution(params) {
|
|
17
|
+
const { primaryApiKey, provider } = params;
|
|
18
|
+
return dedupeApiKeys([primaryApiKey?.trim() ?? "", ...collectProviderApiKeys(provider)]);
|
|
19
|
+
}
|
|
20
|
+
export async function executeWithApiKeyRotation(params) {
|
|
21
|
+
const keys = dedupeApiKeys(params.apiKeys);
|
|
22
|
+
if (keys.length === 0) {
|
|
23
|
+
throw new Error(`No API keys configured for provider "${params.provider}".`);
|
|
24
|
+
}
|
|
25
|
+
let lastError;
|
|
26
|
+
for (let attempt = 0; attempt < keys.length; attempt += 1) {
|
|
27
|
+
const apiKey = keys[attempt];
|
|
28
|
+
try {
|
|
29
|
+
return await params.execute(apiKey);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
lastError = error;
|
|
33
|
+
const message = formatErrorMessage(error);
|
|
34
|
+
const retryable = params.shouldRetry
|
|
35
|
+
? params.shouldRetry({ apiKey, error, attempt, message })
|
|
36
|
+
: isApiKeyRateLimitError(message);
|
|
37
|
+
if (!retryable || attempt + 1 >= keys.length) {
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
params.onRetry?.({ apiKey, error, attempt, message });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (lastError === undefined) {
|
|
44
|
+
throw new Error(`Failed to run API request for ${params.provider}.`);
|
|
45
|
+
}
|
|
46
|
+
throw lastError;
|
|
47
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
async function defaultReadFile(filePath) {
|
|
3
|
+
return fs.readFile(filePath, "utf8");
|
|
4
|
+
}
|
|
5
|
+
export async function applyUpdateHunk(filePath, chunks, options) {
|
|
6
|
+
const reader = options?.readFile ?? defaultReadFile;
|
|
7
|
+
const originalContents = await reader(filePath).catch((err) => {
|
|
4
8
|
throw new Error(`Failed to read file to update ${filePath}: ${err}`);
|
|
5
9
|
});
|
|
6
10
|
const originalLines = originalContents.split("\n");
|
|
@@ -53,7 +57,7 @@ function computeReplacements(originalLines, filePath, chunks) {
|
|
|
53
57
|
}
|
|
54
58
|
function applyReplacements(lines, replacements) {
|
|
55
59
|
const result = [...lines];
|
|
56
|
-
for (const [startIndex, oldLen, newLines] of [...replacements].
|
|
60
|
+
for (const [startIndex, oldLen, newLines] of [...replacements].toReversed()) {
|
|
57
61
|
for (let i = 0; i < oldLen; i += 1) {
|
|
58
62
|
if (startIndex < result.length) {
|
|
59
63
|
result.splice(startIndex, 1);
|
|
@@ -66,25 +70,31 @@ function applyReplacements(lines, replacements) {
|
|
|
66
70
|
return result;
|
|
67
71
|
}
|
|
68
72
|
function seekSequence(lines, pattern, start, eof) {
|
|
69
|
-
if (pattern.length === 0)
|
|
73
|
+
if (pattern.length === 0) {
|
|
70
74
|
return start;
|
|
71
|
-
|
|
75
|
+
}
|
|
76
|
+
if (pattern.length > lines.length) {
|
|
72
77
|
return null;
|
|
78
|
+
}
|
|
73
79
|
const maxStart = lines.length - pattern.length;
|
|
74
80
|
const searchStart = eof && lines.length >= pattern.length ? maxStart : start;
|
|
75
|
-
if (searchStart > maxStart)
|
|
81
|
+
if (searchStart > maxStart) {
|
|
76
82
|
return null;
|
|
83
|
+
}
|
|
77
84
|
for (let i = searchStart; i <= maxStart; i += 1) {
|
|
78
|
-
if (linesMatch(lines, pattern, i, (value) => value))
|
|
85
|
+
if (linesMatch(lines, pattern, i, (value) => value)) {
|
|
79
86
|
return i;
|
|
87
|
+
}
|
|
80
88
|
}
|
|
81
89
|
for (let i = searchStart; i <= maxStart; i += 1) {
|
|
82
|
-
if (linesMatch(lines, pattern, i, (value) => value.trimEnd()))
|
|
90
|
+
if (linesMatch(lines, pattern, i, (value) => value.trimEnd())) {
|
|
83
91
|
return i;
|
|
92
|
+
}
|
|
84
93
|
}
|
|
85
94
|
for (let i = searchStart; i <= maxStart; i += 1) {
|
|
86
|
-
if (linesMatch(lines, pattern, i, (value) => value.trim()))
|
|
95
|
+
if (linesMatch(lines, pattern, i, (value) => value.trim())) {
|
|
87
96
|
return i;
|
|
97
|
+
}
|
|
88
98
|
}
|
|
89
99
|
for (let i = searchStart; i <= maxStart; i += 1) {
|
|
90
100
|
if (linesMatch(lines, pattern, i, (value) => normalizePunctuation(value.trim()))) {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
|
-
import os from "node:os";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
import { Type } from "@sinclair/typebox";
|
|
5
4
|
import { applyUpdateHunk } from "./apply-patch-update.js";
|
|
6
|
-
import { assertSandboxPath } from "./sandbox-paths.js";
|
|
5
|
+
import { assertSandboxPath, resolveSandboxInputPath } from "./sandbox-paths.js";
|
|
7
6
|
const BEGIN_PATCH_MARKER = "*** Begin Patch";
|
|
8
7
|
const END_PATCH_MARKER = "*** End Patch";
|
|
9
8
|
const ADD_FILE_MARKER = "*** Add File: ";
|
|
@@ -13,7 +12,6 @@ const MOVE_TO_MARKER = "*** Move to: ";
|
|
|
13
12
|
const EOF_MARKER = "*** End of File";
|
|
14
13
|
const CHANGE_CONTEXT_MARKER = "@@ ";
|
|
15
14
|
const EMPTY_CHANGE_CONTEXT_MARKER = "@@";
|
|
16
|
-
const UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
|
|
17
15
|
const applyPatchSchema = Type.Object({
|
|
18
16
|
input: Type.String({
|
|
19
17
|
description: "Patch content using the *** Begin Patch/End Patch format.",
|
|
@@ -21,7 +19,8 @@ const applyPatchSchema = Type.Object({
|
|
|
21
19
|
});
|
|
22
20
|
export function createApplyPatchTool(options = {}) {
|
|
23
21
|
const cwd = options.cwd ?? process.cwd();
|
|
24
|
-
const
|
|
22
|
+
const sandbox = options.sandbox;
|
|
23
|
+
const workspaceOnly = options.workspaceOnly !== false;
|
|
25
24
|
return {
|
|
26
25
|
name: "apply_patch",
|
|
27
26
|
label: "apply_patch",
|
|
@@ -40,7 +39,8 @@ export function createApplyPatchTool(options = {}) {
|
|
|
40
39
|
}
|
|
41
40
|
const result = await applyPatch(input, {
|
|
42
41
|
cwd,
|
|
43
|
-
|
|
42
|
+
sandbox,
|
|
43
|
+
workspaceOnly,
|
|
44
44
|
signal,
|
|
45
45
|
});
|
|
46
46
|
return {
|
|
@@ -65,6 +65,7 @@ export async function applyPatch(input, options) {
|
|
|
65
65
|
modified: new Set(),
|
|
66
66
|
deleted: new Set(),
|
|
67
67
|
};
|
|
68
|
+
const fileOps = resolvePatchFileOps(options);
|
|
68
69
|
for (const hunk of parsed.hunks) {
|
|
69
70
|
if (options.signal?.aborted) {
|
|
70
71
|
const err = new Error("Aborted");
|
|
@@ -73,28 +74,30 @@ export async function applyPatch(input, options) {
|
|
|
73
74
|
}
|
|
74
75
|
if (hunk.kind === "add") {
|
|
75
76
|
const target = await resolvePatchPath(hunk.path, options);
|
|
76
|
-
await ensureDir(target.resolved);
|
|
77
|
-
await
|
|
77
|
+
await ensureDir(target.resolved, fileOps);
|
|
78
|
+
await fileOps.writeFile(target.resolved, hunk.contents);
|
|
78
79
|
recordSummary(summary, seen, "added", target.display);
|
|
79
80
|
continue;
|
|
80
81
|
}
|
|
81
82
|
if (hunk.kind === "delete") {
|
|
82
|
-
const target = await resolvePatchPath(hunk.path, options);
|
|
83
|
-
await
|
|
83
|
+
const target = await resolvePatchPath(hunk.path, options, "unlink");
|
|
84
|
+
await fileOps.remove(target.resolved);
|
|
84
85
|
recordSummary(summary, seen, "deleted", target.display);
|
|
85
86
|
continue;
|
|
86
87
|
}
|
|
87
88
|
const target = await resolvePatchPath(hunk.path, options);
|
|
88
|
-
const applied = await applyUpdateHunk(target.resolved, hunk.chunks
|
|
89
|
+
const applied = await applyUpdateHunk(target.resolved, hunk.chunks, {
|
|
90
|
+
readFile: (path) => fileOps.readFile(path),
|
|
91
|
+
});
|
|
89
92
|
if (hunk.movePath) {
|
|
90
93
|
const moveTarget = await resolvePatchPath(hunk.movePath, options);
|
|
91
|
-
await ensureDir(moveTarget.resolved);
|
|
92
|
-
await
|
|
93
|
-
await
|
|
94
|
+
await ensureDir(moveTarget.resolved, fileOps);
|
|
95
|
+
await fileOps.writeFile(moveTarget.resolved, applied);
|
|
96
|
+
await fileOps.remove(target.resolved);
|
|
94
97
|
recordSummary(summary, seen, "modified", moveTarget.display);
|
|
95
98
|
}
|
|
96
99
|
else {
|
|
97
|
-
await
|
|
100
|
+
await fileOps.writeFile(target.resolved, applied);
|
|
98
101
|
recordSummary(summary, seen, "modified", target.display);
|
|
99
102
|
}
|
|
100
103
|
}
|
|
@@ -104,68 +107,88 @@ export async function applyPatch(input, options) {
|
|
|
104
107
|
};
|
|
105
108
|
}
|
|
106
109
|
function recordSummary(summary, seen, bucket, value) {
|
|
107
|
-
if (seen[bucket].has(value))
|
|
110
|
+
if (seen[bucket].has(value)) {
|
|
108
111
|
return;
|
|
112
|
+
}
|
|
109
113
|
seen[bucket].add(value);
|
|
110
114
|
summary[bucket].push(value);
|
|
111
115
|
}
|
|
112
116
|
function formatSummary(summary) {
|
|
113
117
|
const lines = ["Success. Updated the following files:"];
|
|
114
|
-
for (const file of summary.added)
|
|
118
|
+
for (const file of summary.added) {
|
|
115
119
|
lines.push(`A ${file}`);
|
|
116
|
-
|
|
120
|
+
}
|
|
121
|
+
for (const file of summary.modified) {
|
|
117
122
|
lines.push(`M ${file}`);
|
|
118
|
-
|
|
123
|
+
}
|
|
124
|
+
for (const file of summary.deleted) {
|
|
119
125
|
lines.push(`D ${file}`);
|
|
126
|
+
}
|
|
120
127
|
return lines.join("\n");
|
|
121
128
|
}
|
|
122
|
-
|
|
129
|
+
function resolvePatchFileOps(options) {
|
|
130
|
+
if (options.sandbox) {
|
|
131
|
+
const { root, bridge } = options.sandbox;
|
|
132
|
+
return {
|
|
133
|
+
readFile: async (filePath) => {
|
|
134
|
+
const buf = await bridge.readFile({ filePath, cwd: root });
|
|
135
|
+
return buf.toString("utf8");
|
|
136
|
+
},
|
|
137
|
+
writeFile: (filePath, content) => bridge.writeFile({ filePath, cwd: root, data: content }),
|
|
138
|
+
remove: (filePath) => bridge.remove({ filePath, cwd: root, force: false }),
|
|
139
|
+
mkdirp: (dir) => bridge.mkdirp({ filePath: dir, cwd: root }),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
readFile: (filePath) => fs.readFile(filePath, "utf8"),
|
|
144
|
+
writeFile: (filePath, content) => fs.writeFile(filePath, content, "utf8"),
|
|
145
|
+
remove: (filePath) => fs.rm(filePath),
|
|
146
|
+
mkdirp: (dir) => fs.mkdir(dir, { recursive: true }).then(() => { }),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
async function ensureDir(filePath, ops) {
|
|
123
150
|
const parent = path.dirname(filePath);
|
|
124
|
-
if (!parent || parent === ".")
|
|
151
|
+
if (!parent || parent === ".") {
|
|
125
152
|
return;
|
|
126
|
-
|
|
153
|
+
}
|
|
154
|
+
await ops.mkdirp(parent);
|
|
127
155
|
}
|
|
128
|
-
async function resolvePatchPath(filePath, options) {
|
|
129
|
-
if (options.
|
|
130
|
-
const resolved =
|
|
156
|
+
async function resolvePatchPath(filePath, options, purpose = "readWrite") {
|
|
157
|
+
if (options.sandbox) {
|
|
158
|
+
const resolved = options.sandbox.bridge.resolvePath({
|
|
131
159
|
filePath,
|
|
132
160
|
cwd: options.cwd,
|
|
133
|
-
root: options.sandboxRoot,
|
|
134
161
|
});
|
|
135
162
|
return {
|
|
136
|
-
resolved: resolved.
|
|
137
|
-
display: resolved.
|
|
163
|
+
resolved: resolved.hostPath,
|
|
164
|
+
display: resolved.relativePath || resolved.hostPath,
|
|
138
165
|
};
|
|
139
166
|
}
|
|
140
|
-
const
|
|
167
|
+
const workspaceOnly = options.workspaceOnly !== false;
|
|
168
|
+
const resolved = workspaceOnly
|
|
169
|
+
? (await assertSandboxPath({
|
|
170
|
+
filePath,
|
|
171
|
+
cwd: options.cwd,
|
|
172
|
+
root: options.cwd,
|
|
173
|
+
allowFinalSymlink: purpose === "unlink",
|
|
174
|
+
})).resolved
|
|
175
|
+
: resolvePathFromCwd(filePath, options.cwd);
|
|
141
176
|
return {
|
|
142
177
|
resolved,
|
|
143
178
|
display: toDisplayPath(resolved, options.cwd),
|
|
144
179
|
};
|
|
145
180
|
}
|
|
146
|
-
function normalizeUnicodeSpaces(value) {
|
|
147
|
-
return value.replace(UNICODE_SPACES, " ");
|
|
148
|
-
}
|
|
149
|
-
function expandPath(filePath) {
|
|
150
|
-
const normalized = normalizeUnicodeSpaces(filePath);
|
|
151
|
-
if (normalized === "~")
|
|
152
|
-
return os.homedir();
|
|
153
|
-
if (normalized.startsWith("~/"))
|
|
154
|
-
return os.homedir() + normalized.slice(1);
|
|
155
|
-
return normalized;
|
|
156
|
-
}
|
|
157
181
|
function resolvePathFromCwd(filePath, cwd) {
|
|
158
|
-
|
|
159
|
-
if (path.isAbsolute(expanded))
|
|
160
|
-
return path.normalize(expanded);
|
|
161
|
-
return path.resolve(cwd, expanded);
|
|
182
|
+
return path.normalize(resolveSandboxInputPath(filePath, cwd));
|
|
162
183
|
}
|
|
163
184
|
function toDisplayPath(resolved, cwd) {
|
|
164
185
|
const relative = path.relative(cwd, resolved);
|
|
165
|
-
if (!relative || relative === "")
|
|
186
|
+
if (!relative || relative === "") {
|
|
166
187
|
return path.basename(resolved);
|
|
167
|
-
|
|
188
|
+
}
|
|
189
|
+
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
168
190
|
return resolved;
|
|
191
|
+
}
|
|
169
192
|
return relative;
|
|
170
193
|
}
|
|
171
194
|
function parsePatchText(input) {
|
|
@@ -189,8 +212,9 @@ function parsePatchText(input) {
|
|
|
189
212
|
}
|
|
190
213
|
function checkPatchBoundariesLenient(lines) {
|
|
191
214
|
const strictError = checkPatchBoundariesStrict(lines);
|
|
192
|
-
if (!strictError)
|
|
215
|
+
if (!strictError) {
|
|
193
216
|
return lines;
|
|
217
|
+
}
|
|
194
218
|
if (lines.length < 4) {
|
|
195
219
|
throw new Error(strictError);
|
|
196
220
|
}
|
|
@@ -199,8 +223,9 @@ function checkPatchBoundariesLenient(lines) {
|
|
|
199
223
|
if ((first === "<<EOF" || first === "<<'EOF'" || first === '<<"EOF"') && last.endsWith("EOF")) {
|
|
200
224
|
const inner = lines.slice(1, lines.length - 1);
|
|
201
225
|
const innerError = checkPatchBoundariesStrict(inner);
|
|
202
|
-
if (!innerError)
|
|
226
|
+
if (!innerError) {
|
|
203
227
|
return inner;
|
|
228
|
+
}
|
|
204
229
|
throw new Error(innerError);
|
|
205
230
|
}
|
|
206
231
|
throw new Error(strictError);
|