clawdbot 2026.1.4-1
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 +120 -0
- package/LICENSE +21 -0
- package/README-header.png +0 -0
- package/README.md +297 -0
- package/dist/agents/agent-paths.js +17 -0
- package/dist/agents/bash-process-registry.js +126 -0
- package/dist/agents/bash-tools.js +837 -0
- package/dist/agents/clawdbot-tools.js +30 -0
- package/dist/agents/clawdis-tools.js +27 -0
- package/dist/agents/context.js +34 -0
- package/dist/agents/defaults.js +6 -0
- package/dist/agents/model-auth.js +112 -0
- package/dist/agents/model-catalog.js +55 -0
- package/dist/agents/model-fallback.js +191 -0
- package/dist/agents/model-scan.js +263 -0
- package/dist/agents/model-selection.js +116 -0
- package/dist/agents/models-config.js +49 -0
- package/dist/agents/pi-embedded-helpers.js +74 -0
- package/dist/agents/pi-embedded-runner.js +407 -0
- package/dist/agents/pi-embedded-subscribe.js +568 -0
- package/dist/agents/pi-embedded-utils.js +20 -0
- package/dist/agents/pi-embedded.js +1 -0
- package/dist/agents/pi-oauth.js +88 -0
- package/dist/agents/pi-tools.js +433 -0
- package/dist/agents/sandbox-paths.js +68 -0
- package/dist/agents/sandbox.js +644 -0
- package/dist/agents/shell-utils.js +53 -0
- package/dist/agents/skills-install.js +244 -0
- package/dist/agents/skills-status.js +157 -0
- package/dist/agents/skills.js +470 -0
- package/dist/agents/steerable-agent-loop.js +338 -0
- package/dist/agents/steerable-provider-transport.js +48 -0
- package/dist/agents/system-prompt.js +104 -0
- package/dist/agents/tool-display.js +162 -0
- package/dist/agents/tool-images.js +138 -0
- package/dist/agents/tools/browser-tool.js +339 -0
- package/dist/agents/tools/canvas-tool.js +193 -0
- package/dist/agents/tools/common.js +88 -0
- package/dist/agents/tools/cron-tool.js +124 -0
- package/dist/agents/tools/discord-actions-guild.js +186 -0
- package/dist/agents/tools/discord-actions-messaging.js +285 -0
- package/dist/agents/tools/discord-actions-moderation.js +70 -0
- package/dist/agents/tools/discord-actions.js +56 -0
- package/dist/agents/tools/discord-schema.js +199 -0
- package/dist/agents/tools/discord-tool.js +16 -0
- package/dist/agents/tools/gateway-tool.js +46 -0
- package/dist/agents/tools/gateway.js +27 -0
- package/dist/agents/tools/image-tool.js +132 -0
- package/dist/agents/tools/nodes-tool.js +413 -0
- package/dist/agents/tools/nodes-utils.js +92 -0
- package/dist/agents/tools/sessions-helpers.js +88 -0
- package/dist/agents/tools/sessions-history-tool.js +53 -0
- package/dist/agents/tools/sessions-list-tool.js +143 -0
- package/dist/agents/tools/sessions-send-helpers.js +100 -0
- package/dist/agents/tools/sessions-send-tool.js +347 -0
- package/dist/agents/tools/slack-actions.js +129 -0
- package/dist/agents/tools/slack-schema.js +59 -0
- package/dist/agents/tools/slack-tool.js +16 -0
- package/dist/agents/usage.js +39 -0
- package/dist/agents/workspace.js +241 -0
- package/dist/auto-reply/chunk.js +76 -0
- package/dist/auto-reply/envelope.js +38 -0
- package/dist/auto-reply/group-activation.js +20 -0
- package/dist/auto-reply/heartbeat.js +57 -0
- package/dist/auto-reply/model.js +14 -0
- package/dist/auto-reply/reply/abort.js +14 -0
- package/dist/auto-reply/reply/agent-runner.js +371 -0
- package/dist/auto-reply/reply/block-streaming.js +34 -0
- package/dist/auto-reply/reply/body.js +29 -0
- package/dist/auto-reply/reply/commands.js +207 -0
- package/dist/auto-reply/reply/directive-handling.js +361 -0
- package/dist/auto-reply/reply/directives.js +47 -0
- package/dist/auto-reply/reply/followup-runner.js +149 -0
- package/dist/auto-reply/reply/groups.js +91 -0
- package/dist/auto-reply/reply/mentions.js +38 -0
- package/dist/auto-reply/reply/model-selection.js +114 -0
- package/dist/auto-reply/reply/queue.js +399 -0
- package/dist/auto-reply/reply/reply-tags.js +26 -0
- package/dist/auto-reply/reply/session-updates.js +87 -0
- package/dist/auto-reply/reply/session.js +160 -0
- package/dist/auto-reply/reply/typing.js +75 -0
- package/dist/auto-reply/reply.js +535 -0
- package/dist/auto-reply/send-policy.js +28 -0
- package/dist/auto-reply/status.js +158 -0
- package/dist/auto-reply/templating.js +9 -0
- package/dist/auto-reply/thinking.js +49 -0
- package/dist/auto-reply/tokens.js +2 -0
- package/dist/auto-reply/tool-meta.js +74 -0
- package/dist/auto-reply/transcription.js +57 -0
- package/dist/auto-reply/types.js +1 -0
- package/dist/browser/bridge-server.js +37 -0
- package/dist/browser/cdp.js +382 -0
- package/dist/browser/chrome.js +432 -0
- package/dist/browser/client-actions-core.js +67 -0
- package/dist/browser/client-actions-observe.js +24 -0
- package/dist/browser/client-actions-types.js +1 -0
- package/dist/browser/client-actions.js +3 -0
- package/dist/browser/client-fetch.js +43 -0
- package/dist/browser/client.js +105 -0
- package/dist/browser/config.js +140 -0
- package/dist/browser/constants.js +4 -0
- package/dist/browser/profiles-service.js +122 -0
- package/dist/browser/profiles.js +85 -0
- package/dist/browser/pw-ai.js +2 -0
- package/dist/browser/pw-session.js +144 -0
- package/dist/browser/pw-tools-core.js +363 -0
- package/dist/browser/routes/agent.js +535 -0
- package/dist/browser/routes/basic.js +155 -0
- package/dist/browser/routes/index.js +8 -0
- package/dist/browser/routes/tabs.js +105 -0
- package/dist/browser/routes/utils.js +62 -0
- package/dist/browser/screenshot.js +40 -0
- package/dist/browser/server-context.js +377 -0
- package/dist/browser/server.js +81 -0
- package/dist/browser/target-id.js +18 -0
- package/dist/browser/trash.js +21 -0
- package/dist/canvas-host/a2ui/.bundle.hash +1 -0
- package/dist/canvas-host/a2ui/a2ui.bundle.js +17768 -0
- package/dist/canvas-host/a2ui/index.html +246 -0
- package/dist/canvas-host/a2ui.js +187 -0
- package/dist/canvas-host/server.js +382 -0
- package/dist/cli/browser-cli-actions-input.js +459 -0
- package/dist/cli/browser-cli-actions-observe.js +56 -0
- package/dist/cli/browser-cli-examples.js +31 -0
- package/dist/cli/browser-cli-inspect.js +97 -0
- package/dist/cli/browser-cli-manage.js +286 -0
- package/dist/cli/browser-cli-shared.js +1 -0
- package/dist/cli/browser-cli.js +26 -0
- package/dist/cli/canvas-cli.js +416 -0
- package/dist/cli/cron-cli.js +454 -0
- package/dist/cli/deps.js +17 -0
- package/dist/cli/dns-cli.js +180 -0
- package/dist/cli/gateway-cli.js +489 -0
- package/dist/cli/gateway-rpc.js +20 -0
- package/dist/cli/hooks-cli.js +135 -0
- package/dist/cli/models-cli.js +248 -0
- package/dist/cli/nodes-camera.js +57 -0
- package/dist/cli/nodes-canvas.js +26 -0
- package/dist/cli/nodes-cli.js +946 -0
- package/dist/cli/nodes-screen.js +37 -0
- package/dist/cli/parse-duration.js +20 -0
- package/dist/cli/ports.js +97 -0
- package/dist/cli/program.js +406 -0
- package/dist/cli/prompt.js +19 -0
- package/dist/cli/tui-cli.js +35 -0
- package/dist/cli/wait.js +8 -0
- package/dist/commands/agent.js +645 -0
- package/dist/commands/antigravity-oauth.js +327 -0
- package/dist/commands/configure.js +480 -0
- package/dist/commands/doctor.js +484 -0
- package/dist/commands/health.js +108 -0
- package/dist/commands/models/aliases.js +64 -0
- package/dist/commands/models/fallbacks.js +99 -0
- package/dist/commands/models/image-fallbacks.js +99 -0
- package/dist/commands/models/list.js +323 -0
- package/dist/commands/models/scan.js +266 -0
- package/dist/commands/models/set-image.js +23 -0
- package/dist/commands/models/set.js +23 -0
- package/dist/commands/models/shared.js +72 -0
- package/dist/commands/models.js +7 -0
- package/dist/commands/onboard-auth.js +70 -0
- package/dist/commands/onboard-helpers.js +295 -0
- package/dist/commands/onboard-interactive.js +17 -0
- package/dist/commands/onboard-non-interactive.js +202 -0
- package/dist/commands/onboard-providers.js +634 -0
- package/dist/commands/onboard-remote.js +120 -0
- package/dist/commands/onboard-skills.js +148 -0
- package/dist/commands/onboard-types.js +1 -0
- package/dist/commands/onboard.js +12 -0
- package/dist/commands/send.js +124 -0
- package/dist/commands/sessions.js +212 -0
- package/dist/commands/setup.js +58 -0
- package/dist/commands/signal-install.js +135 -0
- package/dist/commands/status.js +207 -0
- package/dist/commands/update.js +16 -0
- package/dist/config/config.js +6 -0
- package/dist/config/defaults.js +61 -0
- package/dist/config/io.js +147 -0
- package/dist/config/legacy-migrate.js +13 -0
- package/dist/config/legacy.js +159 -0
- package/dist/config/paths.js +71 -0
- package/dist/config/schema.js +150 -0
- package/dist/config/sessions.js +282 -0
- package/dist/config/talk.js +31 -0
- package/dist/config/types.js +1 -0
- package/dist/config/validation.js +29 -0
- package/dist/config/zod-schema.js +831 -0
- package/dist/control-ui/assets/index-BFID3yAA.css +1 -0
- package/dist/control-ui/assets/index-CE_axlTS.js +2235 -0
- package/dist/control-ui/assets/index-CE_axlTS.js.map +1 -0
- package/dist/control-ui/index.html +15 -0
- package/dist/cron/isolated-agent.js +499 -0
- package/dist/cron/run-log.js +72 -0
- package/dist/cron/schedule.js +24 -0
- package/dist/cron/service.js +471 -0
- package/dist/cron/store.js +43 -0
- package/dist/cron/types.js +1 -0
- package/dist/daemon/constants.js +10 -0
- package/dist/daemon/launchd.js +276 -0
- package/dist/daemon/legacy.js +63 -0
- package/dist/daemon/program-args.js +76 -0
- package/dist/daemon/schtasks.js +257 -0
- package/dist/daemon/service.js +60 -0
- package/dist/daemon/systemd.js +266 -0
- package/dist/discord/index.js +2 -0
- package/dist/discord/monitor.js +1188 -0
- package/dist/discord/probe.js +54 -0
- package/dist/discord/send.js +577 -0
- package/dist/discord/token.js +8 -0
- package/dist/gateway/auth.js +121 -0
- package/dist/gateway/call.js +94 -0
- package/dist/gateway/chat-attachments.js +41 -0
- package/dist/gateway/client.js +180 -0
- package/dist/gateway/config-reload.js +274 -0
- package/dist/gateway/control-ui.js +184 -0
- package/dist/gateway/hooks-mapping.js +282 -0
- package/dist/gateway/hooks.js +168 -0
- package/dist/gateway/net.js +29 -0
- package/dist/gateway/protocol/index.js +61 -0
- package/dist/gateway/protocol/schema.js +560 -0
- package/dist/gateway/server-bridge-subscriptions.js +93 -0
- package/dist/gateway/server-bridge.js +1013 -0
- package/dist/gateway/server-browser.js +12 -0
- package/dist/gateway/server-chat.js +159 -0
- package/dist/gateway/server-constants.js +8 -0
- package/dist/gateway/server-discovery.js +62 -0
- package/dist/gateway/server-http.js +165 -0
- package/dist/gateway/server-methods/agent-job.js +125 -0
- package/dist/gateway/server-methods/agent.js +250 -0
- package/dist/gateway/server-methods/chat.js +200 -0
- package/dist/gateway/server-methods/config.js +50 -0
- package/dist/gateway/server-methods/connect.js +6 -0
- package/dist/gateway/server-methods/cron.js +83 -0
- package/dist/gateway/server-methods/health.js +28 -0
- package/dist/gateway/server-methods/models.js +16 -0
- package/dist/gateway/server-methods/nodes.js +294 -0
- package/dist/gateway/server-methods/providers.js +217 -0
- package/dist/gateway/server-methods/send.js +166 -0
- package/dist/gateway/server-methods/sessions.js +305 -0
- package/dist/gateway/server-methods/skills.js +83 -0
- package/dist/gateway/server-methods/system.js +118 -0
- package/dist/gateway/server-methods/talk.js +22 -0
- package/dist/gateway/server-methods/types.js +1 -0
- package/dist/gateway/server-methods/voicewake.js +30 -0
- package/dist/gateway/server-methods/web.js +58 -0
- package/dist/gateway/server-methods/wizard.js +100 -0
- package/dist/gateway/server-methods.js +53 -0
- package/dist/gateway/server-providers.js +644 -0
- package/dist/gateway/server-shared.js +1 -0
- package/dist/gateway/server-utils.js +35 -0
- package/dist/gateway/server.js +1437 -0
- package/dist/gateway/session-utils.js +216 -0
- package/dist/gateway/ws-log.js +349 -0
- package/dist/gateway/ws-logging.js +8 -0
- package/dist/globals.js +41 -0
- package/dist/hooks/gmail-ops.js +236 -0
- package/dist/hooks/gmail-setup-utils.js +278 -0
- package/dist/hooks/gmail-watcher.js +175 -0
- package/dist/hooks/gmail.js +177 -0
- package/dist/imessage/client.js +165 -0
- package/dist/imessage/index.js +3 -0
- package/dist/imessage/monitor.js +272 -0
- package/dist/imessage/probe.js +26 -0
- package/dist/imessage/send.js +83 -0
- package/dist/imessage/targets.js +176 -0
- package/dist/index.js +50 -0
- package/dist/infra/agent-events.js +46 -0
- package/dist/infra/binaries.js +9 -0
- package/dist/infra/bonjour-discovery.js +163 -0
- package/dist/infra/bonjour.js +200 -0
- package/dist/infra/bridge/server.js +562 -0
- package/dist/infra/canvas-host-url.js +54 -0
- package/dist/infra/env.js +8 -0
- package/dist/infra/errors.js +28 -0
- package/dist/infra/gateway-lock.js +8 -0
- package/dist/infra/heartbeat-events.js +21 -0
- package/dist/infra/heartbeat-runner.js +453 -0
- package/dist/infra/heartbeat-wake.js +61 -0
- package/dist/infra/is-main.js +37 -0
- package/dist/infra/machine-name.js +40 -0
- package/dist/infra/node-pairing.js +211 -0
- package/dist/infra/pam.js +42 -0
- package/dist/infra/path-env.js +92 -0
- package/dist/infra/ports.js +87 -0
- package/dist/infra/provider-summary.js +80 -0
- package/dist/infra/restart.js +29 -0
- package/dist/infra/retry.js +16 -0
- package/dist/infra/runtime-guard.js +59 -0
- package/dist/infra/system-events.js +44 -0
- package/dist/infra/system-presence.js +216 -0
- package/dist/infra/tailnet.js +46 -0
- package/dist/infra/tailscale.js +149 -0
- package/dist/infra/voicewake.js +77 -0
- package/dist/infra/widearea-dns.js +123 -0
- package/dist/infra/ws.js +13 -0
- package/dist/logger.js +52 -0
- package/dist/logging.js +490 -0
- package/dist/macos/gateway-daemon.js +141 -0
- package/dist/macos/relay.js +46 -0
- package/dist/media/constants.js +33 -0
- package/dist/media/host.js +42 -0
- package/dist/media/image-ops.js +121 -0
- package/dist/media/mime.js +115 -0
- package/dist/media/parse.js +81 -0
- package/dist/media/server.js +64 -0
- package/dist/media/store.js +139 -0
- package/dist/process/command-queue.js +97 -0
- package/dist/process/exec.js +75 -0
- package/dist/protocol.schema.json +2918 -0
- package/dist/provider-web.js +8 -0
- package/dist/providers/web/index.js +2 -0
- package/dist/runtime.js +8 -0
- package/dist/sessions/send-policy.js +68 -0
- package/dist/signal/client.js +134 -0
- package/dist/signal/daemon.js +69 -0
- package/dist/signal/index.js +3 -0
- package/dist/signal/monitor.js +336 -0
- package/dist/signal/probe.js +46 -0
- package/dist/signal/send.js +91 -0
- package/dist/slack/actions.js +97 -0
- package/dist/slack/index.js +5 -0
- package/dist/slack/monitor.js +1029 -0
- package/dist/slack/probe.js +47 -0
- package/dist/slack/send.js +131 -0
- package/dist/slack/token.js +10 -0
- package/dist/telegram/bot.js +394 -0
- package/dist/telegram/download.js +34 -0
- package/dist/telegram/index.js +4 -0
- package/dist/telegram/monitor.js +47 -0
- package/dist/telegram/probe.js +63 -0
- package/dist/telegram/proxy.js +9 -0
- package/dist/telegram/send.js +138 -0
- package/dist/telegram/token.js +30 -0
- package/dist/telegram/webhook-set.js +12 -0
- package/dist/telegram/webhook.js +56 -0
- package/dist/tui/commands.js +74 -0
- package/dist/tui/components/assistant-message.js +16 -0
- package/dist/tui/components/chat-log.js +92 -0
- package/dist/tui/components/custom-editor.js +53 -0
- package/dist/tui/components/selectors.js +8 -0
- package/dist/tui/components/tool-execution.js +111 -0
- package/dist/tui/components/user-message.js +17 -0
- package/dist/tui/gateway-chat.js +140 -0
- package/dist/tui/layout.js +41 -0
- package/dist/tui/message-list.js +57 -0
- package/dist/tui/theme/theme.js +80 -0
- package/dist/tui/theme.js +25 -0
- package/dist/tui/tui.js +708 -0
- package/dist/utils.js +133 -0
- package/dist/version.js +18 -0
- package/dist/web/active-listener.js +7 -0
- package/dist/web/auto-reply.js +1203 -0
- package/dist/web/inbound.js +481 -0
- package/dist/web/login-qr.js +204 -0
- package/dist/web/login.js +59 -0
- package/dist/web/media.js +148 -0
- package/dist/web/outbound.js +67 -0
- package/dist/web/qr-image.js +97 -0
- package/dist/web/reconnect.js +60 -0
- package/dist/web/reply-heartbeat-wake.js +61 -0
- package/dist/web/session.js +346 -0
- package/dist/wizard/clack-prompter.js +56 -0
- package/dist/wizard/onboarding.js +452 -0
- package/dist/wizard/prompts.js +6 -0
- package/dist/wizard/session.js +203 -0
- package/docs/AGENTS.default.md +116 -0
- package/docs/CNAME +1 -0
- package/docs/RELEASING.md +64 -0
- package/docs/_config.yml +51 -0
- package/docs/_layouts/default.html +145 -0
- package/docs/agent-send.md +21 -0
- package/docs/agent.md +104 -0
- package/docs/android/connect.md +131 -0
- package/docs/architecture.md +89 -0
- package/docs/assets/markdown.css +130 -0
- package/docs/assets/pixel-lobster.svg +60 -0
- package/docs/assets/terminal.css +497 -0
- package/docs/assets/theme.js +55 -0
- package/docs/audio.md +50 -0
- package/docs/background-process.md +74 -0
- package/docs/bash.md +32 -0
- package/docs/bonjour.md +159 -0
- package/docs/browser.md +289 -0
- package/docs/camera.md +152 -0
- package/docs/clawd.md +199 -0
- package/docs/clawdbot-mac.md +104 -0
- package/docs/configuration.md +1177 -0
- package/docs/control-api.md +49 -0
- package/docs/control-ui.md +83 -0
- package/docs/cron.md +374 -0
- package/docs/dashboard.md +17 -0
- package/docs/device-models.md +46 -0
- package/docs/discord.md +293 -0
- package/docs/discovery.md +112 -0
- package/docs/docker.md +251 -0
- package/docs/docs.json +86 -0
- package/docs/doctor.md +47 -0
- package/docs/elevated.md +31 -0
- package/docs/faq.md +640 -0
- package/docs/gateway/pairing.md +109 -0
- package/docs/gateway-lock.md +28 -0
- package/docs/gateway.md +174 -0
- package/docs/gmail-pubsub.md +191 -0
- package/docs/grammy.md +27 -0
- package/docs/group-messages.md +71 -0
- package/docs/groups.md +78 -0
- package/docs/health.md +28 -0
- package/docs/heartbeat.md +64 -0
- package/docs/images.md +52 -0
- package/docs/imessage.md +63 -0
- package/docs/index.md +182 -0
- package/docs/ios/connect.md +177 -0
- package/docs/ios/spec.md +236 -0
- package/docs/location-command.md +95 -0
- package/docs/logging.md +99 -0
- package/docs/lore.md +131 -0
- package/docs/mac/bun.md +133 -0
- package/docs/mac/canvas.md +161 -0
- package/docs/mac/child-process.md +72 -0
- package/docs/mac/dev-setup.md +81 -0
- package/docs/mac/health.md +28 -0
- package/docs/mac/icon.md +26 -0
- package/docs/mac/logging.md +51 -0
- package/docs/mac/menu-bar.md +69 -0
- package/docs/mac/peekaboo.md +170 -0
- package/docs/mac/permissions.md +40 -0
- package/docs/mac/release.md +76 -0
- package/docs/mac/remote.md +57 -0
- package/docs/mac/signing.md +41 -0
- package/docs/mac/skills.md +27 -0
- package/docs/mac/voice-overlay.md +52 -0
- package/docs/mac/voicewake.md +56 -0
- package/docs/mac/webchat.md +27 -0
- package/docs/mac/xpc.md +40 -0
- package/docs/models.md +90 -0
- package/docs/nix.md +49 -0
- package/docs/nodes.md +157 -0
- package/docs/onboarding-config-protocol.md +29 -0
- package/docs/onboarding.md +185 -0
- package/docs/presence.md +133 -0
- package/docs/queue.md +78 -0
- package/docs/refactor/browser-control-simplification.md +58 -0
- package/docs/refactor/canvas-a2ui.md +93 -0
- package/docs/refactor/cli-unification.md +64 -0
- package/docs/refactor/gateway-client.md +31 -0
- package/docs/refactor/gateway.md +99 -0
- package/docs/refactor/new-arch.md +171 -0
- package/docs/refactor/tui.md +26 -0
- package/docs/refactor/web-gateway-troubleshooting.md +37 -0
- package/docs/refactor/webagent-session.md +46 -0
- package/docs/remote-gateway-readme.md +148 -0
- package/docs/remote.md +66 -0
- package/docs/research/memory.md +227 -0
- package/docs/rpc.md +35 -0
- package/docs/security.md +168 -0
- package/docs/session-tool.md +119 -0
- package/docs/session.md +84 -0
- package/docs/sessions.md +8 -0
- package/docs/setup.md +118 -0
- package/docs/signal.md +113 -0
- package/docs/skills-config.md +58 -0
- package/docs/skills.md +149 -0
- package/docs/slack.md +158 -0
- package/docs/surface.md +20 -0
- package/docs/tailscale.md +71 -0
- package/docs/talk.md +79 -0
- package/docs/telegram.md +90 -0
- package/docs/templates/AGENTS.md +126 -0
- package/docs/templates/BOOTSTRAP.md +53 -0
- package/docs/templates/IDENTITY.md +17 -0
- package/docs/templates/SOUL.md +41 -0
- package/docs/templates/TOOLS.md +41 -0
- package/docs/templates/USER.md +22 -0
- package/docs/test.md +35 -0
- package/docs/thinking.md +46 -0
- package/docs/tools.md +248 -0
- package/docs/troubleshooting.md +227 -0
- package/docs/tui.md +69 -0
- package/docs/typebox.md +42 -0
- package/docs/voicewake.md +61 -0
- package/docs/web.md +115 -0
- package/docs/webchat.md +34 -0
- package/docs/webhook.md +132 -0
- package/docs/whatsapp-clawd.jpg +0 -0
- package/docs/whatsapp.md +142 -0
- package/docs/wizard.md +158 -0
- package/package.json +186 -0
- package/skills/apple-notes/SKILL.md +50 -0
- package/skills/apple-reminders/SKILL.md +67 -0
- package/skills/bear-notes/SKILL.md +79 -0
- package/skills/bird/SKILL.md +25 -0
- package/skills/blogwatcher/SKILL.md +46 -0
- package/skills/blucli/SKILL.md +27 -0
- package/skills/brave-search/SKILL.md +30 -0
- package/skills/brave-search/scripts/content.mjs +53 -0
- package/skills/brave-search/scripts/search.mjs +79 -0
- package/skills/camsnap/SKILL.md +25 -0
- package/skills/clawdhub/SKILL.md +53 -0
- package/skills/coding-agent/SKILL.md +275 -0
- package/skills/discord/SKILL.md +369 -0
- package/skills/eightctl/SKILL.md +29 -0
- package/skills/food-order/SKILL.md +41 -0
- package/skills/gemini/SKILL.md +23 -0
- package/skills/gifgrep/SKILL.md +47 -0
- package/skills/github/SKILL.md +47 -0
- package/skills/gog/SKILL.md +36 -0
- package/skills/goplaces/SKILL.md +30 -0
- package/skills/imsg/SKILL.md +25 -0
- package/skills/local-places/SERVER_README.md +101 -0
- package/skills/local-places/SKILL.md +91 -0
- package/skills/local-places/pyproject.toml +27 -0
- package/skills/local-places/src/local_places/__init__.py +2 -0
- package/skills/local-places/src/local_places/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/local-places/src/local_places/__pycache__/google_places.cpython-314.pyc +0 -0
- package/skills/local-places/src/local_places/__pycache__/main.cpython-314.pyc +0 -0
- package/skills/local-places/src/local_places/__pycache__/schemas.cpython-314.pyc +0 -0
- package/skills/local-places/src/local_places/google_places.py +314 -0
- package/skills/local-places/src/local_places/main.py +65 -0
- package/skills/local-places/src/local_places/schemas.py +107 -0
- package/skills/mcporter/SKILL.md +38 -0
- package/skills/nano-banana-pro/SKILL.md +29 -0
- package/skills/nano-banana-pro/scripts/generate_image.py +167 -0
- package/skills/nano-pdf/SKILL.md +20 -0
- package/skills/notion/SKILL.md +156 -0
- package/skills/obsidian/SKILL.md +55 -0
- package/skills/openai-image-gen/SKILL.md +31 -0
- package/skills/openai-image-gen/scripts/gen.py +173 -0
- package/skills/openai-whisper/SKILL.md +19 -0
- package/skills/openai-whisper-api/SKILL.md +43 -0
- package/skills/openai-whisper-api/scripts/transcribe.sh +85 -0
- package/skills/openhue/SKILL.md +30 -0
- package/skills/oracle/SKILL.md +105 -0
- package/skills/ordercli/SKILL.md +47 -0
- package/skills/peekaboo/SKILL.md +153 -0
- package/skills/qmd/SKILL.md +26 -0
- package/skills/sag/SKILL.md +62 -0
- package/skills/slack/SKILL.md +143 -0
- package/skills/songsee/SKILL.md +29 -0
- package/skills/sonoscli/SKILL.md +26 -0
- package/skills/spotify-player/SKILL.md +34 -0
- package/skills/summarize/SKILL.md +49 -0
- package/skills/things-mac/SKILL.md +61 -0
- package/skills/tmux/SKILL.md +121 -0
- package/skills/tmux/scripts/find-sessions.sh +112 -0
- package/skills/tmux/scripts/wait-for-text.sh +83 -0
- package/skills/trello/SKILL.md +84 -0
- package/skills/video-frames/SKILL.md +29 -0
- package/skills/video-frames/scripts/frame.sh +81 -0
- package/skills/wacli/SKILL.md +42 -0
- package/skills/weather/SKILL.md +49 -0
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { CONFIG_PATH_CLAWDBOT, loadConfig, resolveGatewayPort, } from "../config/config.js";
|
|
3
|
+
import { callGateway, randomIdempotencyKey } from "../gateway/call.js";
|
|
4
|
+
import { startGatewayServer } from "../gateway/server.js";
|
|
5
|
+
import { setGatewayWsLogStyle, } from "../gateway/ws-logging.js";
|
|
6
|
+
import { setVerbose } from "../globals.js";
|
|
7
|
+
import { GatewayLockError } from "../infra/gateway-lock.js";
|
|
8
|
+
import { createSubsystemLogger } from "../logging.js";
|
|
9
|
+
import { defaultRuntime } from "../runtime.js";
|
|
10
|
+
import { createDefaultDeps } from "./deps.js";
|
|
11
|
+
import { forceFreePortAndWait } from "./ports.js";
|
|
12
|
+
const gatewayLog = createSubsystemLogger("gateway");
|
|
13
|
+
function parsePort(raw) {
|
|
14
|
+
if (raw === undefined || raw === null)
|
|
15
|
+
return null;
|
|
16
|
+
const value = typeof raw === "string"
|
|
17
|
+
? raw
|
|
18
|
+
: typeof raw === "number" || typeof raw === "bigint"
|
|
19
|
+
? raw.toString()
|
|
20
|
+
: null;
|
|
21
|
+
if (value === null)
|
|
22
|
+
return null;
|
|
23
|
+
const parsed = Number.parseInt(value, 10);
|
|
24
|
+
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
25
|
+
return null;
|
|
26
|
+
return parsed;
|
|
27
|
+
}
|
|
28
|
+
async function runGatewayLoop(params) {
|
|
29
|
+
let server = null;
|
|
30
|
+
let shuttingDown = false;
|
|
31
|
+
let restartResolver = null;
|
|
32
|
+
const cleanupSignals = () => {
|
|
33
|
+
process.removeListener("SIGTERM", onSigterm);
|
|
34
|
+
process.removeListener("SIGINT", onSigint);
|
|
35
|
+
process.removeListener("SIGUSR1", onSigusr1);
|
|
36
|
+
};
|
|
37
|
+
const request = (action, signal) => {
|
|
38
|
+
if (shuttingDown) {
|
|
39
|
+
gatewayLog.info(`received ${signal} during shutdown; ignoring`);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
shuttingDown = true;
|
|
43
|
+
const isRestart = action === "restart";
|
|
44
|
+
gatewayLog.info(`received ${signal}; ${isRestart ? "restarting" : "shutting down"}`);
|
|
45
|
+
const forceExitTimer = setTimeout(() => {
|
|
46
|
+
gatewayLog.error("shutdown timed out; exiting without full cleanup");
|
|
47
|
+
cleanupSignals();
|
|
48
|
+
params.runtime.exit(0);
|
|
49
|
+
}, 5000);
|
|
50
|
+
void (async () => {
|
|
51
|
+
try {
|
|
52
|
+
await server?.close({
|
|
53
|
+
reason: isRestart ? "gateway restarting" : "gateway stopping",
|
|
54
|
+
restartExpectedMs: isRestart ? 1500 : null,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
gatewayLog.error(`shutdown error: ${String(err)}`);
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
clearTimeout(forceExitTimer);
|
|
62
|
+
server = null;
|
|
63
|
+
if (isRestart) {
|
|
64
|
+
shuttingDown = false;
|
|
65
|
+
restartResolver?.();
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
cleanupSignals();
|
|
69
|
+
params.runtime.exit(0);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
})();
|
|
73
|
+
};
|
|
74
|
+
const onSigterm = () => request("stop", "SIGTERM");
|
|
75
|
+
const onSigint = () => request("stop", "SIGINT");
|
|
76
|
+
const onSigusr1 = () => request("restart", "SIGUSR1");
|
|
77
|
+
process.on("SIGTERM", onSigterm);
|
|
78
|
+
process.on("SIGINT", onSigint);
|
|
79
|
+
process.on("SIGUSR1", onSigusr1);
|
|
80
|
+
try {
|
|
81
|
+
// Keep process alive; SIGUSR1 triggers an in-process restart (no supervisor required).
|
|
82
|
+
// SIGTERM/SIGINT still exit after a graceful shutdown.
|
|
83
|
+
// eslint-disable-next-line no-constant-condition
|
|
84
|
+
while (true) {
|
|
85
|
+
server = await params.start();
|
|
86
|
+
await new Promise((resolve) => {
|
|
87
|
+
restartResolver = resolve;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
cleanupSignals();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const gatewayCallOpts = (cmd) => cmd
|
|
96
|
+
.option("--url <url>", "Gateway WebSocket URL (defaults to gateway.remote.url when configured)")
|
|
97
|
+
.option("--token <token>", "Gateway token (if required)")
|
|
98
|
+
.option("--password <password>", "Gateway password (password auth)")
|
|
99
|
+
.option("--timeout <ms>", "Timeout in ms", "10000")
|
|
100
|
+
.option("--expect-final", "Wait for final response (agent)", false);
|
|
101
|
+
const callGatewayCli = async (method, opts, params) => callGateway({
|
|
102
|
+
url: opts.url,
|
|
103
|
+
token: opts.token,
|
|
104
|
+
password: opts.password,
|
|
105
|
+
method,
|
|
106
|
+
params,
|
|
107
|
+
expectFinal: Boolean(opts.expectFinal),
|
|
108
|
+
timeoutMs: Number(opts.timeout ?? 10_000),
|
|
109
|
+
clientName: "cli",
|
|
110
|
+
mode: "cli",
|
|
111
|
+
});
|
|
112
|
+
export function registerGatewayCli(program) {
|
|
113
|
+
program
|
|
114
|
+
.command("gateway-daemon")
|
|
115
|
+
.description("Run the WebSocket Gateway as a long-lived daemon")
|
|
116
|
+
.option("--port <port>", "Port for the gateway WebSocket", "18789")
|
|
117
|
+
.option("--bind <mode>", 'Bind mode ("loopback"|"tailnet"|"lan"|"auto"). Defaults to config gateway.bind (or loopback).')
|
|
118
|
+
.option("--token <token>", "Shared token required in connect.params.auth.token (default: CLAWDBOT_GATEWAY_TOKEN env if set)")
|
|
119
|
+
.option("--auth <mode>", 'Gateway auth mode ("token"|"password")')
|
|
120
|
+
.option("--password <password>", "Password for auth mode=password")
|
|
121
|
+
.option("--tailscale <mode>", 'Tailscale exposure mode ("off"|"serve"|"funnel")')
|
|
122
|
+
.option("--tailscale-reset-on-exit", "Reset Tailscale serve/funnel configuration on shutdown", false)
|
|
123
|
+
.option("--verbose", "Verbose logging to stdout/stderr", false)
|
|
124
|
+
.option("--ws-log <style>", 'WebSocket log style ("auto"|"full"|"compact")', "auto")
|
|
125
|
+
.option("--compact", 'Alias for "--ws-log compact"', false)
|
|
126
|
+
.action(async (opts) => {
|
|
127
|
+
setVerbose(Boolean(opts.verbose));
|
|
128
|
+
const wsLogRaw = (opts.compact ? "compact" : opts.wsLog);
|
|
129
|
+
const wsLogStyle = wsLogRaw === "compact"
|
|
130
|
+
? "compact"
|
|
131
|
+
: wsLogRaw === "full"
|
|
132
|
+
? "full"
|
|
133
|
+
: "auto";
|
|
134
|
+
if (wsLogRaw !== undefined &&
|
|
135
|
+
wsLogRaw !== "auto" &&
|
|
136
|
+
wsLogRaw !== "compact" &&
|
|
137
|
+
wsLogRaw !== "full") {
|
|
138
|
+
defaultRuntime.error('Invalid --ws-log (use "auto", "full", "compact")');
|
|
139
|
+
defaultRuntime.exit(1);
|
|
140
|
+
}
|
|
141
|
+
setGatewayWsLogStyle(wsLogStyle);
|
|
142
|
+
const cfg = loadConfig();
|
|
143
|
+
const portOverride = parsePort(opts.port);
|
|
144
|
+
if (opts.port !== undefined && portOverride === null) {
|
|
145
|
+
defaultRuntime.error("Invalid port");
|
|
146
|
+
defaultRuntime.exit(1);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const port = portOverride ?? resolveGatewayPort(cfg);
|
|
150
|
+
if (!Number.isFinite(port) || port <= 0) {
|
|
151
|
+
defaultRuntime.error("Invalid port");
|
|
152
|
+
defaultRuntime.exit(1);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (opts.token) {
|
|
156
|
+
process.env.CLAWDBOT_GATEWAY_TOKEN = String(opts.token);
|
|
157
|
+
}
|
|
158
|
+
const authModeRaw = opts.auth ? String(opts.auth) : undefined;
|
|
159
|
+
const authMode = authModeRaw === "token" || authModeRaw === "password"
|
|
160
|
+
? authModeRaw
|
|
161
|
+
: null;
|
|
162
|
+
if (authModeRaw && !authMode) {
|
|
163
|
+
defaultRuntime.error('Invalid --auth (use "token" or "password")');
|
|
164
|
+
defaultRuntime.exit(1);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const tailscaleRaw = opts.tailscale ? String(opts.tailscale) : undefined;
|
|
168
|
+
const tailscaleMode = tailscaleRaw === "off" ||
|
|
169
|
+
tailscaleRaw === "serve" ||
|
|
170
|
+
tailscaleRaw === "funnel"
|
|
171
|
+
? tailscaleRaw
|
|
172
|
+
: null;
|
|
173
|
+
if (tailscaleRaw && !tailscaleMode) {
|
|
174
|
+
defaultRuntime.error('Invalid --tailscale (use "off", "serve", or "funnel")');
|
|
175
|
+
defaultRuntime.exit(1);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const bindRaw = String(opts.bind ?? cfg.gateway?.bind ?? "loopback");
|
|
179
|
+
const bind = bindRaw === "loopback" ||
|
|
180
|
+
bindRaw === "tailnet" ||
|
|
181
|
+
bindRaw === "lan" ||
|
|
182
|
+
bindRaw === "auto"
|
|
183
|
+
? bindRaw
|
|
184
|
+
: null;
|
|
185
|
+
if (!bind) {
|
|
186
|
+
defaultRuntime.error('Invalid --bind (use "loopback", "tailnet", "lan", or "auto")');
|
|
187
|
+
defaultRuntime.exit(1);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
try {
|
|
191
|
+
await runGatewayLoop({
|
|
192
|
+
runtime: defaultRuntime,
|
|
193
|
+
start: async () => await startGatewayServer(port, {
|
|
194
|
+
bind,
|
|
195
|
+
auth: authMode || opts.password || authModeRaw
|
|
196
|
+
? {
|
|
197
|
+
mode: authMode ?? undefined,
|
|
198
|
+
password: opts.password
|
|
199
|
+
? String(opts.password)
|
|
200
|
+
: undefined,
|
|
201
|
+
}
|
|
202
|
+
: undefined,
|
|
203
|
+
tailscale: tailscaleMode || opts.tailscaleResetOnExit
|
|
204
|
+
? {
|
|
205
|
+
mode: tailscaleMode ?? undefined,
|
|
206
|
+
resetOnExit: Boolean(opts.tailscaleResetOnExit),
|
|
207
|
+
}
|
|
208
|
+
: undefined,
|
|
209
|
+
}),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
if (err instanceof GatewayLockError) {
|
|
214
|
+
defaultRuntime.error(`Gateway failed to start: ${err.message}`);
|
|
215
|
+
defaultRuntime.exit(1);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
defaultRuntime.error(`Gateway failed to start: ${String(err)}`);
|
|
219
|
+
defaultRuntime.exit(1);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
const gateway = program
|
|
223
|
+
.command("gateway")
|
|
224
|
+
.description("Run the WebSocket Gateway")
|
|
225
|
+
.option("--port <port>", "Port for the gateway WebSocket", "18789")
|
|
226
|
+
.option("--bind <mode>", 'Bind mode ("loopback"|"tailnet"|"lan"|"auto"). Defaults to config gateway.bind (or loopback).')
|
|
227
|
+
.option("--token <token>", "Shared token required in connect.params.auth.token (default: CLAWDBOT_GATEWAY_TOKEN env if set)")
|
|
228
|
+
.option("--auth <mode>", 'Gateway auth mode ("token"|"password")')
|
|
229
|
+
.option("--password <password>", "Password for auth mode=password")
|
|
230
|
+
.option("--tailscale <mode>", 'Tailscale exposure mode ("off"|"serve"|"funnel")')
|
|
231
|
+
.option("--tailscale-reset-on-exit", "Reset Tailscale serve/funnel configuration on shutdown", false)
|
|
232
|
+
.option("--allow-unconfigured", "Allow gateway start without gateway.mode=local in config", false)
|
|
233
|
+
.option("--force", "Kill any existing listener on the target port before starting", false)
|
|
234
|
+
.option("--verbose", "Verbose logging to stdout/stderr", false)
|
|
235
|
+
.option("--ws-log <style>", 'WebSocket log style ("auto"|"full"|"compact")', "auto")
|
|
236
|
+
.option("--compact", 'Alias for "--ws-log compact"', false)
|
|
237
|
+
.action(async (opts) => {
|
|
238
|
+
setVerbose(Boolean(opts.verbose));
|
|
239
|
+
const wsLogRaw = (opts.compact ? "compact" : opts.wsLog);
|
|
240
|
+
const wsLogStyle = wsLogRaw === "compact"
|
|
241
|
+
? "compact"
|
|
242
|
+
: wsLogRaw === "full"
|
|
243
|
+
? "full"
|
|
244
|
+
: "auto";
|
|
245
|
+
if (wsLogRaw !== undefined &&
|
|
246
|
+
wsLogRaw !== "auto" &&
|
|
247
|
+
wsLogRaw !== "compact" &&
|
|
248
|
+
wsLogRaw !== "full") {
|
|
249
|
+
defaultRuntime.error('Invalid --ws-log (use "auto", "full", "compact")');
|
|
250
|
+
defaultRuntime.exit(1);
|
|
251
|
+
}
|
|
252
|
+
setGatewayWsLogStyle(wsLogStyle);
|
|
253
|
+
const cfg = loadConfig();
|
|
254
|
+
const portOverride = parsePort(opts.port);
|
|
255
|
+
if (opts.port !== undefined && portOverride === null) {
|
|
256
|
+
defaultRuntime.error("Invalid port");
|
|
257
|
+
defaultRuntime.exit(1);
|
|
258
|
+
}
|
|
259
|
+
const port = portOverride ?? resolveGatewayPort(cfg);
|
|
260
|
+
if (!Number.isFinite(port) || port <= 0) {
|
|
261
|
+
defaultRuntime.error("Invalid port");
|
|
262
|
+
defaultRuntime.exit(1);
|
|
263
|
+
}
|
|
264
|
+
if (opts.force) {
|
|
265
|
+
try {
|
|
266
|
+
const { killed, waitedMs, escalatedToSigkill } = await forceFreePortAndWait(port, {
|
|
267
|
+
timeoutMs: 2000,
|
|
268
|
+
intervalMs: 100,
|
|
269
|
+
sigtermTimeoutMs: 700,
|
|
270
|
+
});
|
|
271
|
+
if (killed.length === 0) {
|
|
272
|
+
gatewayLog.info(`force: no listeners on port ${port}`);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
for (const proc of killed) {
|
|
276
|
+
gatewayLog.info(`force: killed pid ${proc.pid}${proc.command ? ` (${proc.command})` : ""} on port ${port}`);
|
|
277
|
+
}
|
|
278
|
+
if (escalatedToSigkill) {
|
|
279
|
+
gatewayLog.info(`force: escalated to SIGKILL while freeing port ${port}`);
|
|
280
|
+
}
|
|
281
|
+
if (waitedMs > 0) {
|
|
282
|
+
gatewayLog.info(`force: waited ${waitedMs}ms for port ${port} to free`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
defaultRuntime.error(`Force: ${String(err)}`);
|
|
288
|
+
defaultRuntime.exit(1);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (opts.token) {
|
|
293
|
+
process.env.CLAWDBOT_GATEWAY_TOKEN = String(opts.token);
|
|
294
|
+
}
|
|
295
|
+
const authModeRaw = opts.auth ? String(opts.auth) : undefined;
|
|
296
|
+
const authMode = authModeRaw === "token" || authModeRaw === "password"
|
|
297
|
+
? authModeRaw
|
|
298
|
+
: null;
|
|
299
|
+
if (authModeRaw && !authMode) {
|
|
300
|
+
defaultRuntime.error('Invalid --auth (use "token" or "password")');
|
|
301
|
+
defaultRuntime.exit(1);
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
const tailscaleRaw = opts.tailscale ? String(opts.tailscale) : undefined;
|
|
305
|
+
const tailscaleMode = tailscaleRaw === "off" ||
|
|
306
|
+
tailscaleRaw === "serve" ||
|
|
307
|
+
tailscaleRaw === "funnel"
|
|
308
|
+
? tailscaleRaw
|
|
309
|
+
: null;
|
|
310
|
+
if (tailscaleRaw && !tailscaleMode) {
|
|
311
|
+
defaultRuntime.error('Invalid --tailscale (use "off", "serve", or "funnel")');
|
|
312
|
+
defaultRuntime.exit(1);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
const configExists = fs.existsSync(CONFIG_PATH_CLAWDBOT);
|
|
316
|
+
const mode = cfg.gateway?.mode;
|
|
317
|
+
if (!opts.allowUnconfigured && mode !== "local") {
|
|
318
|
+
if (!configExists) {
|
|
319
|
+
defaultRuntime.error("Missing config. Run `clawdbot setup` or set gateway.mode=local (or pass --allow-unconfigured).");
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
defaultRuntime.error("Gateway start blocked: set gateway.mode=local (or pass --allow-unconfigured).");
|
|
323
|
+
}
|
|
324
|
+
defaultRuntime.exit(1);
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const bindRaw = String(opts.bind ?? cfg.gateway?.bind ?? "loopback");
|
|
328
|
+
const bind = bindRaw === "loopback" ||
|
|
329
|
+
bindRaw === "tailnet" ||
|
|
330
|
+
bindRaw === "lan" ||
|
|
331
|
+
bindRaw === "auto"
|
|
332
|
+
? bindRaw
|
|
333
|
+
: null;
|
|
334
|
+
if (!bind) {
|
|
335
|
+
defaultRuntime.error('Invalid --bind (use "loopback", "tailnet", "lan", or "auto")');
|
|
336
|
+
defaultRuntime.exit(1);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
await runGatewayLoop({
|
|
341
|
+
runtime: defaultRuntime,
|
|
342
|
+
start: async () => await startGatewayServer(port, {
|
|
343
|
+
bind,
|
|
344
|
+
auth: authMode || opts.password || authModeRaw
|
|
345
|
+
? {
|
|
346
|
+
mode: authMode ?? undefined,
|
|
347
|
+
password: opts.password
|
|
348
|
+
? String(opts.password)
|
|
349
|
+
: undefined,
|
|
350
|
+
}
|
|
351
|
+
: undefined,
|
|
352
|
+
tailscale: tailscaleMode || opts.tailscaleResetOnExit
|
|
353
|
+
? {
|
|
354
|
+
mode: tailscaleMode ?? undefined,
|
|
355
|
+
resetOnExit: Boolean(opts.tailscaleResetOnExit),
|
|
356
|
+
}
|
|
357
|
+
: undefined,
|
|
358
|
+
}),
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
catch (err) {
|
|
362
|
+
if (err instanceof GatewayLockError) {
|
|
363
|
+
defaultRuntime.error(`Gateway failed to start: ${err.message}`);
|
|
364
|
+
defaultRuntime.exit(1);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
defaultRuntime.error(`Gateway failed to start: ${String(err)}`);
|
|
368
|
+
defaultRuntime.exit(1);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
gatewayCallOpts(gateway
|
|
372
|
+
.command("call")
|
|
373
|
+
.description("Call a Gateway method and print JSON")
|
|
374
|
+
.argument("<method>", "Method name (health/status/system-presence/send/agent/cron.*)")
|
|
375
|
+
.option("--params <json>", "JSON object string for params", "{}")
|
|
376
|
+
.action(async (method, opts) => {
|
|
377
|
+
try {
|
|
378
|
+
const params = JSON.parse(String(opts.params ?? "{}"));
|
|
379
|
+
const result = await callGatewayCli(method, opts, params);
|
|
380
|
+
defaultRuntime.log(JSON.stringify(result, null, 2));
|
|
381
|
+
}
|
|
382
|
+
catch (err) {
|
|
383
|
+
defaultRuntime.error(`Gateway call failed: ${String(err)}`);
|
|
384
|
+
defaultRuntime.exit(1);
|
|
385
|
+
}
|
|
386
|
+
}));
|
|
387
|
+
gatewayCallOpts(gateway
|
|
388
|
+
.command("health")
|
|
389
|
+
.description("Fetch Gateway health")
|
|
390
|
+
.action(async (opts) => {
|
|
391
|
+
try {
|
|
392
|
+
const result = await callGatewayCli("health", opts);
|
|
393
|
+
defaultRuntime.log(JSON.stringify(result, null, 2));
|
|
394
|
+
}
|
|
395
|
+
catch (err) {
|
|
396
|
+
defaultRuntime.error(String(err));
|
|
397
|
+
defaultRuntime.exit(1);
|
|
398
|
+
}
|
|
399
|
+
}));
|
|
400
|
+
gatewayCallOpts(gateway
|
|
401
|
+
.command("status")
|
|
402
|
+
.description("Fetch Gateway status")
|
|
403
|
+
.action(async (opts) => {
|
|
404
|
+
try {
|
|
405
|
+
const result = await callGatewayCli("status", opts);
|
|
406
|
+
defaultRuntime.log(JSON.stringify(result, null, 2));
|
|
407
|
+
}
|
|
408
|
+
catch (err) {
|
|
409
|
+
defaultRuntime.error(String(err));
|
|
410
|
+
defaultRuntime.exit(1);
|
|
411
|
+
}
|
|
412
|
+
}));
|
|
413
|
+
gatewayCallOpts(gateway
|
|
414
|
+
.command("wake")
|
|
415
|
+
.description("Enqueue a system event and optionally trigger a heartbeat")
|
|
416
|
+
.requiredOption("--text <text>", "System event text")
|
|
417
|
+
.option("--mode <mode>", "Wake mode (now|next-heartbeat)", "next-heartbeat")
|
|
418
|
+
.action(async (opts) => {
|
|
419
|
+
try {
|
|
420
|
+
const result = await callGatewayCli("wake", opts, {
|
|
421
|
+
mode: opts.mode,
|
|
422
|
+
text: opts.text,
|
|
423
|
+
});
|
|
424
|
+
defaultRuntime.log(JSON.stringify(result, null, 2));
|
|
425
|
+
}
|
|
426
|
+
catch (err) {
|
|
427
|
+
defaultRuntime.error(String(err));
|
|
428
|
+
defaultRuntime.exit(1);
|
|
429
|
+
}
|
|
430
|
+
}));
|
|
431
|
+
gatewayCallOpts(gateway
|
|
432
|
+
.command("send")
|
|
433
|
+
.description("Send a message via the Gateway")
|
|
434
|
+
.requiredOption("--to <jidOrPhone>", "Destination (E.164 or jid)")
|
|
435
|
+
.requiredOption("--message <text>", "Message text")
|
|
436
|
+
.option("--media-url <url>", "Optional media URL")
|
|
437
|
+
.option("--gif-playback", "Treat video media as GIF playback", false)
|
|
438
|
+
.option("--idempotency-key <key>", "Idempotency key")
|
|
439
|
+
.action(async (opts) => {
|
|
440
|
+
try {
|
|
441
|
+
const idempotencyKey = opts.idempotencyKey ?? randomIdempotencyKey();
|
|
442
|
+
const result = await callGatewayCli("send", opts, {
|
|
443
|
+
to: opts.to,
|
|
444
|
+
message: opts.message,
|
|
445
|
+
mediaUrl: opts.mediaUrl,
|
|
446
|
+
gifPlayback: opts.gifPlayback,
|
|
447
|
+
idempotencyKey,
|
|
448
|
+
});
|
|
449
|
+
defaultRuntime.log(JSON.stringify(result, null, 2));
|
|
450
|
+
}
|
|
451
|
+
catch (err) {
|
|
452
|
+
defaultRuntime.error(String(err));
|
|
453
|
+
defaultRuntime.exit(1);
|
|
454
|
+
}
|
|
455
|
+
}));
|
|
456
|
+
gatewayCallOpts(gateway
|
|
457
|
+
.command("agent")
|
|
458
|
+
.description("Run an agent turn via the Gateway (waits for final)")
|
|
459
|
+
.requiredOption("--message <text>", "User message")
|
|
460
|
+
.option("--to <jidOrPhone>", "Destination")
|
|
461
|
+
.option("--session-id <id>", "Session id")
|
|
462
|
+
.option("--thinking <level>", "Thinking level")
|
|
463
|
+
.option("--deliver", "Deliver response", false)
|
|
464
|
+
.option("--timeout-seconds <n>", "Agent timeout seconds")
|
|
465
|
+
.option("--idempotency-key <key>", "Idempotency key")
|
|
466
|
+
.action(async (opts) => {
|
|
467
|
+
try {
|
|
468
|
+
const idempotencyKey = opts.idempotencyKey ?? randomIdempotencyKey();
|
|
469
|
+
const result = await callGatewayCli("agent", { ...opts, expectFinal: true }, {
|
|
470
|
+
message: opts.message,
|
|
471
|
+
to: opts.to,
|
|
472
|
+
sessionId: opts.sessionId,
|
|
473
|
+
thinking: opts.thinking,
|
|
474
|
+
deliver: Boolean(opts.deliver),
|
|
475
|
+
timeout: opts.timeoutSeconds
|
|
476
|
+
? Number.parseInt(String(opts.timeoutSeconds), 10)
|
|
477
|
+
: undefined,
|
|
478
|
+
idempotencyKey,
|
|
479
|
+
});
|
|
480
|
+
defaultRuntime.log(JSON.stringify(result, null, 2));
|
|
481
|
+
}
|
|
482
|
+
catch (err) {
|
|
483
|
+
defaultRuntime.error(String(err));
|
|
484
|
+
defaultRuntime.exit(1);
|
|
485
|
+
}
|
|
486
|
+
}));
|
|
487
|
+
// Build default deps (keeps parity with other commands; future-proofing).
|
|
488
|
+
void createDefaultDeps();
|
|
489
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { callGateway } from "../gateway/call.js";
|
|
2
|
+
export function addGatewayClientOptions(cmd) {
|
|
3
|
+
return cmd
|
|
4
|
+
.option("--url <url>", "Gateway WebSocket URL (defaults to gateway.remote.url when configured)")
|
|
5
|
+
.option("--token <token>", "Gateway token (if required)")
|
|
6
|
+
.option("--timeout <ms>", "Timeout in ms", "10000")
|
|
7
|
+
.option("--expect-final", "Wait for final response (agent)", false);
|
|
8
|
+
}
|
|
9
|
+
export async function callGatewayFromCli(method, opts, params, extra) {
|
|
10
|
+
return await callGateway({
|
|
11
|
+
url: opts.url,
|
|
12
|
+
token: opts.token,
|
|
13
|
+
method,
|
|
14
|
+
params,
|
|
15
|
+
expectFinal: extra?.expectFinal ?? Boolean(opts.expectFinal),
|
|
16
|
+
timeoutMs: Number(opts.timeout ?? 10_000),
|
|
17
|
+
clientName: "cli",
|
|
18
|
+
mode: "cli",
|
|
19
|
+
});
|
|
20
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { danger } from "../globals.js";
|
|
2
|
+
import { DEFAULT_GMAIL_LABEL, DEFAULT_GMAIL_MAX_BYTES, DEFAULT_GMAIL_RENEW_MINUTES, DEFAULT_GMAIL_SERVE_BIND, DEFAULT_GMAIL_SERVE_PATH, DEFAULT_GMAIL_SERVE_PORT, DEFAULT_GMAIL_SUBSCRIPTION, DEFAULT_GMAIL_TOPIC, } from "../hooks/gmail.js";
|
|
3
|
+
import { runGmailService, runGmailSetup, } from "../hooks/gmail-ops.js";
|
|
4
|
+
import { defaultRuntime } from "../runtime.js";
|
|
5
|
+
export function registerHooksCli(program) {
|
|
6
|
+
const hooks = program
|
|
7
|
+
.command("hooks")
|
|
8
|
+
.description("Webhook helpers and hook-based integrations");
|
|
9
|
+
const gmail = hooks
|
|
10
|
+
.command("gmail")
|
|
11
|
+
.description("Gmail Pub/Sub hooks (via gogcli)");
|
|
12
|
+
gmail
|
|
13
|
+
.command("setup")
|
|
14
|
+
.description("Configure Gmail watch + Pub/Sub + Clawdbot hooks")
|
|
15
|
+
.requiredOption("--account <email>", "Gmail account to watch")
|
|
16
|
+
.option("--project <id>", "GCP project id (OAuth client owner)")
|
|
17
|
+
.option("--topic <name>", "Pub/Sub topic name", DEFAULT_GMAIL_TOPIC)
|
|
18
|
+
.option("--subscription <name>", "Pub/Sub subscription name", DEFAULT_GMAIL_SUBSCRIPTION)
|
|
19
|
+
.option("--label <label>", "Gmail label to watch", DEFAULT_GMAIL_LABEL)
|
|
20
|
+
.option("--hook-url <url>", "Clawdbot hook URL")
|
|
21
|
+
.option("--hook-token <token>", "Clawdbot hook token")
|
|
22
|
+
.option("--push-token <token>", "Push token for gog watch serve")
|
|
23
|
+
.option("--bind <host>", "gog watch serve bind host", DEFAULT_GMAIL_SERVE_BIND)
|
|
24
|
+
.option("--port <port>", "gog watch serve port", String(DEFAULT_GMAIL_SERVE_PORT))
|
|
25
|
+
.option("--path <path>", "gog watch serve path", DEFAULT_GMAIL_SERVE_PATH)
|
|
26
|
+
.option("--include-body", "Include email body snippets", true)
|
|
27
|
+
.option("--max-bytes <n>", "Max bytes for body snippets", String(DEFAULT_GMAIL_MAX_BYTES))
|
|
28
|
+
.option("--renew-minutes <n>", "Renew watch every N minutes", String(DEFAULT_GMAIL_RENEW_MINUTES))
|
|
29
|
+
.option("--tailscale <mode>", "Expose push endpoint via tailscale (funnel|serve|off)", "funnel")
|
|
30
|
+
.option("--tailscale-path <path>", "Path for tailscale serve/funnel")
|
|
31
|
+
.option("--push-endpoint <url>", "Explicit Pub/Sub push endpoint")
|
|
32
|
+
.option("--json", "Output JSON summary", false)
|
|
33
|
+
.action(async (opts) => {
|
|
34
|
+
try {
|
|
35
|
+
const parsed = parseGmailSetupOptions(opts);
|
|
36
|
+
await runGmailSetup(parsed);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
defaultRuntime.error(danger(String(err)));
|
|
40
|
+
defaultRuntime.exit(1);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
gmail
|
|
44
|
+
.command("run")
|
|
45
|
+
.description("Run gog watch serve + auto-renew loop")
|
|
46
|
+
.option("--account <email>", "Gmail account to watch")
|
|
47
|
+
.option("--topic <topic>", "Pub/Sub topic path (projects/.../topics/..)")
|
|
48
|
+
.option("--subscription <name>", "Pub/Sub subscription name")
|
|
49
|
+
.option("--label <label>", "Gmail label to watch")
|
|
50
|
+
.option("--hook-url <url>", "Clawdbot hook URL")
|
|
51
|
+
.option("--hook-token <token>", "Clawdbot hook token")
|
|
52
|
+
.option("--push-token <token>", "Push token for gog watch serve")
|
|
53
|
+
.option("--bind <host>", "gog watch serve bind host")
|
|
54
|
+
.option("--port <port>", "gog watch serve port")
|
|
55
|
+
.option("--path <path>", "gog watch serve path")
|
|
56
|
+
.option("--include-body", "Include email body snippets")
|
|
57
|
+
.option("--max-bytes <n>", "Max bytes for body snippets")
|
|
58
|
+
.option("--renew-minutes <n>", "Renew watch every N minutes")
|
|
59
|
+
.option("--tailscale <mode>", "Expose push endpoint via tailscale (funnel|serve|off)")
|
|
60
|
+
.option("--tailscale-path <path>", "Path for tailscale serve/funnel")
|
|
61
|
+
.action(async (opts) => {
|
|
62
|
+
try {
|
|
63
|
+
const parsed = parseGmailRunOptions(opts);
|
|
64
|
+
await runGmailService(parsed);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
defaultRuntime.error(danger(String(err)));
|
|
68
|
+
defaultRuntime.exit(1);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function parseGmailSetupOptions(raw) {
|
|
73
|
+
const accountRaw = raw.account;
|
|
74
|
+
const account = typeof accountRaw === "string" ? accountRaw.trim() : "";
|
|
75
|
+
if (!account)
|
|
76
|
+
throw new Error("--account is required");
|
|
77
|
+
return {
|
|
78
|
+
account,
|
|
79
|
+
project: stringOption(raw.project),
|
|
80
|
+
topic: stringOption(raw.topic),
|
|
81
|
+
subscription: stringOption(raw.subscription),
|
|
82
|
+
label: stringOption(raw.label),
|
|
83
|
+
hookUrl: stringOption(raw.hookUrl),
|
|
84
|
+
hookToken: stringOption(raw.hookToken),
|
|
85
|
+
pushToken: stringOption(raw.pushToken),
|
|
86
|
+
bind: stringOption(raw.bind),
|
|
87
|
+
port: numberOption(raw.port),
|
|
88
|
+
path: stringOption(raw.path),
|
|
89
|
+
includeBody: booleanOption(raw.includeBody),
|
|
90
|
+
maxBytes: numberOption(raw.maxBytes),
|
|
91
|
+
renewEveryMinutes: numberOption(raw.renewMinutes),
|
|
92
|
+
tailscale: stringOption(raw.tailscale),
|
|
93
|
+
tailscalePath: stringOption(raw.tailscalePath),
|
|
94
|
+
pushEndpoint: stringOption(raw.pushEndpoint),
|
|
95
|
+
json: Boolean(raw.json),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function parseGmailRunOptions(raw) {
|
|
99
|
+
return {
|
|
100
|
+
account: stringOption(raw.account),
|
|
101
|
+
topic: stringOption(raw.topic),
|
|
102
|
+
subscription: stringOption(raw.subscription),
|
|
103
|
+
label: stringOption(raw.label),
|
|
104
|
+
hookUrl: stringOption(raw.hookUrl),
|
|
105
|
+
hookToken: stringOption(raw.hookToken),
|
|
106
|
+
pushToken: stringOption(raw.pushToken),
|
|
107
|
+
bind: stringOption(raw.bind),
|
|
108
|
+
port: numberOption(raw.port),
|
|
109
|
+
path: stringOption(raw.path),
|
|
110
|
+
includeBody: booleanOption(raw.includeBody),
|
|
111
|
+
maxBytes: numberOption(raw.maxBytes),
|
|
112
|
+
renewEveryMinutes: numberOption(raw.renewMinutes),
|
|
113
|
+
tailscale: stringOption(raw.tailscale),
|
|
114
|
+
tailscalePath: stringOption(raw.tailscalePath),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function stringOption(value) {
|
|
118
|
+
if (typeof value !== "string")
|
|
119
|
+
return undefined;
|
|
120
|
+
const trimmed = value.trim();
|
|
121
|
+
return trimmed ? trimmed : undefined;
|
|
122
|
+
}
|
|
123
|
+
function numberOption(value) {
|
|
124
|
+
if (value === undefined || value === null)
|
|
125
|
+
return undefined;
|
|
126
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
127
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
128
|
+
return undefined;
|
|
129
|
+
return Math.floor(n);
|
|
130
|
+
}
|
|
131
|
+
function booleanOption(value) {
|
|
132
|
+
if (value === undefined || value === null)
|
|
133
|
+
return undefined;
|
|
134
|
+
return Boolean(value);
|
|
135
|
+
}
|