From 76361ae3abe5f3bc830fbf023828b3fcacce421a Mon Sep 17 00:00:00 2001 From: cpojer Date: Sat, 31 Jan 2026 18:31:49 +0900 Subject: [PATCH] revert: Switch back to `tsc` for compiling. --- .github/workflows/ci.yml | 2 +- Dockerfile | 2 +- .../Sources/OpenClaw/CommandResolver.swift | 10 +- .../OpenClawIPCTests/UtilitiesTests.swift | 2 +- docker-compose.yml | 20 +- docker-setup.sh | 2 +- docs/install/docker.md | 128 ++++-- docs/platforms/fly.md | 50 ++- docs/platforms/gcp.md | 70 +-- docs/platforms/hetzner.md | 84 ++-- docs/plugin.md | 177 ++++---- fly.private.toml | 24 +- fly.toml | 36 +- openclaw.mjs | 4 +- package.json | 7 +- pnpm-lock.yaml | 424 +----------------- scripts/e2e/gateway-network-docker.sh | 2 +- scripts/e2e/onboard-docker.sh | 14 +- scripts/e2e/plugins-docker.sh | 14 +- scripts/package-mac-app.sh | 4 +- scripts/postinstall.js | 134 +++--- scripts/run-node.mjs | 59 +-- scripts/watch-node.mjs | 2 +- src/agents/skills/refresh.test.ts | 2 +- src/cli/browser-cli.test.ts | 2 +- src/cli/run-main.test.ts | 14 +- src/cli/update-cli.ts | 10 +- src/commands/status.test.ts | 11 +- src/daemon/program-args.test.ts | 8 +- src/infra/control-ui-assets.ts | 2 +- src/infra/gateway-lock.ts | 4 +- src/infra/is-main.test.ts | 10 +- src/infra/ports.test.ts | 2 +- src/plugins/install.test.ts | 18 +- test/gateway.multi.e2e.test.ts | 4 +- tsdown.config.ts | 12 - 36 files changed, 527 insertions(+), 843 deletions(-) delete mode 100644 tsdown.config.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54556ce708..6eae1f7d46 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,7 +94,7 @@ jobs: command: pnpm canvas:a2ui:bundle && bunx vitest run - runtime: bun task: build - command: bunx tsdown + command: bunx tsc -p tsconfig.json --noEmit false steps: - name: Checkout uses: actions/checkout@v4 diff --git a/Dockerfile b/Dockerfile index 2e93dbef0a..ad08bd37c6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,4 +36,4 @@ ENV NODE_ENV=production # This reduces the attack surface by preventing container escape via root privileges USER node -CMD ["node", "dist/index.mjs"] +CMD ["node", "dist/index.js"] diff --git a/apps/macos/Sources/OpenClaw/CommandResolver.swift b/apps/macos/Sources/OpenClaw/CommandResolver.swift index c8398961e4..c17f64e30e 100644 --- a/apps/macos/Sources/OpenClaw/CommandResolver.swift +++ b/apps/macos/Sources/OpenClaw/CommandResolver.swift @@ -5,7 +5,7 @@ enum CommandResolver { private static let helperName = "openclaw" static func gatewayEntrypoint(in root: URL) -> String? { - let distEntry = root.appendingPathComponent("dist/index.mjs").path + let distEntry = root.appendingPathComponent("dist/index.js").path if FileManager().isReadableFile(atPath: distEntry) { return distEntry } let openclawEntry = root.appendingPathComponent("openclaw.mjs").path if FileManager().isReadableFile(atPath: openclawEntry) { return openclawEntry } @@ -271,7 +271,7 @@ enum CommandResolver { } let missingEntry = """ - openclaw entrypoint missing (looked for dist/index.mjs or openclaw.mjs); run pnpm build. + openclaw entrypoint missing (looked for dist/index.js or openclaw.mjs); run pnpm build. """ return self.errorCommand(with: missingEntry) @@ -360,10 +360,10 @@ enum CommandResolver { if command -v openclaw >/dev/null 2>&1; then CLI="$(command -v openclaw)" openclaw \(quotedArgs); - elif [ -n "${PRJ:-}" ] && [ -f "$PRJ/dist/index.mjs" ]; then + elif [ -n "${PRJ:-}" ] && [ -f "$PRJ/dist/index.js" ]; then if command -v node >/dev/null 2>&1; then - CLI="node $PRJ/dist/index.mjs" - node "$PRJ/dist/index.mjs" \(quotedArgs); + CLI="node $PRJ/dist/index.js" + node "$PRJ/dist/index.js" \(quotedArgs); else echo "Node >=22 required on remote host"; exit 127; fi diff --git a/apps/macos/Tests/OpenClawIPCTests/UtilitiesTests.swift b/apps/macos/Tests/OpenClawIPCTests/UtilitiesTests.swift index 12f5c07218..ddeef38dc1 100644 --- a/apps/macos/Tests/OpenClawIPCTests/UtilitiesTests.swift +++ b/apps/macos/Tests/OpenClawIPCTests/UtilitiesTests.swift @@ -45,7 +45,7 @@ import Testing @Test func gatewayEntrypointPrefersDistOverBin() throws { let tmp = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true) .appendingPathComponent(UUID().uuidString, isDirectory: true) - let dist = tmp.appendingPathComponent("dist/index.mjs") + let dist = tmp.appendingPathComponent("dist/index.js") let bin = tmp.appendingPathComponent("bin/openclaw.js") try FileManager().createDirectory(at: dist.deletingLastPathComponent(), withIntermediateDirectories: true) try FileManager().createDirectory(at: bin.deletingLastPathComponent(), withIntermediateDirectories: true) diff --git a/docker-compose.yml b/docker-compose.yml index 28aadf1040..6453acef96 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,19 +12,19 @@ services: - ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw - ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace ports: - - "${OPENCLAW_GATEWAY_PORT:-18789}:18789" - - "${OPENCLAW_BRIDGE_PORT:-18790}:18790" + - '${OPENCLAW_GATEWAY_PORT:-18789}:18789' + - '${OPENCLAW_BRIDGE_PORT:-18790}:18790' init: true restart: unless-stopped command: [ - "node", - "dist/index.mjs", - "gateway", - "--bind", - "${OPENCLAW_GATEWAY_BIND:-lan}", - "--port", - "${OPENCLAW_GATEWAY_PORT:-18789}" + 'node', + 'dist/index.js', + 'gateway', + '--bind', + '${OPENCLAW_GATEWAY_BIND:-lan}', + '--port', + '${OPENCLAW_GATEWAY_PORT:-18789}', ] openclaw-cli: @@ -42,4 +42,4 @@ services: stdin_open: true tty: true init: true - entrypoint: ["node", "dist/index.mjs"] + entrypoint: ['node', 'dist/index.js'] diff --git a/docker-setup.sh b/docker-setup.sh index 9a65fb788c..0395d20f42 100755 --- a/docker-setup.sh +++ b/docker-setup.sh @@ -211,4 +211,4 @@ echo "Token: $OPENCLAW_GATEWAY_TOKEN" echo "" echo "Commands:" echo " ${COMPOSE_HINT} logs -f openclaw-gateway" -echo " ${COMPOSE_HINT} exec openclaw-gateway node dist/index.mjs health --token \"$OPENCLAW_GATEWAY_TOKEN\"" +echo " ${COMPOSE_HINT} exec openclaw-gateway node dist/index.js health --token \"$OPENCLAW_GATEWAY_TOKEN\"" diff --git a/docs/install/docker.md b/docs/install/docker.md index 11e2f5a523..04f4048d46 100644 --- a/docs/install/docker.md +++ b/docs/install/docker.md @@ -1,5 +1,5 @@ --- -summary: "Optional Docker-based setup and onboarding for OpenClaw" +summary: 'Optional Docker-based setup and onboarding for OpenClaw' read_when: - You want a containerized gateway instead of local installs - You are validating the Docker flow @@ -16,6 +16,7 @@ Docker is **optional**. Use it only if you want a containerized gateway or to va - **Sandboxing note**: agent sandboxing uses Docker too, but it does **not** require the full gateway to run in Docker. See [Sandboxing](/gateway/sandboxing). This guide covers: + - Containerized Gateway (full OpenClaw in Docker) - Per-session Agent Sandbox (host gateway + Docker-isolated agent tools) @@ -37,6 +38,7 @@ From repo root: ``` This script: + - builds the gateway image - runs the onboarding wizard - prints optional provider setup hints @@ -44,15 +46,18 @@ This script: - generates a gateway token and writes it to `.env` Optional env vars: + - `OPENCLAW_DOCKER_APT_PACKAGES` — install extra apt packages during build - `OPENCLAW_EXTRA_MOUNTS` — add extra host bind mounts - `OPENCLAW_HOME_VOLUME` — persist `/home/node` in a named volume After it finishes: + - Open `http://127.0.0.1:18789/` in your browser. - Paste the token into the Control UI (Settings → token). It writes config/workspace on the host: + - `~/.openclaw/` - `~/.openclaw/workspace` @@ -81,6 +86,7 @@ export OPENCLAW_EXTRA_MOUNTS="$HOME/.codex:/home/node/.codex:ro,$HOME/github:/ho ``` Notes: + - Paths must be shared with Docker Desktop on macOS/Windows. - If you edit `OPENCLAW_EXTRA_MOUNTS`, rerun `docker-setup.sh` to regenerate the extra compose file. @@ -110,6 +116,7 @@ export OPENCLAW_EXTRA_MOUNTS="$HOME/.codex:/home/node/.codex:ro,$HOME/github:/ho ``` Notes: + - If you change `OPENCLAW_HOME_VOLUME`, rerun `docker-setup.sh` to regenerate the extra compose file. - The named volume persists until removed with `docker volume rm `. @@ -129,6 +136,7 @@ export OPENCLAW_DOCKER_APT_PACKAGES="ffmpeg build-essential" ``` Notes: + - This accepts a space-separated list of apt package names. - If you change `OPENCLAW_DOCKER_APT_PACKAGES`, rerun `docker-setup.sh` to rebuild the image. @@ -163,7 +171,7 @@ RUN pnpm ui:build ENV NODE_ENV=production -CMD ["node","dist/index.mjs"] +CMD ["node","dist/index.js"] ``` ### Channel setup (optional) @@ -171,16 +179,19 @@ CMD ["node","dist/index.mjs"] Use the CLI container to configure channels, then restart the gateway if needed. WhatsApp (QR): + ```bash docker compose run --rm openclaw-cli channels login ``` Telegram (bot token): + ```bash docker compose run --rm openclaw-cli channels add --channel telegram --token "" ``` Discord (bot token): + ```bash docker compose run --rm openclaw-cli channels add --channel discord --token "" ``` @@ -190,7 +201,7 @@ Docs: [WhatsApp](/channels/whatsapp), [Telegram](/channels/telegram), [Discord]( ### Health check ```bash -docker compose exec openclaw-gateway node dist/index.mjs health --token "$OPENCLAW_GATEWAY_TOKEN" +docker compose exec openclaw-gateway node dist/index.js health --token "$OPENCLAW_GATEWAY_TOKEN" ``` ### E2E smoke test (Docker) @@ -218,6 +229,7 @@ Deep dive: [Sandboxing](/gateway/sandboxing) When `agents.defaults.sandbox` is enabled, **non-main sessions** run tools inside a Docker container. The gateway stays on your host, but the tool execution is isolated: + - scope: `"agent"` by default (one container + workspace per agent) - scope: `"session"` for per-session isolation - per-scope workspace folder mounted at `/workspace` @@ -233,6 +245,7 @@ one container and one workspace. If you use multi-agent routing, each agent can override sandbox + tool settings: `agents.list[].sandbox` and `agents.list[].tools` (plus `agents.list[].tools.sandbox.tools`). This lets you run mixed access levels in one gateway: + - Full access (personal agent) - Read-only tools + read-only workspace (family/work agent) - No filesystem/shell tools (public agent) @@ -255,60 +268,72 @@ precedence, and troubleshooting. ### Enable sandboxing If you plan to install packages in `setupCommand`, note: + - Default `docker.network` is `"none"` (no egress). - `readOnlyRoot: true` blocks package installs. - `user` must be root for `apt-get` (omit `user` or set `user: "0:0"`). -OpenClaw auto-recreates containers when `setupCommand` (or docker config) changes -unless the container was **recently used** (within ~5 minutes). Hot containers -log a warning with the exact `openclaw sandbox recreate ...` command. + OpenClaw auto-recreates containers when `setupCommand` (or docker config) changes + unless the container was **recently used** (within ~5 minutes). Hot containers + log a warning with the exact `openclaw sandbox recreate ...` command. ```json5 { agents: { defaults: { sandbox: { - mode: "non-main", // off | non-main | all - scope: "agent", // session | agent | shared (agent is default) - workspaceAccess: "none", // none | ro | rw - workspaceRoot: "~/.openclaw/sandboxes", + mode: 'non-main', // off | non-main | all + scope: 'agent', // session | agent | shared (agent is default) + workspaceAccess: 'none', // none | ro | rw + workspaceRoot: '~/.openclaw/sandboxes', docker: { - image: "openclaw-sandbox:bookworm-slim", - workdir: "/workspace", + image: 'openclaw-sandbox:bookworm-slim', + workdir: '/workspace', readOnlyRoot: true, - tmpfs: ["/tmp", "/var/tmp", "/run"], - network: "none", - user: "1000:1000", - capDrop: ["ALL"], - env: { LANG: "C.UTF-8" }, - setupCommand: "apt-get update && apt-get install -y git curl jq", + tmpfs: ['/tmp', '/var/tmp', '/run'], + network: 'none', + user: '1000:1000', + capDrop: ['ALL'], + env: { LANG: 'C.UTF-8' }, + setupCommand: 'apt-get update && apt-get install -y git curl jq', pidsLimit: 256, - memory: "1g", - memorySwap: "2g", + memory: '1g', + memorySwap: '2g', cpus: 1, ulimits: { nofile: { soft: 1024, hard: 2048 }, - nproc: 256 + nproc: 256, }, - seccompProfile: "/path/to/seccomp.json", - apparmorProfile: "openclaw-sandbox", - dns: ["1.1.1.1", "8.8.8.8"], - extraHosts: ["internal.service:10.0.0.5"] + seccompProfile: '/path/to/seccomp.json', + apparmorProfile: 'openclaw-sandbox', + dns: ['1.1.1.1', '8.8.8.8'], + extraHosts: ['internal.service:10.0.0.5'], }, prune: { idleHours: 24, // 0 disables idle pruning - maxAgeDays: 7 // 0 disables max-age pruning - } - } - } + maxAgeDays: 7, // 0 disables max-age pruning + }, + }, + }, }, tools: { sandbox: { tools: { - allow: ["exec", "process", "read", "write", "edit", "sessions_list", "sessions_history", "sessions_send", "sessions_spawn", "session_status"], - deny: ["browser", "canvas", "nodes", "cron", "discord", "gateway"] - } - } - } + allow: [ + 'exec', + 'process', + 'read', + 'write', + 'edit', + 'sessions_list', + 'sessions_history', + 'sessions_send', + 'sessions_spawn', + 'session_status', + ], + deny: ['browser', 'canvas', 'nodes', 'cron', 'discord', 'gateway'], + }, + }, + }, } ``` @@ -328,6 +353,7 @@ scripts/sandbox-setup.sh This builds `openclaw-sandbox:bookworm-slim` using `Dockerfile.sandbox`. ### Sandbox common image (optional) + If you want a sandbox image with common build tooling (Node, Go, Rust, etc.), build the common image: ```bash @@ -338,7 +364,11 @@ This builds `openclaw-sandbox-common:bookworm-slim`. To use it: ```json5 { - agents: { defaults: { sandbox: { docker: { image: "openclaw-sandbox-common:bookworm-slim" } } } } + agents: { + defaults: { + sandbox: { docker: { image: 'openclaw-sandbox-common:bookworm-slim' } }, + }, + }, } ``` @@ -355,6 +385,7 @@ This builds `openclaw-sandbox-browser:bookworm-slim` using an optional noVNC observer (headful via Xvfb). Notes: + - Headful (Xvfb) reduces bot blocking vs headless. - Headless can still be used by setting `agents.defaults.sandbox.browser.headless=true`. - No full desktop environment (GNOME) is needed; Xvfb provides the display. @@ -366,10 +397,10 @@ Use config: agents: { defaults: { sandbox: { - browser: { enabled: true } - } - } - } + browser: { enabled: true }, + }, + }, + }, } ``` @@ -379,13 +410,14 @@ Custom browser image: { agents: { defaults: { - sandbox: { browser: { image: "my-openclaw-browser" } } - } - } + sandbox: { browser: { image: 'my-openclaw-browser' } }, + }, + }, } ``` When enabled, the agent receives: + - a sandbox browser control URL (for the `browser` tool) - a noVNC URL (if enabled and headless=false) @@ -405,9 +437,9 @@ docker build -t my-openclaw-sbx -f Dockerfile.sandbox . { agents: { defaults: { - sandbox: { docker: { image: "my-openclaw-sbx" } } - } - } + sandbox: { docker: { image: 'my-openclaw-sbx' } }, + }, + }, } ``` @@ -420,10 +452,12 @@ docker build -t my-openclaw-sbx -f Dockerfile.sandbox . ### Pruning strategy Two knobs: + - `prune.idleHours`: remove containers not used in X hours (0 = disable) - `prune.maxAgeDays`: remove containers older than X days (0 = disable) Example: + - Keep busy sessions but cap lifetime: `idleHours: 24`, `maxAgeDays: 7` - Never prune: @@ -431,8 +465,8 @@ Example: ### Security notes -- Hard wall only applies to **tools** (exec/read/write/edit/apply_patch). -- Host-only tools like browser/camera/canvas are blocked by default. +- Hard wall only applies to **tools** (exec/read/write/edit/apply_patch). +- Host-only tools like browser/camera/canvas are blocked by default. - Allowing `browser` in sandbox **breaks isolation** (browser runs on host). ## Troubleshooting diff --git a/docs/platforms/fly.md b/docs/platforms/fly.md index 4fa3c3a1ec..78e9ad59f1 100644 --- a/docs/platforms/fly.md +++ b/docs/platforms/fly.md @@ -57,7 +57,7 @@ primary_region = "iad" NODE_OPTIONS = "--max-old-space-size=1536" [processes] - app = "node dist/index.mjs gateway --allow-unconfigured --port 3000 --bind lan" + app = "node dist/index.js gateway --allow-unconfigured --port 3000 --bind lan" [http_service] internal_port = 3000 @@ -78,13 +78,13 @@ primary_region = "iad" **Key settings:** -| Setting | Why | -|---------|-----| -| `--bind lan` | Binds to `0.0.0.0` so Fly's proxy can reach the gateway | -| `--allow-unconfigured` | Starts without a config file (you'll create one after) | -| `internal_port = 3000` | Must match `--port 3000` (or `OPENCLAW_GATEWAY_PORT`) for Fly health checks | -| `memory = "2048mb"` | 512MB is too small; 2GB recommended | -| `OPENCLAW_STATE_DIR = "/data"` | Persists state on the volume | +| Setting | Why | +| ------------------------------ | --------------------------------------------------------------------------- | +| `--bind lan` | Binds to `0.0.0.0` so Fly's proxy can reach the gateway | +| `--allow-unconfigured` | Starts without a config file (you'll create one after) | +| `internal_port = 3000` | Must match `--port 3000` (or `OPENCLAW_GATEWAY_PORT`) for Fly health checks | +| `memory = "2048mb"` | 512MB is too small; 2GB recommended | +| `OPENCLAW_STATE_DIR = "/data"` | Persists state on the volume | ## 3) Set secrets @@ -104,6 +104,7 @@ fly secrets set DISCORD_BOT_TOKEN=MTQ... ``` **Notes:** + - Non-loopback binds (`--bind lan`) require `OPENCLAW_GATEWAY_TOKEN` for security. - Treat these tokens like passwords. - **Prefer env vars over config file** for all API keys and tokens. This keeps secrets out of `openclaw.json` where they could be accidentally exposed or logged. @@ -117,12 +118,14 @@ fly deploy First deploy builds the Docker image (~2-3 minutes). Subsequent deploys are faster. After deployment, verify: + ```bash fly status fly logs ``` You should see: + ``` [gateway] listening on ws://0.0.0.0:3000 (PID xxx) [discord] logged in to discord as xxx @@ -137,6 +140,7 @@ fly ssh console ``` Create the config directory and file: + ```bash mkdir -p /data cat > /data/openclaw.json << 'EOF' @@ -194,12 +198,14 @@ EOF **Note:** With `OPENCLAW_STATE_DIR=/data`, the config path is `/data/openclaw.json`. **Note:** The Discord token can come from either: + - Environment variable: `DISCORD_BOT_TOKEN` (recommended for secrets) - Config file: `channels.discord.token` If using env var, no need to add token to config. The gateway reads `DISCORD_BOT_TOKEN` automatically. Restart to apply: + ```bash exit fly machine restart @@ -210,6 +216,7 @@ fly machine restart ### Control UI Open in browser: + ```bash fly open ``` @@ -250,12 +257,14 @@ Fly can't reach the gateway on the configured port. Container keeps restarting or getting killed. Signs: `SIGABRT`, `v8::internal::Runtime_AllocateInYoungGeneration`, or silent restarts. **Fix:** Increase memory in `fly.toml`: + ```toml [[vm]] memory = "2048mb" ``` Or update an existing machine: + ```bash fly machine update --vm-memory 2048 -y ``` @@ -269,6 +278,7 @@ Gateway refuses to start with "already running" errors. This happens when the container restarts but the PID lock file persists on the volume. **Fix:** Delete the lock file: + ```bash fly ssh console --command "rm -f /data/gateway.*.lock" fly machine restart @@ -281,6 +291,7 @@ The lock file is at `/data/gateway.*.lock` (not in a subdirectory). If using `--allow-unconfigured`, the gateway creates a minimal config. Your custom config at `/data/openclaw.json` should be read on restart. Verify the config exists: + ```bash fly ssh console --command "cat /data/openclaw.json" ``` @@ -299,6 +310,7 @@ fly sftp shell ``` **Note:** `fly sftp` may fail if the file already exists. Delete first: + ```bash fly ssh console --command "rm /data/openclaw.json" ``` @@ -332,10 +344,10 @@ If you need to change the startup command without a full redeploy: fly machines list # Update command -fly machine update --command "node dist/index.mjs gateway --port 3000 --bind lan" -y +fly machine update --command "node dist/index.js gateway --port 3000 --bind lan" -y # Or with memory increase -fly machine update --vm-memory 2048 --command "node dist/index.mjs gateway --port 3000 --bind lan" -y +fly machine update --vm-memory 2048 --command "node dist/index.js gateway --port 3000 --bind lan" -y ``` **Note:** After `fly deploy`, the machine command may reset to what's in `fly.toml`. If you made manual changes, re-apply them after deploy. @@ -381,6 +393,7 @@ fly ips allocate-v6 --private -a my-openclaw ``` After this, `fly ips list` should show only a `private` type IP: + ``` VERSION IP TYPE REGION v6 fdaa:x:x:x:x::x private global @@ -391,6 +404,7 @@ v6 fdaa:x:x:x:x::x private global Since there's no public URL, use one of these methods: **Option 1: Local proxy (simplest)** + ```bash # Forward local port 3000 to the app fly proxy 3000:3000 -a my-openclaw @@ -399,6 +413,7 @@ fly proxy 3000:3000 -a my-openclaw ``` **Option 2: WireGuard VPN** + ```bash # Create WireGuard config (one-time) fly wireguard create @@ -408,6 +423,7 @@ fly wireguard create ``` **Option 3: SSH only** + ```bash fly ssh console -a my-openclaw ``` @@ -421,6 +437,7 @@ If you need webhook callbacks (Twilio, Telnyx, etc.) without public exposure: 3. **Outbound-only** - Some providers (Twilio) work fine for outbound calls without webhooks Example voice-call config with ngrok: + ```json { "plugins": { @@ -441,12 +458,12 @@ The ngrok tunnel runs inside the container and provides a public webhook URL wit ### Security benefits -| Aspect | Public | Private | -|--------|--------|---------| -| Internet scanners | Discoverable | Hidden | -| Direct attacks | Possible | Blocked | -| Control UI access | Browser | Proxy/VPN | -| Webhook delivery | Direct | Via tunnel | +| Aspect | Public | Private | +| ----------------- | ------------ | ---------- | +| Internet scanners | Discoverable | Hidden | +| Direct attacks | Possible | Blocked | +| Control UI access | Browser | Proxy/VPN | +| Webhook delivery | Direct | Via tunnel | ## Notes @@ -459,6 +476,7 @@ The ngrok tunnel runs inside the container and provides a public webhook URL wit ## Cost With the recommended config (`shared-cpu-2x`, 2GB RAM): + - ~$10-15/month depending on usage - Free tier includes some allowance diff --git a/docs/platforms/gcp.md b/docs/platforms/gcp.md index c82c59a18d..27d5d68b48 100644 --- a/docs/platforms/gcp.md +++ b/docs/platforms/gcp.md @@ -1,5 +1,5 @@ --- -summary: "Run OpenClaw Gateway 24/7 on a GCP Compute Engine VM (Docker) with durable state" +summary: 'Run OpenClaw Gateway 24/7 on a GCP Compute Engine VM (Docker) with durable state' read_when: - You want OpenClaw running 24/7 on GCP - You want a production-grade, always-on Gateway on your own VM @@ -25,6 +25,7 @@ Pricing varies by machine type and region; pick the smallest VM that fits your w - Access the Control UI from your laptop via an SSH tunnel The Gateway can be accessed via: + - SSH port forwarding from your laptop - Direct port exposure if you manage firewalling and tokens yourself @@ -36,14 +37,14 @@ For the generic Docker flow, see [Docker](/install/docker). ## Quick path (experienced operators) -1) Create GCP project + enable Compute Engine API -2) Create Compute Engine VM (e2-small, Debian 12, 20GB) -3) SSH into the VM -4) Install Docker -5) Clone OpenClaw repository -6) Create persistent host directories -7) Configure `.env` and `docker-compose.yml` -8) Bake required binaries, build, and launch +1. Create GCP project + enable Compute Engine API +2. Create Compute Engine VM (e2-small, Debian 12, 20GB) +3. SSH into the VM +4. Install Docker +5. Clone OpenClaw repository +6. Create persistent host directories +7. Configure `.env` and `docker-compose.yml` +8. Bake required binaries, build, and launch --- @@ -112,9 +113,9 @@ gcloud services enable compute.googleapis.com **Machine types:** -| Type | Specs | Cost | Notes | -|------|-------|------|-------| -| e2-small | 2 vCPU, 2GB RAM | ~$12/mo | Recommended | +| Type | Specs | Cost | Notes | +| -------- | ------------------------ | ------------------ | ------------------ | +| e2-small | 2 vCPU, 2GB RAM | ~$12/mo | Recommended | | e2-micro | 2 vCPU (shared), 1GB RAM | Free tier eligible | May OOM under load | **CLI:** @@ -263,20 +264,20 @@ services: ports: # Recommended: keep the Gateway loopback-only on the VM; access via SSH tunnel. # To expose it publicly, remove the `127.0.0.1:` prefix and firewall accordingly. - - "127.0.0.1:${OPENCLAW_GATEWAY_PORT}:18789" + - '127.0.0.1:${OPENCLAW_GATEWAY_PORT}:18789' # Optional: only if you run iOS/Android nodes against this VM and need Canvas host. # If you expose this publicly, read /gateway/security and firewall accordingly. # - "18793:18793" command: [ - "node", - "dist/index.mjs", - "gateway", - "--bind", - "${OPENCLAW_GATEWAY_BIND}", - "--port", - "${OPENCLAW_GATEWAY_PORT}" + 'node', + 'dist/index.js', + 'gateway', + '--bind', + '${OPENCLAW_GATEWAY_BIND}', + '--port', + '${OPENCLAW_GATEWAY_PORT}', ] ``` @@ -290,6 +291,7 @@ Anything installed at runtime will be lost on restart. All external binaries required by skills must be installed at image build time. The examples below show three common binaries only: + - `gog` for Gmail access - `goplaces` for Google Places - `wacli` for WhatsApp @@ -298,6 +300,7 @@ These are examples, not a complete list. You may install as many binaries as needed using the same pattern. If you add new skills later that depend on additional binaries, you must: + 1. Update the Dockerfile 2. Rebuild the image 3. Restart the containers @@ -338,7 +341,7 @@ RUN pnpm ui:build ENV NODE_ENV=production -CMD ["node","dist/index.mjs"] +CMD ["node","dist/index.js"] ``` --- @@ -403,18 +406,18 @@ Paste your gateway token. OpenClaw runs in Docker, but Docker is not the source of truth. All long-lived state must survive restarts, rebuilds, and reboots. -| Component | Location | Persistence mechanism | Notes | -|---|---|---|---| -| Gateway config | `/home/node/.openclaw/` | Host volume mount | Includes `openclaw.json`, tokens | -| Model auth profiles | `/home/node/.openclaw/` | Host volume mount | OAuth tokens, API keys | -| Skill configs | `/home/node/.openclaw/skills/` | Host volume mount | Skill-level state | -| Agent workspace | `/home/node/.openclaw/workspace/` | Host volume mount | Code and agent artifacts | -| WhatsApp session | `/home/node/.openclaw/` | Host volume mount | Preserves QR login | -| Gmail keyring | `/home/node/.openclaw/` | Host volume + password | Requires `GOG_KEYRING_PASSWORD` | -| External binaries | `/usr/local/bin/` | Docker image | Must be baked at build time | -| Node runtime | Container filesystem | Docker image | Rebuilt every image build | -| OS packages | Container filesystem | Docker image | Do not install at runtime | -| Docker container | Ephemeral | Restartable | Safe to destroy | +| Component | Location | Persistence mechanism | Notes | +| ------------------- | --------------------------------- | ---------------------- | -------------------------------- | +| Gateway config | `/home/node/.openclaw/` | Host volume mount | Includes `openclaw.json`, tokens | +| Model auth profiles | `/home/node/.openclaw/` | Host volume mount | OAuth tokens, API keys | +| Skill configs | `/home/node/.openclaw/skills/` | Host volume mount | Skill-level state | +| Agent workspace | `/home/node/.openclaw/workspace/` | Host volume mount | Code and agent artifacts | +| WhatsApp session | `/home/node/.openclaw/` | Host volume mount | Preserves QR login | +| Gmail keyring | `/home/node/.openclaw/` | Host volume + password | Requires `GOG_KEYRING_PASSWORD` | +| External binaries | `/usr/local/bin/` | Docker image | Must be baked at build time | +| Node runtime | Container filesystem | Docker image | Rebuilt every image build | +| OS packages | Container filesystem | Docker image | Do not install at runtime | +| Docker container | Ephemeral | Restartable | Safe to destroy | --- @@ -473,6 +476,7 @@ For personal use, your default user account works fine. For automation or CI/CD pipelines, create a dedicated service account with minimal permissions: 1. Create a service account: + ```bash gcloud iam service-accounts create openclaw-deploy \ --display-name="OpenClaw Deployment" diff --git a/docs/platforms/hetzner.md b/docs/platforms/hetzner.md index 0c9ffdc8e6..afd7d8694f 100644 --- a/docs/platforms/hetzner.md +++ b/docs/platforms/hetzner.md @@ -1,5 +1,5 @@ --- -summary: "Run OpenClaw Gateway 24/7 on a cheap Hetzner VPS (Docker) with durable state and baked-in binaries" +summary: 'Run OpenClaw Gateway 24/7 on a cheap Hetzner VPS (Docker) with durable state and baked-in binaries' read_when: - You want OpenClaw running 24/7 on a cloud VPS (not your laptop) - You want a production-grade, always-on Gateway on your own VPS @@ -10,6 +10,7 @@ read_when: # OpenClaw on Hetzner (Docker, Production VPS Guide) ## Goal + Run a persistent OpenClaw Gateway on a Hetzner VPS using Docker, with durable state, baked-in binaries, and safe restart behavior. If you want “OpenClaw 24/7 for ~$5”, this is the simplest reliable setup. @@ -24,6 +25,7 @@ Hetzner pricing changes; pick the smallest Debian/Ubuntu VPS and scale up if you - Access the Control UI from your laptop via an SSH tunnel The Gateway can be accessed via: + - SSH port forwarding from your laptop - Direct port exposure if you manage firewalling and tokens yourself @@ -35,29 +37,29 @@ For the generic Docker flow, see [Docker](/install/docker). ## Quick path (experienced operators) -1) Provision Hetzner VPS -2) Install Docker -3) Clone OpenClaw repository -4) Create persistent host directories -5) Configure `.env` and `docker-compose.yml` -6) Bake required binaries into the image -7) `docker compose up -d` -8) Verify persistence and Gateway access +1. Provision Hetzner VPS +2. Install Docker +3. Clone OpenClaw repository +4. Create persistent host directories +5. Configure `.env` and `docker-compose.yml` +6. Bake required binaries into the image +7. `docker compose up -d` +8. Verify persistence and Gateway access --- ## What you need -- Hetzner VPS with root access -- SSH access from your laptop -- Basic comfort with SSH + copy/paste -- ~20 minutes -- Docker and Docker Compose -- Model auth credentials -- Optional provider credentials - - WhatsApp QR - - Telegram bot token - - Gmail OAuth +- Hetzner VPS with root access +- SSH access from your laptop +- Basic comfort with SSH + copy/paste +- ~20 minutes +- Docker and Docker Compose +- Model auth credentials +- Optional provider credentials + - WhatsApp QR + - Telegram bot token + - Gmail OAuth --- @@ -175,20 +177,20 @@ services: ports: # Recommended: keep the Gateway loopback-only on the VPS; access via SSH tunnel. # To expose it publicly, remove the `127.0.0.1:` prefix and firewall accordingly. - - "127.0.0.1:${OPENCLAW_GATEWAY_PORT}:18789" + - '127.0.0.1:${OPENCLAW_GATEWAY_PORT}:18789' # Optional: only if you run iOS/Android nodes against this VPS and need Canvas host. # If you expose this publicly, read /gateway/security and firewall accordingly. # - "18793:18793" command: [ - "node", - "dist/index.mjs", - "gateway", - "--bind", - "${OPENCLAW_GATEWAY_BIND}", - "--port", - "${OPENCLAW_GATEWAY_PORT}" + 'node', + 'dist/index.js', + 'gateway', + '--bind', + '${OPENCLAW_GATEWAY_BIND}', + '--port', + '${OPENCLAW_GATEWAY_PORT}', ] ``` @@ -202,6 +204,7 @@ Anything installed at runtime will be lost on restart. All external binaries required by skills must be installed at image build time. The examples below show three common binaries only: + - `gog` for Gmail access - `goplaces` for Google Places - `wacli` for WhatsApp @@ -210,6 +213,7 @@ These are examples, not a complete list. You may install as many binaries as needed using the same pattern. If you add new skills later that depend on additional binaries, you must: + 1. Update the Dockerfile 2. Rebuild the image 3. Restart the containers @@ -250,7 +254,7 @@ RUN pnpm ui:build ENV NODE_ENV=production -CMD ["node","dist/index.mjs"] +CMD ["node","dist/index.js"] ``` --- @@ -311,15 +315,15 @@ Paste your gateway token. OpenClaw runs in Docker, but Docker is not the source of truth. All long-lived state must survive restarts, rebuilds, and reboots. -| Component | Location | Persistence mechanism | Notes | -|---|---|---|---| -| Gateway config | `/home/node/.openclaw/` | Host volume mount | Includes `openclaw.json`, tokens | -| Model auth profiles | `/home/node/.openclaw/` | Host volume mount | OAuth tokens, API keys | -| Skill configs | `/home/node/.openclaw/skills/` | Host volume mount | Skill-level state | -| Agent workspace | `/home/node/.openclaw/workspace/` | Host volume mount | Code and agent artifacts | -| WhatsApp session | `/home/node/.openclaw/` | Host volume mount | Preserves QR login | -| Gmail keyring | `/home/node/.openclaw/` | Host volume + password | Requires `GOG_KEYRING_PASSWORD` | -| External binaries | `/usr/local/bin/` | Docker image | Must be baked at build time | -| Node runtime | Container filesystem | Docker image | Rebuilt every image build | -| OS packages | Container filesystem | Docker image | Do not install at runtime | -| Docker container | Ephemeral | Restartable | Safe to destroy | +| Component | Location | Persistence mechanism | Notes | +| ------------------- | --------------------------------- | ---------------------- | -------------------------------- | +| Gateway config | `/home/node/.openclaw/` | Host volume mount | Includes `openclaw.json`, tokens | +| Model auth profiles | `/home/node/.openclaw/` | Host volume mount | OAuth tokens, API keys | +| Skill configs | `/home/node/.openclaw/skills/` | Host volume mount | Skill-level state | +| Agent workspace | `/home/node/.openclaw/workspace/` | Host volume mount | Code and agent artifacts | +| WhatsApp session | `/home/node/.openclaw/` | Host volume mount | Preserves QR login | +| Gmail keyring | `/home/node/.openclaw/` | Host volume + password | Requires `GOG_KEYRING_PASSWORD` | +| External binaries | `/usr/local/bin/` | Docker image | Must be baked at build time | +| Node runtime | Container filesystem | Docker image | Rebuilt every image build | +| OS packages | Container filesystem | Docker image | Do not install at runtime | +| Docker container | Ephemeral | Restartable | Safe to destroy | diff --git a/docs/plugin.md b/docs/plugin.md index ec0ec2e029..dfeea568e0 100644 --- a/docs/plugin.md +++ b/docs/plugin.md @@ -1,9 +1,10 @@ --- -summary: "OpenClaw plugins/extensions: discovery, config, and safety" +summary: 'OpenClaw plugins/extensions: discovery, config, and safety' read_when: - Adding or modifying plugins/extensions - Documenting plugin install or load rules --- + # Plugins (Extensions) ## Quick start (new to plugins?) @@ -17,19 +18,19 @@ install). Fast path: -1) See what’s already loaded: +1. See what’s already loaded: ```bash openclaw plugins list ``` -2) Install an official plugin (example: Voice Call): +2. Install an official plugin (example: Voice Call): ```bash openclaw plugins install @openclaw/voice-call ``` -3) Restart the Gateway, then configure under `plugins.entries..config`. +3. Restart the Gateway, then configure under `plugins.entries..config`. See [Voice Call](/plugins/voice-call) for a concrete example plugin. @@ -73,12 +74,13 @@ Plugins can access selected core helpers via `api.runtime`. For telephony TTS: ```ts const result = await api.runtime.tts.textToSpeechTelephony({ - text: "Hello from OpenClaw", + text: 'Hello from OpenClaw', cfg: api.config, }); ``` Notes: + - Uses core `messages.tts` configuration (OpenAI or ElevenLabs). - Returns PCM audio buffer + sample rate. Plugins must resample/encode for providers. - Edge TTS is not supported for telephony. @@ -87,18 +89,22 @@ Notes: OpenClaw scans, in order: -1) Config paths +1. Config paths + - `plugins.load.paths` (file or directory) -2) Workspace extensions +2. Workspace extensions + - `/.openclaw/extensions/*.ts` - `/.openclaw/extensions/*/index.ts` -3) Global extensions +3. Global extensions + - `~/.openclaw/extensions/*.ts` - `~/.openclaw/extensions/*/index.ts` -4) Bundled extensions (shipped with OpenClaw, **disabled by default**) +4. Bundled extensions (shipped with OpenClaw, **disabled by default**) + - `/extensions/*` Bundled plugins must be enabled explicitly via `plugins.entries..enabled` @@ -164,6 +170,7 @@ Example: OpenClaw can also merge **external channel catalogs** (for example, an MPM registry export). Drop a JSON file at one of: + - `~/.openclaw/mpm/plugins.json` - `~/.openclaw/mpm/catalog.json` - `~/.openclaw/plugins/catalog.json` @@ -188,17 +195,18 @@ configured id. { plugins: { enabled: true, - allow: ["voice-call"], - deny: ["untrusted-plugin"], - load: { paths: ["~/Projects/oss/voice-call-extension"] }, + allow: ['voice-call'], + deny: ['untrusted-plugin'], + load: { paths: ['~/Projects/oss/voice-call-extension'] }, entries: { - "voice-call": { enabled: true, config: { provider: "twilio" } } - } - } + 'voice-call': { enabled: true, config: { provider: 'twilio' } }, + }, + }, } ``` Fields: + - `enabled`: master toggle (default: true) - `allow`: allowlist (optional) - `deny`: denylist (optional; deny wins) @@ -208,6 +216,7 @@ Fields: Config changes **require a gateway restart**. Validation rules (strict): + - Unknown plugin ids in `entries`, `allow`, `deny`, or `slots` are **errors**. - Unknown `channels.` keys are **errors** unless a plugin manifest declares the channel id. @@ -224,9 +233,9 @@ Some plugin categories are **exclusive** (only one active at a time). Use { plugins: { slots: { - memory: "memory-core" // or "none" to disable memory plugins - } - } + memory: 'memory-core', // or "none" to disable memory plugins + }, + }, } ``` @@ -311,6 +320,7 @@ export default function register(api) { ``` Notes: + - Hook directories follow the normal hook structure (`HOOK.md` + `handler.ts`). - Hook eligibility rules still apply (OS/bins/env/config requirements). - Plugin-managed hooks show up in `openclaw hooks list` with `plugin:`. @@ -330,29 +340,29 @@ Example: ```ts api.registerProvider({ - id: "acme", - label: "AcmeAI", + id: 'acme', + label: 'AcmeAI', auth: [ { - id: "oauth", - label: "OAuth", - kind: "oauth", + id: 'oauth', + label: 'OAuth', + kind: 'oauth', run: async (ctx) => { // Run OAuth flow and return auth profiles. return { profiles: [ { - profileId: "acme:default", + profileId: 'acme:default', credential: { - type: "oauth", - provider: "acme", - access: "...", - refresh: "...", + type: 'oauth', + provider: 'acme', + access: '...', + refresh: '...', expires: Date.now() + 3600 * 1000, }, }, ], - defaultModel: "acme/opus-1", + defaultModel: 'acme/opus-1', }; }, }, @@ -361,6 +371,7 @@ api.registerProvider({ ``` Notes: + - `run` receives a `ProviderAuthContext` with `prompter`, `runtime`, `openUrl`, and `oauth.createVpsAwareHandlers` helpers. - Return `configPatch` when you need to add default models or provider config. @@ -374,23 +385,26 @@ validated by your channel plugin code. ```ts const myChannel = { - id: "acmechat", + id: 'acmechat', meta: { - id: "acmechat", - label: "AcmeChat", - selectionLabel: "AcmeChat (API)", - docsPath: "/channels/acmechat", - blurb: "demo channel plugin.", - aliases: ["acme"], + id: 'acmechat', + label: 'AcmeChat', + selectionLabel: 'AcmeChat (API)', + docsPath: '/channels/acmechat', + blurb: 'demo channel plugin.', + aliases: ['acme'], }, - capabilities: { chatTypes: ["direct"] }, + capabilities: { chatTypes: ['direct'] }, config: { - listAccountIds: (cfg) => Object.keys(cfg.channels?.acmechat?.accounts ?? {}), + listAccountIds: (cfg) => + Object.keys(cfg.channels?.acmechat?.accounts ?? {}), resolveAccount: (cfg, accountId) => - (cfg.channels?.acmechat?.accounts?.[accountId ?? "default"] ?? { accountId }), + cfg.channels?.acmechat?.accounts?.[accountId ?? 'default'] ?? { + accountId, + }, }, outbound: { - deliveryMode: "direct", + deliveryMode: 'direct', sendText: async () => ({ ok: true }), }, }; @@ -401,6 +415,7 @@ export default function (api) { ``` Notes: + - Put config under `channels.` (not `plugins.entries`). - `meta.label` is used for labels in CLI/UI lists. - `meta.aliases` adds alternate ids for normalization and CLI inputs. @@ -412,27 +427,32 @@ Notes: Use this when you want a **new chat surface** (a “messaging channel”), not a model provider. Model provider docs live under `/providers/*`. -1) Pick an id + config shape +1. Pick an id + config shape + - All channel config lives under `channels.`. - Prefer `channels..accounts.` for multi‑account setups. -2) Define the channel metadata +2. Define the channel metadata + - `meta.label`, `meta.selectionLabel`, `meta.docsPath`, `meta.blurb` control CLI/UI lists. - `meta.docsPath` should point at a docs page like `/channels/`. - `meta.preferOver` lets a plugin replace another channel (auto-enable prefers it). - `meta.detailLabel` and `meta.systemImage` are used by UIs for detail text/icons. -3) Implement the required adapters +3. Implement the required adapters + - `config.listAccountIds` + `config.resolveAccount` - `capabilities` (chat types, media, threads, etc.) - `outbound.deliveryMode` + `outbound.sendText` (for basic send) -4) Add optional adapters as needed +4. Add optional adapters as needed + - `setup` (wizard), `security` (DM policy), `status` (health/diagnostics) - `gateway` (start/stop/login), `mentions`, `threading`, `streaming` - `actions` (message actions), `commands` (native command behavior) -5) Register the channel in your plugin +5. Register the channel in your plugin + - `api.registerChannel({ plugin })` Minimal config example: @@ -442,10 +462,10 @@ Minimal config example: channels: { acmechat: { accounts: { - default: { token: "ACME_TOKEN", enabled: true } - } - } - } + default: { token: 'ACME_TOKEN', enabled: true }, + }, + }, + }, } ``` @@ -453,23 +473,26 @@ Minimal channel plugin (outbound‑only): ```ts const plugin = { - id: "acmechat", + id: 'acmechat', meta: { - id: "acmechat", - label: "AcmeChat", - selectionLabel: "AcmeChat (API)", - docsPath: "/channels/acmechat", - blurb: "AcmeChat messaging channel.", - aliases: ["acme"], + id: 'acmechat', + label: 'AcmeChat', + selectionLabel: 'AcmeChat (API)', + docsPath: '/channels/acmechat', + blurb: 'AcmeChat messaging channel.', + aliases: ['acme'], }, - capabilities: { chatTypes: ["direct"] }, + capabilities: { chatTypes: ['direct'] }, config: { - listAccountIds: (cfg) => Object.keys(cfg.channels?.acmechat?.accounts ?? {}), + listAccountIds: (cfg) => + Object.keys(cfg.channels?.acmechat?.accounts ?? {}), resolveAccount: (cfg, accountId) => - (cfg.channels?.acmechat?.accounts?.[accountId ?? "default"] ?? { accountId }), + cfg.channels?.acmechat?.accounts?.[accountId ?? 'default'] ?? { + accountId, + }, }, outbound: { - deliveryMode: "direct", + deliveryMode: 'direct', sendText: async ({ text }) => { // deliver `text` to your channel here return { ok: true }; @@ -493,7 +516,7 @@ See the dedicated guide: [Plugin agent tools](/plugins/agent-tools). ```ts export default function (api) { - api.registerGatewayMethod("myplugin.status", ({ respond }) => { + api.registerGatewayMethod('myplugin.status', ({ respond }) => { respond(true, { ok: true }); }); } @@ -503,11 +526,14 @@ export default function (api) { ```ts export default function (api) { - api.registerCli(({ program }) => { - program.command("mycmd").action(() => { - console.log("Hello"); - }); - }, { commands: ["mycmd"] }); + api.registerCli( + ({ program }) => { + program.command('mycmd').action(() => { + console.log('Hello'); + }); + }, + { commands: ['mycmd'] }, + ); } ``` @@ -520,8 +546,8 @@ that don't need LLM processing. ```ts export default function (api) { api.registerCommand({ - name: "mystatus", - description: "Show plugin status", + name: 'mystatus', + description: 'Show plugin status', handler: (ctx) => ({ text: `Plugin is running! Channel: ${ctx.channel}`, }), @@ -550,12 +576,12 @@ Example with authorization and arguments: ```ts api.registerCommand({ - name: "setmode", - description: "Set plugin mode", + name: 'setmode', + description: 'Set plugin mode', acceptsArgs: true, requireAuth: true, handler: async (ctx) => { - const mode = ctx.args?.trim() || "default"; + const mode = ctx.args?.trim() || 'default'; await saveMode(mode); return { text: `Mode set to: ${mode}` }; }, @@ -563,6 +589,7 @@ api.registerCommand({ ``` Notes: + - Plugin commands are processed **before** built-in commands and the AI agent - Commands are registered globally and work across all channels - Command names are case-insensitive (`/MyStatus` matches `/mystatus`) @@ -575,9 +602,9 @@ Notes: ```ts export default function (api) { api.registerService({ - id: "my-service", - start: () => api.logger.info("ready"), - stop: () => api.logger.info("bye"), + id: 'my-service', + start: () => api.logger.info('ready'), + stop: () => api.logger.info('bye'), }); } ``` @@ -635,4 +662,4 @@ Plugins run in-process with the Gateway. Treat them as trusted code: Plugins can (and should) ship tests: - In-repo plugins can keep Vitest tests under `src/**` (example: `src/plugins/voice-call.plugin.test.ts`). -- Separately published plugins should run their own CI (lint/build/test) and validate `openclaw.extensions` points at the built entrypoint (`dist/index.mjs`). +- Separately published plugins should run their own CI (lint/build/test) and validate `openclaw.extensions` points at the built entrypoint (`dist/index.js`). diff --git a/fly.private.toml b/fly.private.toml index ee37e7d344..4f0086c516 100644 --- a/fly.private.toml +++ b/fly.private.toml @@ -9,20 +9,20 @@ # # See https://fly.io/docs/reference/configuration/ -app = "my-openclaw" # change to your app name -primary_region = "iad" # change to your closest region +app = "my-openclaw" # change to your app name +primary_region = "iad" # change to your closest region [build] - dockerfile = "Dockerfile" +dockerfile = "Dockerfile" [env] - NODE_ENV = "production" - OPENCLAW_PREFER_PNPM = "1" - OPENCLAW_STATE_DIR = "/data" - NODE_OPTIONS = "--max-old-space-size=1536" +NODE_ENV = "production" +OPENCLAW_PREFER_PNPM = "1" +OPENCLAW_STATE_DIR = "/data" +NODE_OPTIONS = "--max-old-space-size=1536" [processes] - app = "node dist/index.mjs gateway --allow-unconfigured --port 3000 --bind lan" +app = "node dist/index.js gateway --allow-unconfigured --port 3000 --bind lan" # NOTE: No [http_service] block = no public ingress allocated. # The gateway will only be accessible via: @@ -31,9 +31,9 @@ primary_region = "iad" # change to your closest region # - fly ssh console [[vm]] - size = "shared-cpu-2x" - memory = "2048mb" +size = "shared-cpu-2x" +memory = "2048mb" [mounts] - source = "openclaw_data" - destination = "/data" +source = "openclaw_data" +destination = "/data" diff --git a/fly.toml b/fly.toml index 73a250f95a..9aca608c5c 100644 --- a/fly.toml +++ b/fly.toml @@ -2,33 +2,33 @@ # See https://fly.io/docs/reference/configuration/ app = "openclaw" -primary_region = "iad" # change to your closest region +primary_region = "iad" # change to your closest region [build] - dockerfile = "Dockerfile" +dockerfile = "Dockerfile" [env] - NODE_ENV = "production" - # Fly uses x86, but keep this for consistency - OPENCLAW_PREFER_PNPM = "1" - OPENCLAW_STATE_DIR = "/data" - NODE_OPTIONS = "--max-old-space-size=1536" +NODE_ENV = "production" +# Fly uses x86, but keep this for consistency +OPENCLAW_PREFER_PNPM = "1" +OPENCLAW_STATE_DIR = "/data" +NODE_OPTIONS = "--max-old-space-size=1536" [processes] - app = "node dist/index.mjs gateway --allow-unconfigured --port 3000 --bind lan" +app = "node dist/index.js gateway --allow-unconfigured --port 3000 --bind lan" [http_service] - internal_port = 3000 - force_https = true - auto_stop_machines = false # Keep running for persistent connections - auto_start_machines = true - min_machines_running = 1 - processes = ["app"] +internal_port = 3000 +force_https = true +auto_stop_machines = false # Keep running for persistent connections +auto_start_machines = true +min_machines_running = 1 +processes = ["app"] [[vm]] - size = "shared-cpu-2x" - memory = "2048mb" +size = "shared-cpu-2x" +memory = "2048mb" [mounts] - source = "openclaw_data" - destination = "/data" +source = "openclaw_data" +destination = "/data" diff --git a/openclaw.mjs b/openclaw.mjs index a83cdc844b..bec1b5fd5f 100755 --- a/openclaw.mjs +++ b/openclaw.mjs @@ -1,6 +1,6 @@ #!/usr/bin/env node -import module from "node:module"; +import module from 'node:module'; // https://nodejs.org/api/module.html#module-compile-cache if (module.enableCompileCache && !process.env.NODE_DISABLE_COMPILE_CACHE) { @@ -11,4 +11,4 @@ if (module.enableCompileCache && !process.env.NODE_DISABLE_COMPILE_CACHE) { } } -await import("./dist/entry.mjs"); +await import('./dist/entry.js'); diff --git a/package.json b/package.json index a22a718389..559104994a 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,9 @@ "version": "2026.1.29", "description": "WhatsApp gateway CLI (Baileys web) with Pi RPC agent", "type": "module", - "main": "dist/index.mjs", + "main": "dist/index.js", "exports": { - ".": "./dist/index.mjs", + ".": "./dist/index.js", "./plugin-sdk": "./dist/plugin-sdk/index.js", "./plugin-sdk/*": "./dist/plugin-sdk/*", "./cli-entry": "./openclaw.mjs" @@ -85,7 +85,7 @@ "docs:bin": "node scripts/build-docs-list.mjs", "docs:dev": "cd docs && mint dev", "docs:build": "cd docs && pnpm dlx --reporter append-only mint broken-links", - "build": "pnpm canvas:a2ui:bundle && tsdown && node --import tsx scripts/canvas-a2ui-copy.ts && node --import tsx scripts/copy-hook-metadata.ts && node --import tsx scripts/write-build-info.ts", + "build": "pnpm canvas:a2ui:bundle && tsc -p tsconfig.json --noEmit false && node --import tsx scripts/canvas-a2ui-copy.ts && node --import tsx scripts/copy-hook-metadata.ts && node --import tsx scripts/write-build-info.ts", "plugins:sync": "node --import tsx scripts/sync-plugin-versions.ts", "release:check": "node --import tsx scripts/release-check.ts", "ui:install": "node scripts/ui.js install", @@ -227,7 +227,6 @@ "oxlint": "^1.42.0", "oxlint-tsgolint": "^0.11.4", "rolldown": "1.0.0-rc.2", - "tsdown": "^0.20.1", "tsx": "^4.21.0", "typescript": "^5.9.3", "vitest": "^4.0.18" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bea693e503..eea99e3c06 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -220,9 +220,6 @@ importers: rolldown: specifier: 1.0.0-rc.2 version: 1.0.0-rc.2 - tsdown: - specifier: ^0.20.1 - version: 0.20.1(@typescript/native-preview@7.0.0-dev.20260130.1)(typescript@5.9.3) tsx: specifier: ^4.21.0 version: 4.21.0 @@ -663,36 +660,19 @@ packages: resolution: {integrity: sha512-XTmhdItcBckcVVTy65Xp+42xG4LX5GK+9AqAsXPXk4IqUNv+LyQo5TMwNjuFYBfAB2GTG9iSQGk+QLc03vhf3w==} engines: {node: '>=16'} - '@babel/generator@8.0.0-beta.4': - resolution: {integrity: sha512-5xRfRZk6wx1BRu2XnTE8cTh2mx1ixrZ3/vpn7p/RCJpgctL6pexVVHE3eqtwlYvHhPAuOYCAlnsAyXpBdmfh5Q==} - engines: {node: ^20.19.0 || >=22.12.0} - '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@8.0.0-beta.4': - resolution: {integrity: sha512-FGwbdQ/I2nJXXfyxa7dT0Fr/zPWwgX7m+hNVj0HrIHYJtyLxSQeQY1Kd8QkAYviQJV3OWFlRLuGd5epF03bdQg==} - engines: {node: ^20.19.0 || >=22.12.0} - '@babel/helper-validator-identifier@7.28.5': resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@8.0.0-beta.4': - resolution: {integrity: sha512-6t0IaUEzlinbLmsGIvBZIHEJGjuchx+cMj+FbS78zL17tucYervgbwO07V5/CgBenVraontpmyMCTVyqCfxhFQ==} - engines: {node: ^20.19.0 || >=22.12.0} - '@babel/parser@7.28.6': resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/parser@8.0.0-beta.4': - resolution: {integrity: sha512-fBcUqUN3eenLyg25QFkOwY1lmV6L0RdG92g6gxyS2CVCY8kHdibkQz1+zV3bLzxcvNnfHoi3i9n5Dci+g93acg==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - '@babel/runtime@7.28.6': resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} engines: {node: '>=6.9.0'} @@ -701,10 +681,6 @@ packages: resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} engines: {node: '>=6.9.0'} - '@babel/types@8.0.0-beta.4': - resolution: {integrity: sha512-xjk2xqYp25ePzAs0I08hN2lrbUDDQFfCjwq6MIEa8HwHa0WK8NfNtdvtXod8Ku2CbE1iui7qwWojGvjQiyrQeA==} - engines: {node: ^20.19.0 || >=22.12.0} - '@bcoe/v8-coverage@1.0.2': resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} @@ -1145,9 +1121,6 @@ packages: resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} engines: {node: '>=18.0.0'} - '@jridgewell/gen-mapping@0.3.13': - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -1822,9 +1795,6 @@ packages: resolution: {integrity: sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==} engines: {node: '>=14'} - '@oxc-project/types@0.110.0': - resolution: {integrity: sha512-6Ct21OIlrEnFEJk5LT4e63pk3btsI6/TusD/GStLi7wYlGJNOl1GI9qvXAnRAxQU9zqA2Oz+UwhfTOU2rPZVow==} - '@oxc-project/types@0.111.0': resolution: {integrity: sha512-bh54LJMafgRGl2cPQ/QM+tI5rWaShm/wK9KywEj/w36MhiPKXYM67H2y3q+9pr4YO7ufwg2AKdBAZkhHBD8ClA==} @@ -1978,9 +1948,6 @@ packages: '@protobufjs/utf8@1.1.0': resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - '@quansync/fs@1.0.0': - resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} - '@reflink/reflink-darwin-arm64@0.1.19': resolution: {integrity: sha512-ruy44Lpepdk1FqDz38vExBY/PVUsjxZA+chd9wozjUH9JjuDT/HEaQYA6wYN9mf041l0yLVar6BCZuWABJvHSA==} engines: {node: '>= 10'} @@ -2033,163 +2000,83 @@ packages: resolution: {integrity: sha512-DmCG8GzysnCZ15bres3N5AHCmwBwYgp0As6xjhQ47rAUTUXxJiK+lLUxaGsX3hd/30qUpVElh05PbGuxRPgJwA==} engines: {node: '>= 10'} - '@rolldown/binding-android-arm64@1.0.0-rc.1': - resolution: {integrity: sha512-He6ZoCfv5D7dlRbrhNBkuMVIHd0GDnjJwbICE1OWpG7G3S2gmJ+eXkcNLJjzjNDpeI2aRy56ou39AJM9AD8YFA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [android] - '@rolldown/binding-android-arm64@1.0.0-rc.2': resolution: {integrity: sha512-AGV80viZ4Hil4C16GFH+PSwq10jclV9oyRFhD+5HdowPOCJ+G+99N5AClQvMkUMIahTY8cX0SQpKEEWcCg6fSA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.0-rc.1': - resolution: {integrity: sha512-YzJdn08kSOXnj85ghHauH2iHpOJ6eSmstdRTLyaziDcUxe9SyQJgGyx/5jDIhDvtOcNvMm2Ju7m19+S/Rm1jFg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [darwin] - '@rolldown/binding-darwin-arm64@1.0.0-rc.2': resolution: {integrity: sha512-PYR+PQu1mMmQiiKHN2JiOctvH32Xc/Mf+Su2RSmWtC9BbIqlqsVWjbulnShk0imjRim0IsbkMMCN5vYQwiuqaA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-rc.1': - resolution: {integrity: sha512-cIvAbqM+ZVV6lBSKSBtlNqH5iCiW933t1q8j0H66B3sjbe8AxIRetVqfGgcHcJtMzBIkIALlL9fcDrElWLJQcQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-rc.2': resolution: {integrity: sha512-X2G36Z6oh5ynoYpE2JAyG+uQ4kO/3N7XydM/I98FNk8VVgDKjajFF+v7TXJ2FMq6xa7Xm0UIUKHW2MRQroqoUA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.0-rc.1': - resolution: {integrity: sha512-rVt+B1B/qmKwCl1XD02wKfgh3vQPXRXdB/TicV2w6g7RVAM1+cZcpigwhLarqiVCxDObFZ7UgXCxPC7tpDoRog==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [freebsd] - '@rolldown/binding-freebsd-x64@1.0.0-rc.2': resolution: {integrity: sha512-XpiFTsl9qjiDfrmJF6CE3dgj1nmSbxUIT+p2HIbXV6WOj/32btO8FKkWSsOphUwVinEt3R8HVkVrcLtFNruMMQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.1': - resolution: {integrity: sha512-69YKwJJBOFprQa1GktPgbuBOfnn+EGxu8sBJ1TjPER+zhSpYeaU4N07uqmyBiksOLGXsMegymuecLobfz03h8Q==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.2': resolution: {integrity: sha512-zjYZ99e47Wlygs4hW+sQ+kshlO8ake9OoY2ecnJ9cwpDGiiIB9rQ3LgP3kt8j6IeVyMSksu//VEhc8Mrd1lRIw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.1': - resolution: {integrity: sha512-9JDhHUf3WcLfnViFWm+TyorqUtnSAHaCzlSNmMOq824prVuuzDOK91K0Hl8DUcEb9M5x2O+d2/jmBMsetRIn3g==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.2': resolution: {integrity: sha512-Piso04EZ9IHV1aZSsLQVMOPTiCq4Ps2UPL3pchjNXHGJGFiB9U42s22LubPaEBFS+i6tCawS5EarIwex1zC4BA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.1': - resolution: {integrity: sha512-UvApLEGholmxw/HIwmUnLq3CwdydbhaHHllvWiCTNbyGom7wTwOtz5OAQbAKZYyiEOeIXZNPkM7nA4Dtng7CLw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.2': resolution: {integrity: sha512-OwJCeMZlmjKsN9pfJfTmqYpe3JC+L6RO87+hu9ajRLr1Lh6cM2FRQ8e48DLRyRDww8Ti695XQvqEANEMmsuzLw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.1': - resolution: {integrity: sha512-uVctNgZHiGnJx5Fij7wHLhgw4uyZBVi6mykeWKOqE7bVy9Hcxn0fM/IuqdMwk6hXlaf9fFShDTFz2+YejP+x0A==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.2': resolution: {integrity: sha512-uQqBmA8dTWbKvfqbeSsXNUssRGfdgQCc0hkGfhQN7Pf85wG2h0Fd/z2d+ykyT4YbcsjQdgEGxBNsg3v4ekOuEA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@rolldown/binding-linux-x64-musl@1.0.0-rc.1': - resolution: {integrity: sha512-T6Eg0xWwcxd/MzBcuv4Z37YVbUbJxy5cMNnbIt/Yr99wFwli30O4BPlY8hKeGyn6lWNtU0QioBS46lVzDN38bg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - '@rolldown/binding-linux-x64-musl@1.0.0-rc.2': resolution: {integrity: sha512-ItZabVsICCYWHbP+jcAgNzjPAYg5GIVQp/NpqT6iOgWctaMYtobClc5m0kNtxwqfNrLXoyt998xUey4AvcxnGQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@rolldown/binding-openharmony-arm64@1.0.0-rc.1': - resolution: {integrity: sha512-PuGZVS2xNJyLADeh2F04b+Cz4NwvpglbtWACgrDOa5YDTEHKwmiTDjoD5eZ9/ptXtcpeFrMqD2H4Zn33KAh1Eg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [openharmony] - '@rolldown/binding-openharmony-arm64@1.0.0-rc.2': resolution: {integrity: sha512-U4UYANwafcMXSUC0VqdrqTAgCo2v8T7SiuTYwVFXgia0KOl8jiv3okwCFqeZNuw/G6EWDiqhT8kK1DLgyLsxow==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.0-rc.1': - resolution: {integrity: sha512-2mOxY562ihHlz9lEXuaGEIDCZ1vI+zyFdtsoa3M62xsEunDXQE+DVPO4S4x5MPK9tKulG/aFcA/IH5eVN257Cw==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - '@rolldown/binding-wasm32-wasi@1.0.0-rc.2': resolution: {integrity: sha512-ZIWCjQsMon4tqRoao0Vzowjwx0cmFT3kublh2nNlgeasIJMWlIGHtr0d4fPypm57Rqx4o1h4L8SweoK2q6sMGA==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.1': - resolution: {integrity: sha512-oQVOP5cfAWZwRD0Q3nGn/cA9FW3KhMMuQ0NIndALAe6obqjLhqYVYDiGGRGrxvnjJsVbpLwR14gIUYnpIcHR1g==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [win32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.2': resolution: {integrity: sha512-NIo7vwRUPEzZ4MuZGr5YbDdjJ84xdiG+YYf8ZBfTgvIsk9wM0sZamJPEXvaLkzVIHpOw5uqEHXS85Gqqb7aaqQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.1': - resolution: {integrity: sha512-Ydsxxx++FNOuov3wCBPaYjZrEvKOOGq3k+BF4BPridhg2pENfitSRD2TEuQ8i33bp5VptuNdC9IzxRKU031z5A==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.2': resolution: {integrity: sha512-bLKzyLFbvngeNPZocuLo3LILrKwCrkyMxmRXs6fZYDrvh7cyZRw9v56maDL9ipPas0OOmQK1kAKYwvTs30G21Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rolldown/pluginutils@1.0.0-rc.1': - resolution: {integrity: sha512-UTBjtTxVOhodhzFVp/ayITaTETRHPUPYZPXQe0WU0wOgxghMojXxYjOiPOauKIYNWJAWS2fd7gJgGQK8GU8vDA==} - '@rolldown/pluginutils@1.0.0-rc.2': resolution: {integrity: sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==} @@ -2649,9 +2536,6 @@ packages: '@types/http-errors@2.0.5': resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} - '@types/jsesc@2.5.1': - resolution: {integrity: sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==} - '@types/jsonwebtoken@9.0.10': resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==} @@ -2928,10 +2812,6 @@ packages: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} - ansis@4.2.0: - resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} - engines: {node: '>=14'} - any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -2972,10 +2852,6 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} - ast-kit@3.0.0-beta.1: - resolution: {integrity: sha512-trmleAnZ2PxN/loHWVhhx1qeOHSRXq4TDsBBxq3GqeJitfk3+jTQ+v/C1km/KYq9M7wKqCewMh+/NAvVH7m+bw==} - engines: {node: '>=20.19.0'} - ast-types@0.13.4: resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} engines: {node: '>=4'} @@ -3041,9 +2917,6 @@ packages: bignumber.js@9.3.1: resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} - birpc@4.0.0: - resolution: {integrity: sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==} - bluebird@3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} @@ -3083,10 +2956,6 @@ packages: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - cacheable@2.3.2: resolution: {integrity: sha512-w+ZuRNmex9c1TR9RcsxbfTKCjSL0rh1WA5SABbrWprIHeNBdmyQLSYonlDy9gpD+63XT8DgZ/wNh1Smvc9WnJA==} @@ -3287,9 +3156,6 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} - defu@6.1.4: - resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} - degenerator@5.0.1: resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} engines: {node: '>= 14'} @@ -3343,15 +3209,6 @@ packages: resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} engines: {node: '>=12'} - dts-resolver@2.1.3: - resolution: {integrity: sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==} - engines: {node: '>=20.19.0'} - peerDependencies: - oxc-resolver: '>=11.0.0' - peerDependenciesMeta: - oxc-resolver: - optional: true - dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -3377,10 +3234,6 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - empathic@2.0.0: - resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} - engines: {node: '>=14'} - encodeurl@2.0.0: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} @@ -3719,9 +3572,6 @@ packages: resolution: {integrity: sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==} engines: {node: '>=16.9.0'} - hookable@6.0.1: - resolution: {integrity: sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw==} - hookified@1.15.0: resolution: {integrity: sha512-51w+ZZGt7Zw5q7rM3nC4t3aLn/xvKDETsXqMczndvwyVQhAHfUmUuFBRFcos8Iyebtk7OAE9dL26wFNzZVVOkw==} @@ -3781,10 +3631,6 @@ packages: import-in-the-middle@2.0.6: resolution: {integrity: sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw==} - import-without-cache@0.2.5: - resolution: {integrity: sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A==} - engines: {node: '>=20.19.0'} - inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -3892,11 +3738,6 @@ packages: jsbn@0.1.1: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} - jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} - hasBin: true - json-bigint@1.0.0: resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} @@ -4698,9 +4539,6 @@ packages: resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} engines: {node: '>=0.6'} - quansync@1.0.0: - resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} - quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} @@ -4787,30 +4625,6 @@ packages: resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} hasBin: true - rolldown-plugin-dts@0.21.8: - resolution: {integrity: sha512-czOQoe6eZpRKCv9P+ijO/v4A2TwQjASAV7qezUxRZSua06Yb2REPIZv/mbfXiZDP1ZfI7Ez7re7qfK9F9u0Epw==} - engines: {node: '>=20.19.0'} - peerDependencies: - '@ts-macro/tsc': ^0.3.6 - '@typescript/native-preview': '>=7.0.0-dev.20250601.1' - rolldown: ^1.0.0-beta.57 - typescript: ^5.0.0 - vue-tsc: ~3.2.0 - peerDependenciesMeta: - '@ts-macro/tsc': - optional: true - '@typescript/native-preview': - optional: true - typescript: - optional: true - vue-tsc: - optional: true - - rolldown@1.0.0-rc.1: - resolution: {integrity: sha512-M3AeZjYE6UclblEf531Hch0WfVC/NOL43Cc+WdF3J50kk5/fvouHhDumSGTh0oRjbZ8C4faaVr5r6Nx1xMqDGg==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - rolldown@1.0.0-rc.2: resolution: {integrity: sha512-1g/8Us9J8sgJGn3hZfBecX1z4U3y5KO7V/aV2U1M/9UUzLNqHA8RfFQ/NPT7HLxOIldyIgrcjaYTRvA81KhJIg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -5134,38 +4948,9 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - tree-kill@1.2.2: - resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} - hasBin: true - ts-algebra@2.0.0: resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==} - tsdown@0.20.1: - resolution: {integrity: sha512-Wo1BzqNQVZ6SFQV8rjQBwMmNubO+yV3F+vp2WNTjEaS4S5CT1C1dHtUbeFMrCEasZpGy5w6TshpehNnfTe8QBQ==} - engines: {node: '>=20.19.0'} - hasBin: true - peerDependencies: - '@arethetypeswrong/core': ^0.18.1 - '@vitejs/devtools': '*' - publint: ^0.3.0 - typescript: ^5.0.0 - unplugin-lightningcss: ^0.4.0 - unplugin-unused: ^0.5.0 - peerDependenciesMeta: - '@arethetypeswrong/core': - optional: true - '@vitejs/devtools': - optional: true - publint: - optional: true - typescript: - optional: true - unplugin-lightningcss: - optional: true - unplugin-unused: - optional: true - tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -5219,9 +5004,6 @@ packages: resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} engines: {node: '>=18'} - unconfig-core@7.4.2: - resolution: {integrity: sha512-VgPCvLWugINbXvMQDf8Jh0mlbvNjNC6eSUziHsBCMpxR05OPrNrvDnyatdMjRgcHaaNsCqz+wjNXxNw1kRLHUg==} - undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} @@ -5246,16 +5028,6 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - unrun@0.2.26: - resolution: {integrity: sha512-A3DQLBcDyTui4Hlaoojkldg+8x+CIR+tcSHY0wzW+CgB4X/DNyH58jJpXp1B/EkE+yG6tU8iH1mWsLtwFU3IQg==} - engines: {node: '>=20.19.0'} - hasBin: true - peerDependencies: - synckit: ^0.11.11 - peerDependenciesMeta: - synckit: - optional: true - uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -5979,31 +5751,14 @@ snapshots: jsonwebtoken: 9.0.3 uuid: 8.3.2 - '@babel/generator@8.0.0-beta.4': - dependencies: - '@babel/parser': 8.0.0-beta.4 - '@babel/types': 8.0.0-beta.4 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - '@types/jsesc': 2.5.1 - jsesc: 3.1.0 - '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-string-parser@8.0.0-beta.4': {} - '@babel/helper-validator-identifier@7.28.5': {} - '@babel/helper-validator-identifier@8.0.0-beta.4': {} - '@babel/parser@7.28.6': dependencies: '@babel/types': 7.28.6 - '@babel/parser@8.0.0-beta.4': - dependencies: - '@babel/types': 8.0.0-beta.4 - '@babel/runtime@7.28.6': {} '@babel/types@7.28.6': @@ -6011,11 +5766,6 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@babel/types@8.0.0-beta.4': - dependencies: - '@babel/helper-string-parser': 8.0.0-beta.4 - '@babel/helper-validator-identifier': 8.0.0-beta.4 - '@bcoe/v8-coverage@1.0.2': {} '@borewit/text-codec@0.2.1': {} @@ -6403,11 +6153,6 @@ snapshots: dependencies: minipass: 7.1.2 - '@jridgewell/gen-mapping@0.3.13': - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.31 - '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/sourcemap-codec@1.5.5': {} @@ -6473,7 +6218,7 @@ snapshots: dependencies: '@types/node': 24.10.9 optionalDependencies: - axios: 1.13.4 + axios: 1.13.4(debug@4.4.3) transitivePeerDependencies: - debug @@ -6670,7 +6415,7 @@ snapshots: '@azure/core-auth': 1.10.1 '@azure/msal-node': 3.8.6 '@microsoft/agents-activity': 1.2.3 - axios: 1.13.4 + axios: 1.13.4(debug@4.4.3) jsonwebtoken: 9.0.3 jwks-rsa: 3.2.2 object-path: 0.11.8 @@ -7171,8 +6916,6 @@ snapshots: '@opentelemetry/semantic-conventions@1.39.0': {} - '@oxc-project/types@0.110.0': {} - '@oxc-project/types@0.111.0': {} '@oxfmt/darwin-arm64@0.27.0': @@ -7271,10 +7014,6 @@ snapshots: '@protobufjs/utf8@1.1.0': {} - '@quansync/fs@1.0.0': - dependencies: - quansync: 1.0.0 - '@reflink/reflink-darwin-arm64@0.1.19': optional: true @@ -7311,90 +7050,47 @@ snapshots: '@reflink/reflink-win32-x64-msvc': 0.1.19 optional: true - '@rolldown/binding-android-arm64@1.0.0-rc.1': - optional: true - '@rolldown/binding-android-arm64@1.0.0-rc.2': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-rc.1': - optional: true - '@rolldown/binding-darwin-arm64@1.0.0-rc.2': optional: true - '@rolldown/binding-darwin-x64@1.0.0-rc.1': - optional: true - '@rolldown/binding-darwin-x64@1.0.0-rc.2': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-rc.1': - optional: true - '@rolldown/binding-freebsd-x64@1.0.0-rc.2': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.1': - optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.2': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.1': - optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.2': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.1': - optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-rc.2': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.1': - optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-rc.2': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-rc.1': - optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-rc.2': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-rc.1': - optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-rc.2': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.1': - dependencies: - '@napi-rs/wasm-runtime': 1.1.1 - optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.2': dependencies: '@napi-rs/wasm-runtime': 1.1.1 optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.1': - optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.2': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.1': - optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-rc.2': optional: true - '@rolldown/pluginutils@1.0.0-rc.1': {} - '@rolldown/pluginutils@1.0.0-rc.2': {} '@rollup/rollup-android-arm-eabi@4.57.1': @@ -7502,7 +7198,7 @@ snapshots: '@slack/types': 2.19.0 '@slack/web-api': 7.13.0 '@types/express': 5.0.6 - axios: 1.13.4 + axios: 1.13.4(debug@4.4.3) express: 5.2.1 path-to-regexp: 8.3.0 raw-body: 3.0.2 @@ -7548,7 +7244,7 @@ snapshots: '@slack/types': 2.19.0 '@types/node': 25.1.0 '@types/retry': 0.12.0 - axios: 1.13.4 + axios: 1.13.4(debug@4.4.3) eventemitter3: 5.0.4 form-data: 4.0.5 is-electron: 2.2.2 @@ -8006,8 +7702,6 @@ snapshots: '@types/http-errors@2.0.5': {} - '@types/jsesc@2.5.1': {} - '@types/jsonwebtoken@9.0.10': dependencies: '@types/ms': 2.1.0 @@ -8351,8 +8045,6 @@ snapshots: ansi-styles@6.2.3: {} - ansis@4.2.0: {} - any-promise@1.3.0: {} apache-arrow@18.1.0: @@ -8390,12 +8082,6 @@ snapshots: assertion-error@2.0.1: {} - ast-kit@3.0.0-beta.1: - dependencies: - '@babel/parser': 8.0.0-beta.4 - estree-walker: 3.0.3 - pathe: 2.0.3 - ast-types@0.13.4: dependencies: tslib: 2.8.1 @@ -8442,14 +8128,6 @@ snapshots: aws4@1.13.2: {} - axios@1.13.4: - dependencies: - follow-redirects: 1.15.11 - form-data: 4.0.5 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - axios@1.13.4(debug@4.4.3): dependencies: follow-redirects: 1.15.11(debug@4.4.3) @@ -8476,8 +8154,6 @@ snapshots: bignumber.js@9.3.1: {} - birpc@4.0.0: {} - bluebird@3.7.2: {} body-parser@1.20.4: @@ -8534,8 +8210,6 @@ snapshots: bytes@3.1.2: {} - cac@6.7.14: {} - cacheable@2.3.2: dependencies: '@cacheable/memory': 2.0.7 @@ -8722,8 +8396,6 @@ snapshots: deepmerge@4.3.1: {} - defu@6.1.4: {} - degenerator@5.0.1: dependencies: ast-types: 0.13.4 @@ -8770,8 +8442,6 @@ snapshots: dotenv@17.2.3: {} - dts-resolver@2.1.3: {} - dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -8797,8 +8467,6 @@ snapshots: emoji-regex@9.2.2: {} - empathic@2.0.0: {} - encodeurl@2.0.0: {} entities@4.5.0: {} @@ -9025,8 +8693,6 @@ snapshots: flatbuffers@24.12.23: {} - follow-redirects@1.15.11: {} - follow-redirects@1.15.11(debug@4.4.3): optionalDependencies: debug: 4.4.3 @@ -9241,8 +8907,6 @@ snapshots: hono@4.11.4: optional: true - hookable@6.0.1: {} - hookified@1.15.0: {} html-escaper@2.0.2: {} @@ -9322,8 +8986,6 @@ snapshots: cjs-module-lexer: 2.2.0 module-details-from-path: 1.0.4 - import-without-cache@0.2.5: {} - inherits@2.0.4: {} ini@1.3.8: {} @@ -9432,8 +9094,6 @@ snapshots: jsbn@0.1.1: {} - jsesc@3.1.0: {} - json-bigint@1.0.0: dependencies: bignumber.js: 9.3.1 @@ -10283,8 +9943,6 @@ snapshots: qs@6.5.3: {} - quansync@1.0.0: {} - quick-format-unescaped@4.0.4: {} range-parser@1.2.1: {} @@ -10394,42 +10052,6 @@ snapshots: dependencies: glob: 10.5.0 - rolldown-plugin-dts@0.21.8(@typescript/native-preview@7.0.0-dev.20260130.1)(rolldown@1.0.0-rc.1)(typescript@5.9.3): - dependencies: - '@babel/generator': 8.0.0-beta.4 - '@babel/parser': 8.0.0-beta.4 - '@babel/types': 8.0.0-beta.4 - ast-kit: 3.0.0-beta.1 - birpc: 4.0.0 - dts-resolver: 2.1.3 - get-tsconfig: 4.13.1 - obug: 2.1.1 - rolldown: 1.0.0-rc.1 - optionalDependencies: - '@typescript/native-preview': 7.0.0-dev.20260130.1 - typescript: 5.9.3 - transitivePeerDependencies: - - oxc-resolver - - rolldown@1.0.0-rc.1: - dependencies: - '@oxc-project/types': 0.110.0 - '@rolldown/pluginutils': 1.0.0-rc.1 - optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-rc.1 - '@rolldown/binding-darwin-arm64': 1.0.0-rc.1 - '@rolldown/binding-darwin-x64': 1.0.0-rc.1 - '@rolldown/binding-freebsd-x64': 1.0.0-rc.1 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.1 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.1 - '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.1 - '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.1 - '@rolldown/binding-linux-x64-musl': 1.0.0-rc.1 - '@rolldown/binding-openharmony-arm64': 1.0.0-rc.1 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.1 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.1 - '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.1 - rolldown@1.0.0-rc.2: dependencies: '@oxc-project/types': 0.111.0 @@ -10865,37 +10487,8 @@ snapshots: tr46@0.0.3: {} - tree-kill@1.2.2: {} - ts-algebra@2.0.0: {} - tsdown@0.20.1(@typescript/native-preview@7.0.0-dev.20260130.1)(typescript@5.9.3): - dependencies: - ansis: 4.2.0 - cac: 6.7.14 - defu: 6.1.4 - empathic: 2.0.0 - hookable: 6.0.1 - import-without-cache: 0.2.5 - obug: 2.1.1 - picomatch: 4.0.3 - rolldown: 1.0.0-rc.1 - rolldown-plugin-dts: 0.21.8(@typescript/native-preview@7.0.0-dev.20260130.1)(rolldown@1.0.0-rc.1)(typescript@5.9.3) - semver: 7.7.3 - tinyexec: 1.0.2 - tinyglobby: 0.2.15 - tree-kill: 1.2.2 - unconfig-core: 7.4.2 - unrun: 0.2.26 - optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - '@ts-macro/tsc' - - '@typescript/native-preview' - - oxc-resolver - - synckit - - vue-tsc - tslib@2.8.1: {} tslog@4.10.2: {} @@ -10938,11 +10531,6 @@ snapshots: uint8array-extras@1.5.0: {} - unconfig-core@7.4.2: - dependencies: - '@quansync/fs': 1.0.0 - quansync: 1.0.0 - undici-types@6.21.0: {} undici-types@7.16.0: {} @@ -10957,10 +10545,6 @@ snapshots: unpipe@1.0.0: {} - unrun@0.2.26: - dependencies: - rolldown: 1.0.0-rc.1 - uri-js@4.4.1: dependencies: punycode: 2.3.1 diff --git a/scripts/e2e/gateway-network-docker.sh b/scripts/e2e/gateway-network-docker.sh index d24c456126..e0faf0115e 100644 --- a/scripts/e2e/gateway-network-docker.sh +++ b/scripts/e2e/gateway-network-docker.sh @@ -31,7 +31,7 @@ echo "Starting gateway container..." -e "OPENCLAW_SKIP_CRON=1" \ -e "OPENCLAW_SKIP_CANVAS_HOST=1" \ "$IMAGE_NAME" \ - bash -lc "node dist/index.mjs gateway --port $PORT --bind lan --allow-unconfigured > /tmp/gateway-net-e2e.log 2>&1" + bash -lc "node dist/index.js gateway --port $PORT --bind lan --allow-unconfigured > /tmp/gateway-net-e2e.log 2>&1" echo "Waiting for gateway to come up..." for _ in $(seq 1 20); do diff --git a/scripts/e2e/onboard-docker.sh b/scripts/e2e/onboard-docker.sh index 8cbf8f9c95..6e9a74ced6 100755 --- a/scripts/e2e/onboard-docker.sh +++ b/scripts/e2e/onboard-docker.sh @@ -83,7 +83,7 @@ TRASH } start_gateway() { - node dist/index.mjs gateway --port 18789 --bind loopback --allow-unconfigured > /tmp/gateway-e2e.log 2>&1 & + node dist/index.js gateway --port 18789 --bind loopback --allow-unconfigured > /tmp/gateway-e2e.log 2>&1 & GATEWAY_PID="$!" } @@ -185,7 +185,7 @@ TRASH local validate_fn="${4:-}" # Default onboarding command wrapper. - run_wizard_cmd "$case_name" "$home_dir" "node dist/index.mjs onboard $ONBOARD_FLAGS" "$send_fn" true "$validate_fn" + run_wizard_cmd "$case_name" "$home_dir" "node dist/index.js onboard $ONBOARD_FLAGS" "$send_fn" true "$validate_fn" } make_home() { @@ -268,7 +268,7 @@ TRASH home_dir="$(make_home local-basic)" export HOME="$home_dir" mkdir -p "$HOME" - node dist/index.mjs onboard \ + node dist/index.js onboard \ --non-interactive \ --accept-risk \ --flow quickstart \ @@ -345,7 +345,7 @@ NODE export HOME="$home_dir" mkdir -p "$HOME" # Smoke test non-interactive remote config write. - node dist/index.mjs onboard --non-interactive --accept-risk \ + node dist/index.js onboard --non-interactive --accept-risk \ --mode remote \ --remote-url ws://gateway.local:18789 \ --remote-token remote-token \ @@ -398,7 +398,7 @@ NODE } JSON - node dist/index.mjs onboard \ + node dist/index.js onboard \ --non-interactive \ --accept-risk \ --flow quickstart \ @@ -441,7 +441,7 @@ NODE local home_dir home_dir="$(make_home channels)" # Channels-only configure flow. - run_wizard_cmd channels "$home_dir" "node dist/index.mjs configure --section channels" send_channels_flow + run_wizard_cmd channels "$home_dir" "node dist/index.js configure --section channels" send_channels_flow config_path="$HOME/.openclaw/openclaw.json" assert_file "$config_path" @@ -492,7 +492,7 @@ NODE } JSON - run_wizard_cmd skills "$home_dir" "node dist/index.mjs configure --section skills" send_skills_flow + run_wizard_cmd skills "$home_dir" "node dist/index.js configure --section skills" send_skills_flow config_path="$HOME/.openclaw/openclaw.json" assert_file "$config_path" diff --git a/scripts/e2e/plugins-docker.sh b/scripts/e2e/plugins-docker.sh index 6668b5951a..5b0a9c5ae4 100755 --- a/scripts/e2e/plugins-docker.sh +++ b/scripts/e2e/plugins-docker.sh @@ -29,7 +29,7 @@ module.exports = { }; JS - node dist/index.mjs plugins list --json > /tmp/plugins.json + node dist/index.js plugins list --json > /tmp/plugins.json node - <<'"'"'NODE'"'"' const fs = require("node:fs"); @@ -81,8 +81,8 @@ module.exports = { JS tar -czf /tmp/demo-plugin-tgz.tgz -C "$pack_dir" package - node dist/index.mjs plugins install /tmp/demo-plugin-tgz.tgz - node dist/index.mjs plugins list --json > /tmp/plugins2.json + node dist/index.js plugins install /tmp/demo-plugin-tgz.tgz + node dist/index.js plugins list --json > /tmp/plugins2.json node - <<'"'"'NODE'"'"' const fs = require("node:fs"); @@ -118,8 +118,8 @@ module.exports = { }; JS - node dist/index.mjs plugins install "$dir_plugin" - node dist/index.mjs plugins list --json > /tmp/plugins3.json + node dist/index.js plugins install "$dir_plugin" + node dist/index.js plugins list --json > /tmp/plugins3.json node - <<'"'"'NODE'"'"' const fs = require("node:fs"); @@ -156,8 +156,8 @@ module.exports = { }; JS - node dist/index.mjs plugins install "file:$file_pack_dir/package" - node dist/index.mjs plugins list --json > /tmp/plugins4.json + node dist/index.js plugins install "file:$file_pack_dir/package" + node dist/index.js plugins list --json > /tmp/plugins4.json node - <<'"'"'NODE'"'"' const fs = require("node:fs"); diff --git a/scripts/package-mac-app.sh b/scripts/package-mac-app.sh index 7f6e904e12..be1eb09c4f 100755 --- a/scripts/package-mac-app.sh +++ b/scripts/package-mac-app.sh @@ -110,8 +110,8 @@ merge_framework_machos() { echo "📦 Ensuring deps (pnpm install)" (cd "$ROOT_DIR" && pnpm install --no-frozen-lockfile --config.node-linker=hoisted) if [[ "${SKIP_TSC:-0}" != "1" ]]; then - echo "📦 Building JS (pnpm tsdown)" - (cd "$ROOT_DIR" && pnpm tsdown) + echo "📦 Building JS (pnpm tsc)" + (cd "$ROOT_DIR" && pnpm tsc -p tsconfig.json --noEmit false) else echo "📦 Skipping TS build (SKIP_TSC=1)" fi diff --git a/scripts/postinstall.js b/scripts/postinstall.js index d262aa3c7b..f1432b1532 100644 --- a/scripts/postinstall.js +++ b/scripts/postinstall.js @@ -1,34 +1,36 @@ -import fs from "node:fs"; -import path from "node:path"; -import { spawnSync } from "node:child_process"; -import { fileURLToPath } from "node:url"; -import { setupGitHooks } from "./setup-git-hooks.js"; +import fs from 'node:fs'; +import path from 'node:path'; +import { spawnSync } from 'node:child_process'; +import { fileURLToPath } from 'node:url'; +import { setupGitHooks } from './setup-git-hooks.js'; -function detectPackageManager(ua = process.env.npm_config_user_agent ?? "") { +function detectPackageManager(ua = process.env.npm_config_user_agent ?? '') { // Examples: // - "pnpm/10.23.0 npm/? node/v22.21.1 darwin arm64" // - "npm/10.9.4 node/v22.12.0 linux x64" // - "bun/1.2.2" const normalized = String(ua).trim(); - if (normalized.startsWith("pnpm/")) return "pnpm"; - if (normalized.startsWith("bun/")) return "bun"; - if (normalized.startsWith("npm/")) return "npm"; - if (normalized.startsWith("yarn/")) return "yarn"; - return "unknown"; + if (normalized.startsWith('pnpm/')) return 'pnpm'; + if (normalized.startsWith('bun/')) return 'bun'; + if (normalized.startsWith('npm/')) return 'npm'; + if (normalized.startsWith('yarn/')) return 'yarn'; + return 'unknown'; } -function shouldApplyPnpmPatchedDependenciesFallback(pm = detectPackageManager()) { +function shouldApplyPnpmPatchedDependenciesFallback( + pm = detectPackageManager(), +) { // pnpm already applies pnpm.patchedDependencies itself; re-applying would fail. - return pm !== "pnpm"; + return pm !== 'pnpm'; } function getRepoRoot() { const here = path.dirname(fileURLToPath(import.meta.url)); - return path.resolve(here, ".."); + return path.resolve(here, '..'); } function ensureExecutable(targetPath) { - if (process.platform === "win32") return; + if (process.platform === 'win32') return; if (!fs.existsSync(targetPath)) return; try { const mode = fs.statSync(targetPath).mode & 0o777; @@ -40,29 +42,32 @@ function ensureExecutable(targetPath) { } function hasGit(repoRoot) { - const result = spawnSync("git", ["--version"], { cwd: repoRoot, stdio: "ignore" }); + const result = spawnSync('git', ['--version'], { + cwd: repoRoot, + stdio: 'ignore', + }); return result.status === 0; } function extractPackageName(key) { - if (key.startsWith("@")) { - const idx = key.indexOf("@", 1); + if (key.startsWith('@')) { + const idx = key.indexOf('@', 1); if (idx === -1) return key; return key.slice(0, idx); } - const idx = key.lastIndexOf("@"); + const idx = key.lastIndexOf('@'); if (idx <= 0) return key; return key.slice(0, idx); } function stripPrefix(p) { - if (p.startsWith("a/") || p.startsWith("b/")) return p.slice(2); + if (p.startsWith('a/') || p.startsWith('b/')) return p.slice(2); return p; } function parseRange(segment) { // segment: "-12,5" or "+7" - const [startRaw, countRaw] = segment.slice(1).split(","); + const [startRaw, countRaw] = segment.slice(1).split(','); const start = Number.parseInt(startRaw, 10); const count = countRaw ? Number.parseInt(countRaw, 10) : 1; if (Number.isNaN(start) || Number.isNaN(count)) { @@ -72,12 +77,12 @@ function parseRange(segment) { } function parsePatch(patchText) { - const lines = patchText.split("\n"); + const lines = patchText.split('\n'); const files = []; let i = 0; while (i < lines.length) { - if (!lines[i].startsWith("diff --git ")) { + if (!lines[i].startsWith('diff --git ')) { i += 1; continue; } @@ -86,20 +91,22 @@ function parsePatch(patchText) { i += 1; // Skip index line(s) - while (i < lines.length && lines[i].startsWith("index ")) i += 1; + while (i < lines.length && lines[i].startsWith('index ')) i += 1; - if (i < lines.length && lines[i].startsWith("--- ")) { + if (i < lines.length && lines[i].startsWith('--- ')) { file.oldPath = stripPrefix(lines[i].slice(4).trim()); i += 1; } - if (i < lines.length && lines[i].startsWith("+++ ")) { + if (i < lines.length && lines[i].startsWith('+++ ')) { file.newPath = stripPrefix(lines[i].slice(4).trim()); i += 1; } - while (i < lines.length && lines[i].startsWith("@@")) { + while (i < lines.length && lines[i].startsWith('@@')) { const header = lines[i]; - const match = /^@@\s+(-\d+(?:,\d+)?)\s+(\+\d+(?:,\d+)?)\s+@@/.exec(header); + const match = /^@@\s+(-\d+(?:,\d+)?)\s+(\+\d+(?:,\d+)?)\s+@@/.exec( + header, + ); if (!match) throw new Error(`invalid hunk header: ${header}`); const oldRange = parseRange(match[1]); const newRange = parseRange(match[2]); @@ -108,12 +115,12 @@ function parsePatch(patchText) { const hunkLines = []; while (i < lines.length) { const line = lines[i]; - if (line.startsWith("@@") || line.startsWith("diff --git ")) break; - if (line === "") { + if (line.startsWith('@@') || line.startsWith('diff --git ')) break; + if (line === '') { i += 1; continue; } - if (line.startsWith("\\ No newline at end of file")) { + if (line.startsWith('\\ No newline at end of file')) { i += 1; continue; } @@ -142,16 +149,16 @@ function readFileLines(targetPath) { if (!fs.existsSync(targetPath)) { throw new Error(`target file missing: ${targetPath}`); } - const raw = fs.readFileSync(targetPath, "utf-8"); - const hasTrailingNewline = raw.endsWith("\n"); - const parts = raw.split("\n"); + const raw = fs.readFileSync(targetPath, 'utf-8'); + const hasTrailingNewline = raw.endsWith('\n'); + const parts = raw.split('\n'); if (hasTrailingNewline) parts.pop(); return { lines: parts, hasTrailingNewline }; } function writeFileLines(targetPath, lines, hadTrailingNewline) { - const content = lines.join("\n") + (hadTrailingNewline ? "\n" : ""); - fs.writeFileSync(targetPath, content, "utf-8"); + const content = lines.join('\n') + (hadTrailingNewline ? '\n' : ''); + fs.writeFileSync(targetPath, content, 'utf-8'); } function applyHunk(lines, hunk, offset) { @@ -159,7 +166,7 @@ function applyHunk(lines, hunk, offset) { const expected = []; for (const raw of hunk.lines) { const marker = raw[0]; - if (marker === " " || marker === "+") { + if (marker === ' ' || marker === '+') { expected.push(raw.slice(1)); } } @@ -180,21 +187,21 @@ function applyHunk(lines, hunk, offset) { for (const raw of hunk.lines) { const marker = raw[0]; const text = raw.slice(1); - if (marker === " ") { + if (marker === ' ') { if (lines[cursor] !== text) { throw new Error( - `context mismatch at line ${cursor + 1}: expected "${text}", found "${lines[cursor] ?? ""}"`, + `context mismatch at line ${cursor + 1}: expected "${text}", found "${lines[cursor] ?? ''}"`, ); } cursor += 1; - } else if (marker === "-") { + } else if (marker === '-') { if (lines[cursor] !== text) { throw new Error( - `delete mismatch at line ${cursor + 1}: expected "${text}", found "${lines[cursor] ?? ""}"`, + `delete mismatch at line ${cursor + 1}: expected "${text}", found "${lines[cursor] ?? ''}"`, ); } lines.splice(cursor, 1); - } else if (marker === "+") { + } else if (marker === '+') { lines.splice(cursor, 0, text); cursor += 1; } else { @@ -207,11 +214,11 @@ function applyHunk(lines, hunk, offset) { } function applyPatchToFile(targetDir, filePatch) { - if (filePatch.newPath === "/dev/null") { + if (filePatch.newPath === '/dev/null') { // deletion not needed for our patches return; } - const relPath = stripPrefix(filePatch.newPath ?? filePatch.oldPath ?? ""); + const relPath = stripPrefix(filePatch.newPath ?? filePatch.oldPath ?? ''); const targetPath = path.join(targetDir, relPath); const { lines, hasTrailingNewline } = readFileLines(targetPath); @@ -225,7 +232,10 @@ function applyPatchToFile(targetDir, filePatch) { function applyPatchSet({ patchText, targetDir }) { let resolvedTarget = path.resolve(targetDir); - if (!fs.existsSync(resolvedTarget) || !fs.statSync(resolvedTarget).isDirectory()) { + if ( + !fs.existsSync(resolvedTarget) || + !fs.statSync(resolvedTarget).isDirectory() + ) { console.warn(`[postinstall] skip missing target: ${resolvedTarget}`); return; } @@ -244,28 +254,28 @@ function applyPatchFile({ patchPath, targetDir }) { if (!fs.existsSync(absPatchPath)) { throw new Error(`missing patch: ${absPatchPath}`); } - const patchText = fs.readFileSync(absPatchPath, "utf-8"); + const patchText = fs.readFileSync(absPatchPath, 'utf-8'); applyPatchSet({ patchText, targetDir }); } function trySetupCompletion(repoRoot) { // Skip in CI or if explicitly disabled if (process.env.CI || process.env.OPENCLAW_SKIP_COMPLETION_SETUP) return; - - const binPath = path.join(repoRoot, "openclaw.mjs"); + + const binPath = path.join(repoRoot, 'openclaw.mjs'); if (!fs.existsSync(binPath)) return; - + // In development, dist might not exist yet during postinstall - const distEntry = path.join(repoRoot, "dist", "index.js"); + const distEntry = path.join(repoRoot, 'dist', 'index.js'); if (!fs.existsSync(distEntry)) return; try { // Run with OPENCLAW_SKIP_POSTINSTALL to avoid any weird recursion, // though distinct from this script. - spawnSync(process.execPath, [binPath, "completion", "--install", "--yes"], { + spawnSync(process.execPath, [binPath, 'completion', '--install', '--yes'], { cwd: repoRoot, - stdio: "inherit", - env: { ...process.env, OPENCLAW_SKIP_POSTINSTALL: "1" }, + stdio: 'inherit', + env: { ...process.env, OPENCLAW_SKIP_POSTINSTALL: '1' }, }); } catch (err) { // Ignore errors to not break install @@ -276,7 +286,7 @@ function main() { const repoRoot = getRepoRoot(); process.chdir(repoRoot); - ensureExecutable(path.join(repoRoot, "dist", "entry.mjs")); + ensureExecutable(path.join(repoRoot, 'dist', '/entry.js')); setupGitHooks({ repoRoot }); trySetupCompletion(repoRoot); @@ -284,18 +294,18 @@ function main() { return; } - const pkgPath = path.join(repoRoot, "package.json"); - const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8")); + const pkgPath = path.join(repoRoot, 'package.json'); + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')); const patched = pkg?.pnpm?.patchedDependencies ?? {}; // Bun does not support pnpm.patchedDependencies. Apply these patch files to // node_modules packages as a best-effort compatibility layer. for (const [key, relPatchPath] of Object.entries(patched)) { - if (typeof relPatchPath !== "string" || !relPatchPath.trim()) continue; + if (typeof relPatchPath !== 'string' || !relPatchPath.trim()) continue; const pkgName = extractPackageName(String(key)); if (!pkgName) continue; applyPatchFile({ - targetDir: path.join("node_modules", ...pkgName.split("/")), + targetDir: path.join('node_modules', ...pkgName.split('/')), patchPath: relPatchPath, }); } @@ -303,10 +313,10 @@ function main() { try { const skip = - process.env.OPENCLAW_SKIP_POSTINSTALL === "1" || - process.env.CLAWDBOT_SKIP_POSTINSTALL === "1" || - process.env.VITEST === "true" || - process.env.NODE_ENV === "test"; + process.env.OPENCLAW_SKIP_POSTINSTALL === '1' || + process.env.CLAWDBOT_SKIP_POSTINSTALL === '1' || + process.env.VITEST === 'true' || + process.env.NODE_ENV === 'test'; if (!skip) { main(); diff --git a/scripts/run-node.mjs b/scripts/run-node.mjs index 3c4d65a9a1..bb3bc28146 100644 --- a/scripts/run-node.mjs +++ b/scripts/run-node.mjs @@ -1,21 +1,24 @@ #!/usr/bin/env node -import { spawn } from "node:child_process"; -import fs from "node:fs"; -import path from "node:path"; -import process from "node:process"; +import { spawn } from 'node:child_process'; +import fs from 'node:fs'; +import path from 'node:path'; +import process from 'node:process'; const args = process.argv.slice(2); const env = { ...process.env }; const cwd = process.cwd(); const compilerOverride = env.OPENCLAW_TS_COMPILER ?? env.CLAWDBOT_TS_COMPILER; -const compiler = compilerOverride === "tsc" ? "tsc" : "tsgo"; -const projectArgs = ["--project", "tsconfig.json"]; +const compiler = compilerOverride === 'tsc' ? 'tsc' : 'tsgo'; +const projectArgs = ['--project', 'tsconfig.json']; -const distRoot = path.join(cwd, "dist"); -const distEntry = path.join(distRoot, "entry.mjs"); -const buildStampPath = path.join(distRoot, ".buildstamp"); -const srcRoot = path.join(cwd, "src"); -const configFiles = [path.join(cwd, "tsconfig.json"), path.join(cwd, "package.json")]; +const distRoot = path.join(cwd, 'dist'); +const distEntry = path.join(distRoot, '/entry.js'); +const buildStampPath = path.join(distRoot, '.buildstamp'); +const srcRoot = path.join(cwd, 'src'); +const configFiles = [ + path.join(cwd, 'tsconfig.json'), + path.join(cwd, 'package.json'), +]; const statMtime = (filePath) => { try { @@ -27,10 +30,10 @@ const statMtime = (filePath) => { const isExcludedSource = (filePath) => { const relativePath = path.relative(srcRoot, filePath); - if (relativePath.startsWith("..")) return false; + if (relativePath.startsWith('..')) return false; return ( - relativePath.endsWith(".test.ts") || - relativePath.endsWith(".test.tsx") || + relativePath.endsWith('.test.ts') || + relativePath.endsWith('.test.tsx') || relativePath.endsWith(`test-helpers.ts`) ); }; @@ -66,7 +69,7 @@ const findLatestMtime = (dirPath, shouldSkip) => { }; const shouldBuild = () => { - if (env.OPENCLAW_FORCE_BUILD === "1") return true; + if (env.OPENCLAW_FORCE_BUILD === '1') return true; const stampMtime = statMtime(buildStampPath); if (stampMtime == null) return true; if (statMtime(distEntry) == null) return true; @@ -82,18 +85,18 @@ const shouldBuild = () => { }; const logRunner = (message) => { - if (env.OPENCLAW_RUNNER_LOG === "0") return; + if (env.OPENCLAW_RUNNER_LOG === '0') return; process.stderr.write(`[openclaw] ${message}\n`); }; const runNode = () => { - const nodeProcess = spawn(process.execPath, ["openclaw.mjs", ...args], { + const nodeProcess = spawn(process.execPath, ['openclaw.mjs', ...args], { cwd, env, - stdio: "inherit", + stdio: 'inherit', }); - nodeProcess.on("exit", (exitCode, exitSignal) => { + nodeProcess.on('exit', (exitCode, exitSignal) => { if (exitSignal) { process.exit(1); } @@ -107,25 +110,29 @@ const writeBuildStamp = () => { fs.writeFileSync(buildStampPath, `${Date.now()}\n`); } catch (error) { // Best-effort stamp; still allow the runner to start. - logRunner(`Failed to write build stamp: ${error?.message ?? "unknown error"}`); + logRunner( + `Failed to write build stamp: ${error?.message ?? 'unknown error'}`, + ); } }; if (!shouldBuild()) { runNode(); } else { - logRunner("Building TypeScript (dist is stale)."); - const pnpmArgs = ["exec", compiler, ...projectArgs]; - const buildCmd = process.platform === "win32" ? "cmd.exe" : "pnpm"; + logRunner('Building TypeScript (dist is stale).'); + const pnpmArgs = ['exec', compiler, ...projectArgs]; + const buildCmd = process.platform === 'win32' ? 'cmd.exe' : 'pnpm'; const buildArgs = - process.platform === "win32" ? ["/d", "/s", "/c", "pnpm", ...pnpmArgs] : pnpmArgs; + process.platform === 'win32' + ? ['/d', '/s', '/c', 'pnpm', ...pnpmArgs] + : pnpmArgs; const build = spawn(buildCmd, buildArgs, { cwd, env, - stdio: "inherit", + stdio: 'inherit', }); - build.on("exit", (code, signal) => { + build.on('exit', (code, signal) => { if (signal) { process.exit(1); } diff --git a/scripts/watch-node.mjs b/scripts/watch-node.mjs index 78947e2036..f97329d4b6 100644 --- a/scripts/watch-node.mjs +++ b/scripts/watch-node.mjs @@ -16,7 +16,7 @@ if (initialBuild.status !== 0) { process.exit(initialBuild.status ?? 1); } -const compilerProcess = spawn("pnpm", ["tsdown", '--watch', 'src/'], { +const compilerProcess = spawn("pnpm", ["tsc", '-p', 'tsconfig.json', '--noEmit', 'false', '--watch'], { cwd, env, stdio: "inherit", diff --git a/src/agents/skills/refresh.test.ts b/src/agents/skills/refresh.test.ts index 555641159f..51b86e7f79 100644 --- a/src/agents/skills/refresh.test.ts +++ b/src/agents/skills/refresh.test.ts @@ -24,7 +24,7 @@ describe("ensureSkillsWatcher", () => { expect(ignored.some((re) => re.test("/tmp/workspace/skills/node_modules/pkg/index.js"))).toBe( true, ); - expect(ignored.some((re) => re.test("/tmp/workspace/skills/dist/index.mjs"))).toBe(true); + expect(ignored.some((re) => re.test("/tmp/workspace/skills/dist/index.js"))).toBe(true); expect(ignored.some((re) => re.test("/tmp/workspace/skills/.git/config"))).toBe(true); expect(ignored.some((re) => re.test("/tmp/.hidden/skills/index.md"))).toBe(false); }); diff --git a/src/cli/browser-cli.test.ts b/src/cli/browser-cli.test.ts index 6c146a3518..622e1c3026 100644 --- a/src/cli/browser-cli.test.ts +++ b/src/cli/browser-cli.test.ts @@ -43,7 +43,7 @@ describe("browser CLI --browser-profile flag", () => { }); it("does not conflict with global --profile flag", () => { - // The global --profile flag is handled by entry.mjs before Commander + // The global --profile flag is handled by /entry.js before Commander // This test verifies --browser-profile is a separate option const program = new Command(); program.name("test"); diff --git a/src/cli/run-main.test.ts b/src/cli/run-main.test.ts index ac16407880..65bc2bf0b4 100644 --- a/src/cli/run-main.test.ts +++ b/src/cli/run-main.test.ts @@ -4,22 +4,22 @@ import { rewriteUpdateFlagArgv } from "./run-main.js"; describe("rewriteUpdateFlagArgv", () => { it("leaves argv unchanged when --update is absent", () => { - const argv = ["node", "entry.mjs", "status"]; + const argv = ["node", "entry.js", "status"]; expect(rewriteUpdateFlagArgv(argv)).toBe(argv); }); it("rewrites --update into the update command", () => { - expect(rewriteUpdateFlagArgv(["node", "entry.mjs", "--update"])).toEqual([ + expect(rewriteUpdateFlagArgv(["node", "entry.js", "--update"])).toEqual([ "node", - "entry.mjs", + "entry.js", "update", ]); }); it("preserves global flags that appear before --update", () => { - expect(rewriteUpdateFlagArgv(["node", "entry.mjs", "--profile", "p", "--update"])).toEqual([ + expect(rewriteUpdateFlagArgv(["node", "entry.js", "--profile", "p", "--update"])).toEqual([ "node", - "entry.mjs", + "entry.js", "--profile", "p", "update", @@ -27,9 +27,9 @@ describe("rewriteUpdateFlagArgv", () => { }); it("keeps update options after the rewritten command", () => { - expect(rewriteUpdateFlagArgv(["node", "entry.mjs", "--update", "--json"])).toEqual([ + expect(rewriteUpdateFlagArgv(["node", "entry.js", "--update", "--json"])).toEqual([ "node", - "entry.mjs", + "entry.js", "update", "--json", ]); diff --git a/src/cli/update-cli.ts b/src/cli/update-cli.ts index f28fa803e3..237fcf5c73 100644 --- a/src/cli/update-cli.ts +++ b/src/cli/update-cli.ts @@ -747,7 +747,7 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise { let afterVersion = beforeVersion; if (pkgRoot) { afterVersion = await readPackageVersion(pkgRoot); - const entryPath = path.join(pkgRoot, "dist", "entry.mjs"); + const entryPath = path.join(pkgRoot, "dist", "entry.js"); if (await pathExists(entryPath)) { const doctorStep = await runUpdateStep({ name: `${CLI_NAME} doctor`, @@ -969,7 +969,9 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise { try { const { doctorCommand } = await import("../commands/doctor.js"); const interactiveDoctor = Boolean(process.stdin.isTTY) && !opts.json && opts.yes !== true; - await doctorCommand(defaultRuntime, { nonInteractive: !interactiveDoctor }); + await doctorCommand(defaultRuntime, { + nonInteractive: !interactiveDoctor, + }); } catch (err) { defaultRuntime.log(theme.warn(`Doctor failed: ${String(err)}`)); } finally { @@ -1220,7 +1222,9 @@ ${theme.muted("Docs:")} ${formatDocsLink("/cli/update", "docs.openclaw.ai/cli/up ) .action(async (opts) => { try { - await updateWizardCommand({ timeout: opts.timeout as string | undefined }); + await updateWizardCommand({ + timeout: opts.timeout as string | undefined, + }); } catch (err) { defaultRuntime.error(String(err)); defaultRuntime.exit(1); diff --git a/src/commands/status.test.ts b/src/commands/status.test.ts index 477f920c5e..0641f7eedb 100644 --- a/src/commands/status.test.ts +++ b/src/commands/status.test.ts @@ -103,7 +103,12 @@ vi.mock("../memory/manager.js", () => ({ sourceCounts: [{ source: "memory", files: 2, chunks: 3 }], cache: { enabled: true, entries: 10, maxEntries: 500 }, fts: { enabled: true, available: true }, - vector: { enabled: true, available: true, extensionPath: "/opt/vec0.dylib", dims: 1024 }, + vector: { + enabled: true, + available: true, + extensionPath: "/opt/vec0.dylib", + dims: 1024, + }, }), close: vi.fn(async () => {}), __agentId: agentId, @@ -254,7 +259,7 @@ vi.mock("../daemon/service.js", () => ({ isLoaded: async () => true, readRuntime: async () => ({ status: "running", pid: 1234 }), readCommand: async () => ({ - programArguments: ["node", "dist/entry.mjs", "gateway"], + programArguments: ["node", "dist/entry.js", "gateway"], sourcePath: "/tmp/Library/LaunchAgents/bot.molt.gateway.plist", }), }), @@ -267,7 +272,7 @@ vi.mock("../daemon/node-service.js", () => ({ isLoaded: async () => true, readRuntime: async () => ({ status: "running", pid: 4321 }), readCommand: async () => ({ - programArguments: ["node", "dist/entry.mjs", "node-host"], + programArguments: ["node", "dist/entry.js", "node-host"], sourcePath: "/tmp/Library/LaunchAgents/bot.molt.node.plist", }), }), diff --git a/src/daemon/program-args.test.ts b/src/daemon/program-args.test.ts index 1227a2443c..68dc4edb71 100644 --- a/src/daemon/program-args.test.ts +++ b/src/daemon/program-args.test.ts @@ -24,7 +24,7 @@ afterEach(() => { describe("resolveGatewayProgramArguments", () => { it("uses realpath-resolved dist entry when running via npx shim", async () => { const argv1 = path.resolve("/tmp/.npm/_npx/63c3/node_modules/.bin/openclaw"); - const entryPath = path.resolve("/tmp/.npm/_npx/63c3/node_modules/openclaw/dist/entry.mjs"); + const entryPath = path.resolve("/tmp/.npm/_npx/63c3/node_modules/openclaw/dist/entry.js"); process.argv = ["node", argv1]; fsMocks.realpath.mockResolvedValue(entryPath); fsMocks.access.mockImplementation(async (target: string) => { @@ -49,10 +49,10 @@ describe("resolveGatewayProgramArguments", () => { // Simulates pnpm global install where node_modules/openclaw is a symlink // to .pnpm/openclaw@X.Y.Z/node_modules/openclaw const symlinkPath = path.resolve( - "/Users/test/Library/pnpm/global/5/node_modules/openclaw/dist/entry.mjs", + "/Users/test/Library/pnpm/global/5/node_modules/openclaw/dist/entry.js", ); const realpathResolved = path.resolve( - "/Users/test/Library/pnpm/global/5/node_modules/.pnpm/openclaw@2026.1.21-2/node_modules/openclaw/dist/entry.mjs", + "/Users/test/Library/pnpm/global/5/node_modules/.pnpm/openclaw@2026.1.21-2/node_modules/openclaw/dist/entry.js", ); process.argv = ["node", symlinkPath]; fsMocks.realpath.mockResolvedValue(realpathResolved); @@ -67,7 +67,7 @@ describe("resolveGatewayProgramArguments", () => { it("falls back to node_modules package dist when .bin path is not resolved", async () => { const argv1 = path.resolve("/tmp/.npm/_npx/63c3/node_modules/.bin/openclaw"); - const indexPath = path.resolve("/tmp/.npm/_npx/63c3/node_modules/openclaw/dist/index.mjs"); + const indexPath = path.resolve("/tmp/.npm/_npx/63c3/node_modules/openclaw/dist/index.js"); process.argv = ["node", argv1]; fsMocks.realpath.mockRejectedValue(new Error("no realpath")); fsMocks.access.mockImplementation(async (target: string) => { diff --git a/src/infra/control-ui-assets.ts b/src/infra/control-ui-assets.ts index fc7c262d16..867485f5cd 100644 --- a/src/infra/control-ui-assets.ts +++ b/src/infra/control-ui-assets.ts @@ -47,7 +47,7 @@ export async function resolveControlUiDistIndexPath( } const normalized = path.resolve(argv1); - // Case 1: entrypoint is directly inside dist/ (e.g., dist/entry.mjs) + // Case 1: entrypoint is directly inside dist/ (e.g., dist/entry.js) const distDir = path.dirname(normalized); if (path.basename(distDir) === "dist") { return path.join(distDir, "control-ui", "index.html"); diff --git a/src/infra/gateway-lock.ts b/src/infra/gateway-lock.ts index 8d83228357..aec746a2d4 100644 --- a/src/infra/gateway-lock.ts +++ b/src/infra/gateway-lock.ts @@ -73,8 +73,8 @@ function isGatewayArgv(args: string[]): boolean { } const entryCandidates = [ - "dist/index.mjs", - "dist/entry.mjs", + "dist/index.js", + "dist/entry.js", "openclaw.mjs", "scripts/run-node.mjs", "src/index.ts", diff --git a/src/infra/is-main.test.ts b/src/infra/is-main.test.ts index 97233ae8f7..5a0eaaab04 100644 --- a/src/infra/is-main.test.ts +++ b/src/infra/is-main.test.ts @@ -6,8 +6,8 @@ describe("isMainModule", () => { it("returns true when argv[1] matches current file", () => { expect( isMainModule({ - currentFile: "/repo/dist/index.mjs", - argv: ["node", "/repo/dist/index.mjs"], + currentFile: "/repo/dist/index.js", + argv: ["node", "/repo/dist/index.js"], cwd: "/repo", env: {}, }), @@ -17,10 +17,10 @@ describe("isMainModule", () => { it("returns true under PM2 when pm_exec_path matches current file", () => { expect( isMainModule({ - currentFile: "/repo/dist/index.mjs", + currentFile: "/repo/dist/index.js", argv: ["node", "/pm2/lib/ProcessContainerFork.js"], cwd: "/repo", - env: { pm_exec_path: "/repo/dist/index.mjs", pm_id: "0" }, + env: { pm_exec_path: "/repo/dist/index.js", pm_id: "0" }, }), ).toBe(true); }); @@ -28,7 +28,7 @@ describe("isMainModule", () => { it("returns false when running under PM2 but this module is imported", () => { expect( isMainModule({ - currentFile: "/repo/node_modules/openclaw/dist/index.mjs", + currentFile: "/repo/node_modules/openclaw/dist/index.js", argv: ["node", "/repo/app.js"], cwd: "/repo", env: { pm_exec_path: "/repo/app.js", pm_id: "0" }, diff --git a/src/infra/ports.test.ts b/src/infra/ports.test.ts index c8f77c2341..9a70d049e0 100644 --- a/src/infra/ports.test.ts +++ b/src/infra/ports.test.ts @@ -37,7 +37,7 @@ describe("ports helpers", () => { expect( classifyPortListener( { - commandLine: "node /Users/me/Projects/openclaw/dist/entry.mjs gateway", + commandLine: "node /Users/me/Projects/openclaw/dist/entry.js gateway", }, 18789, ), diff --git a/src/plugins/install.test.ts b/src/plugins/install.test.ts index 542e6fb4a1..412165fc7c 100644 --- a/src/plugins/install.test.ts +++ b/src/plugins/install.test.ts @@ -102,11 +102,11 @@ describe("installPluginFromArchive", () => { JSON.stringify({ name: "@openclaw/voice-call", version: "0.0.1", - openclaw: { extensions: ["./dist/index.mjs"] }, + openclaw: { extensions: ["./dist/index.js"] }, }), "utf-8", ); - fs.writeFileSync(path.join(pkgDir, "dist", "index.mjs"), "export {};", "utf-8"); + fs.writeFileSync(path.join(pkgDir, "dist", "index.js"), "export {};", "utf-8"); const archivePath = packToArchive({ pkgDir, @@ -127,7 +127,7 @@ describe("installPluginFromArchive", () => { expect(result.pluginId).toBe("voice-call"); expect(result.targetDir).toBe(path.join(stateDir, "extensions", "voice-call")); expect(fs.existsSync(path.join(result.targetDir, "package.json"))).toBe(true); - expect(fs.existsSync(path.join(result.targetDir, "dist", "index.mjs"))).toBe(true); + expect(fs.existsSync(path.join(result.targetDir, "dist", "index.js"))).toBe(true); }); it("rejects installing when plugin already exists", async () => { @@ -140,7 +140,7 @@ describe("installPluginFromArchive", () => { JSON.stringify({ name: "@openclaw/voice-call", version: "0.0.1", - openclaw: { extensions: ["./dist/index.mjs"] }, + openclaw: { extensions: ["./dist/index.js"] }, }), "utf-8", ); @@ -182,10 +182,10 @@ describe("installPluginFromArchive", () => { JSON.stringify({ name: "@openclaw/zipper", version: "0.0.1", - openclaw: { extensions: ["./dist/index.mjs"] }, + openclaw: { extensions: ["./dist/index.js"] }, }), ); - zip.file("package/dist/index.mjs", "export {};"); + zip.file("package/dist/index.js", "export {};"); const buffer = await zip.generateAsync({ type: "nodebuffer" }); fs.writeFileSync(archivePath, buffer); @@ -203,7 +203,7 @@ describe("installPluginFromArchive", () => { expect(result.pluginId).toBe("zipper"); expect(result.targetDir).toBe(path.join(stateDir, "extensions", "zipper")); expect(fs.existsSync(path.join(result.targetDir, "package.json"))).toBe(true); - expect(fs.existsSync(path.join(result.targetDir, "dist", "index.mjs"))).toBe(true); + expect(fs.existsSync(path.join(result.targetDir, "dist", "index.js"))).toBe(true); }); it("allows updates when mode is update", async () => { @@ -216,7 +216,7 @@ describe("installPluginFromArchive", () => { JSON.stringify({ name: "@openclaw/voice-call", version: "0.0.1", - openclaw: { extensions: ["./dist/index.mjs"] }, + openclaw: { extensions: ["./dist/index.js"] }, }), "utf-8", ); @@ -234,7 +234,7 @@ describe("installPluginFromArchive", () => { JSON.stringify({ name: "@openclaw/voice-call", version: "0.0.2", - openclaw: { extensions: ["./dist/index.mjs"] }, + openclaw: { extensions: ["./dist/index.js"] }, }), "utf-8", ); diff --git a/test/gateway.multi.e2e.test.ts b/test/gateway.multi.e2e.test.ts index 8829ea300d..809d3a855b 100644 --- a/test/gateway.multi.e2e.test.ts +++ b/test/gateway.multi.e2e.test.ts @@ -114,7 +114,7 @@ const spawnGatewayInstance = async (name: string): Promise => { child = spawn( "node", [ - "dist/index.mjs", + "dist/index.js", "gateway", "--port", String(port), @@ -201,7 +201,7 @@ const stopGatewayInstance = async (inst: GatewayInstance) => { const runCliJson = async (args: string[], env: NodeJS.ProcessEnv): Promise => { const stdout: string[] = []; const stderr: string[] = []; - const child = spawn("node", ["dist/index.mjs", ...args], { + const child = spawn("node", ["dist/index.js", ...args], { cwd: process.cwd(), env: { ...process.env, ...env }, stdio: ["ignore", "pipe", "pipe"], diff --git a/tsdown.config.ts b/tsdown.config.ts deleted file mode 100644 index 09fdaf0260..0000000000 --- a/tsdown.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { defineConfig } from 'tsdown' - -export default defineConfig([ - { - entry: 'src/index.ts', - platform: 'node', - }, - { - entry: 'src/entry.ts', - platform: 'node', - }, -])