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,484 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { confirm, intro, note, outro } from "@clack/prompts";
|
|
5
|
+
import { DEFAULT_SANDBOX_BROWSER_IMAGE, DEFAULT_SANDBOX_COMMON_IMAGE, DEFAULT_SANDBOX_IMAGE, } from "../agents/sandbox.js";
|
|
6
|
+
import { buildWorkspaceSkillStatus } from "../agents/skills-status.js";
|
|
7
|
+
import { CONFIG_PATH_CLAWDBOT, createConfigIO, migrateLegacyConfig, readConfigFileSnapshot, writeConfigFile, } from "../config/config.js";
|
|
8
|
+
import { resolveGatewayPort, resolveIsNixMode } from "../config/paths.js";
|
|
9
|
+
import { GATEWAY_LAUNCH_AGENT_LABEL } from "../daemon/constants.js";
|
|
10
|
+
import { findLegacyGatewayServices, uninstallLegacyGatewayServices, } from "../daemon/legacy.js";
|
|
11
|
+
import { resolveGatewayProgramArguments } from "../daemon/program-args.js";
|
|
12
|
+
import { resolveGatewayService } from "../daemon/service.js";
|
|
13
|
+
import { runCommandWithTimeout, runExec } from "../process/exec.js";
|
|
14
|
+
import { defaultRuntime } from "../runtime.js";
|
|
15
|
+
import { resolveUserPath, sleep } from "../utils.js";
|
|
16
|
+
import { healthCommand } from "./health.js";
|
|
17
|
+
import { applyWizardMetadata, DEFAULT_WORKSPACE, guardCancel, printWizardHeader, } from "./onboard-helpers.js";
|
|
18
|
+
function resolveMode(cfg) {
|
|
19
|
+
return cfg.gateway?.mode === "remote" ? "remote" : "local";
|
|
20
|
+
}
|
|
21
|
+
function resolveLegacyConfigPath(env) {
|
|
22
|
+
const override = env.CLAWDIS_CONFIG_PATH?.trim();
|
|
23
|
+
if (override)
|
|
24
|
+
return override;
|
|
25
|
+
return path.join(os.homedir(), ".clawdis", "clawdis.json");
|
|
26
|
+
}
|
|
27
|
+
function replacePathSegment(value, from, to) {
|
|
28
|
+
if (!value)
|
|
29
|
+
return value;
|
|
30
|
+
const pattern = new RegExp(`(^|[\\/])${from}([\\/]|$)`, "g");
|
|
31
|
+
if (!pattern.test(value))
|
|
32
|
+
return value;
|
|
33
|
+
return value.replace(pattern, `$1${to}$2`);
|
|
34
|
+
}
|
|
35
|
+
function replaceLegacyName(value) {
|
|
36
|
+
if (!value)
|
|
37
|
+
return value;
|
|
38
|
+
const replacedClawdis = value.replace(/clawdis/g, "clawdbot");
|
|
39
|
+
return replacedClawdis.replace(/clawd(?!bot)/g, "clawdbot");
|
|
40
|
+
}
|
|
41
|
+
function replaceModernName(value) {
|
|
42
|
+
if (!value)
|
|
43
|
+
return value;
|
|
44
|
+
if (!value.includes("clawdbot"))
|
|
45
|
+
return value;
|
|
46
|
+
return value.replace(/clawdbot/g, "clawdis");
|
|
47
|
+
}
|
|
48
|
+
function resolveSandboxScript(scriptRel) {
|
|
49
|
+
const candidates = new Set();
|
|
50
|
+
candidates.add(process.cwd());
|
|
51
|
+
const argv1 = process.argv[1];
|
|
52
|
+
if (argv1) {
|
|
53
|
+
const normalized = path.resolve(argv1);
|
|
54
|
+
candidates.add(path.resolve(path.dirname(normalized), ".."));
|
|
55
|
+
candidates.add(path.resolve(path.dirname(normalized)));
|
|
56
|
+
}
|
|
57
|
+
for (const root of candidates) {
|
|
58
|
+
const scriptPath = path.join(root, scriptRel);
|
|
59
|
+
if (fs.existsSync(scriptPath)) {
|
|
60
|
+
return { scriptPath, cwd: root };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
async function runSandboxScript(scriptRel, runtime) {
|
|
66
|
+
const script = resolveSandboxScript(scriptRel);
|
|
67
|
+
if (!script) {
|
|
68
|
+
note(`Unable to locate ${scriptRel}. Run it from the repo root.`, "Sandbox");
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
runtime.log(`Running ${scriptRel}...`);
|
|
72
|
+
const result = await runCommandWithTimeout(["bash", script.scriptPath], {
|
|
73
|
+
timeoutMs: 20 * 60 * 1000,
|
|
74
|
+
cwd: script.cwd,
|
|
75
|
+
});
|
|
76
|
+
if (result.code !== 0) {
|
|
77
|
+
runtime.error(`Failed running ${scriptRel}: ${result.stderr.trim() || result.stdout.trim() || "unknown error"}`);
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
runtime.log(`Completed ${scriptRel}.`);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
async function isDockerAvailable() {
|
|
84
|
+
try {
|
|
85
|
+
await runExec("docker", ["version", "--format", "{{.Server.Version}}"], {
|
|
86
|
+
timeoutMs: 5_000,
|
|
87
|
+
});
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async function dockerImageExists(image) {
|
|
95
|
+
try {
|
|
96
|
+
await runExec("docker", ["image", "inspect", image], { timeoutMs: 5_000 });
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function resolveSandboxDockerImage(cfg) {
|
|
104
|
+
const image = cfg.agent?.sandbox?.docker?.image?.trim();
|
|
105
|
+
return image ? image : DEFAULT_SANDBOX_IMAGE;
|
|
106
|
+
}
|
|
107
|
+
function resolveSandboxBrowserImage(cfg) {
|
|
108
|
+
const image = cfg.agent?.sandbox?.browser?.image?.trim();
|
|
109
|
+
return image ? image : DEFAULT_SANDBOX_BROWSER_IMAGE;
|
|
110
|
+
}
|
|
111
|
+
function updateSandboxDockerImage(cfg, image) {
|
|
112
|
+
return {
|
|
113
|
+
...cfg,
|
|
114
|
+
agent: {
|
|
115
|
+
...cfg.agent,
|
|
116
|
+
sandbox: {
|
|
117
|
+
...cfg.agent?.sandbox,
|
|
118
|
+
docker: {
|
|
119
|
+
...cfg.agent?.sandbox?.docker,
|
|
120
|
+
image,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function updateSandboxBrowserImage(cfg, image) {
|
|
127
|
+
return {
|
|
128
|
+
...cfg,
|
|
129
|
+
agent: {
|
|
130
|
+
...cfg.agent,
|
|
131
|
+
sandbox: {
|
|
132
|
+
...cfg.agent?.sandbox,
|
|
133
|
+
browser: {
|
|
134
|
+
...cfg.agent?.sandbox?.browser,
|
|
135
|
+
image,
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
async function handleMissingSandboxImage(params, runtime) {
|
|
142
|
+
const exists = await dockerImageExists(params.image);
|
|
143
|
+
if (exists)
|
|
144
|
+
return;
|
|
145
|
+
const buildHint = params.buildScript
|
|
146
|
+
? `Build it with ${params.buildScript}.`
|
|
147
|
+
: "Build or pull it first.";
|
|
148
|
+
note(`Sandbox ${params.label} image missing: ${params.image}. ${buildHint}`, "Sandbox");
|
|
149
|
+
let built = false;
|
|
150
|
+
if (params.buildScript) {
|
|
151
|
+
const build = guardCancel(await confirm({
|
|
152
|
+
message: `Build ${params.label} sandbox image now?`,
|
|
153
|
+
initialValue: true,
|
|
154
|
+
}), runtime);
|
|
155
|
+
if (build) {
|
|
156
|
+
built = await runSandboxScript(params.buildScript, runtime);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (built)
|
|
160
|
+
return;
|
|
161
|
+
const legacyImage = replaceModernName(params.image);
|
|
162
|
+
if (!legacyImage || legacyImage === params.image)
|
|
163
|
+
return;
|
|
164
|
+
const legacyExists = await dockerImageExists(legacyImage);
|
|
165
|
+
if (!legacyExists)
|
|
166
|
+
return;
|
|
167
|
+
const fallback = guardCancel(await confirm({
|
|
168
|
+
message: `Switch config to legacy image ${legacyImage}?`,
|
|
169
|
+
initialValue: false,
|
|
170
|
+
}), runtime);
|
|
171
|
+
if (!fallback)
|
|
172
|
+
return;
|
|
173
|
+
params.updateConfig(legacyImage);
|
|
174
|
+
}
|
|
175
|
+
async function maybeRepairSandboxImages(cfg, runtime) {
|
|
176
|
+
const sandbox = cfg.agent?.sandbox;
|
|
177
|
+
const mode = sandbox?.mode ?? "off";
|
|
178
|
+
if (!sandbox || mode === "off")
|
|
179
|
+
return cfg;
|
|
180
|
+
const dockerAvailable = await isDockerAvailable();
|
|
181
|
+
if (!dockerAvailable) {
|
|
182
|
+
note("Docker not available; skipping sandbox image checks.", "Sandbox");
|
|
183
|
+
return cfg;
|
|
184
|
+
}
|
|
185
|
+
let next = cfg;
|
|
186
|
+
const changes = [];
|
|
187
|
+
const dockerImage = resolveSandboxDockerImage(cfg);
|
|
188
|
+
await handleMissingSandboxImage({
|
|
189
|
+
label: "base",
|
|
190
|
+
image: dockerImage,
|
|
191
|
+
buildScript: dockerImage === DEFAULT_SANDBOX_COMMON_IMAGE
|
|
192
|
+
? "scripts/sandbox-common-setup.sh"
|
|
193
|
+
: dockerImage === DEFAULT_SANDBOX_IMAGE
|
|
194
|
+
? "scripts/sandbox-setup.sh"
|
|
195
|
+
: undefined,
|
|
196
|
+
updateConfig: (image) => {
|
|
197
|
+
next = updateSandboxDockerImage(next, image);
|
|
198
|
+
changes.push(`Updated agent.sandbox.docker.image → ${image}`);
|
|
199
|
+
},
|
|
200
|
+
}, runtime);
|
|
201
|
+
if (sandbox.browser?.enabled) {
|
|
202
|
+
await handleMissingSandboxImage({
|
|
203
|
+
label: "browser",
|
|
204
|
+
image: resolveSandboxBrowserImage(cfg),
|
|
205
|
+
buildScript: "scripts/sandbox-browser-setup.sh",
|
|
206
|
+
updateConfig: (image) => {
|
|
207
|
+
next = updateSandboxBrowserImage(next, image);
|
|
208
|
+
changes.push(`Updated agent.sandbox.browser.image → ${image}`);
|
|
209
|
+
},
|
|
210
|
+
}, runtime);
|
|
211
|
+
}
|
|
212
|
+
if (changes.length > 0) {
|
|
213
|
+
note(changes.join("\n"), "Doctor changes");
|
|
214
|
+
}
|
|
215
|
+
return next;
|
|
216
|
+
}
|
|
217
|
+
function normalizeLegacyConfigValues(cfg) {
|
|
218
|
+
const changes = [];
|
|
219
|
+
let next = cfg;
|
|
220
|
+
const workspace = cfg.agent?.workspace;
|
|
221
|
+
const updatedWorkspace = replacePathSegment(replacePathSegment(workspace, "clawdis", "clawdbot"), "clawd", "clawdbot");
|
|
222
|
+
if (updatedWorkspace && updatedWorkspace !== workspace) {
|
|
223
|
+
next = {
|
|
224
|
+
...next,
|
|
225
|
+
agent: {
|
|
226
|
+
...next.agent,
|
|
227
|
+
workspace: updatedWorkspace,
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
changes.push(`Updated agent.workspace → ${updatedWorkspace}`);
|
|
231
|
+
}
|
|
232
|
+
const workspaceRoot = cfg.agent?.sandbox?.workspaceRoot;
|
|
233
|
+
const updatedWorkspaceRoot = replacePathSegment(replacePathSegment(workspaceRoot, "clawdis", "clawdbot"), "clawd", "clawdbot");
|
|
234
|
+
if (updatedWorkspaceRoot && updatedWorkspaceRoot !== workspaceRoot) {
|
|
235
|
+
next = {
|
|
236
|
+
...next,
|
|
237
|
+
agent: {
|
|
238
|
+
...next.agent,
|
|
239
|
+
sandbox: {
|
|
240
|
+
...next.agent?.sandbox,
|
|
241
|
+
workspaceRoot: updatedWorkspaceRoot,
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
changes.push(`Updated agent.sandbox.workspaceRoot → ${updatedWorkspaceRoot}`);
|
|
246
|
+
}
|
|
247
|
+
const dockerImage = cfg.agent?.sandbox?.docker?.image;
|
|
248
|
+
const updatedDockerImage = replaceLegacyName(dockerImage);
|
|
249
|
+
if (updatedDockerImage && updatedDockerImage !== dockerImage) {
|
|
250
|
+
next = {
|
|
251
|
+
...next,
|
|
252
|
+
agent: {
|
|
253
|
+
...next.agent,
|
|
254
|
+
sandbox: {
|
|
255
|
+
...next.agent?.sandbox,
|
|
256
|
+
docker: {
|
|
257
|
+
...next.agent?.sandbox?.docker,
|
|
258
|
+
image: updatedDockerImage,
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
changes.push(`Updated agent.sandbox.docker.image → ${updatedDockerImage}`);
|
|
264
|
+
}
|
|
265
|
+
const containerPrefix = cfg.agent?.sandbox?.docker?.containerPrefix;
|
|
266
|
+
const updatedContainerPrefix = replaceLegacyName(containerPrefix);
|
|
267
|
+
if (updatedContainerPrefix && updatedContainerPrefix !== containerPrefix) {
|
|
268
|
+
next = {
|
|
269
|
+
...next,
|
|
270
|
+
agent: {
|
|
271
|
+
...next.agent,
|
|
272
|
+
sandbox: {
|
|
273
|
+
...next.agent?.sandbox,
|
|
274
|
+
docker: {
|
|
275
|
+
...next.agent?.sandbox?.docker,
|
|
276
|
+
containerPrefix: updatedContainerPrefix,
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
};
|
|
281
|
+
changes.push(`Updated agent.sandbox.docker.containerPrefix → ${updatedContainerPrefix}`);
|
|
282
|
+
}
|
|
283
|
+
return { config: next, changes };
|
|
284
|
+
}
|
|
285
|
+
async function maybeMigrateLegacyConfigFile(runtime) {
|
|
286
|
+
const legacyConfigPath = resolveLegacyConfigPath(process.env);
|
|
287
|
+
if (legacyConfigPath === CONFIG_PATH_CLAWDBOT)
|
|
288
|
+
return;
|
|
289
|
+
const legacyIo = createConfigIO({ configPath: legacyConfigPath });
|
|
290
|
+
const legacySnapshot = await legacyIo.readConfigFileSnapshot();
|
|
291
|
+
if (!legacySnapshot.exists)
|
|
292
|
+
return;
|
|
293
|
+
const currentSnapshot = await readConfigFileSnapshot();
|
|
294
|
+
if (currentSnapshot.exists) {
|
|
295
|
+
note(`Legacy config still exists at ${legacyConfigPath}. Current config at ${CONFIG_PATH_CLAWDBOT}.`, "Legacy config");
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const gatewayMode = typeof legacySnapshot.parsed?.gateway?.mode === "string"
|
|
299
|
+
? legacySnapshot.parsed.gateway?.mode
|
|
300
|
+
: undefined;
|
|
301
|
+
const gatewayBind = typeof legacySnapshot.parsed?.gateway?.bind === "string"
|
|
302
|
+
? legacySnapshot.parsed.gateway?.bind
|
|
303
|
+
: undefined;
|
|
304
|
+
const agentWorkspace = typeof legacySnapshot.parsed?.agent?.workspace ===
|
|
305
|
+
"string"
|
|
306
|
+
? legacySnapshot.parsed.agent?.workspace
|
|
307
|
+
: undefined;
|
|
308
|
+
note([
|
|
309
|
+
`- File exists at ${legacyConfigPath}`,
|
|
310
|
+
gatewayMode ? `- gateway.mode: ${gatewayMode}` : undefined,
|
|
311
|
+
gatewayBind ? `- gateway.bind: ${gatewayBind}` : undefined,
|
|
312
|
+
agentWorkspace ? `- agent.workspace: ${agentWorkspace}` : undefined,
|
|
313
|
+
]
|
|
314
|
+
.filter(Boolean)
|
|
315
|
+
.join("\n"), "Legacy Clawdis config detected");
|
|
316
|
+
let nextConfig = legacySnapshot.valid ? legacySnapshot.config : null;
|
|
317
|
+
const { config: migratedConfig, changes } = migrateLegacyConfig(legacySnapshot.parsed);
|
|
318
|
+
if (migratedConfig) {
|
|
319
|
+
nextConfig = migratedConfig;
|
|
320
|
+
}
|
|
321
|
+
else if (!nextConfig) {
|
|
322
|
+
note(`Legacy config at ${legacyConfigPath} is invalid; skipping migration.`, "Legacy config");
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const normalized = normalizeLegacyConfigValues(nextConfig);
|
|
326
|
+
const mergedChanges = [...changes, ...normalized.changes];
|
|
327
|
+
if (mergedChanges.length > 0) {
|
|
328
|
+
note(mergedChanges.join("\n"), "Doctor changes");
|
|
329
|
+
}
|
|
330
|
+
await writeConfigFile(normalized.config);
|
|
331
|
+
runtime.log(`Migrated legacy config to ${CONFIG_PATH_CLAWDBOT}`);
|
|
332
|
+
}
|
|
333
|
+
async function maybeMigrateLegacyGatewayService(cfg, runtime) {
|
|
334
|
+
const legacyServices = await findLegacyGatewayServices(process.env);
|
|
335
|
+
if (legacyServices.length === 0)
|
|
336
|
+
return;
|
|
337
|
+
note(legacyServices
|
|
338
|
+
.map((svc) => `- ${svc.label} (${svc.platform}, ${svc.detail})`)
|
|
339
|
+
.join("\n"), "Legacy Clawdis services detected");
|
|
340
|
+
const migrate = guardCancel(await confirm({
|
|
341
|
+
message: "Migrate legacy Clawdis services to Clawdbot now?",
|
|
342
|
+
initialValue: true,
|
|
343
|
+
}), runtime);
|
|
344
|
+
if (!migrate)
|
|
345
|
+
return;
|
|
346
|
+
try {
|
|
347
|
+
await uninstallLegacyGatewayServices({
|
|
348
|
+
env: process.env,
|
|
349
|
+
stdout: process.stdout,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
catch (err) {
|
|
353
|
+
runtime.error(`Legacy service cleanup failed: ${String(err)}`);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
if (resolveIsNixMode(process.env)) {
|
|
357
|
+
note("Nix mode detected; skip installing services.", "Gateway");
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
if (resolveMode(cfg) === "remote") {
|
|
361
|
+
note("Gateway mode is remote; skipped local service install.", "Gateway");
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
const service = resolveGatewayService();
|
|
365
|
+
const loaded = await service.isLoaded({ env: process.env });
|
|
366
|
+
if (loaded) {
|
|
367
|
+
note(`Clawdbot ${service.label} already ${service.loadedText}.`, "Gateway");
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const install = guardCancel(await confirm({
|
|
371
|
+
message: "Install Clawdbot gateway service now?",
|
|
372
|
+
initialValue: true,
|
|
373
|
+
}), runtime);
|
|
374
|
+
if (!install)
|
|
375
|
+
return;
|
|
376
|
+
const devMode = process.argv[1]?.includes(`${path.sep}src${path.sep}`) &&
|
|
377
|
+
process.argv[1]?.endsWith(".ts");
|
|
378
|
+
const port = resolveGatewayPort(cfg, process.env);
|
|
379
|
+
const { programArguments, workingDirectory } = await resolveGatewayProgramArguments({ port, dev: devMode });
|
|
380
|
+
const environment = {
|
|
381
|
+
PATH: process.env.PATH,
|
|
382
|
+
CLAWDBOT_GATEWAY_TOKEN: cfg.gateway?.auth?.token ?? process.env.CLAWDBOT_GATEWAY_TOKEN,
|
|
383
|
+
CLAWDBOT_LAUNCHD_LABEL: process.platform === "darwin" ? GATEWAY_LAUNCH_AGENT_LABEL : undefined,
|
|
384
|
+
};
|
|
385
|
+
await service.install({
|
|
386
|
+
env: process.env,
|
|
387
|
+
stdout: process.stdout,
|
|
388
|
+
programArguments,
|
|
389
|
+
workingDirectory,
|
|
390
|
+
environment,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
export async function doctorCommand(runtime = defaultRuntime) {
|
|
394
|
+
printWizardHeader(runtime);
|
|
395
|
+
intro("Clawdbot doctor");
|
|
396
|
+
await maybeMigrateLegacyConfigFile(runtime);
|
|
397
|
+
const snapshot = await readConfigFileSnapshot();
|
|
398
|
+
let cfg = snapshot.valid ? snapshot.config : {};
|
|
399
|
+
if (snapshot.exists &&
|
|
400
|
+
!snapshot.valid &&
|
|
401
|
+
snapshot.legacyIssues.length === 0) {
|
|
402
|
+
note("Config invalid; doctor will run with defaults.", "Config");
|
|
403
|
+
}
|
|
404
|
+
if (snapshot.legacyIssues.length > 0) {
|
|
405
|
+
note(snapshot.legacyIssues
|
|
406
|
+
.map((issue) => `- ${issue.path}: ${issue.message}`)
|
|
407
|
+
.join("\n"), "Legacy config keys detected");
|
|
408
|
+
const migrate = guardCancel(await confirm({
|
|
409
|
+
message: "Migrate legacy config entries now?",
|
|
410
|
+
initialValue: true,
|
|
411
|
+
}), runtime);
|
|
412
|
+
if (migrate) {
|
|
413
|
+
// Legacy migration (2026-01-02, commit: 16420e5b) — normalize per-provider allowlists; move WhatsApp gating into whatsapp.allowFrom.
|
|
414
|
+
const { config: migrated, changes } = migrateLegacyConfig(snapshot.parsed);
|
|
415
|
+
if (changes.length > 0) {
|
|
416
|
+
note(changes.join("\n"), "Doctor changes");
|
|
417
|
+
}
|
|
418
|
+
if (migrated) {
|
|
419
|
+
cfg = migrated;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
const normalized = normalizeLegacyConfigValues(cfg);
|
|
424
|
+
if (normalized.changes.length > 0) {
|
|
425
|
+
note(normalized.changes.join("\n"), "Doctor changes");
|
|
426
|
+
cfg = normalized.config;
|
|
427
|
+
}
|
|
428
|
+
cfg = await maybeRepairSandboxImages(cfg, runtime);
|
|
429
|
+
await maybeMigrateLegacyGatewayService(cfg, runtime);
|
|
430
|
+
const workspaceDir = resolveUserPath(cfg.agent?.workspace ?? DEFAULT_WORKSPACE);
|
|
431
|
+
const skillsReport = buildWorkspaceSkillStatus(workspaceDir, { config: cfg });
|
|
432
|
+
note([
|
|
433
|
+
`Eligible: ${skillsReport.skills.filter((s) => s.eligible).length}`,
|
|
434
|
+
`Missing requirements: ${skillsReport.skills.filter((s) => !s.eligible && !s.disabled && !s.blockedByAllowlist).length}`,
|
|
435
|
+
`Blocked by allowlist: ${skillsReport.skills.filter((s) => s.blockedByAllowlist).length}`,
|
|
436
|
+
].join("\n"), "Skills status");
|
|
437
|
+
let healthOk = false;
|
|
438
|
+
try {
|
|
439
|
+
await healthCommand({ json: false, timeoutMs: 10_000 }, runtime);
|
|
440
|
+
healthOk = true;
|
|
441
|
+
}
|
|
442
|
+
catch (err) {
|
|
443
|
+
const message = String(err);
|
|
444
|
+
if (message.includes("gateway closed")) {
|
|
445
|
+
note("Gateway not running.", "Gateway");
|
|
446
|
+
}
|
|
447
|
+
else {
|
|
448
|
+
runtime.error(`Health check failed: ${message}`);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (!healthOk) {
|
|
452
|
+
const service = resolveGatewayService();
|
|
453
|
+
const loaded = await service.isLoaded({ env: process.env });
|
|
454
|
+
if (!loaded) {
|
|
455
|
+
note("Gateway daemon not installed.", "Gateway");
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
const restart = guardCancel(await confirm({
|
|
459
|
+
message: "Restart gateway daemon now?",
|
|
460
|
+
initialValue: true,
|
|
461
|
+
}), runtime);
|
|
462
|
+
if (restart) {
|
|
463
|
+
await service.restart({ stdout: process.stdout });
|
|
464
|
+
await sleep(1500);
|
|
465
|
+
try {
|
|
466
|
+
await healthCommand({ json: false, timeoutMs: 10_000 }, runtime);
|
|
467
|
+
}
|
|
468
|
+
catch (err) {
|
|
469
|
+
const message = String(err);
|
|
470
|
+
if (message.includes("gateway closed")) {
|
|
471
|
+
note("Gateway not running.", "Gateway");
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
runtime.error(`Health check failed: ${message}`);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
cfg = applyWizardMetadata(cfg, { command: "doctor", mode: resolveMode(cfg) });
|
|
481
|
+
await writeConfigFile(cfg);
|
|
482
|
+
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
|
483
|
+
outro("Doctor complete.");
|
|
484
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { loadConfig } from "../config/config.js";
|
|
2
|
+
import { loadSessionStore, resolveStorePath } from "../config/sessions.js";
|
|
3
|
+
import { probeDiscord } from "../discord/probe.js";
|
|
4
|
+
import { callGateway } from "../gateway/call.js";
|
|
5
|
+
import { info } from "../globals.js";
|
|
6
|
+
import { probeTelegram } from "../telegram/probe.js";
|
|
7
|
+
import { resolveTelegramToken } from "../telegram/token.js";
|
|
8
|
+
import { resolveHeartbeatSeconds } from "../web/reconnect.js";
|
|
9
|
+
import { getWebAuthAgeMs, logWebSelfId, webAuthExists, } from "../web/session.js";
|
|
10
|
+
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
11
|
+
export async function getHealthSnapshot(timeoutMs) {
|
|
12
|
+
const cfg = loadConfig();
|
|
13
|
+
const linked = await webAuthExists();
|
|
14
|
+
const authAgeMs = getWebAuthAgeMs();
|
|
15
|
+
const heartbeatSeconds = resolveHeartbeatSeconds(cfg, undefined);
|
|
16
|
+
const storePath = resolveStorePath(cfg.session?.store);
|
|
17
|
+
const store = loadSessionStore(storePath);
|
|
18
|
+
const sessions = Object.entries(store)
|
|
19
|
+
.filter(([key]) => key !== "global" && key !== "unknown")
|
|
20
|
+
.map(([key, entry]) => ({ key, updatedAt: entry?.updatedAt ?? 0 }))
|
|
21
|
+
.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
22
|
+
const recent = sessions.slice(0, 5).map((s) => ({
|
|
23
|
+
key: s.key,
|
|
24
|
+
updatedAt: s.updatedAt || null,
|
|
25
|
+
age: s.updatedAt ? Date.now() - s.updatedAt : null,
|
|
26
|
+
}));
|
|
27
|
+
const start = Date.now();
|
|
28
|
+
const cappedTimeout = Math.max(1000, timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
29
|
+
const { token: telegramToken } = resolveTelegramToken(cfg);
|
|
30
|
+
const telegramConfigured = telegramToken.trim().length > 0;
|
|
31
|
+
const telegramProxy = cfg.telegram?.proxy;
|
|
32
|
+
const telegramProbe = telegramConfigured
|
|
33
|
+
? await probeTelegram(telegramToken.trim(), cappedTimeout, telegramProxy)
|
|
34
|
+
: undefined;
|
|
35
|
+
const discordToken = process.env.DISCORD_BOT_TOKEN ?? cfg.discord?.token ?? "";
|
|
36
|
+
const discordConfigured = discordToken.trim().length > 0;
|
|
37
|
+
const discordProbe = discordConfigured
|
|
38
|
+
? await probeDiscord(discordToken.trim(), cappedTimeout)
|
|
39
|
+
: undefined;
|
|
40
|
+
const summary = {
|
|
41
|
+
ok: true,
|
|
42
|
+
ts: Date.now(),
|
|
43
|
+
durationMs: Date.now() - start,
|
|
44
|
+
web: { linked, authAgeMs },
|
|
45
|
+
telegram: { configured: telegramConfigured, probe: telegramProbe },
|
|
46
|
+
discord: { configured: discordConfigured, probe: discordProbe },
|
|
47
|
+
heartbeatSeconds,
|
|
48
|
+
sessions: {
|
|
49
|
+
path: storePath,
|
|
50
|
+
count: sessions.length,
|
|
51
|
+
recent,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
return summary;
|
|
55
|
+
}
|
|
56
|
+
export async function healthCommand(opts, runtime) {
|
|
57
|
+
// Always query the running gateway; do not open a direct Baileys socket here.
|
|
58
|
+
const summary = await callGateway({
|
|
59
|
+
method: "health",
|
|
60
|
+
timeoutMs: opts.timeoutMs,
|
|
61
|
+
});
|
|
62
|
+
// Gateway reachability defines success; provider issues are reported but not fatal here.
|
|
63
|
+
const fatal = false;
|
|
64
|
+
if (opts.json) {
|
|
65
|
+
runtime.log(JSON.stringify(summary, null, 2));
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
runtime.log(summary.web.linked
|
|
69
|
+
? `Web: linked (auth age ${summary.web.authAgeMs ? `${Math.round(summary.web.authAgeMs / 60000)}m` : "unknown"})`
|
|
70
|
+
: "Web: not linked (run clawdbot login)");
|
|
71
|
+
if (summary.web.linked) {
|
|
72
|
+
logWebSelfId(runtime, true);
|
|
73
|
+
}
|
|
74
|
+
if (summary.web.connect) {
|
|
75
|
+
const base = summary.web.connect.ok
|
|
76
|
+
? info(`Connect: ok (${summary.web.connect.elapsedMs}ms)`)
|
|
77
|
+
: `Connect: failed (${summary.web.connect.status ?? "unknown"})`;
|
|
78
|
+
runtime.log(base +
|
|
79
|
+
(summary.web.connect.error ? ` - ${summary.web.connect.error}` : ""));
|
|
80
|
+
}
|
|
81
|
+
const tgLabel = summary.telegram.configured
|
|
82
|
+
? summary.telegram.probe?.ok
|
|
83
|
+
? info(`Telegram: ok${summary.telegram.probe.bot?.username ? ` (@${summary.telegram.probe.bot.username})` : ""} (${summary.telegram.probe.elapsedMs}ms)` +
|
|
84
|
+
(summary.telegram.probe.webhook?.url
|
|
85
|
+
? ` - webhook ${summary.telegram.probe.webhook.url}`
|
|
86
|
+
: ""))
|
|
87
|
+
: `Telegram: failed (${summary.telegram.probe?.status ?? "unknown"})${summary.telegram.probe?.error ? ` - ${summary.telegram.probe.error}` : ""}`
|
|
88
|
+
: "Telegram: not configured";
|
|
89
|
+
runtime.log(tgLabel);
|
|
90
|
+
const discordLabel = summary.discord.configured
|
|
91
|
+
? summary.discord.probe?.ok
|
|
92
|
+
? info(`Discord: ok${summary.discord.probe.bot?.username ? ` (@${summary.discord.probe.bot.username})` : ""} (${summary.discord.probe.elapsedMs}ms)`)
|
|
93
|
+
: `Discord: failed (${summary.discord.probe?.status ?? "unknown"})${summary.discord.probe?.error ? ` - ${summary.discord.probe.error}` : ""}`
|
|
94
|
+
: "Discord: not configured";
|
|
95
|
+
runtime.log(discordLabel);
|
|
96
|
+
runtime.log(info(`Heartbeat interval: ${summary.heartbeatSeconds}s`));
|
|
97
|
+
runtime.log(info(`Session store: ${summary.sessions.path} (${summary.sessions.count} entries)`));
|
|
98
|
+
if (summary.sessions.recent.length > 0) {
|
|
99
|
+
runtime.log("Recent sessions:");
|
|
100
|
+
for (const r of summary.sessions.recent) {
|
|
101
|
+
runtime.log(`- ${r.key} (${r.updatedAt ? `${Math.round((Date.now() - r.updatedAt) / 60000)}m ago` : "no activity"})`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (fatal) {
|
|
106
|
+
runtime.exit(1);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { CONFIG_PATH_CLAWDBOT, loadConfig } from "../../config/config.js";
|
|
2
|
+
import { ensureFlagCompatibility, normalizeAlias, resolveModelTarget, updateConfig, } from "./shared.js";
|
|
3
|
+
export async function modelsAliasesListCommand(opts, runtime) {
|
|
4
|
+
ensureFlagCompatibility(opts);
|
|
5
|
+
const cfg = loadConfig();
|
|
6
|
+
const aliases = cfg.agent?.modelAliases ?? {};
|
|
7
|
+
if (opts.json) {
|
|
8
|
+
runtime.log(JSON.stringify({ aliases }, null, 2));
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (opts.plain) {
|
|
12
|
+
for (const [alias, target] of Object.entries(aliases)) {
|
|
13
|
+
runtime.log(`${alias} ${target}`);
|
|
14
|
+
}
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
runtime.log(`Aliases (${Object.keys(aliases).length}):`);
|
|
18
|
+
if (Object.keys(aliases).length === 0) {
|
|
19
|
+
runtime.log("- none");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
for (const [alias, target] of Object.entries(aliases)) {
|
|
23
|
+
runtime.log(`- ${alias} -> ${target}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export async function modelsAliasesAddCommand(aliasRaw, modelRaw, runtime) {
|
|
27
|
+
const alias = normalizeAlias(aliasRaw);
|
|
28
|
+
const updated = await updateConfig((cfg) => {
|
|
29
|
+
const resolved = resolveModelTarget({ raw: modelRaw, cfg });
|
|
30
|
+
const nextAliases = { ...cfg.agent?.modelAliases };
|
|
31
|
+
nextAliases[alias] = `${resolved.provider}/${resolved.model}`;
|
|
32
|
+
return {
|
|
33
|
+
...cfg,
|
|
34
|
+
agent: {
|
|
35
|
+
...cfg.agent,
|
|
36
|
+
modelAliases: nextAliases,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
|
41
|
+
runtime.log(`Alias ${alias} -> ${updated.agent?.modelAliases?.[alias]}`);
|
|
42
|
+
}
|
|
43
|
+
export async function modelsAliasesRemoveCommand(aliasRaw, runtime) {
|
|
44
|
+
const alias = normalizeAlias(aliasRaw);
|
|
45
|
+
const updated = await updateConfig((cfg) => {
|
|
46
|
+
const nextAliases = { ...cfg.agent?.modelAliases };
|
|
47
|
+
if (!nextAliases[alias]) {
|
|
48
|
+
throw new Error(`Alias not found: ${alias}`);
|
|
49
|
+
}
|
|
50
|
+
delete nextAliases[alias];
|
|
51
|
+
return {
|
|
52
|
+
...cfg,
|
|
53
|
+
agent: {
|
|
54
|
+
...cfg.agent,
|
|
55
|
+
modelAliases: nextAliases,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
runtime.log(`Updated ${CONFIG_PATH_CLAWDBOT}`);
|
|
60
|
+
if (!updated.agent?.modelAliases ||
|
|
61
|
+
Object.keys(updated.agent.modelAliases).length === 0) {
|
|
62
|
+
runtime.log("No aliases configured.");
|
|
63
|
+
}
|
|
64
|
+
}
|