@poolzin/pool-bot 2026.2.17 → 2026.2.18
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/agent-scope.js +4 -0
- package/dist/agents/announce-idempotency.js +14 -0
- package/dist/agents/auth-profiles.resolve-auth-profile-order.fixtures.js +23 -0
- package/dist/agents/bash-tools.exec-runtime.js +438 -0
- package/dist/agents/bash-tools.shared.js +6 -0
- package/dist/agents/cli-runner/reliability.js +61 -0
- package/dist/agents/cli-watchdog-defaults.js +11 -0
- package/dist/agents/command-poll-backoff.js +63 -0
- package/dist/agents/current-time.js +16 -0
- package/dist/agents/model-alias-lines.js +18 -0
- package/dist/agents/model-auth-label.js +61 -0
- package/dist/agents/models-config.e2e-harness.js +115 -0
- package/dist/agents/ollama-stream.js +11 -3
- package/dist/agents/openclaw-tools.js +135 -0
- package/dist/agents/pi-auth-json.js +118 -0
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +147 -0
- package/dist/agents/pi-embedded-subscribe.e2e-harness.js +90 -0
- package/dist/agents/pi-embedded-subscribe.handlers.compaction.js +63 -0
- package/dist/agents/pi-embedded-subscribe.handlers.tools.media.test-helpers.js +30 -0
- package/dist/agents/pi-extensions/session-manager-runtime-registry.js +23 -0
- package/dist/agents/pi-tools.js +2 -0
- package/dist/agents/queued-file-writer.js +22 -0
- package/dist/agents/sandbox/docker.js +133 -40
- package/dist/agents/sandbox/fs-bridge.js +146 -0
- package/dist/agents/sandbox/fs-paths.js +205 -0
- package/dist/agents/sandbox/hash.js +4 -0
- package/dist/agents/sandbox-paths.js +3 -0
- package/dist/agents/session-dirs.js +20 -0
- package/dist/agents/skills/filter.js +24 -0
- package/dist/agents/skills/tools-dir.js +9 -0
- package/dist/agents/skills-install-download.js +290 -0
- package/dist/agents/skills-install-output.js +30 -0
- package/dist/agents/skills-install.download-test-utils.js +36 -0
- package/dist/agents/skills.e2e-test-helpers.js +13 -0
- package/dist/agents/subagent-announce-queue.js +59 -15
- package/dist/agents/subagent-depth.js +137 -0
- package/dist/agents/subagent-registry.js +448 -96
- package/dist/agents/subagent-spawn.js +262 -0
- package/dist/agents/test-helpers/fast-tool-stubs.js +18 -0
- package/dist/agents/test-helpers/host-sandbox-fs-bridge.js +74 -0
- package/dist/agents/tool-display-common.js +782 -0
- package/dist/agents/tools/image-tool.js +1 -1
- package/dist/agents/tools/sessions-access.js +178 -0
- package/dist/agents/tools/sessions-resolution.js +206 -0
- package/dist/agents/tools/subagents-tool.js +616 -0
- package/dist/agents/workspace-dir.js +18 -0
- package/dist/agents/workspace-dirs.js +14 -0
- package/dist/agents/workspace.js +70 -0
- package/dist/auto-reply/heartbeat-reply-payload.js +18 -0
- package/dist/auto-reply/reply/commands-export-session.js +163 -0
- package/dist/auto-reply/reply/commands-mesh.js +245 -0
- package/dist/auto-reply/reply/commands-setunset.js +28 -0
- package/dist/auto-reply/reply/commands-slash-parse.js +31 -0
- package/dist/auto-reply/reply/commands-system-prompt.js +117 -0
- package/dist/auto-reply/reply/directive-handling.levels.js +17 -0
- package/dist/auto-reply/reply/directive-handling.params.js +1 -0
- package/dist/auto-reply/reply/directive-parsing.js +36 -0
- package/dist/auto-reply/reply/dispatcher-registry.js +43 -0
- package/dist/auto-reply/reply/elevated-unavailable.js +20 -0
- package/dist/auto-reply/reply/reply-delivery.js +92 -0
- package/dist/auto-reply/reply/session-reset-prompt.js +1 -0
- package/dist/auto-reply/reply/session-run-accounting.js +33 -0
- package/dist/auto-reply/reply.directive.directive-behavior.e2e-harness.js +115 -0
- package/dist/auto-reply/reply.directive.directive-behavior.e2e-mocks.js +12 -0
- package/dist/browser/bridge-auth-registry.js +26 -0
- package/dist/browser/client-actions-url.js +10 -0
- package/dist/browser/control-auth.js +73 -0
- package/dist/browser/csrf.js +64 -0
- package/dist/browser/http-auth.js +52 -0
- package/dist/browser/paths.js +37 -0
- package/dist/browser/proxy-files.js +32 -0
- package/dist/browser/pw-ai-state.js +7 -0
- package/dist/browser/resolved-config-refresh.js +42 -0
- package/dist/browser/routes/path-output.js +1 -0
- package/dist/browser/server-context.chrome-test-harness.js +20 -0
- package/dist/browser/server-middleware.js +31 -0
- package/dist/browser/test-port.js +16 -0
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/file-resolver.js +43 -0
- package/dist/channels/account-summary.js +19 -0
- package/dist/channels/draft-stream-loop.js +77 -0
- package/dist/channels/plugins/account-helpers.js +26 -0
- package/dist/channels/telegram/allow-from.js +10 -0
- package/dist/cli/browser-cli-resize.js +22 -0
- package/dist/cli/browser-cli-shared.js +8 -0
- package/dist/cli/clawbot-cli.js +5 -0
- package/dist/cli/completion-cli.js +566 -0
- package/dist/cli/config-cli.js +63 -5
- package/dist/cli/daemon-cli/lifecycle-core.js +256 -0
- package/dist/cli/daemon-cli/register-service-commands.js +60 -0
- package/dist/cli/daemon-cli-compat.js +80 -0
- package/dist/cli/nodes-cli/pairing-render.js +26 -0
- package/dist/cli/program/action-reparse.js +17 -0
- package/dist/cli/program/command-registry.js +17 -0
- package/dist/cli/program/program-context.js +8 -0
- package/dist/cli/program/register.subclis.js +7 -0
- package/dist/cli/program/routes.js +233 -0
- package/dist/cli/qr-cli.js +132 -0
- package/dist/cli/requirements-test-fixtures.js +17 -0
- package/dist/cli/respawn-policy.js +4 -0
- package/dist/cli/shared/parse-port.js +18 -0
- package/dist/cli/skills-cli.format.js +241 -0
- package/dist/cli/update-cli/progress.js +121 -0
- package/dist/cli/update-cli/restart-helper.js +108 -0
- package/dist/cli/update-cli/shared.js +196 -0
- package/dist/cli/update-cli/status.js +97 -0
- package/dist/cli/update-cli/suppress-deprecations.js +17 -0
- package/dist/cli/update-cli/update-command.js +506 -0
- package/dist/cli/update-cli/wizard.js +130 -0
- package/dist/cli/update-cli.js +3 -9
- package/dist/cli/windows-argv.js +69 -0
- package/dist/commands/auth-choice-legacy.js +20 -0
- package/dist/commands/auth-choice.apply-helpers.js +8 -0
- package/dist/commands/channel-test-helpers.js +19 -0
- package/dist/commands/cleanup-plan.js +10 -0
- package/dist/commands/cleanup-utils.js +7 -0
- package/dist/commands/config-validation.js +15 -0
- package/dist/commands/doctor-completion.js +112 -0
- package/dist/commands/doctor-memory-search.js +119 -0
- package/dist/commands/doctor-session-locks.js +73 -0
- package/dist/commands/doctor.e2e-harness.js +364 -0
- package/dist/commands/gateway-presence.js +19 -0
- package/dist/commands/model-default.js +35 -0
- package/dist/commands/models/fallbacks-shared.js +102 -0
- package/dist/commands/models/shared.js +24 -0
- package/dist/commands/onboard-auth.config-gateways.js +64 -0
- package/dist/commands/onboard-auth.config-litellm.js +45 -0
- package/dist/commands/onboard-auth.config-shared.js +116 -0
- package/dist/commands/onboard-config.js +16 -0
- package/dist/commands/onboard-non-interactive.test-helpers.js +31 -0
- package/dist/commands/onboard-provider-auth-flags.js +136 -0
- package/dist/commands/openai-codex-oauth.js +40 -0
- package/dist/commands/test-runtime-config-helpers.js +21 -0
- package/dist/commands/test-wizard-helpers.js +68 -0
- package/dist/commands/vllm-setup.js +66 -0
- package/dist/compat/legacy-names.js +2 -0
- package/dist/config/backup-rotation.js +19 -0
- package/dist/config/env-preserve.js +122 -0
- package/dist/config/includes-scan.js +78 -0
- package/dist/config/plugins-allowlist.js +13 -0
- package/dist/config/schema.help.js +256 -0
- package/dist/config/schema.hints.js +189 -0
- package/dist/config/schema.irc.js +20 -0
- package/dist/config/schema.labels.js +317 -0
- package/dist/config/sessions/delivery-info.js +40 -0
- package/dist/config/types.irc.js +1 -0
- package/dist/config/zod-schema.agent-model.js +10 -0
- package/dist/config/zod-schema.allowdeny.js +35 -0
- package/dist/config/zod-schema.sensitive.js +4 -0
- package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
- package/dist/cron/isolated-agent/skills-snapshot.js +26 -0
- package/dist/cron/isolated-agent/subagent-followup.js +127 -0
- package/dist/cron/isolated-agent.mocks.js +12 -0
- package/dist/cron/isolated-agent.test-setup.js +22 -0
- package/dist/cron/legacy-delivery.js +43 -0
- package/dist/cron/webhook-url.js +22 -0
- package/dist/daemon/arg-split.js +40 -0
- package/dist/daemon/exec-file.js +23 -0
- package/dist/daemon/output.js +6 -0
- package/dist/daemon/runtime-format.js +31 -0
- package/dist/daemon/schtasks-exec.js +4 -0
- package/dist/daemon/service-audit.js +22 -0
- package/dist/discord/client.js +41 -0
- package/dist/discord/components-registry.js +57 -0
- package/dist/discord/components.js +816 -0
- package/dist/discord/guilds.js +12 -0
- package/dist/discord/monitor/gateway-plugin.js +48 -0
- package/dist/discord/monitor/presence.js +30 -0
- package/dist/discord/send.components.js +115 -0
- package/dist/discord/send.shared.js +4 -0
- package/dist/discord/ui.js +26 -0
- package/dist/discord/voice-message.js +254 -0
- package/dist/gateway/agent-event-assistant-text.js +5 -0
- package/dist/gateway/agent-prompt.js +33 -0
- package/dist/gateway/auth-rate-limit.js +136 -0
- package/dist/gateway/channel-health-monitor.js +114 -0
- package/dist/gateway/control-ui-contract.js +1 -0
- package/dist/gateway/control-ui-csp.js +15 -0
- package/dist/gateway/gateway-config-prompts.shared.js +25 -0
- package/dist/gateway/http-auth-helpers.js +18 -0
- package/dist/gateway/http-common.js +18 -0
- package/dist/gateway/http-endpoint-helpers.js +27 -0
- package/dist/gateway/node-invoke-sanitize.js +11 -0
- package/dist/gateway/node-invoke-system-run-approval.js +205 -0
- package/dist/gateway/probe-auth.js +21 -0
- package/dist/gateway/protocol/index.js +7 -2
- package/dist/gateway/protocol/schema/mesh.js +54 -0
- package/dist/gateway/protocol/schema/protocol-schemas.js +7 -0
- package/dist/gateway/protocol/schema.js +1 -0
- package/dist/gateway/server/ws-connection/auth-messages.js +54 -0
- package/dist/gateway/server-channels.js +11 -0
- package/dist/gateway/server-methods/attachment-normalize.js +16 -0
- package/dist/gateway/server-methods/base-hash.js +8 -0
- package/dist/gateway/server-methods/mesh.js +700 -0
- package/dist/gateway/server-methods/nodes.handlers.invoke-result.js +55 -0
- package/dist/gateway/server-methods/restart-request.js +13 -0
- package/dist/gateway/server-methods/validation.js +8 -0
- package/dist/gateway/server.agent.gateway-server-agent.mocks.js +35 -0
- package/dist/gateway/server.e2e-registry-helpers.js +1 -0
- package/dist/gateway/server.e2e-ws-harness.js +20 -0
- package/dist/gateway/test-helpers.js +2 -0
- package/dist/gateway/test-helpers.server.js +3 -1
- package/dist/gateway/test-http-response.js +12 -0
- package/dist/gateway/test-openai-responses-model.js +20 -0
- package/dist/gateway/test-temp-config.js +30 -0
- package/dist/gateway/test-with-server.js +32 -0
- package/dist/hooks/bundled/bootstrap-extra-files/handler.js +46 -0
- package/dist/imessage/monitor/abort-handler.js +23 -0
- package/dist/imessage/monitor/inbound-processing.js +346 -0
- package/dist/imessage/monitor/parse-notification.js +64 -0
- package/dist/imessage/target-parsing-helpers.js +92 -0
- package/dist/infra/archive.js +244 -20
- package/dist/infra/detect-package-manager.js +26 -0
- package/dist/infra/exec-approvals-allowlist.js +257 -0
- package/dist/infra/exec-approvals-analysis.js +770 -0
- package/dist/infra/exec-approvals.js +13 -0
- package/dist/infra/file-lock.js +1 -0
- package/dist/infra/gemini-auth.js +39 -0
- package/dist/infra/heartbeat-active-hours.js +85 -0
- package/dist/infra/heartbeat-events-filter.js +50 -0
- package/dist/infra/heartbeat-runner.test-utils.js +39 -0
- package/dist/infra/http-body.js +265 -0
- package/dist/infra/install-package-dir.js +50 -0
- package/dist/infra/install-safe-path.js +49 -0
- package/dist/infra/json-files.js +49 -0
- package/dist/infra/jsonl-socket.js +52 -0
- package/dist/infra/map-size.js +14 -0
- package/dist/infra/net/hostname.js +7 -0
- package/dist/infra/npm-registry-spec.js +39 -0
- package/dist/infra/openclaw-root.js +109 -0
- package/dist/infra/outbound/delivery-queue.js +214 -0
- package/dist/infra/outbound/identity.js +23 -0
- package/dist/infra/outbound/message-action-params.js +307 -0
- package/dist/infra/outbound/tool-payload.js +21 -0
- package/dist/infra/package-json.js +23 -0
- package/dist/infra/pairing-files.js +19 -0
- package/dist/infra/pairing-token.js +9 -0
- package/dist/infra/path-prepend.js +51 -0
- package/dist/infra/process-respawn.js +49 -0
- package/dist/infra/runtime-status.js +16 -0
- package/dist/infra/session-cost-usage.types.js +1 -0
- package/dist/infra/session-maintenance-warning.js +89 -0
- package/dist/infra/system-run-command.js +78 -0
- package/dist/infra/tmp-openclaw-dir.js +81 -0
- package/dist/infra/tmp-poolbot-dir.js +2 -0
- package/dist/infra/update-channels.js +19 -0
- package/dist/line/actions.js +45 -0
- package/dist/line/channel-access-token.js +9 -0
- package/dist/line/flex-templates/basic-cards.js +332 -0
- package/dist/line/flex-templates/common.js +18 -0
- package/dist/line/flex-templates/media-control-cards.js +453 -0
- package/dist/line/flex-templates/message.js +10 -0
- package/dist/line/flex-templates/schedule-cards.js +399 -0
- package/dist/line/flex-templates/types.js +1 -0
- package/dist/line/webhook-node.js +100 -0
- package/dist/line/webhook-utils.js +11 -0
- package/dist/logging/timestamps.js +14 -0
- package/dist/markdown/whatsapp.js +62 -0
- package/dist/media/base64.js +34 -0
- package/dist/media/local-roots.js +32 -0
- package/dist/media/outbound-attachment.js +10 -0
- package/dist/media/read-response-with-limit.js +41 -0
- package/dist/media/sniff-mime-from-base64.js +19 -0
- package/dist/media-understanding/audio-preflight.js +67 -0
- package/dist/media-understanding/fs.js +13 -0
- package/dist/media-understanding/output-extract.js +26 -0
- package/dist/media-understanding/providers/audio.test-helpers.js +34 -0
- package/dist/media-understanding/providers/google/inline-data.js +64 -0
- package/dist/media-understanding/providers/shared.js +7 -0
- package/dist/media-understanding/runner.entries.js +459 -0
- package/dist/memory/batch-error-utils.js +11 -0
- package/dist/memory/batch-http.js +27 -0
- package/dist/memory/batch-output.js +29 -0
- package/dist/memory/batch-runner.js +22 -0
- package/dist/memory/batch-upload.js +23 -0
- package/dist/memory/batch-utils.js +26 -0
- package/dist/memory/embeddings-debug.js +11 -0
- package/dist/memory/embeddings-remote-client.js +22 -0
- package/dist/memory/embeddings-remote-fetch.js +14 -0
- package/dist/memory/manager-embedding-ops.js +616 -0
- package/dist/memory/manager-sync-ops.js +953 -0
- package/dist/memory/qmd-manager.js +1061 -0
- package/dist/memory/qmd-query-parser.js +107 -0
- package/dist/memory/qmd-scope.js +93 -0
- package/dist/memory/search-manager.js +0 -1
- package/dist/memory/sync-index.js +21 -0
- package/dist/memory/sync-progress.js +22 -0
- package/dist/memory/sync-stale.js +30 -0
- package/dist/memory/test-embeddings-mock.js +16 -0
- package/dist/memory/test-manager-helpers.js +14 -0
- package/dist/memory/test-runtime-mocks.js +11 -0
- package/dist/node-host/invoke-browser.js +177 -0
- package/dist/node-host/invoke.js +685 -0
- package/dist/pairing/setup-code.js +285 -0
- package/dist/plugin-sdk/account-id.js +1 -0
- package/dist/plugin-sdk/agent-media-payload.js +13 -0
- package/dist/plugin-sdk/allow-from.js +47 -0
- package/dist/plugin-sdk/command-auth.js +23 -0
- package/dist/plugin-sdk/config-paths.js +9 -0
- package/dist/plugin-sdk/file-lock.js +116 -0
- package/dist/plugin-sdk/json-store.js +31 -0
- package/dist/plugin-sdk/onboarding.js +28 -0
- package/dist/plugin-sdk/provider-auth-result.js +29 -0
- package/dist/plugin-sdk/slack-message-actions.js +133 -0
- package/dist/plugin-sdk/status-helpers.js +35 -0
- package/dist/plugin-sdk/text-chunking.js +31 -0
- package/dist/plugin-sdk/tool-send.js +12 -0
- package/dist/plugin-sdk/webhook-path.js +27 -0
- package/dist/plugin-sdk/webhook-targets.js +34 -0
- package/dist/plugins/hooks.test-helpers.js +21 -0
- package/dist/plugins/uninstall.js +171 -0
- package/dist/process/supervisor/adapters/child.js +143 -0
- package/dist/process/supervisor/adapters/env.js +13 -0
- package/dist/process/supervisor/adapters/pty.js +148 -0
- package/dist/process/supervisor/index.js +10 -0
- package/dist/process/supervisor/registry.js +117 -0
- package/dist/process/supervisor/supervisor.js +244 -0
- package/dist/process/supervisor/types.js +1 -0
- package/dist/providers/google-shared.test-helpers.js +75 -0
- package/dist/security/audit-channel.js +419 -0
- package/dist/security/audit-tool-policy.js +1 -0
- package/dist/security/scan-paths.js +12 -0
- package/dist/sessions/input-provenance.js +55 -0
- package/dist/sessions/session-key-utils.js +7 -0
- package/dist/shared/chat-content.js +31 -0
- package/dist/shared/chat-envelope.js +45 -0
- package/dist/shared/config-eval.js +117 -0
- package/dist/shared/device-auth.js +16 -0
- package/dist/shared/entry-metadata.js +9 -0
- package/dist/shared/entry-status.js +25 -0
- package/dist/shared/frontmatter.js +98 -0
- package/dist/shared/model-param-b.js +19 -0
- package/dist/shared/net/ipv4.js +17 -0
- package/dist/shared/node-match.js +53 -0
- package/dist/shared/requirements.js +128 -0
- package/dist/shared/subagents-format.js +84 -0
- package/dist/shared/usage-aggregates.js +28 -0
- package/dist/signal/monitor/mentions.js +45 -0
- package/dist/signal/rpc-context.js +19 -0
- package/dist/slack/blocks-fallback.js +76 -0
- package/dist/slack/blocks-input.js +40 -0
- package/dist/slack/draft-stream.js +106 -0
- package/dist/slack/message-actions.js +51 -0
- package/dist/slack/modal-metadata.js +32 -0
- package/dist/slack/monitor/events/interactions.js +462 -0
- package/dist/slack/monitor/room-context.js +17 -0
- package/dist/slack/stream-mode.js +41 -0
- package/dist/telegram/bot-native-command-menu.js +64 -0
- package/dist/telegram/bot.media.e2e-harness.js +81 -0
- package/dist/telegram/button-types.js +1 -0
- package/dist/telegram/group-access.js +65 -0
- package/dist/telegram/outbound-params.js +21 -0
- package/dist/telegram/poll-vote-cache.js +21 -0
- package/dist/terminal/health-style.js +36 -0
- package/dist/test-utils/chunk-test-helpers.js +21 -0
- package/dist/test-utils/env.js +72 -0
- package/dist/test-utils/exec-assertions.js +12 -0
- package/dist/test-utils/imessage-test-plugin.js +54 -0
- package/dist/test-utils/mock-http-response.js +17 -0
- package/dist/test-utils/vitest-mock-fn.js +1 -0
- package/dist/tts/tts-core.js +550 -0
- package/dist/utils/chunk-items.js +10 -0
- package/dist/utils/reaction-level.js +52 -0
- package/dist/utils/safe-json.js +22 -0
- package/dist/utils/with-timeout.js +14 -0
- package/dist/web/media.js +17 -5
- package/dist/whatsapp/resolve-outbound-target.js +42 -0
- package/dist/wizard/onboarding.completion.js +74 -0
- package/extensions/bluebubbles/src/account-resolve.ts +29 -0
- package/extensions/bluebubbles/src/monitor-normalize.ts +796 -0
- package/extensions/bluebubbles/src/monitor-processing.ts +1007 -0
- package/extensions/bluebubbles/src/monitor-reply-cache.ts +185 -0
- package/extensions/bluebubbles/src/monitor-shared.ts +51 -0
- package/extensions/bluebubbles/src/multipart.ts +32 -0
- package/extensions/bluebubbles/src/send-helpers.ts +53 -0
- package/extensions/bluebubbles/src/test-harness.ts +50 -0
- package/extensions/bluebubbles/src/test-mocks.ts +11 -0
- package/extensions/device-pair/index.ts +554 -0
- package/extensions/discord/src/channel.js +366 -0
- package/extensions/discord/src/runtime.js +10 -0
- package/extensions/feishu/index.ts +63 -0
- package/extensions/feishu/src/accounts.ts +114 -0
- package/extensions/feishu/src/bitable.ts +739 -0
- package/extensions/feishu/src/bot.ts +965 -0
- package/extensions/feishu/src/channel.ts +351 -0
- package/extensions/feishu/src/client.ts +118 -0
- package/extensions/feishu/src/config-schema.ts +206 -0
- package/extensions/feishu/src/dedup.ts +33 -0
- package/extensions/feishu/src/directory.ts +177 -0
- package/extensions/feishu/src/doc-schema.ts +47 -0
- package/extensions/feishu/src/docx.ts +536 -0
- package/extensions/feishu/src/drive-schema.ts +46 -0
- package/extensions/feishu/src/drive.ts +227 -0
- package/extensions/feishu/src/dynamic-agent.ts +131 -0
- package/extensions/feishu/src/media.ts +449 -0
- package/extensions/feishu/src/mention.ts +126 -0
- package/extensions/feishu/src/monitor.ts +330 -0
- package/extensions/feishu/src/onboarding.ts +359 -0
- package/extensions/feishu/src/outbound.ts +55 -0
- package/extensions/feishu/src/perm-schema.ts +52 -0
- package/extensions/feishu/src/perm.ts +173 -0
- package/extensions/feishu/src/policy.ts +84 -0
- package/extensions/feishu/src/probe.ts +44 -0
- package/extensions/feishu/src/reactions.ts +160 -0
- package/extensions/feishu/src/reply-dispatcher.ts +239 -0
- package/extensions/feishu/src/runtime.ts +14 -0
- package/extensions/feishu/src/send-result.ts +29 -0
- package/extensions/feishu/src/send.ts +335 -0
- package/extensions/feishu/src/streaming-card.ts +223 -0
- package/extensions/feishu/src/targets.ts +78 -0
- package/extensions/feishu/src/tools-config.ts +21 -0
- package/extensions/feishu/src/types.ts +81 -0
- package/extensions/feishu/src/typing.ts +80 -0
- package/extensions/feishu/src/wiki-schema.ts +55 -0
- package/extensions/feishu/src/wiki.ts +232 -0
- package/extensions/imessage/src/channel.js +253 -0
- package/extensions/imessage/src/runtime.js +10 -0
- package/extensions/irc/index.ts +17 -0
- package/extensions/irc/src/accounts.ts +268 -0
- package/extensions/irc/src/channel.ts +367 -0
- package/extensions/irc/src/client.ts +439 -0
- package/extensions/irc/src/config-schema.ts +97 -0
- package/extensions/irc/src/connect-options.ts +30 -0
- package/extensions/irc/src/control-chars.ts +22 -0
- package/extensions/irc/src/inbound.ts +334 -0
- package/extensions/irc/src/monitor.ts +147 -0
- package/extensions/irc/src/normalize.ts +117 -0
- package/extensions/irc/src/onboarding.ts +479 -0
- package/extensions/irc/src/policy.ts +157 -0
- package/extensions/irc/src/probe.ts +53 -0
- package/extensions/irc/src/protocol.ts +169 -0
- package/extensions/irc/src/runtime.ts +14 -0
- package/extensions/irc/src/send.ts +88 -0
- package/extensions/irc/src/types.ts +93 -0
- package/extensions/matrix/src/matrix/client-bootstrap.ts +39 -0
- package/extensions/mattermost/src/mattermost/monitor-onchar.ts +25 -0
- package/extensions/mattermost/src/mattermost/monitor-websocket.ts +221 -0
- package/extensions/mattermost/src/mattermost/reactions.ts +130 -0
- package/extensions/mattermost/src/mattermost/reconnect.ts +103 -0
- package/extensions/minimax-portal-auth/index.ts +161 -0
- package/extensions/minimax-portal-auth/oauth.ts +247 -0
- package/extensions/msteams/src/file-lock.ts +1 -0
- package/extensions/msteams/src/graph.ts +92 -0
- package/extensions/msteams/src/mentions.ts +114 -0
- package/extensions/msteams/src/test-runtime.ts +16 -0
- package/extensions/openai-codex-auth/index.ts +177 -0
- package/extensions/phone-control/index.ts +421 -0
- package/extensions/shared/resolve-target-test-helpers.ts +66 -0
- package/extensions/signal/src/channel.js +273 -0
- package/extensions/signal/src/runtime.js +10 -0
- package/extensions/slack/src/channel.js +489 -0
- package/extensions/slack/src/runtime.js +10 -0
- package/extensions/talk-voice/index.ts +150 -0
- package/extensions/telegram/src/channel.js +424 -0
- package/extensions/telegram/src/runtime.js +10 -0
- package/extensions/thread-ownership/index.ts +133 -0
- package/extensions/tlon/src/account-fields.ts +25 -0
- package/extensions/tlon/src/urbit/base-url.ts +57 -0
- package/extensions/tlon/src/urbit/channel-client.ts +157 -0
- package/extensions/tlon/src/urbit/channel-ops.ts +164 -0
- package/extensions/tlon/src/urbit/context.ts +47 -0
- package/extensions/tlon/src/urbit/errors.ts +51 -0
- package/extensions/tlon/src/urbit/fetch.ts +39 -0
- package/extensions/twitch/src/test-fixtures.ts +30 -0
- package/extensions/voice-call/src/allowlist.ts +19 -0
- package/extensions/whatsapp/src/channel.js +429 -0
- package/extensions/whatsapp/src/runtime.js +10 -0
- package/package.json +1 -1
|
@@ -0,0 +1,782 @@
|
|
|
1
|
+
function asRecord(args) {
|
|
2
|
+
return args && typeof args === "object" ? args : undefined;
|
|
3
|
+
}
|
|
4
|
+
export function normalizeToolName(name) {
|
|
5
|
+
return (name ?? "tool").trim();
|
|
6
|
+
}
|
|
7
|
+
export function defaultTitle(name) {
|
|
8
|
+
const cleaned = name.replace(/_/g, " ").trim();
|
|
9
|
+
if (!cleaned) {
|
|
10
|
+
return "Tool";
|
|
11
|
+
}
|
|
12
|
+
return cleaned
|
|
13
|
+
.split(/\s+/)
|
|
14
|
+
.map((part) => part.length <= 2 && part.toUpperCase() === part
|
|
15
|
+
? part
|
|
16
|
+
: `${part.at(0)?.toUpperCase() ?? ""}${part.slice(1)}`)
|
|
17
|
+
.join(" ");
|
|
18
|
+
}
|
|
19
|
+
export function normalizeVerb(value) {
|
|
20
|
+
const trimmed = value?.trim();
|
|
21
|
+
if (!trimmed) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
return trimmed.replace(/_/g, " ");
|
|
25
|
+
}
|
|
26
|
+
export function coerceDisplayValue(value, opts = {}) {
|
|
27
|
+
const maxStringChars = opts.maxStringChars ?? 160;
|
|
28
|
+
const maxArrayEntries = opts.maxArrayEntries ?? 3;
|
|
29
|
+
if (value === null || value === undefined) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
if (typeof value === "string") {
|
|
33
|
+
const trimmed = value.trim();
|
|
34
|
+
if (!trimmed) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
const firstLine = trimmed.split(/\r?\n/)[0]?.trim() ?? "";
|
|
38
|
+
if (!firstLine) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
if (firstLine.length > maxStringChars) {
|
|
42
|
+
return `${firstLine.slice(0, Math.max(0, maxStringChars - 3))}…`;
|
|
43
|
+
}
|
|
44
|
+
return firstLine;
|
|
45
|
+
}
|
|
46
|
+
if (typeof value === "boolean") {
|
|
47
|
+
if (!value && !opts.includeFalse) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
return value ? "true" : "false";
|
|
51
|
+
}
|
|
52
|
+
if (typeof value === "number") {
|
|
53
|
+
if (!Number.isFinite(value)) {
|
|
54
|
+
return opts.includeNonFinite ? String(value) : undefined;
|
|
55
|
+
}
|
|
56
|
+
if (value === 0 && !opts.includeZero) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
return String(value);
|
|
60
|
+
}
|
|
61
|
+
if (Array.isArray(value)) {
|
|
62
|
+
const values = value
|
|
63
|
+
.map((item) => coerceDisplayValue(item, opts))
|
|
64
|
+
.filter((item) => Boolean(item));
|
|
65
|
+
if (values.length === 0) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
const preview = values.slice(0, maxArrayEntries).join(", ");
|
|
69
|
+
return values.length > maxArrayEntries ? `${preview}…` : preview;
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
export function lookupValueByPath(args, path) {
|
|
74
|
+
if (!args || typeof args !== "object") {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
let current = args;
|
|
78
|
+
for (const segment of path.split(".")) {
|
|
79
|
+
if (!segment) {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
if (!current || typeof current !== "object") {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
const record = current;
|
|
86
|
+
current = record[segment];
|
|
87
|
+
}
|
|
88
|
+
return current;
|
|
89
|
+
}
|
|
90
|
+
export function formatDetailKey(raw, overrides = {}) {
|
|
91
|
+
const segments = raw.split(".").filter(Boolean);
|
|
92
|
+
const last = segments.at(-1) ?? raw;
|
|
93
|
+
const override = overrides[last];
|
|
94
|
+
if (override) {
|
|
95
|
+
return override;
|
|
96
|
+
}
|
|
97
|
+
const cleaned = last.replace(/_/g, " ").replace(/-/g, " ");
|
|
98
|
+
const spaced = cleaned.replace(/([a-z0-9])([A-Z])/g, "$1 $2");
|
|
99
|
+
return spaced.trim().toLowerCase() || last.toLowerCase();
|
|
100
|
+
}
|
|
101
|
+
export function resolvePathArg(args) {
|
|
102
|
+
const record = asRecord(args);
|
|
103
|
+
if (!record) {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
for (const candidate of [record.path, record.file_path, record.filePath]) {
|
|
107
|
+
if (typeof candidate !== "string") {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const trimmed = candidate.trim();
|
|
111
|
+
if (trimmed) {
|
|
112
|
+
return trimmed;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
export function resolveReadDetail(args) {
|
|
118
|
+
const record = asRecord(args);
|
|
119
|
+
if (!record) {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
const path = resolvePathArg(record);
|
|
123
|
+
if (!path) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
const offsetRaw = typeof record.offset === "number" && Number.isFinite(record.offset)
|
|
127
|
+
? Math.floor(record.offset)
|
|
128
|
+
: undefined;
|
|
129
|
+
const limitRaw = typeof record.limit === "number" && Number.isFinite(record.limit)
|
|
130
|
+
? Math.floor(record.limit)
|
|
131
|
+
: undefined;
|
|
132
|
+
const offset = offsetRaw !== undefined ? Math.max(1, offsetRaw) : undefined;
|
|
133
|
+
const limit = limitRaw !== undefined ? Math.max(1, limitRaw) : undefined;
|
|
134
|
+
if (offset !== undefined && limit !== undefined) {
|
|
135
|
+
const unit = limit === 1 ? "line" : "lines";
|
|
136
|
+
return `${unit} ${offset}-${offset + limit - 1} from ${path}`;
|
|
137
|
+
}
|
|
138
|
+
if (offset !== undefined) {
|
|
139
|
+
return `from line ${offset} in ${path}`;
|
|
140
|
+
}
|
|
141
|
+
if (limit !== undefined) {
|
|
142
|
+
const unit = limit === 1 ? "line" : "lines";
|
|
143
|
+
return `first ${limit} ${unit} of ${path}`;
|
|
144
|
+
}
|
|
145
|
+
return `from ${path}`;
|
|
146
|
+
}
|
|
147
|
+
export function resolveWriteDetail(toolKey, args) {
|
|
148
|
+
const record = asRecord(args);
|
|
149
|
+
if (!record) {
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
const path = resolvePathArg(record) ?? (typeof record.url === "string" ? record.url.trim() : undefined);
|
|
153
|
+
if (!path) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
if (toolKey === "attach") {
|
|
157
|
+
return `from ${path}`;
|
|
158
|
+
}
|
|
159
|
+
const destinationPrefix = toolKey === "edit" ? "in" : "to";
|
|
160
|
+
const content = typeof record.content === "string"
|
|
161
|
+
? record.content
|
|
162
|
+
: typeof record.newText === "string"
|
|
163
|
+
? record.newText
|
|
164
|
+
: typeof record.new_string === "string"
|
|
165
|
+
? record.new_string
|
|
166
|
+
: undefined;
|
|
167
|
+
if (content && content.length > 0) {
|
|
168
|
+
return `${destinationPrefix} ${path} (${content.length} chars)`;
|
|
169
|
+
}
|
|
170
|
+
return `${destinationPrefix} ${path}`;
|
|
171
|
+
}
|
|
172
|
+
export function resolveWebSearchDetail(args) {
|
|
173
|
+
const record = asRecord(args);
|
|
174
|
+
if (!record) {
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
const query = typeof record.query === "string" ? record.query.trim() : undefined;
|
|
178
|
+
const count = typeof record.count === "number" && Number.isFinite(record.count) && record.count > 0
|
|
179
|
+
? Math.floor(record.count)
|
|
180
|
+
: undefined;
|
|
181
|
+
if (!query) {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
return count !== undefined ? `for "${query}" (top ${count})` : `for "${query}"`;
|
|
185
|
+
}
|
|
186
|
+
export function resolveWebFetchDetail(args) {
|
|
187
|
+
const record = asRecord(args);
|
|
188
|
+
if (!record) {
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
const url = typeof record.url === "string" ? record.url.trim() : undefined;
|
|
192
|
+
if (!url) {
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
const mode = typeof record.extractMode === "string" ? record.extractMode.trim() : undefined;
|
|
196
|
+
const maxChars = typeof record.maxChars === "number" && Number.isFinite(record.maxChars) && record.maxChars > 0
|
|
197
|
+
? Math.floor(record.maxChars)
|
|
198
|
+
: undefined;
|
|
199
|
+
const suffix = [
|
|
200
|
+
mode ? `mode ${mode}` : undefined,
|
|
201
|
+
maxChars !== undefined ? `max ${maxChars} chars` : undefined,
|
|
202
|
+
]
|
|
203
|
+
.filter((value) => Boolean(value))
|
|
204
|
+
.join(", ");
|
|
205
|
+
return suffix ? `from ${url} (${suffix})` : `from ${url}`;
|
|
206
|
+
}
|
|
207
|
+
function stripOuterQuotes(value) {
|
|
208
|
+
if (!value) {
|
|
209
|
+
return value;
|
|
210
|
+
}
|
|
211
|
+
const trimmed = value.trim();
|
|
212
|
+
if (trimmed.length >= 2 &&
|
|
213
|
+
((trimmed.startsWith('"') && trimmed.endsWith('"')) ||
|
|
214
|
+
(trimmed.startsWith("'") && trimmed.endsWith("'")))) {
|
|
215
|
+
return trimmed.slice(1, -1).trim();
|
|
216
|
+
}
|
|
217
|
+
return trimmed;
|
|
218
|
+
}
|
|
219
|
+
function splitShellWords(input, maxWords = 48) {
|
|
220
|
+
if (!input) {
|
|
221
|
+
return [];
|
|
222
|
+
}
|
|
223
|
+
const words = [];
|
|
224
|
+
let current = "";
|
|
225
|
+
let quote;
|
|
226
|
+
let escaped = false;
|
|
227
|
+
for (let i = 0; i < input.length; i += 1) {
|
|
228
|
+
const char = input[i];
|
|
229
|
+
if (escaped) {
|
|
230
|
+
current += char;
|
|
231
|
+
escaped = false;
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
if (char === "\\") {
|
|
235
|
+
escaped = true;
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
if (quote) {
|
|
239
|
+
if (char === quote) {
|
|
240
|
+
quote = undefined;
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
current += char;
|
|
244
|
+
}
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (char === '"' || char === "'") {
|
|
248
|
+
quote = char;
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
if (/\s/.test(char)) {
|
|
252
|
+
if (!current) {
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
words.push(current);
|
|
256
|
+
if (words.length >= maxWords) {
|
|
257
|
+
return words;
|
|
258
|
+
}
|
|
259
|
+
current = "";
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
current += char;
|
|
263
|
+
}
|
|
264
|
+
if (current) {
|
|
265
|
+
words.push(current);
|
|
266
|
+
}
|
|
267
|
+
return words;
|
|
268
|
+
}
|
|
269
|
+
function binaryName(token) {
|
|
270
|
+
if (!token) {
|
|
271
|
+
return undefined;
|
|
272
|
+
}
|
|
273
|
+
const cleaned = stripOuterQuotes(token) ?? token;
|
|
274
|
+
const segment = cleaned.split(/[/]/).at(-1) ?? cleaned;
|
|
275
|
+
return segment.trim().toLowerCase();
|
|
276
|
+
}
|
|
277
|
+
function optionValue(words, names) {
|
|
278
|
+
const lookup = new Set(names);
|
|
279
|
+
for (let i = 0; i < words.length; i += 1) {
|
|
280
|
+
const token = words[i];
|
|
281
|
+
if (!token) {
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
if (lookup.has(token)) {
|
|
285
|
+
const value = words[i + 1];
|
|
286
|
+
if (value && !value.startsWith("-")) {
|
|
287
|
+
return value;
|
|
288
|
+
}
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
for (const name of names) {
|
|
292
|
+
if (name.startsWith("--") && token.startsWith(`${name}=`)) {
|
|
293
|
+
return token.slice(name.length + 1);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return undefined;
|
|
298
|
+
}
|
|
299
|
+
function positionalArgs(words, from = 1, optionsWithValue = []) {
|
|
300
|
+
const args = [];
|
|
301
|
+
const takesValue = new Set(optionsWithValue);
|
|
302
|
+
for (let i = from; i < words.length; i += 1) {
|
|
303
|
+
const token = words[i];
|
|
304
|
+
if (!token) {
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
if (token === "--") {
|
|
308
|
+
for (let j = i + 1; j < words.length; j += 1) {
|
|
309
|
+
const candidate = words[j];
|
|
310
|
+
if (candidate) {
|
|
311
|
+
args.push(candidate);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
if (token.startsWith("--")) {
|
|
317
|
+
if (token.includes("=")) {
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
if (takesValue.has(token)) {
|
|
321
|
+
i += 1;
|
|
322
|
+
}
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
if (token.startsWith("-")) {
|
|
326
|
+
if (takesValue.has(token)) {
|
|
327
|
+
i += 1;
|
|
328
|
+
}
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
args.push(token);
|
|
332
|
+
}
|
|
333
|
+
return args;
|
|
334
|
+
}
|
|
335
|
+
function firstPositional(words, from = 1, optionsWithValue = []) {
|
|
336
|
+
return positionalArgs(words, from, optionsWithValue)[0];
|
|
337
|
+
}
|
|
338
|
+
function trimLeadingEnv(words) {
|
|
339
|
+
if (words.length === 0) {
|
|
340
|
+
return words;
|
|
341
|
+
}
|
|
342
|
+
let index = 0;
|
|
343
|
+
if (binaryName(words[0]) === "env") {
|
|
344
|
+
index = 1;
|
|
345
|
+
while (index < words.length) {
|
|
346
|
+
const token = words[index];
|
|
347
|
+
if (!token) {
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
if (token.startsWith("-")) {
|
|
351
|
+
index += 1;
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(token)) {
|
|
355
|
+
index += 1;
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
return words.slice(index);
|
|
361
|
+
}
|
|
362
|
+
while (index < words.length && /^[A-Za-z_][A-Za-z0-9_]*=/.test(words[index])) {
|
|
363
|
+
index += 1;
|
|
364
|
+
}
|
|
365
|
+
return words.slice(index);
|
|
366
|
+
}
|
|
367
|
+
function unwrapShellWrapper(command) {
|
|
368
|
+
const words = splitShellWords(command, 10);
|
|
369
|
+
if (words.length < 3) {
|
|
370
|
+
return command;
|
|
371
|
+
}
|
|
372
|
+
const bin = binaryName(words[0]);
|
|
373
|
+
if (!(bin === "bash" || bin === "sh" || bin === "zsh" || bin === "fish")) {
|
|
374
|
+
return command;
|
|
375
|
+
}
|
|
376
|
+
const flagIndex = words.findIndex((token, index) => index > 0 && (token === "-c" || token === "-lc" || token === "-ic"));
|
|
377
|
+
if (flagIndex === -1) {
|
|
378
|
+
return command;
|
|
379
|
+
}
|
|
380
|
+
const inner = words
|
|
381
|
+
.slice(flagIndex + 1)
|
|
382
|
+
.join(" ")
|
|
383
|
+
.trim();
|
|
384
|
+
return inner ? (stripOuterQuotes(inner) ?? command) : command;
|
|
385
|
+
}
|
|
386
|
+
function scanTopLevelChars(command, visit) {
|
|
387
|
+
let quote;
|
|
388
|
+
let escaped = false;
|
|
389
|
+
for (let i = 0; i < command.length; i += 1) {
|
|
390
|
+
const char = command[i];
|
|
391
|
+
if (escaped) {
|
|
392
|
+
escaped = false;
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
if (char === "\\") {
|
|
396
|
+
escaped = true;
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
if (quote) {
|
|
400
|
+
if (char === quote) {
|
|
401
|
+
quote = undefined;
|
|
402
|
+
}
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
if (char === '"' || char === "'") {
|
|
406
|
+
quote = char;
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
if (visit(char, i) === false) {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
function firstTopLevelStage(command) {
|
|
415
|
+
let splitIndex = -1;
|
|
416
|
+
scanTopLevelChars(command, (char, index) => {
|
|
417
|
+
if (char === ";") {
|
|
418
|
+
splitIndex = index;
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
if ((char === "&" || char === "|") && command[index + 1] === char) {
|
|
422
|
+
splitIndex = index;
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
return true;
|
|
426
|
+
});
|
|
427
|
+
return splitIndex >= 0 ? command.slice(0, splitIndex) : command;
|
|
428
|
+
}
|
|
429
|
+
function splitTopLevelPipes(command) {
|
|
430
|
+
const parts = [];
|
|
431
|
+
let start = 0;
|
|
432
|
+
scanTopLevelChars(command, (char, index) => {
|
|
433
|
+
if (char === "|" && command[index - 1] !== "|" && command[index + 1] !== "|") {
|
|
434
|
+
parts.push(command.slice(start, index));
|
|
435
|
+
start = index + 1;
|
|
436
|
+
}
|
|
437
|
+
return true;
|
|
438
|
+
});
|
|
439
|
+
parts.push(command.slice(start));
|
|
440
|
+
return parts.map((part) => part.trim()).filter((part) => part.length > 0);
|
|
441
|
+
}
|
|
442
|
+
function stripShellPreamble(command) {
|
|
443
|
+
let rest = command.trim();
|
|
444
|
+
for (let i = 0; i < 4; i += 1) {
|
|
445
|
+
const andIndex = rest.indexOf("&&");
|
|
446
|
+
const semicolonIndex = rest.indexOf(";");
|
|
447
|
+
const newlineIndex = rest.indexOf("\n");
|
|
448
|
+
const candidates = [
|
|
449
|
+
{ index: andIndex, length: 2 },
|
|
450
|
+
{ index: semicolonIndex, length: 1 },
|
|
451
|
+
{ index: newlineIndex, length: 1 },
|
|
452
|
+
]
|
|
453
|
+
.filter((candidate) => candidate.index >= 0)
|
|
454
|
+
.toSorted((a, b) => a.index - b.index);
|
|
455
|
+
const first = candidates[0];
|
|
456
|
+
const head = (first ? rest.slice(0, first.index) : rest).trim();
|
|
457
|
+
const isPreamble = head.startsWith("set ") || head.startsWith("export ") || head.startsWith("unset ");
|
|
458
|
+
if (!isPreamble) {
|
|
459
|
+
break;
|
|
460
|
+
}
|
|
461
|
+
rest = first ? rest.slice(first.index + first.length).trimStart() : "";
|
|
462
|
+
if (!rest) {
|
|
463
|
+
break;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
return rest.trim();
|
|
467
|
+
}
|
|
468
|
+
function summarizeKnownExec(words) {
|
|
469
|
+
if (words.length === 0) {
|
|
470
|
+
return "run command";
|
|
471
|
+
}
|
|
472
|
+
const bin = binaryName(words[0]) ?? "command";
|
|
473
|
+
if (bin === "git") {
|
|
474
|
+
const globalWithValue = new Set([
|
|
475
|
+
"-C",
|
|
476
|
+
"-c",
|
|
477
|
+
"--git-dir",
|
|
478
|
+
"--work-tree",
|
|
479
|
+
"--namespace",
|
|
480
|
+
"--config-env",
|
|
481
|
+
]);
|
|
482
|
+
const gitCwd = optionValue(words, ["-C"]);
|
|
483
|
+
let sub;
|
|
484
|
+
for (let i = 1; i < words.length; i += 1) {
|
|
485
|
+
const token = words[i];
|
|
486
|
+
if (!token) {
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
if (token === "--") {
|
|
490
|
+
sub = firstPositional(words, i + 1);
|
|
491
|
+
break;
|
|
492
|
+
}
|
|
493
|
+
if (token.startsWith("--")) {
|
|
494
|
+
if (token.includes("=")) {
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
if (globalWithValue.has(token)) {
|
|
498
|
+
i += 1;
|
|
499
|
+
}
|
|
500
|
+
continue;
|
|
501
|
+
}
|
|
502
|
+
if (token.startsWith("-")) {
|
|
503
|
+
if (globalWithValue.has(token)) {
|
|
504
|
+
i += 1;
|
|
505
|
+
}
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
sub = token;
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
const map = {
|
|
512
|
+
status: "check git status",
|
|
513
|
+
diff: "check git diff",
|
|
514
|
+
log: "view git history",
|
|
515
|
+
show: "show git object",
|
|
516
|
+
branch: "list git branches",
|
|
517
|
+
checkout: "switch git branch",
|
|
518
|
+
switch: "switch git branch",
|
|
519
|
+
commit: "create git commit",
|
|
520
|
+
pull: "pull git changes",
|
|
521
|
+
push: "push git changes",
|
|
522
|
+
fetch: "fetch git changes",
|
|
523
|
+
merge: "merge git changes",
|
|
524
|
+
rebase: "rebase git branch",
|
|
525
|
+
add: "stage git changes",
|
|
526
|
+
restore: "restore git files",
|
|
527
|
+
reset: "reset git state",
|
|
528
|
+
stash: "stash git changes",
|
|
529
|
+
};
|
|
530
|
+
if (sub && map[sub]) {
|
|
531
|
+
return map[sub];
|
|
532
|
+
}
|
|
533
|
+
if (!sub || sub.startsWith("/") || sub.startsWith("~") || sub.includes("/")) {
|
|
534
|
+
return gitCwd ? `run git command in ${gitCwd}` : "run git command";
|
|
535
|
+
}
|
|
536
|
+
return `run git ${sub}`;
|
|
537
|
+
}
|
|
538
|
+
if (bin === "grep" || bin === "rg" || bin === "ripgrep") {
|
|
539
|
+
const positional = positionalArgs(words, 1, [
|
|
540
|
+
"-e",
|
|
541
|
+
"--regexp",
|
|
542
|
+
"-f",
|
|
543
|
+
"--file",
|
|
544
|
+
"-m",
|
|
545
|
+
"--max-count",
|
|
546
|
+
"-A",
|
|
547
|
+
"--after-context",
|
|
548
|
+
"-B",
|
|
549
|
+
"--before-context",
|
|
550
|
+
"-C",
|
|
551
|
+
"--context",
|
|
552
|
+
]);
|
|
553
|
+
const pattern = optionValue(words, ["-e", "--regexp"]) ?? positional[0];
|
|
554
|
+
const target = positional.length > 1 ? positional.at(-1) : undefined;
|
|
555
|
+
if (pattern) {
|
|
556
|
+
return target ? `search "${pattern}" in ${target}` : `search "${pattern}"`;
|
|
557
|
+
}
|
|
558
|
+
return "search text";
|
|
559
|
+
}
|
|
560
|
+
if (bin === "find") {
|
|
561
|
+
const path = words[1] && !words[1].startsWith("-") ? words[1] : ".";
|
|
562
|
+
const name = optionValue(words, ["-name", "-iname"]);
|
|
563
|
+
return name ? `find files named "${name}" in ${path}` : `find files in ${path}`;
|
|
564
|
+
}
|
|
565
|
+
if (bin === "ls") {
|
|
566
|
+
const target = firstPositional(words, 1);
|
|
567
|
+
return target ? `list files in ${target}` : "list files";
|
|
568
|
+
}
|
|
569
|
+
if (bin === "head" || bin === "tail") {
|
|
570
|
+
const lines = optionValue(words, ["-n", "--lines"]) ??
|
|
571
|
+
words
|
|
572
|
+
.slice(1)
|
|
573
|
+
.find((token) => /^-\d+$/.test(token))
|
|
574
|
+
?.slice(1);
|
|
575
|
+
const positional = positionalArgs(words, 1, ["-n", "--lines"]);
|
|
576
|
+
let target = positional.at(-1);
|
|
577
|
+
if (target && /^\d+$/.test(target) && positional.length === 1) {
|
|
578
|
+
target = undefined;
|
|
579
|
+
}
|
|
580
|
+
const side = bin === "head" ? "first" : "last";
|
|
581
|
+
const unit = lines === "1" ? "line" : "lines";
|
|
582
|
+
if (lines && target) {
|
|
583
|
+
return `show ${side} ${lines} ${unit} of ${target}`;
|
|
584
|
+
}
|
|
585
|
+
if (lines) {
|
|
586
|
+
return `show ${side} ${lines} ${unit}`;
|
|
587
|
+
}
|
|
588
|
+
if (target) {
|
|
589
|
+
return `show ${target}`;
|
|
590
|
+
}
|
|
591
|
+
return `show ${bin} output`;
|
|
592
|
+
}
|
|
593
|
+
if (bin === "cat") {
|
|
594
|
+
const target = firstPositional(words, 1);
|
|
595
|
+
return target ? `show ${target}` : "show output";
|
|
596
|
+
}
|
|
597
|
+
if (bin === "sed") {
|
|
598
|
+
const expression = optionValue(words, ["-e", "--expression"]);
|
|
599
|
+
const positional = positionalArgs(words, 1, ["-e", "--expression", "-f", "--file"]);
|
|
600
|
+
const script = expression ?? positional[0];
|
|
601
|
+
const target = expression ? positional[0] : positional[1];
|
|
602
|
+
if (script) {
|
|
603
|
+
const compact = (stripOuterQuotes(script) ?? script).replace(/\s+/g, "");
|
|
604
|
+
const range = compact.match(/^([0-9]+),([0-9]+)p$/);
|
|
605
|
+
if (range) {
|
|
606
|
+
return target
|
|
607
|
+
? `print lines ${range[1]}-${range[2]} from ${target}`
|
|
608
|
+
: `print lines ${range[1]}-${range[2]}`;
|
|
609
|
+
}
|
|
610
|
+
const single = compact.match(/^([0-9]+)p$/);
|
|
611
|
+
if (single) {
|
|
612
|
+
return target ? `print line ${single[1]} from ${target}` : `print line ${single[1]}`;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
return target ? `run sed on ${target}` : "run sed transform";
|
|
616
|
+
}
|
|
617
|
+
if (bin === "printf" || bin === "echo") {
|
|
618
|
+
return "print text";
|
|
619
|
+
}
|
|
620
|
+
if (bin === "cp" || bin === "mv") {
|
|
621
|
+
const positional = positionalArgs(words, 1, ["-t", "--target-directory", "-S", "--suffix"]);
|
|
622
|
+
const src = positional[0];
|
|
623
|
+
const dst = positional[1];
|
|
624
|
+
const action = bin === "cp" ? "copy" : "move";
|
|
625
|
+
if (src && dst) {
|
|
626
|
+
return `${action} ${src} to ${dst}`;
|
|
627
|
+
}
|
|
628
|
+
if (src) {
|
|
629
|
+
return `${action} ${src}`;
|
|
630
|
+
}
|
|
631
|
+
return `${action} files`;
|
|
632
|
+
}
|
|
633
|
+
if (bin === "rm") {
|
|
634
|
+
const target = firstPositional(words, 1);
|
|
635
|
+
return target ? `remove ${target}` : "remove files";
|
|
636
|
+
}
|
|
637
|
+
if (bin === "mkdir") {
|
|
638
|
+
const target = firstPositional(words, 1);
|
|
639
|
+
return target ? `create folder ${target}` : "create folder";
|
|
640
|
+
}
|
|
641
|
+
if (bin === "touch") {
|
|
642
|
+
const target = firstPositional(words, 1);
|
|
643
|
+
return target ? `create file ${target}` : "create file";
|
|
644
|
+
}
|
|
645
|
+
if (bin === "curl" || bin === "wget") {
|
|
646
|
+
const url = words.find((token) => /^https?:\/\//i.test(token));
|
|
647
|
+
return url ? `fetch ${url}` : "fetch url";
|
|
648
|
+
}
|
|
649
|
+
if (bin === "npm" || bin === "pnpm" || bin === "yarn" || bin === "bun") {
|
|
650
|
+
const positional = positionalArgs(words, 1, ["--prefix", "-C", "--cwd", "--config"]);
|
|
651
|
+
const sub = positional[0] ?? "command";
|
|
652
|
+
const map = {
|
|
653
|
+
install: "install dependencies",
|
|
654
|
+
test: "run tests",
|
|
655
|
+
build: "run build",
|
|
656
|
+
start: "start app",
|
|
657
|
+
lint: "run lint",
|
|
658
|
+
run: positional[1] ? `run ${positional[1]}` : "run script",
|
|
659
|
+
};
|
|
660
|
+
return map[sub] ?? `run ${bin} ${sub}`;
|
|
661
|
+
}
|
|
662
|
+
if (bin === "node" || bin === "python" || bin === "python3" || bin === "ruby" || bin === "php") {
|
|
663
|
+
const heredoc = words.slice(1).find((token) => token.startsWith("<<"));
|
|
664
|
+
if (heredoc) {
|
|
665
|
+
return `run ${bin} inline script (heredoc)`;
|
|
666
|
+
}
|
|
667
|
+
const inline = bin === "node"
|
|
668
|
+
? optionValue(words, ["-e", "--eval"])
|
|
669
|
+
: bin === "python" || bin === "python3"
|
|
670
|
+
? optionValue(words, ["-c"])
|
|
671
|
+
: undefined;
|
|
672
|
+
if (inline !== undefined) {
|
|
673
|
+
return `run ${bin} inline script`;
|
|
674
|
+
}
|
|
675
|
+
const nodeOptsWithValue = ["-e", "--eval", "-m"];
|
|
676
|
+
const otherOptsWithValue = ["-c", "-e", "--eval", "-m"];
|
|
677
|
+
const script = firstPositional(words, 1, bin === "node" ? nodeOptsWithValue : otherOptsWithValue);
|
|
678
|
+
if (!script) {
|
|
679
|
+
return `run ${bin}`;
|
|
680
|
+
}
|
|
681
|
+
if (bin === "node") {
|
|
682
|
+
const mode = words.includes("--check") || words.includes("-c")
|
|
683
|
+
? "check js syntax for"
|
|
684
|
+
: "run node script";
|
|
685
|
+
return `${mode} ${script}`;
|
|
686
|
+
}
|
|
687
|
+
return `run ${bin} ${script}`;
|
|
688
|
+
}
|
|
689
|
+
if (bin === "poolbot") {
|
|
690
|
+
const sub = firstPositional(words, 1);
|
|
691
|
+
return sub ? `run openclaw ${sub}` : "run openclaw";
|
|
692
|
+
}
|
|
693
|
+
const arg = firstPositional(words, 1);
|
|
694
|
+
if (!arg || arg.length > 48) {
|
|
695
|
+
return `run ${bin}`;
|
|
696
|
+
}
|
|
697
|
+
return /^[A-Za-z0-9._/-]+$/.test(arg) ? `run ${bin} ${arg}` : `run ${bin}`;
|
|
698
|
+
}
|
|
699
|
+
function summarizeExecCommand(command) {
|
|
700
|
+
const cleaned = stripShellPreamble(command);
|
|
701
|
+
const stage = firstTopLevelStage(cleaned).trim();
|
|
702
|
+
if (!stage) {
|
|
703
|
+
return cleaned ? summarizeKnownExec(trimLeadingEnv(splitShellWords(cleaned))) : undefined;
|
|
704
|
+
}
|
|
705
|
+
const pipeline = splitTopLevelPipes(stage);
|
|
706
|
+
if (pipeline.length > 1) {
|
|
707
|
+
const first = summarizeKnownExec(trimLeadingEnv(splitShellWords(pipeline[0])));
|
|
708
|
+
const last = summarizeKnownExec(trimLeadingEnv(splitShellWords(pipeline[pipeline.length - 1])));
|
|
709
|
+
const extra = pipeline.length > 2 ? ` (+${pipeline.length - 2} steps)` : "";
|
|
710
|
+
return `${first} -> ${last}${extra}`;
|
|
711
|
+
}
|
|
712
|
+
return summarizeKnownExec(trimLeadingEnv(splitShellWords(stage)));
|
|
713
|
+
}
|
|
714
|
+
export function resolveExecDetail(args) {
|
|
715
|
+
const record = asRecord(args);
|
|
716
|
+
if (!record) {
|
|
717
|
+
return undefined;
|
|
718
|
+
}
|
|
719
|
+
const raw = typeof record.command === "string" ? record.command.trim() : undefined;
|
|
720
|
+
if (!raw) {
|
|
721
|
+
return undefined;
|
|
722
|
+
}
|
|
723
|
+
const unwrapped = unwrapShellWrapper(raw);
|
|
724
|
+
const summary = summarizeExecCommand(unwrapped) ?? summarizeExecCommand(raw) ?? "run command";
|
|
725
|
+
const cwdRaw = typeof record.workdir === "string"
|
|
726
|
+
? record.workdir
|
|
727
|
+
: typeof record.cwd === "string"
|
|
728
|
+
? record.cwd
|
|
729
|
+
: undefined;
|
|
730
|
+
const cwd = cwdRaw?.trim();
|
|
731
|
+
return cwd ? `${summary} (in ${cwd})` : summary;
|
|
732
|
+
}
|
|
733
|
+
export function resolveActionSpec(spec, action) {
|
|
734
|
+
if (!spec || !action) {
|
|
735
|
+
return undefined;
|
|
736
|
+
}
|
|
737
|
+
return spec.actions?.[action] ?? undefined;
|
|
738
|
+
}
|
|
739
|
+
export function resolveDetailFromKeys(args, keys, opts) {
|
|
740
|
+
if (opts.mode === "first") {
|
|
741
|
+
for (const key of keys) {
|
|
742
|
+
const value = lookupValueByPath(args, key);
|
|
743
|
+
const display = coerceDisplayValue(value, opts.coerce);
|
|
744
|
+
if (display) {
|
|
745
|
+
return display;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
return undefined;
|
|
749
|
+
}
|
|
750
|
+
const entries = [];
|
|
751
|
+
for (const key of keys) {
|
|
752
|
+
const value = lookupValueByPath(args, key);
|
|
753
|
+
const display = coerceDisplayValue(value, opts.coerce);
|
|
754
|
+
if (!display) {
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
entries.push({ label: opts.formatKey ? opts.formatKey(key) : key, value: display });
|
|
758
|
+
}
|
|
759
|
+
if (entries.length === 0) {
|
|
760
|
+
return undefined;
|
|
761
|
+
}
|
|
762
|
+
if (entries.length === 1) {
|
|
763
|
+
return entries[0].value;
|
|
764
|
+
}
|
|
765
|
+
const seen = new Set();
|
|
766
|
+
const unique = [];
|
|
767
|
+
for (const entry of entries) {
|
|
768
|
+
const token = `${entry.label}:${entry.value}`;
|
|
769
|
+
if (seen.has(token)) {
|
|
770
|
+
continue;
|
|
771
|
+
}
|
|
772
|
+
seen.add(token);
|
|
773
|
+
unique.push(entry);
|
|
774
|
+
}
|
|
775
|
+
if (unique.length === 0) {
|
|
776
|
+
return undefined;
|
|
777
|
+
}
|
|
778
|
+
return unique
|
|
779
|
+
.slice(0, opts.maxEntries ?? 8)
|
|
780
|
+
.map((entry) => `${entry.label} ${entry.value}`)
|
|
781
|
+
.join(" · ");
|
|
782
|
+
}
|