From 4168709f0fd8cbfcd3722150d6c56a36678c3041 Mon Sep 17 00:00:00 2001 From: Nicholas Scarabosio Date: Mon, 9 Feb 2026 12:11:33 -0700 Subject: [PATCH 1/9] Add remote R2 bucket binding for local development Co-Authored-By: Claude Opus 4.6 --- wrangler.jsonc | 219 ++++++++++++++++++++++++++----------------------- 1 file changed, 117 insertions(+), 102 deletions(-) diff --git a/wrangler.jsonc b/wrangler.jsonc index 5d64e40e3..0c9524893 100644 --- a/wrangler.jsonc +++ b/wrangler.jsonc @@ -1,103 +1,118 @@ { - "$schema": "node_modules/wrangler/config-schema.json", - "name": "moltbot-sandbox", - "main": "src/index.ts", - "compatibility_date": "2025-05-06", - "compatibility_flags": ["nodejs_compat"], - "observability": { - "enabled": true, - }, - // Static assets for admin UI (built by vite) - "assets": { - "directory": "./dist/client", - "not_found_handling": "single-page-application", - "html_handling": "auto-trailing-slash", - "binding": "ASSETS", - "run_worker_first": true, - }, - // Allow importing HTML files as text modules and PNG files as binary - "rules": [ - { - "type": "Text", - "globs": ["**/*.html"], - "fallthrough": false, - }, - { - "type": "Data", - "globs": ["**/*.png"], - "fallthrough": false, - }, - ], - // Build command for vite - "build": { - "command": "npm run build", - }, - // Container configuration for the Moltbot sandbox - "containers": [ - { - "class_name": "Sandbox", - "image": "./Dockerfile", - "instance_type": "standard-1", - "max_instances": 1, - }, - ], - "durable_objects": { - "bindings": [ - { - "class_name": "Sandbox", - "name": "Sandbox", - }, - ], - }, - "migrations": [ - { - "new_sqlite_classes": ["Sandbox"], - "tag": "v1", - }, - ], - // R2 bucket for persistent storage (moltbot data, conversations, etc.) - "r2_buckets": [ - { - "binding": "MOLTBOT_BUCKET", - "bucket_name": "moltbot-data", - }, - ], - // Cron trigger to sync moltbot data to R2 every 5 minutes - "triggers": { - "crons": ["*/5 * * * *"], - }, - // Browser Rendering binding for CDP shim - "browser": { - "binding": "BROWSER", - }, - // Note: CF_ACCOUNT_ID should be set via `wrangler secret put CF_ACCOUNT_ID` - // Secrets to configure via `wrangler secret put`: - // - // AI Provider (at least one set required): - // - ANTHROPIC_API_KEY: Direct Anthropic API key - // - OPENAI_API_KEY: Direct OpenAI API key - // - Cloudflare AI Gateway (alternative to direct keys): - // - CLOUDFLARE_AI_GATEWAY_API_KEY: API key for requests through the gateway - // - CF_AI_GATEWAY_ACCOUNT_ID: Your Cloudflare account ID - // - CF_AI_GATEWAY_GATEWAY_ID: Your AI Gateway ID - // - Legacy AI Gateway (still supported): - // - AI_GATEWAY_API_KEY: API key - // - AI_GATEWAY_BASE_URL: Gateway endpoint URL - // - // Authentication: - // - MOLTBOT_GATEWAY_TOKEN: Token to protect gateway access - // - CF_ACCESS_TEAM_DOMAIN: Cloudflare Access team domain - // - CF_ACCESS_AUD: Cloudflare Access application audience - // - // Chat channels (optional): - // - TELEGRAM_BOT_TOKEN, DISCORD_BOT_TOKEN, SLACK_BOT_TOKEN, SLACK_APP_TOKEN - // - // Browser automation (optional): - // - CDP_SECRET: Shared secret for /cdp endpoint authentication - // - WORKER_URL: Public URL of the worker - // - // R2 persistent storage (optional, for data persistence across sessions): - // - R2_ACCESS_KEY_ID: R2 access key ID (from R2 API tokens) - // - R2_SECRET_ACCESS_KEY: R2 secret access key (from R2 API tokens) - // - CF_ACCOUNT_ID: Your Cloudflare account ID (for R2 endpoint URL) -} + "$schema": "node_modules/wrangler/config-schema.json", + "name": "moltbot-sandbox", + "main": "src/index.ts", + "compatibility_date": "2025-05-06", + "compatibility_flags": [ + "nodejs_compat" + ], + "observability": { + "enabled": true, + }, + // Static assets for admin UI (built by vite) + "assets": { + "directory": "./dist/client", + "not_found_handling": "single-page-application", + "html_handling": "auto-trailing-slash", + "binding": "ASSETS", + "run_worker_first": true, + }, + // Allow importing HTML files as text modules and PNG files as binary + "rules": [ + { + "type": "Text", + "globs": [ + "**/*.html" + ], + "fallthrough": false, + }, + { + "type": "Data", + "globs": [ + "**/*.png" + ], + "fallthrough": false, + }, + ], + // Build command for vite + "build": { + "command": "npm run build", + }, + // Container configuration for the Moltbot sandbox + "containers": [ + { + "class_name": "Sandbox", + "image": "./Dockerfile", + "instance_type": "standard-1", + "max_instances": 1, + }, + ], + "durable_objects": { + "bindings": [ + { + "class_name": "Sandbox", + "name": "Sandbox", + }, + ], + }, + "migrations": [ + { + "new_sqlite_classes": [ + "Sandbox" + ], + "tag": "v1", + }, + ], + // R2 bucket for persistent storage (moltbot data, conversations, etc.) + "r2_buckets": [ + { + "binding": "MOLTBOT_BUCKET", + "bucket_name": "moltbot-data", + }, + { + "bucket_name": "moltbot-data", + "binding": "moltbot_data", + "remote": true + }, + ], + // Cron trigger to sync moltbot data to R2 every 5 minutes + "triggers": { + "crons": [ + "*/5 * * * *" + ], + }, + // Browser Rendering binding for CDP shim + "browser": { + "binding": "BROWSER", + }, + // Note: CF_ACCOUNT_ID should be set via `wrangler secret put CF_ACCOUNT_ID` + // Secrets to configure via `wrangler secret put`: + // + // AI Provider (at least one set required): + // - ANTHROPIC_API_KEY: Direct Anthropic API key + // - OPENAI_API_KEY: Direct OpenAI API key + // - Cloudflare AI Gateway (alternative to direct keys): + // - CLOUDFLARE_AI_GATEWAY_API_KEY: API key for requests through the gateway + // - CF_AI_GATEWAY_ACCOUNT_ID: Your Cloudflare account ID + // - CF_AI_GATEWAY_GATEWAY_ID: Your AI Gateway ID + // - Legacy AI Gateway (still supported): + // - AI_GATEWAY_API_KEY: API key + // - AI_GATEWAY_BASE_URL: Gateway endpoint URL + // + // Authentication: + // - MOLTBOT_GATEWAY_TOKEN: Token to protect gateway access + // - CF_ACCESS_TEAM_DOMAIN: Cloudflare Access team domain + // - CF_ACCESS_AUD: Cloudflare Access application audience + // + // Chat channels (optional): + // - TELEGRAM_BOT_TOKEN, DISCORD_BOT_TOKEN, SLACK_BOT_TOKEN, SLACK_APP_TOKEN + // + // Browser automation (optional): + // - CDP_SECRET: Shared secret for /cdp endpoint authentication + // - WORKER_URL: Public URL of the worker + // + // R2 persistent storage (optional, for data persistence across sessions): + // - R2_ACCESS_KEY_ID: R2 access key ID (from R2 API tokens) + // - R2_SECRET_ACCESS_KEY: R2 secret access key (from R2 API tokens) + // - CF_ACCOUNT_ID: Your Cloudflare account ID (for R2 endpoint URL) +} \ No newline at end of file From 311b51bc47ca02ab8d92d9d6c35fda66e890e788 Mon Sep 17 00:00:00 2001 From: Nicholas Scarabosio Date: Mon, 9 Feb 2026 12:16:06 -0700 Subject: [PATCH 2/9] Update package-lock.json with resolved optional dependencies Co-Authored-By: Claude Opus 4.6 --- package-lock.json | 525 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 522 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2e5494df7..201a2c201 100644 --- a/package-lock.json +++ b/package-lock.json @@ -434,6 +434,23 @@ "wrangler": "^4.60.0" } }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20260120.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260120.0.tgz", + "integrity": "sha512-JLHx3p5dpwz4wjVSis45YNReftttnI3ndhdMh5BUbbpdreN/g0jgxNt5Qp9tDFqEKl++N63qv+hxJiIIvSLR+Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, "node_modules/@cloudflare/workerd-darwin-arm64": { "version": "1.20260120.0", "cpu": [ @@ -449,6 +466,57 @@ "node": ">=16" } }, + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20260120.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260120.0.tgz", + "integrity": "sha512-O0mIfJfvU7F8N5siCoRDaVDuI12wkz2xlG4zK6/Ct7U9c9FiE0ViXNFWXFQm5PPj+qbkNRyhjUwhP+GCKTk5EQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20260120.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260120.0.tgz", + "integrity": "sha512-aRHO/7bjxVpjZEmVVcpmhbzpN6ITbFCxuLLZSW0H9O0C0w40cDCClWSi19T87Ax/PQcYjFNT22pTewKsupkckA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20260120.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260120.0.tgz", + "integrity": "sha512-ASZIz1E8sqZQqQCgcfY1PJbBpUDrxPt8NZ+lqNil0qxnO4qX38hbCsdDF2/TDAuq0Txh7nu8ztgTelfNDlb4EA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, "node_modules/@cloudflare/workers-types": { "version": "4.20260124.0", "dev": true, @@ -465,6 +533,17 @@ "node": ">=12" } }, + "node_modules/@emnapi/runtime": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", @@ -934,6 +1013,29 @@ "@img/sharp-libvips-darwin-arm64": "1.2.4" } }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, "node_modules/@img/sharp-libvips-darwin-arm64": { "version": "1.2.4", "cpu": [ @@ -949,6 +1051,423 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -3051,9 +3570,9 @@ } }, "node_modules/hono": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.6.tgz", - "integrity": "sha512-ofIiiHyl34SV6AuhE3YT2mhO5HRWokce+eUYE82TsP6z0/H3JeJcjVWEMSIAiw2QkjDOEpES/lYsg8eEbsLtdw==", + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.9.tgz", + "integrity": "sha512-Eaw2YTGM6WOxA6CXbckaEvslr2Ne4NFsKrvc0v97JD5awbmeBLO5w9Ho9L9kmKonrwF9RJlW6BxT1PVv/agBHQ==", "license": "MIT", "engines": { "node": ">=16.9.0" From 088b1828e6a4e73bb582b2dc7cfdbb9bdef793d7 Mon Sep 17 00:00:00 2001 From: Nicholas Scarabosio Date: Mon, 9 Feb 2026 12:18:49 -0700 Subject: [PATCH 3/9] Revert "Update package-lock.json with resolved optional dependencies" This reverts commit 311b51bc47ca02ab8d92d9d6c35fda66e890e788. --- package-lock.json | 525 +--------------------------------------------- 1 file changed, 3 insertions(+), 522 deletions(-) diff --git a/package-lock.json b/package-lock.json index 201a2c201..2e5494df7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -434,23 +434,6 @@ "wrangler": "^4.60.0" } }, - "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20260120.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260120.0.tgz", - "integrity": "sha512-JLHx3p5dpwz4wjVSis45YNReftttnI3ndhdMh5BUbbpdreN/g0jgxNt5Qp9tDFqEKl++N63qv+hxJiIIvSLR+Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=16" - } - }, "node_modules/@cloudflare/workerd-darwin-arm64": { "version": "1.20260120.0", "cpu": [ @@ -466,57 +449,6 @@ "node": ">=16" } }, - "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20260120.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260120.0.tgz", - "integrity": "sha512-O0mIfJfvU7F8N5siCoRDaVDuI12wkz2xlG4zK6/Ct7U9c9FiE0ViXNFWXFQm5PPj+qbkNRyhjUwhP+GCKTk5EQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20260120.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260120.0.tgz", - "integrity": "sha512-aRHO/7bjxVpjZEmVVcpmhbzpN6ITbFCxuLLZSW0H9O0C0w40cDCClWSi19T87Ax/PQcYjFNT22pTewKsupkckA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=16" - } - }, - "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20260120.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260120.0.tgz", - "integrity": "sha512-ASZIz1E8sqZQqQCgcfY1PJbBpUDrxPt8NZ+lqNil0qxnO4qX38hbCsdDF2/TDAuq0Txh7nu8ztgTelfNDlb4EA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=16" - } - }, "node_modules/@cloudflare/workers-types": { "version": "4.20260124.0", "dev": true, @@ -533,17 +465,6 @@ "node": ">=12" } }, - "node_modules/@emnapi/runtime": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", - "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", @@ -1013,29 +934,6 @@ "@img/sharp-libvips-darwin-arm64": "1.2.4" } }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", - "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.4" - } - }, "node_modules/@img/sharp-libvips-darwin-arm64": { "version": "1.2.4", "cpu": [ @@ -1051,423 +949,6 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", - "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", - "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", - "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", - "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", - "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", - "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", - "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", - "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", - "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", - "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", - "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", - "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-riscv64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", - "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", - "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", - "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.4" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", - "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", - "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.4" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", - "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.7.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", - "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", - "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", - "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -3570,9 +3051,9 @@ } }, "node_modules/hono": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.9.tgz", - "integrity": "sha512-Eaw2YTGM6WOxA6CXbckaEvslr2Ne4NFsKrvc0v97JD5awbmeBLO5w9Ho9L9kmKonrwF9RJlW6BxT1PVv/agBHQ==", + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.6.tgz", + "integrity": "sha512-ofIiiHyl34SV6AuhE3YT2mhO5HRWokce+eUYE82TsP6z0/H3JeJcjVWEMSIAiw2QkjDOEpES/lYsg8eEbsLtdw==", "license": "MIT", "engines": { "node": ">=16.9.0" From 4ce85ea956b855e9b15d25beed090d65798b000c Mon Sep 17 00:00:00 2001 From: Nicholas Scarabosio Date: Mon, 9 Feb 2026 14:18:12 -0700 Subject: [PATCH 4/9] Add Google Workspace skill for Gmail and Calendar access Enables the OpenClaw agent to query Gmail and Google Calendar remotely via OAuth2 credentials passed as worker secrets. Includes scripts for searching/reading/sending email and listing/creating calendar events. Co-Authored-By: Claude Opus 4.6 --- Dockerfile | 5 +- skills/google-workspace/SKILL.md | 55 ++++++++++++ .../scripts/calendar-create.js | 80 +++++++++++++++++ .../scripts/calendar-events.js | 81 +++++++++++++++++ skills/google-workspace/scripts/gmail-read.js | 86 +++++++++++++++++++ .../google-workspace/scripts/gmail-search.js | 67 +++++++++++++++ skills/google-workspace/scripts/gmail-send.js | 63 ++++++++++++++ .../google-workspace/scripts/google-auth.js | 42 +++++++++ src/gateway/env.ts | 3 + src/types.ts | 4 + 10 files changed, 485 insertions(+), 1 deletion(-) create mode 100644 skills/google-workspace/SKILL.md create mode 100644 skills/google-workspace/scripts/calendar-create.js create mode 100644 skills/google-workspace/scripts/calendar-events.js create mode 100644 skills/google-workspace/scripts/gmail-read.js create mode 100644 skills/google-workspace/scripts/gmail-search.js create mode 100644 skills/google-workspace/scripts/gmail-send.js create mode 100644 skills/google-workspace/scripts/google-auth.js diff --git a/Dockerfile b/Dockerfile index 340183e46..2e2e87abe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,6 +20,9 @@ RUN ARCH="$(dpkg --print-architecture)" \ # Install pnpm globally RUN npm install -g pnpm +# Install Google APIs client (for Google Workspace skill) +RUN npm install -g googleapis google-auth-library + # Install OpenClaw (formerly clawdbot/moltbot) # Pin to specific version for reproducible builds RUN npm install -g openclaw@2026.2.3 \ @@ -32,7 +35,7 @@ RUN mkdir -p /root/.openclaw \ && mkdir -p /root/clawd/skills # Copy startup script -# Build cache bust: 2026-02-06-v29-sync-workspace +# Build cache bust: 2026-02-09-v30-google-workspace COPY start-openclaw.sh /usr/local/bin/start-openclaw.sh RUN chmod +x /usr/local/bin/start-openclaw.sh diff --git a/skills/google-workspace/SKILL.md b/skills/google-workspace/SKILL.md new file mode 100644 index 000000000..35b7372f3 --- /dev/null +++ b/skills/google-workspace/SKILL.md @@ -0,0 +1,55 @@ +--- +name: google-workspace +description: Access Gmail and Google Calendar via Google APIs. Search/read/send email and list/create calendar events. Requires GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and GOOGLE_REFRESH_TOKEN env vars. +--- + +# Google Workspace + +Access Gmail and Google Calendar from the container via Google APIs with OAuth2 authentication. + +## Prerequisites + +- `GOOGLE_CLIENT_ID` environment variable set +- `GOOGLE_CLIENT_SECRET` environment variable set +- `GOOGLE_REFRESH_TOKEN` environment variable set + +## Quick Start + +### Search Gmail +```bash +node /root/clawd/skills/google-workspace/scripts/gmail-search.js "from:someone@example.com" --max 10 +``` + +### Read an email +```bash +node /root/clawd/skills/google-workspace/scripts/gmail-read.js +``` + +### Send an email +```bash +node /root/clawd/skills/google-workspace/scripts/gmail-send.js --to user@example.com --subject "Hello" --body "Message body" +``` + +### List calendar events +```bash +node /root/clawd/skills/google-workspace/scripts/calendar-events.js primary --from 2026-02-09 --to 2026-02-10 +``` + +### Create a calendar event +```bash +node /root/clawd/skills/google-workspace/scripts/calendar-create.js primary --summary "Meeting" --start "2026-02-10T10:00:00" --end "2026-02-10T11:00:00" +``` + +## Available Scripts + +| Script | Purpose | +|--------|---------| +| `gmail-search.js` | Search Gmail messages by query | +| `gmail-read.js` | Read full content of a single email | +| `gmail-send.js` | Send an email | +| `calendar-events.js` | List calendar events in a date range | +| `calendar-create.js` | Create a new calendar event | + +## Output Format + +Gmail search and calendar events output TSV (tab-separated values) for easy parsing, matching the format used by gogcli. diff --git a/skills/google-workspace/scripts/calendar-create.js b/skills/google-workspace/scripts/calendar-create.js new file mode 100644 index 000000000..b05ac3b0e --- /dev/null +++ b/skills/google-workspace/scripts/calendar-create.js @@ -0,0 +1,80 @@ +#!/usr/bin/env node +/** + * Calendar Create Event + * + * Usage: node calendar-create.js --summary --start --end [--description ] [--location ] + * + * Creates a new calendar event. + * + * calendarId: 'primary' for the user's main calendar, or a specific calendar ID + * Datetimes: ISO 8601 format (e.g., 2026-02-10T10:00:00) + */ + +const { getCalendar } = require('./google-auth'); + +function parseArgs(args) { + const result = { calendarId: 'primary' }; + for (let i = 0; i < args.length; i++) { + if (args[i] === '--summary' && args[i + 1]) { + result.summary = args[++i]; + } else if (args[i] === '--start' && args[i + 1]) { + result.start = args[++i]; + } else if (args[i] === '--end' && args[i + 1]) { + result.end = args[++i]; + } else if (args[i] === '--description' && args[i + 1]) { + result.description = args[++i]; + } else if (args[i] === '--location' && args[i + 1]) { + result.location = args[++i]; + } else if (!args[i].startsWith('--')) { + result.calendarId = args[i]; + } + } + return result; +} + +function toEventDateTime(dateStr) { + if (!dateStr) return undefined; + // All-day event: just a date + if (/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) { + return { date: dateStr }; + } + // Datetime event + let dt = dateStr; + if (!dt.includes('Z') && !dt.includes('+') && !dt.includes('-', 10)) { + dt += ':00'; // Ensure seconds + } + return { dateTime: dt, timeZone: 'America/Los_Angeles' }; +} + +async function main() { + const opts = parseArgs(process.argv.slice(2)); + + if (!opts.summary || !opts.start || !opts.end) { + console.error('Usage: node calendar-create.js --summary --start --end [--description ] [--location ]'); + process.exit(1); + } + + const calendar = getCalendar(); + + const event = { + summary: opts.summary, + start: toEventDateTime(opts.start), + end: toEventDateTime(opts.end), + }; + + if (opts.description) event.description = opts.description; + if (opts.location) event.location = opts.location; + + const res = await calendar.events.insert({ + calendarId: opts.calendarId, + requestBody: event, + }); + + console.log(`Created event: ${res.data.id}`); + console.log(`Link: ${res.data.htmlLink}`); +} + +main().catch(err => { + console.error('Error:', err.message); + process.exit(1); +}); diff --git a/skills/google-workspace/scripts/calendar-events.js b/skills/google-workspace/scripts/calendar-events.js new file mode 100644 index 000000000..a12142b8b --- /dev/null +++ b/skills/google-workspace/scripts/calendar-events.js @@ -0,0 +1,81 @@ +#!/usr/bin/env node +/** + * Calendar Events + * + * Usage: node calendar-events.js --from --to [--max N] + * + * Lists calendar events using events.list API. + * Outputs: ID, start, end, summary (TSV format) + * + * calendarId: 'primary' for the user's main calendar, or a specific calendar ID + * Dates: YYYY-MM-DD or ISO 8601 datetime + */ + +const { getCalendar } = require('./google-auth'); + +function parseArgs(args) { + const result = { calendarId: 'primary', maxResults: 50 }; + for (let i = 0; i < args.length; i++) { + if (args[i] === '--from' && args[i + 1]) { + result.from = args[++i]; + } else if (args[i] === '--to' && args[i + 1]) { + result.to = args[++i]; + } else if (args[i] === '--max' && args[i + 1]) { + result.maxResults = parseInt(args[++i], 10); + } else if (!args[i].startsWith('--')) { + result.calendarId = args[i]; + } + } + return result; +} + +function toRFC3339(dateStr) { + if (!dateStr) return undefined; + // If it's just a date (YYYY-MM-DD), append time + if (/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) { + return dateStr + 'T00:00:00Z'; + } + // If no timezone info, assume UTC + if (!dateStr.includes('Z') && !dateStr.includes('+') && !dateStr.includes('-', 10)) { + return dateStr + 'Z'; + } + return dateStr; +} + +async function main() { + const opts = parseArgs(process.argv.slice(2)); + + const calendar = getCalendar(); + + const params = { + calendarId: opts.calendarId, + maxResults: opts.maxResults, + singleEvents: true, + orderBy: 'startTime', + }; + + if (opts.from) params.timeMin = toRFC3339(opts.from); + if (opts.to) params.timeMax = toRFC3339(opts.to); + + const res = await calendar.events.list(params); + const events = res.data.items || []; + + if (events.length === 0) { + console.log('No events found.'); + return; + } + + console.log('ID\tStart\tEnd\tSummary'); + + for (const event of events) { + const start = event.start?.dateTime || event.start?.date || ''; + const end = event.end?.dateTime || event.end?.date || ''; + const summary = event.summary || '(no title)'; + console.log(`${event.id}\t${start}\t${end}\t${summary}`); + } +} + +main().catch(err => { + console.error('Error:', err.message); + process.exit(1); +}); diff --git a/skills/google-workspace/scripts/gmail-read.js b/skills/google-workspace/scripts/gmail-read.js new file mode 100644 index 000000000..804aaa5cd --- /dev/null +++ b/skills/google-workspace/scripts/gmail-read.js @@ -0,0 +1,86 @@ +#!/usr/bin/env node +/** + * Gmail Read + * + * Usage: node gmail-read.js + * + * Reads a single email's full content. + */ + +const { getGmail } = require('./google-auth'); + +function decodeBody(body) { + if (!body?.data) return ''; + return Buffer.from(body.data, 'base64url').toString('utf-8'); +} + +function extractText(payload) { + if (!payload) return ''; + + // Simple text/plain or text/html body + if (payload.mimeType === 'text/plain' && payload.body?.data) { + return decodeBody(payload.body); + } + + // Multipart: recurse through parts + if (payload.parts) { + // Prefer text/plain + for (const part of payload.parts) { + if (part.mimeType === 'text/plain' && part.body?.data) { + return decodeBody(part.body); + } + } + // Fall back to text/html + for (const part of payload.parts) { + if (part.mimeType === 'text/html' && part.body?.data) { + return decodeBody(part.body); + } + } + // Recurse into nested multipart + for (const part of payload.parts) { + const text = extractText(part); + if (text) return text; + } + } + + // Fallback: decode whatever body is there + if (payload.body?.data) { + return decodeBody(payload.body); + } + + return ''; +} + +async function main() { + const messageId = process.argv[2]; + if (!messageId) { + console.error('Usage: node gmail-read.js '); + process.exit(1); + } + + const gmail = getGmail(); + + const res = await gmail.users.messages.get({ + userId: 'me', + id: messageId, + format: 'full', + }); + + const headers = res.data.payload?.headers || []; + const getHeader = (name) => headers.find(h => h.name === name)?.value || ''; + + console.log(`From: ${getHeader('From')}`); + console.log(`To: ${getHeader('To')}`); + console.log(`Date: ${getHeader('Date')}`); + console.log(`Subject: ${getHeader('Subject')}`); + console.log(`Labels: ${(res.data.labelIds || []).join(', ')}`); + console.log('---'); + + const body = extractText(res.data.payload); + console.log(body || '(no text content)'); +} + +main().catch(err => { + console.error('Error:', err.message); + process.exit(1); +}); diff --git a/skills/google-workspace/scripts/gmail-search.js b/skills/google-workspace/scripts/gmail-search.js new file mode 100644 index 000000000..66474036b --- /dev/null +++ b/skills/google-workspace/scripts/gmail-search.js @@ -0,0 +1,67 @@ +#!/usr/bin/env node +/** + * Gmail Search + * + * Usage: node gmail-search.js [--max N] + * + * Searches Gmail using the users.messages.list + get API. + * Outputs: ID, date, from, subject, labels (TSV format) + */ + +const { getGmail } = require('./google-auth'); + +async function main() { + const args = process.argv.slice(2); + if (args.length === 0) { + console.error('Usage: node gmail-search.js [--max N]'); + process.exit(1); + } + + let query = ''; + let maxResults = 20; + + for (let i = 0; i < args.length; i++) { + if (args[i] === '--max' && args[i + 1]) { + maxResults = parseInt(args[i + 1], 10); + i++; + } else { + query += (query ? ' ' : '') + args[i]; + } + } + + const gmail = getGmail(); + + const listRes = await gmail.users.messages.list({ + userId: 'me', + q: query, + maxResults, + }); + + const messages = listRes.data.messages || []; + if (messages.length === 0) { + console.log('No messages found.'); + return; + } + + console.log('ID\tDate\tFrom\tSubject\tLabels'); + + for (const msg of messages) { + const detail = await gmail.users.messages.get({ + userId: 'me', + id: msg.id, + format: 'metadata', + metadataHeaders: ['From', 'Subject', 'Date'], + }); + + const headers = detail.data.payload?.headers || []; + const getHeader = (name) => headers.find(h => h.name === name)?.value || ''; + const labels = (detail.data.labelIds || []).join(','); + + console.log(`${msg.id}\t${getHeader('Date')}\t${getHeader('From')}\t${getHeader('Subject')}\t${labels}`); + } +} + +main().catch(err => { + console.error('Error:', err.message); + process.exit(1); +}); diff --git a/skills/google-workspace/scripts/gmail-send.js b/skills/google-workspace/scripts/gmail-send.js new file mode 100644 index 000000000..654c5163c --- /dev/null +++ b/skills/google-workspace/scripts/gmail-send.js @@ -0,0 +1,63 @@ +#!/usr/bin/env node +/** + * Gmail Send + * + * Usage: node gmail-send.js --to --subject --body + * + * Sends an email via Gmail API. + */ + +const { getGmail } = require('./google-auth'); + +function parseArgs(args) { + const result = {}; + for (let i = 0; i < args.length; i++) { + if (args[i] === '--to' && args[i + 1]) { + result.to = args[++i]; + } else if (args[i] === '--subject' && args[i + 1]) { + result.subject = args[++i]; + } else if (args[i] === '--body' && args[i + 1]) { + result.body = args[++i]; + } else if (args[i] === '--cc' && args[i + 1]) { + result.cc = args[++i]; + } else if (args[i] === '--bcc' && args[i + 1]) { + result.bcc = args[++i]; + } + } + return result; +} + +async function main() { + const opts = parseArgs(process.argv.slice(2)); + + if (!opts.to || !opts.subject || !opts.body) { + console.error('Usage: node gmail-send.js --to --subject --body [--cc ] [--bcc ]'); + process.exit(1); + } + + const gmail = getGmail(); + + // Build RFC 2822 message + let message = `To: ${opts.to}\n`; + if (opts.cc) message += `Cc: ${opts.cc}\n`; + if (opts.bcc) message += `Bcc: ${opts.bcc}\n`; + message += `Subject: ${opts.subject}\n`; + message += `Content-Type: text/plain; charset=utf-8\n\n`; + message += opts.body; + + const encodedMessage = Buffer.from(message).toString('base64url'); + + const res = await gmail.users.messages.send({ + userId: 'me', + requestBody: { + raw: encodedMessage, + }, + }); + + console.log(`Sent message ID: ${res.data.id}`); +} + +main().catch(err => { + console.error('Error:', err.message); + process.exit(1); +}); diff --git a/skills/google-workspace/scripts/google-auth.js b/skills/google-workspace/scripts/google-auth.js new file mode 100644 index 000000000..7a9282e88 --- /dev/null +++ b/skills/google-workspace/scripts/google-auth.js @@ -0,0 +1,42 @@ +#!/usr/bin/env node +/** + * Google Workspace - Shared Auth Library + * + * Creates authenticated Google API clients using OAuth2 credentials + * from environment variables. Handles token refresh automatically. + * + * Usage: + * const { getGmail, getCalendar } = require('./google-auth'); + * const gmail = getGmail(); + * const calendar = getCalendar(); + */ + +const { google } = require('googleapis'); + +function getAuth() { + const clientId = process.env.GOOGLE_CLIENT_ID; + const clientSecret = process.env.GOOGLE_CLIENT_SECRET; + const refreshToken = process.env.GOOGLE_REFRESH_TOKEN; + + if (!clientId || !clientSecret || !refreshToken) { + const missing = []; + if (!clientId) missing.push('GOOGLE_CLIENT_ID'); + if (!clientSecret) missing.push('GOOGLE_CLIENT_SECRET'); + if (!refreshToken) missing.push('GOOGLE_REFRESH_TOKEN'); + throw new Error(`Missing environment variables: ${missing.join(', ')}`); + } + + const oauth2Client = new google.auth.OAuth2(clientId, clientSecret); + oauth2Client.setCredentials({ refresh_token: refreshToken }); + return oauth2Client; +} + +function getGmail() { + return google.gmail({ version: 'v1', auth: getAuth() }); +} + +function getCalendar() { + return google.calendar({ version: 'v3', auth: getAuth() }); +} + +module.exports = { getAuth, getGmail, getCalendar }; diff --git a/src/gateway/env.ts b/src/gateway/env.ts index 23dea539d..a4064cead 100644 --- a/src/gateway/env.ts +++ b/src/gateway/env.ts @@ -49,6 +49,9 @@ export function buildEnvVars(env: MoltbotEnv): Record { if (env.CF_ACCOUNT_ID) envVars.CF_ACCOUNT_ID = env.CF_ACCOUNT_ID; if (env.CDP_SECRET) envVars.CDP_SECRET = env.CDP_SECRET; if (env.WORKER_URL) envVars.WORKER_URL = env.WORKER_URL; + if (env.GOOGLE_CLIENT_ID) envVars.GOOGLE_CLIENT_ID = env.GOOGLE_CLIENT_ID; + if (env.GOOGLE_CLIENT_SECRET) envVars.GOOGLE_CLIENT_SECRET = env.GOOGLE_CLIENT_SECRET; + if (env.GOOGLE_REFRESH_TOKEN) envVars.GOOGLE_REFRESH_TOKEN = env.GOOGLE_REFRESH_TOKEN; return envVars; } diff --git a/src/types.ts b/src/types.ts index a85d32da3..712de062e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -42,6 +42,10 @@ export interface MoltbotEnv { BROWSER?: Fetcher; CDP_SECRET?: string; // Shared secret for CDP endpoint authentication WORKER_URL?: string; // Public URL of the worker (for CDP endpoint) + // Google Workspace OAuth credentials (for Gmail/Calendar access) + GOOGLE_CLIENT_ID?: string; + GOOGLE_CLIENT_SECRET?: string; + GOOGLE_REFRESH_TOKEN?: string; } /** From bc3ca0f4194ffcc75c3c1c2ddd5d40d5322ab055 Mon Sep 17 00:00:00 2001 From: Nicholas Scarabosio Date: Mon, 9 Feb 2026 15:10:28 -0700 Subject: [PATCH 5/9] Fix NODE_PATH for globally installed googleapis in sandbox The sandbox's startProcess does not inherit Dockerfile ENV vars, so globally installed npm packages aren't found by require(). Add NODE_PATH initialization directly in google-auth.js and as a Dockerfile ENV for other contexts. Co-Authored-By: Claude Opus 4.6 --- Dockerfile | 4 +++- skills/google-workspace/scripts/google-auth.js | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 2e2e87abe..51086036b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,6 +21,8 @@ RUN ARCH="$(dpkg --print-architecture)" \ RUN npm install -g pnpm # Install Google APIs client (for Google Workspace skill) +# NODE_PATH ensures globally installed modules are found by require() +ENV NODE_PATH=/usr/local/lib/node_modules RUN npm install -g googleapis google-auth-library # Install OpenClaw (formerly clawdbot/moltbot) @@ -35,7 +37,7 @@ RUN mkdir -p /root/.openclaw \ && mkdir -p /root/clawd/skills # Copy startup script -# Build cache bust: 2026-02-09-v30-google-workspace +# Build cache bust: 2026-02-09-v32-script-node-path COPY start-openclaw.sh /usr/local/bin/start-openclaw.sh RUN chmod +x /usr/local/bin/start-openclaw.sh diff --git a/skills/google-workspace/scripts/google-auth.js b/skills/google-workspace/scripts/google-auth.js index 7a9282e88..44a72884b 100644 --- a/skills/google-workspace/scripts/google-auth.js +++ b/skills/google-workspace/scripts/google-auth.js @@ -11,6 +11,13 @@ * const calendar = getCalendar(); */ +// Ensure globally-installed npm packages are resolvable +// (sandbox startProcess does not inherit Dockerfile ENV vars) +if (!process.env.NODE_PATH) { + process.env.NODE_PATH = '/usr/local/lib/node_modules'; + require('module').Module._initPaths(); +} + const { google } = require('googleapis'); function getAuth() { From 359d70a3cff5a43de66ceba3a10ad4007b2f2275 Mon Sep 17 00:00:00 2001 From: Nicholas Scarabosio Date: Mon, 9 Feb 2026 15:47:28 -0700 Subject: [PATCH 6/9] Install gogcli and configure Google auth on container startup Replace googleapis npm package with the gogcli binary, which is OpenClaw's built-in Google Workspace skill. The startup script now configures gogcli credentials and imports the refresh token from env vars using the file-based keyring backend. Co-Authored-By: Claude Opus 4.6 --- Dockerfile | 14 +++++++++----- start-openclaw.sh | 31 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 51086036b..3da1a01aa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,10 +20,14 @@ RUN ARCH="$(dpkg --print-architecture)" \ # Install pnpm globally RUN npm install -g pnpm -# Install Google APIs client (for Google Workspace skill) -# NODE_PATH ensures globally installed modules are found by require() -ENV NODE_PATH=/usr/local/lib/node_modules -RUN npm install -g googleapis google-auth-library +# Install gogcli (Google Workspace CLI for Gmail/Calendar/Drive) +# OpenClaw has a built-in 'gog' skill that wraps this CLI +ENV GOG_VERSION=0.9.0 +RUN ARCH="$(dpkg --print-architecture)" \ + && curl -fsSL "https://github.com/steipete/gogcli/releases/download/v${GOG_VERSION}/gogcli_${GOG_VERSION}_linux_${ARCH}.tar.gz" -o /tmp/gogcli.tar.gz \ + && tar -xzf /tmp/gogcli.tar.gz -C /usr/local/bin gog \ + && rm /tmp/gogcli.tar.gz \ + && gog --version # Install OpenClaw (formerly clawdbot/moltbot) # Pin to specific version for reproducible builds @@ -37,7 +41,7 @@ RUN mkdir -p /root/.openclaw \ && mkdir -p /root/clawd/skills # Copy startup script -# Build cache bust: 2026-02-09-v32-script-node-path +# Build cache bust: 2026-02-09-v34-gogcli-auth-fix COPY start-openclaw.sh /usr/local/bin/start-openclaw.sh RUN chmod +x /usr/local/bin/start-openclaw.sh diff --git a/start-openclaw.sh b/start-openclaw.sh index dd9381d12..7b7ec7d9b 100644 --- a/start-openclaw.sh +++ b/start-openclaw.sh @@ -284,6 +284,37 @@ fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); console.log('Configuration patched successfully'); EOFPATCH +# ============================================================ +# CONFIGURE GOGCLI (Google Workspace CLI) +# ============================================================ +if [ -n "$GOOGLE_CLIENT_ID" ] && [ -n "$GOOGLE_CLIENT_SECRET" ] && [ -n "$GOOGLE_REFRESH_TOKEN" ]; then + echo "Configuring gogcli..." + + # Use file-based keyring with a fixed password (no TTY in container) + export GOG_KEYRING_PASSWORD="moltbot-container" + gog auth keyring file + + # Write credentials.json in Google Cloud Console "installed" format and import + GOG_CREDS_FILE="/tmp/gog-credentials.json" + cat > "$GOG_CREDS_FILE" <&1 || true + rm -f "$GOG_CREDS_FILE" + + # Write token file and import + GOG_TOKEN_FILE="/tmp/gog-token.json" + cat > "$GOG_TOKEN_FILE" <&1 || true + rm -f "$GOG_TOKEN_FILE" + + echo "gogcli configured for nick@culturetocash.com" +else + echo "GOOGLE_CLIENT_ID/SECRET/REFRESH_TOKEN not set, skipping gogcli setup" +fi + # ============================================================ # START GATEWAY # ============================================================ From bbb80151193605b599ae6fb867b596a18e1b79b0 Mon Sep 17 00:00:00 2001 From: Nicholas Scarabosio Date: Mon, 9 Feb 2026 17:09:36 -0700 Subject: [PATCH 7/9] Fix R2 sync config file detection using stdout instead of exitCode The sandbox SDK can have undefined exitCode for fast-exiting processes like `test -f`, causing the sync to falsely report "no config file found". Switch to ls + stdout parsing (FOUND/NOTFOUND) which is reliable regardless of exitCode timing. Co-Authored-By: Claude Opus 4.6 --- src/gateway/sync.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/gateway/sync.ts b/src/gateway/sync.ts index 63808c471..7e6bcb159 100644 --- a/src/gateway/sync.ts +++ b/src/gateway/sync.ts @@ -42,16 +42,23 @@ export async function syncToR2(sandbox: Sandbox, env: MoltbotEnv): Promise/dev/null && echo FOUND || echo NOTFOUND', + ); await waitForProcess(checkNew, 5000); - if (checkNew.exitCode !== 0) { - const checkLegacy = await sandbox.startProcess('test -f /root/.clawdbot/clawdbot.json'); + const checkNewLogs = await checkNew.getLogs(); + const newFound = checkNewLogs.stdout?.includes('FOUND') ?? false; + if (!newFound) { + const checkLegacy = await sandbox.startProcess( + 'ls /root/.clawdbot/clawdbot.json 2>/dev/null && echo FOUND || echo NOTFOUND', + ); await waitForProcess(checkLegacy, 5000); - if (checkLegacy.exitCode === 0) { + const checkLegacyLogs = await checkLegacy.getLogs(); + if (checkLegacyLogs.stdout?.includes('FOUND')) { configDir = '/root/.clawdbot'; } else { return { From 6f7c22f102e4ad21026af6b30ebd1ee53feac4f8 Mon Sep 17 00:00:00 2001 From: Nicholas Scarabosio Date: Mon, 9 Feb 2026 18:38:43 -0700 Subject: [PATCH 8/9] Add configurable agent model override via OPENCLAW_MODEL env var Allows switching the OpenClaw agent model (e.g. from Opus to Sonnet) without rebuilding the container, via wrangler secret. Co-Authored-By: Claude Opus 4.6 --- src/gateway/env.ts | 1 + src/types.ts | 2 ++ start-openclaw.sh | 8 ++++++++ 3 files changed, 11 insertions(+) diff --git a/src/gateway/env.ts b/src/gateway/env.ts index a4064cead..9c2c64520 100644 --- a/src/gateway/env.ts +++ b/src/gateway/env.ts @@ -49,6 +49,7 @@ export function buildEnvVars(env: MoltbotEnv): Record { if (env.CF_ACCOUNT_ID) envVars.CF_ACCOUNT_ID = env.CF_ACCOUNT_ID; if (env.CDP_SECRET) envVars.CDP_SECRET = env.CDP_SECRET; if (env.WORKER_URL) envVars.WORKER_URL = env.WORKER_URL; + if (env.OPENCLAW_MODEL) envVars.OPENCLAW_MODEL = env.OPENCLAW_MODEL; if (env.GOOGLE_CLIENT_ID) envVars.GOOGLE_CLIENT_ID = env.GOOGLE_CLIENT_ID; if (env.GOOGLE_CLIENT_SECRET) envVars.GOOGLE_CLIENT_SECRET = env.GOOGLE_CLIENT_SECRET; if (env.GOOGLE_REFRESH_TOKEN) envVars.GOOGLE_REFRESH_TOKEN = env.GOOGLE_REFRESH_TOKEN; diff --git a/src/types.ts b/src/types.ts index 712de062e..13edf6c1d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -42,6 +42,8 @@ export interface MoltbotEnv { BROWSER?: Fetcher; CDP_SECRET?: string; // Shared secret for CDP endpoint authentication WORKER_URL?: string; // Public URL of the worker (for CDP endpoint) + // OpenClaw agent model override (e.g. 'anthropic/claude-sonnet-4-5') + OPENCLAW_MODEL?: string; // Google Workspace OAuth credentials (for Gmail/Calendar access) GOOGLE_CLIENT_ID?: string; GOOGLE_CLIENT_SECRET?: string; diff --git a/start-openclaw.sh b/start-openclaw.sh index 7b7ec7d9b..0863ea823 100644 --- a/start-openclaw.sh +++ b/start-openclaw.sh @@ -189,6 +189,14 @@ if (process.env.OPENCLAW_DEV_MODE === 'true') { config.gateway.controlUi.allowInsecureAuth = true; } +// Agent model override (OPENCLAW_MODEL=anthropic/claude-sonnet-4-5) +if (process.env.OPENCLAW_MODEL) { + config.agents = config.agents || {}; + config.agents.defaults = config.agents.defaults || {}; + config.agents.defaults.model = { primary: process.env.OPENCLAW_MODEL }; + console.log('Model override:', process.env.OPENCLAW_MODEL); +} + // Legacy AI Gateway base URL override: // ANTHROPIC_BASE_URL is picked up natively by the Anthropic SDK, // so we don't need to patch the provider config. Writing a provider From a2e4fb5269590b3244940736502c43059686f6a5 Mon Sep 17 00:00:00 2001 From: Nicholas Scarabosio Date: Mon, 9 Feb 2026 19:32:20 -0700 Subject: [PATCH 9/9] Reduce agent concurrency and route through Cloudflare AI Gateway Reduces maxConcurrent from 4 to 1 and subagents from 8 to 2 to avoid Anthropic API rate limits. AI Gateway adds caching, rate limit buffering, and request logging. Co-Authored-By: Claude Opus 4.6 --- start-openclaw.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/start-openclaw.sh b/start-openclaw.sh index 0863ea823..7fcbbba3a 100644 --- a/start-openclaw.sh +++ b/start-openclaw.sh @@ -197,6 +197,15 @@ if (process.env.OPENCLAW_MODEL) { console.log('Model override:', process.env.OPENCLAW_MODEL); } +// Reduce concurrency to avoid Anthropic API rate limits +// Default is maxConcurrent=4 + subagents=8 which can fire 12 parallel requests +config.agents = config.agents || {}; +config.agents.defaults = config.agents.defaults || {}; +config.agents.defaults.maxConcurrent = 1; +config.agents.defaults.subagents = config.agents.defaults.subagents || {}; +config.agents.defaults.subagents.maxConcurrent = 2; +console.log('Concurrency: maxConcurrent=1, subagents.maxConcurrent=2'); + // Legacy AI Gateway base URL override: // ANTHROPIC_BASE_URL is picked up natively by the Anthropic SDK, // so we don't need to patch the provider config. Writing a provider