From 7531bdf3edc3a5622524af981d60dea6de8005e1 Mon Sep 17 00:00:00 2001 From: tranquiliann <168668888+tranquiliann@users.noreply.github.com> Date: Fri, 20 Feb 2026 02:21:05 +0100 Subject: [PATCH 1/7] feat: inject OpenRouter configuration for Kimi K2.5 model into start-openclaw.sh. --- package-lock.json | 519 ++++++++++++++++++++++++++++++++++++++++++++++ start-openclaw.sh | 16 ++ 2 files changed, 535 insertions(+) diff --git a/package-lock.json b/package-lock.json index 2e5494df7..5c3acf0ca 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", diff --git a/start-openclaw.sh b/start-openclaw.sh index c862a80ce..58e146020 100644 --- a/start-openclaw.sh +++ b/start-openclaw.sh @@ -260,6 +260,22 @@ if (process.env.SLACK_BOT_TOKEN && process.env.SLACK_APP_TOKEN) { }; } +// Custom OpenRouter injection for Kimi K2 +if (process.env.OPENAI_API_KEY && process.env.OPENAI_API_KEY.startsWith('sk-or')) { + config.models = config.models || {}; + config.models.providers = config.models.providers || {}; + config.models.providers['openrouter'] = { + baseUrl: 'https://openrouter.ai/api/v1', + apiKey: process.env.OPENAI_API_KEY, + api: 'openai-completions', + models: [{ id: 'moonshotai/kimi-k2.5', name: 'Kimi K2.5', contextWindow: 262144, maxTokens: 8192 }] + }; + config.agents = config.agents || {}; + config.agents.defaults = config.agents.defaults || {}; + config.agents.defaults.model = { primary: 'openrouter/moonshotai/kimi-k2.5' }; + console.log('Injected OpenRouter config with Kimi K2.5 as primary model'); +} + fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); console.log('Configuration patched successfully'); EOFPATCH From de67c3407a6beb568de897524e3bf14c048d424d Mon Sep 17 00:00:00 2001 From: tranquiliann <168668888+tranquiliann@users.noreply.github.com> Date: Fri, 20 Feb 2026 02:27:10 +0100 Subject: [PATCH 2/7] feat: Allow Cloudflare Access bypass when `CF_ACCESS_TEAM_DOMAIN` is 'UNCONFIGURED'. --- src/index.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/index.ts b/src/index.ts index 3a615dd61..747f551f7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -197,6 +197,11 @@ app.use('*', async (c, next) => { // Middleware: Cloudflare Access authentication for protected routes app.use('*', async (c, next) => { + // Allow bypassing Cloudflare Access if configured as 'UNCONFIGURED' (for testing without setup) + if (c.env.CF_ACCESS_TEAM_DOMAIN === 'UNCONFIGURED') { + return next(); + } + // Determine response type based on Accept header const acceptsHtml = c.req.header('Accept')?.includes('text/html'); const middleware = createAccessMiddleware({ From 4b6d04e350655e2a6705579074e40270f736cecd Mon Sep 17 00:00:00 2001 From: tranquiliann <168668888+tranquiliann@users.noreply.github.com> Date: Fri, 20 Feb 2026 02:32:18 +0100 Subject: [PATCH 3/7] Update start-openclaw.sh with MiniMax M2.5 support --- start-openclaw.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/start-openclaw.sh b/start-openclaw.sh index 58e146020..0a0652e22 100644 --- a/start-openclaw.sh +++ b/start-openclaw.sh @@ -268,7 +268,11 @@ if (process.env.OPENAI_API_KEY && process.env.OPENAI_API_KEY.startsWith('sk-or') baseUrl: 'https://openrouter.ai/api/v1', apiKey: process.env.OPENAI_API_KEY, api: 'openai-completions', - models: [{ id: 'moonshotai/kimi-k2.5', name: 'Kimi K2.5', contextWindow: 262144, maxTokens: 8192 }] + models: [ + { id: 'moonshotai/kimi-k2.5', name: 'Kimi K2.5', contextWindow: 262144, maxTokens: 8192 }, + { id: 'minimax/minimax-01', name: 'MiniMax-01', contextWindow: 1000000, maxTokens: 8192 }, + { id: 'minimax/minimax-m2.5', name: 'MiniMax M2.5', contextWindow: 196608, maxTokens: 8192 } + ] }; config.agents = config.agents || {}; config.agents.defaults = config.agents.defaults || {}; From b3cc64e06e6d68441a8a0eb96517c2d934d2ab34 Mon Sep 17 00:00:00 2001 From: tranquiliann <168668888+tranquiliann@users.noreply.github.com> Date: Mon, 23 Feb 2026 22:53:32 +0100 Subject: [PATCH 4/7] feat: Implement `/debug/setup-context` endpoint, introduce new ElevenLabs, Gmail, and Web Researcher skills, and add a comprehensive Moltbot quickstart guide. --- MOLTBOT_QUICKSTART.md | 130 ++++++++++++++++ skills/elevenlabs-operator/SKILL.md | 77 ++++++++++ .../scripts/create-agent.sh | 81 ++++++++++ skills/gmail-assistant/SKILL.md | 76 ++++++++++ skills/gmail-assistant/scripts/draft.js | 140 ++++++++++++++++++ skills/web-researcher/SKILL.md | 69 +++++++++ src/routes/debug.ts | 61 ++++++++ start-openclaw.sh | 10 ++ 8 files changed, 644 insertions(+) create mode 100644 MOLTBOT_QUICKSTART.md create mode 100644 skills/elevenlabs-operator/SKILL.md create mode 100644 skills/elevenlabs-operator/scripts/create-agent.sh create mode 100644 skills/gmail-assistant/SKILL.md create mode 100644 skills/gmail-assistant/scripts/draft.js create mode 100644 skills/web-researcher/SKILL.md diff --git a/MOLTBOT_QUICKSTART.md b/MOLTBOT_QUICKSTART.md new file mode 100644 index 000000000..554598fa1 --- /dev/null +++ b/MOLTBOT_QUICKSTART.md @@ -0,0 +1,130 @@ +# Moltbot / OpenClaw — Quick Start & Debug Notes + +> Created: 2026-02-23 +> Purpose: Help any future AI agent or developer instantly understand how to access, debug, and manage this OpenClaw instance. + +--- + +## 🌐 Deployed Worker + +| Field | Value | +|---|---| +| **Worker URL** | `https://moltbot-sandbox.calebbroohm74.workers.dev` | +| **Gateway Token** | `molt-secret-123` *(consider rotating — see security note below)* | +| **Admin UI** | `https://moltbot-sandbox.calebbroohm74.workers.dev/_admin/?token=molt-secret-123` | +| **Web Chat** | `https://moltbot-sandbox.calebbroohm74.workers.dev/?token=molt-secret-123` | + +--- + +## 🚀 How to "Start" the Agent + +The OpenClaw agent runs inside a **Cloudflare Sandbox container**. It may be asleep (cold start). + +**To wake it up:** Simply visit the Worker URL in a browser or send any HTTP request to it: +``` +https://moltbot-sandbox.calebbroohm74.workers.dev/?token=molt-secret-123 +``` + +The first load may take **30–120 seconds** (cold start) while the container boots and OpenClaw initializes. A loading page will display during this time. **Just wait — it will come up!** + +--- + +## 🐛 Debug Endpoints + +All debug routes require `?token=YOUR_TOKEN` appended to the URL. They are enabled by the `DEBUG_ROUTES=true` secret. + +| Endpoint | What it shows | +|---|---| +| `/debug/processes?logs=true` | All running processes in the container + their logs | +| `/debug/logs` | Startup logs for the OpenClaw gateway process | +| `/debug/container-config` | The final `openclaw.json` config as written inside the container | +| `/debug/env` | Which secrets/env vars are set (values are hidden) | +| `/debug/version` | OpenClaw + Node.js version inside the container | +| `/debug/cli?cmd=COMMAND` | Run any shell command inside the container | + +**Example curl:** +```bash +curl -s "https://moltbot-sandbox.calebbroohm74.workers.dev/debug/logs?token=molt-secret-123" | python3 -m json.tool +``` + +--- + +## 🔑 Required Wrangler Secrets + +Set these with `wrangler secret put ` from the `/Users/calebniikwei/moltworker/` directory. + +| Secret | Required | Purpose | +|---|---|---| +| `MOLTBOT_GATEWAY_TOKEN` | ✅ Yes | Protects gateway access (current: `molt-secret-123`) | +| `ANTHROPIC_API_KEY` | ✅ Yes (or OpenAI) | AI model provider | +| `OPENAI_API_KEY` | ✅ Alt. | Alternative AI model provider | +| `CF_ACCESS_TEAM_DOMAIN` | ✅ Yes | Cloudflare Access team domain | +| `CF_ACCESS_AUD` | ✅ Yes | Cloudflare Access audience tag | +| `TELEGRAM_BOT_TOKEN` | ❌ Optional | Telegram chat channel | +| `DISCORD_BOT_TOKEN` | ❌ Optional | Discord chat channel | +| `R2_ACCESS_KEY_ID` | ❌ Optional | R2 persistence (config/skills backup) | +| `R2_SECRET_ACCESS_KEY` | ❌ Optional | R2 persistence | +| `CF_ACCOUNT_ID` | ❌ Optional | Needed for R2 endpoint | +| `DEBUG_ROUTES` | ❌ Optional | Set to `"true"` to enable `/debug/*` endpoints | + +--- + +## 📁 Project Layout + +``` +moltworker/ +├── start-openclaw.sh # Main startup script — runs inside the container +│ # (restores from R2, runs onboard, patches config, starts gateway) +├── Dockerfile # Container image (sandbox:0.7.0 + Node 22 + openclaw@2026.2.3) +├── wrangler.jsonc # Cloudflare Worker config (routes, R2, containers, etc.) +├── src/ +│ ├── index.ts # Main worker — proxies requests into the sandbox container +│ ├── gateway/process.ts # Logic to start/find the OpenClaw gateway process +│ ├── gateway/env.ts # Maps Worker env secrets → container env vars +│ └── routes/debug.ts # All /debug/* endpoints +├── skills/ # Custom skills copied into the container at /root/clawd/skills/ +│ └── cloudflare-browser/ # Browser automation via CDP +└── MOLTBOT_QUICKSTART.md # ← This file +``` + +--- + +## 🔄 Deploying Changes + +```bash +cd /Users/calebniikwei/moltworker + +# Deploy worker + rebuild container image: +npm run deploy +# or +wrangler deploy + +# Watch live logs: +wrangler tail + +# Update a secret: +wrangler secret put MOLTBOT_GATEWAY_TOKEN +``` + +> **Note:** Changes to `start-openclaw.sh` or `Dockerfile` require a full redeploy to take effect inside the container. + +--- + +## ⚠️ Security Note + +The current gateway token `molt-secret-123` is weak. Generate a proper one: +```bash +openssl rand -hex 32 +# Then: +wrangler secret put MOLTBOT_GATEWAY_TOKEN +``` + +--- + +## 🧠 What Happened on 2026-02-23 + +- OpenClaw appeared "broken" (not responding). +- Root cause: **Cloudflare Sandbox cold start** — the container was simply asleep. +- Fix: Navigating to the Worker URL woke the container. OpenClaw booted and started responding normally within ~60 seconds. +- The agent is working correctly. It correctly refused password sharing and suggested secure auth alternatives. +- **No code changes were needed.** This was a cold-start issue, not a bug. diff --git a/skills/elevenlabs-operator/SKILL.md b/skills/elevenlabs-operator/SKILL.md new file mode 100644 index 000000000..1c4125cc1 --- /dev/null +++ b/skills/elevenlabs-operator/SKILL.md @@ -0,0 +1,77 @@ +--- +name: elevenlabs-operator +description: Create new ElevenLabs conversational voice agents for clients. This skill posts a structured payload to an n8n webhook, which then calls the ElevenLabs API. The agent must NEVER contact ElevenLabs directly. +--- + +# Agency Operator — ElevenLabs Voice Agent Creator + +You help create new ElevenLabs conversational AI voice agents for clients. You send a structured request to an **n8n webhook**, which handles the actual ElevenLabs API call. + +## Hard Constraint + +> [!IMPORTANT] +> **Never contact ElevenLabs directly.** Never call `api.elevenlabs.io` from any skill script. +> ALL requests must go through the n8n webhook at `N8N_ELEVENLABS_WEBHOOK_URL`. + +## Required Information + +Before creating an agent, you MUST collect all of the following from the user: + +| Field | Description | Example | +|---|---|---| +| `client_name` | Name of the client for this agent | `"Acme Corp"` | +| `agent_prompt` | The full system prompt / persona for the voice agent | `"You are a friendly support agent for Acme..."` | +| `voice_id` | ElevenLabs Voice ID to use | `"21m00Tcm4TlvDq8ikWAM"` | +| `post_call_webhook_url` | URL n8n should configure for post-call callbacks | `"https://n8n.yourdomain.com/webhook/post-call"` | + +If any field is missing, ask the user for it before proceeding. + +## How to Create an Agent + +Run the creation script: + +```bash +bash /root/clawd/skills/elevenlabs-operator/scripts/create-agent.sh \ + --client-name "Acme Corp" \ + --agent-prompt "You are a support agent for Acme Corp..." \ + --voice-id "21m00Tcm4TlvDq8ikWAM" \ + --post-call-webhook "https://n8n.yourdomain.com/webhook/post-call" +``` + +## Required Environment Variables + +| Variable | Description | +|---|---| +| `N8N_ELEVENLABS_WEBHOOK_URL` | Full URL of your n8n webhook endpoint | + +## Workflow + +1. **Collect parameters** — Ask for any missing fields from the table above. +2. **Confirm with user** — Show a summary and ask "Shall I create this voice agent?" +3. **Run the script** — Execute `create-agent.sh` with the collected parameters. +4. **Report back** — Parse the response and report the new `agent_id` to the user. + +## Example Interaction + +**User:** "Create a voice agent for my client Acme Corp." + +**Agent:** +> I need a few more details to create the ElevenLabs voice agent: +> 1. What should the agent's persona/system prompt be? +> 2. Which ElevenLabs voice ID should it use? +> 3. Where should post-call data be sent (webhook URL)? + +[User provides info] + +> Here's the agent I'll create: +> - **Client:** Acme Corp +> - **Voice ID:** 21m00Tcm4TlvDq8ikWAM +> - **Post-call webhook:** https://n8n.yourdomain.com/webhook/post-call +> - **Prompt:** You are a support agent for Acme... +> +> Shall I proceed? + +[User confirms → script runs → response parsed] + +> ✅ Voice agent created! Agent ID: `agent_abc123` +> Your client's agent is live in ElevenLabs. diff --git a/skills/elevenlabs-operator/scripts/create-agent.sh b/skills/elevenlabs-operator/scripts/create-agent.sh new file mode 100644 index 000000000..d9635d2f4 --- /dev/null +++ b/skills/elevenlabs-operator/scripts/create-agent.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +# ElevenLabs Voice Agent Creator — via n8n webhook +# +# Usage: +# bash create-agent.sh \ +# --client-name "Acme Corp" \ +# --agent-prompt "You are a support agent..." \ +# --voice-id "21m00Tcm4TlvDq8ikWAM" \ +# --post-call-webhook "https://n8n.yourdomain.com/webhook/post-call" +# +# Required env vars: +# N8N_ELEVENLABS_WEBHOOK_URL - Full URL of your n8n webhook endpoint + +set -e + +# ─── Parse args ─────────────────────────────────────────────────────────────── +CLIENT_NAME="" +AGENT_PROMPT="" +VOICE_ID="" +POST_CALL_WEBHOOK="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --client-name) CLIENT_NAME="$2"; shift 2 ;; + --agent-prompt) AGENT_PROMPT="$2"; shift 2 ;; + --voice-id) VOICE_ID="$2"; shift 2 ;; + --post-call-webhook) POST_CALL_WEBHOOK="$2"; shift 2 ;; + *) echo "Unknown argument: $1" >&2; exit 1 ;; + esac +done + +# ─── Validate ───────────────────────────────────────────────────────────────── +if [ -z "$CLIENT_NAME" ] || [ -z "$AGENT_PROMPT" ] || [ -z "$VOICE_ID" ] || [ -z "$POST_CALL_WEBHOOK" ]; then + echo "ERROR: All of --client-name, --agent-prompt, --voice-id, and --post-call-webhook are required." >&2 + exit 1 +fi + +if [ -z "$N8N_ELEVENLABS_WEBHOOK_URL" ]; then + echo "ERROR: N8N_ELEVENLABS_WEBHOOK_URL environment variable is not set." >&2 + exit 1 +fi + +# ─── Build JSON payload ─────────────────────────────────────────────────────── +PAYLOAD=$(cat </dev/null || echo "(check n8n for agent ID)") + echo " Agent ID: $AGENT_ID" +else + echo "" + echo "❌ Webhook call failed (HTTP $HTTP_CODE). Check your n8n logs." >&2 + exit 1 +fi diff --git a/skills/gmail-assistant/SKILL.md b/skills/gmail-assistant/SKILL.md new file mode 100644 index 000000000..573c26f68 --- /dev/null +++ b/skills/gmail-assistant/SKILL.md @@ -0,0 +1,76 @@ +--- +name: gmail-assistant +description: Draft emails on behalf of the user using the Gmail API. CRITICAL: This skill can ONLY create drafts. It must NEVER send emails autonomously. All drafts require the user to review and send manually in Gmail. +--- + +# Gmail Executive Assistant + +You help manage email by creating **draft emails** in Gmail. You do NOT send emails. Ever. + +## Hard Constraints + +> [!CAUTION] +> **You are PROHIBITED from calling any Gmail API endpoint that sends email.** +> The ONLY permitted Gmail API call is: `POST /gmail/v1/users/me/drafts` +> Never call `/messages/send`, `/drafts/send`, or any sending variant. No exceptions. + +The user **always** sends emails themselves after reviewing the draft in Gmail. + +## How to Create a Draft + +Run the draft script with the required arguments: + +```bash +node /root/clawd/skills/gmail-assistant/scripts/draft.js \ + --to "recipient@example.com" \ + --subject "Subject line here" \ + --body "Full email body text here" +``` + +### Required Arguments +| Flag | Description | +|---|---| +| `--to` | Recipient email address | +| `--subject` | Email subject line | +| `--body` | Plain text email body | + +### Optional Arguments +| Flag | Description | +|---|---| +| `--cc` | CC recipients (comma-separated) | +| `--bcc` | BCC recipients (comma-separated) | + +## Required Environment Variables + +These must be set as Wrangler secrets: + +| Variable | Description | +|---|---| +| `GMAIL_CLIENT_ID` | Google OAuth 2.0 Client ID | +| `GMAIL_CLIENT_SECRET` | Google OAuth 2.0 Client Secret | +| `GMAIL_REFRESH_TOKEN` | OAuth Refresh Token (from one-time auth flow) | + +> See `OAUTH_SETUP.md` for how to obtain these values. + +## Workflow + +1. **Gather required info** — Ask the user for `to`, `subject`, and `body` if not provided. +2. **Confirm before creating** — Always confirm the draft contents with the user before running the script. +3. **Run the script** — Execute `draft.js` with the collected arguments. +4. **Report back** — Tell the user the draft was created and they can find it in Gmail Drafts. + +## Example Interaction + +**User:** "Draft an email to john@company.com telling him our meeting is moved to Thursday at 3pm." + +**Agent response:** +> I'll create a draft with the following: +> - **To:** john@company.com +> - **Subject:** Meeting Rescheduled — Thursday 3pm +> - **Body:** Hi John, just a quick note that our meeting has been moved to Thursday at 3:00 PM. Let me know if that works for you! +> +> Creating draft now... + +[Runs script → confirms draft created] + +> ✅ Draft created! Check your Gmail Drafts folder to review and send. diff --git a/skills/gmail-assistant/scripts/draft.js b/skills/gmail-assistant/scripts/draft.js new file mode 100644 index 000000000..98c6d48c9 --- /dev/null +++ b/skills/gmail-assistant/scripts/draft.js @@ -0,0 +1,140 @@ +#!/usr/bin/env node +/** + * Gmail Draft Creator + * Creates a draft email using the Gmail API via OAuth. + * + * Usage: + * node draft.js --to "someone@example.com" --subject "Hello" --body "Email body" + * + * Required env vars: + * GMAIL_CLIENT_ID - Google OAuth 2.0 Client ID + * GMAIL_CLIENT_SECRET - Google OAuth 2.0 Client Secret + * GMAIL_REFRESH_TOKEN - OAuth refresh token (from one-time auth flow) + */ + +const https = require('https'); + +// ─── Parse CLI args ─────────────────────────────────────────────────────────── +const args = process.argv.slice(2); +const get = (flag) => { + const i = args.indexOf(flag); + return i !== -1 ? args[i + 1] : null; +}; + +const to = get('--to'); +const subject = get('--subject'); +const body = get('--body'); +const cc = get('--cc') || ''; +const bcc = get('--bcc') || ''; + +if (!to || !subject || !body) { + console.error('ERROR: --to, --subject, and --body are required.'); + process.exit(1); +} + +// ─── Env vars ───────────────────────────────────────────────────────────────── +const { GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET, GMAIL_REFRESH_TOKEN } = process.env; +if (!GMAIL_CLIENT_ID || !GMAIL_CLIENT_SECRET || !GMAIL_REFRESH_TOKEN) { + console.error('ERROR: GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET, and GMAIL_REFRESH_TOKEN must be set.'); + process.exit(1); +} + +// ─── Helpers ────────────────────────────────────────────────────────────────── +function request(options, postData) { + return new Promise((resolve, reject) => { + const req = https.request(options, (res) => { + let data = ''; + res.on('data', chunk => data += chunk); + res.on('end', () => { + try { resolve({ status: res.statusCode, body: JSON.parse(data) }); } + catch { resolve({ status: res.statusCode, body: data }); } + }); + }); + req.on('error', reject); + if (postData) req.write(postData); + req.end(); + }); +} + +// ─── Step 1: Refresh access token ───────────────────────────────────────────── +async function getAccessToken() { + const params = new URLSearchParams({ + client_id: GMAIL_CLIENT_ID, + client_secret: GMAIL_CLIENT_SECRET, + refresh_token: GMAIL_REFRESH_TOKEN, + grant_type: 'refresh_token', + }); + + const res = await request({ + hostname: 'oauth2.googleapis.com', + path: '/token', + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + }, params.toString()); + + if (res.status !== 200 || !res.body.access_token) { + throw new Error(`Token refresh failed (${res.status}): ${JSON.stringify(res.body)}`); + } + return res.body.access_token; +} + +// ─── Step 2: Build RFC 2822 email ───────────────────────────────────────────── +function buildRawEmail({ to, cc, bcc, subject, body }) { + const lines = [ + `To: ${to}`, + cc ? `Cc: ${cc}` : null, + bcc ? `Bcc: ${bcc}` : null, + `Subject: ${subject}`, + 'Content-Type: text/plain; charset="UTF-8"', + 'MIME-Version: 1.0', + '', + body, + ].filter(Boolean); + + return Buffer.from(lines.join('\r\n')) + .toString('base64') + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/, ''); +} + +// ─── Step 3: Create Gmail draft ─────────────────────────────────────────────── +async function createDraft(accessToken, rawEmail) { + const payload = JSON.stringify({ message: { raw: rawEmail } }); + + const res = await request({ + hostname: 'gmail.googleapis.com', + path: '/gmail/v1/users/me/drafts', + method: 'POST', + headers: { + 'Authorization': `Bearer ${accessToken}`, + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(payload), + }, + }, payload); + + if (res.status !== 200) { + throw new Error(`Draft creation failed (${res.status}): ${JSON.stringify(res.body)}`); + } + return res.body; +} + +// ─── Main ───────────────────────────────────────────────────────────────────── +(async () => { + try { + console.log('Refreshing Gmail access token...'); + const accessToken = await getAccessToken(); + + console.log(`Creating draft → To: ${to} | Subject: ${subject}`); + const raw = buildRawEmail({ to, cc, bcc, subject, body }); + const draft = await createDraft(accessToken, raw); + + console.log('✅ Draft created successfully!'); + console.log(` Draft ID : ${draft.id}`); + console.log(` Message ID: ${draft.message?.id}`); + console.log(' The draft is in your Gmail Drafts folder. Review and send it yourself.'); + } catch (err) { + console.error('❌ Error:', err.message); + process.exit(1); + } +})(); diff --git a/skills/web-researcher/SKILL.md b/skills/web-researcher/SKILL.md new file mode 100644 index 000000000..e761a34bc --- /dev/null +++ b/skills/web-researcher/SKILL.md @@ -0,0 +1,69 @@ +--- +name: web-researcher +description: Use this skill to research the web. Provides access to web_search (keyword search), web_fetch (retrieve page content), and browser (full headless browser for JS-heavy sites). Apply strict sandboxing rules at all times. +--- + +# Web Researcher + +You are a Web Researcher. Use these tools to find, retrieve, and summarize information from the internet. + +## Tools Available + +| Tool | When to Use | +|---|---| +| `web_search` | **First choice.** Keyword/question searches. Returns ranked links + snippets. | +| `web_fetch` | Retrieve the raw HTML/text of a specific URL. Use when you already know the exact URL. | +| `browser` | **Last resort.** Only when a page requires JavaScript to render (SPAs, login walls, dynamic content). Slower and more resource-intensive. | + +## Research Workflow + +1. **Start with `web_search`** — query the topic, review top results. +2. **Use `web_fetch`** on the most relevant URL(s) to get full content. +3. **Use `browser`** only if `web_fetch` returns empty/JS-blocked content. +4. **Synthesize** — do not just paste raw content. Summarize, extract key facts, cite sources. + +## Safety Rules — READ BEFORE EVERY REQUEST + +> [!IMPORTANT] +> These rules are mandatory. Never bypass them. + +- ❌ **Never** navigate to `file://` URLs (protects local filesystem) +- ❌ **Never** navigate to `localhost`, `127.0.0.1`, or any RFC-1918 private IP (10.x, 172.16.x, 192.168.x) +- ❌ **Never** follow redirects to internal/private addresses +- ❌ **Never** submit forms with credentials unless the user explicitly says "log in for me" +- ✅ **Only** access public internet URLs (http/https) +- ✅ **Always** tell the user what URL you are about to visit before visiting it + +## Output Format + +After research, structure your response as: + +``` +## Summary +[2-4 sentence summary of findings] + +## Key Facts +- Fact 1 (Source: URL) +- Fact 2 (Source: URL) + +## Sources +1. [Title](URL) — one-line description +``` + +## Examples + +**Web Search:** +``` +web_search("latest OpenAI model releases 2025") +``` + +**Fetch a specific page:** +``` +web_fetch("https://openai.com/news") +``` + +**Use browser for JS-heavy site:** +``` +browser.navigate("https://app.example.com/dashboard") +browser.screenshot() +``` diff --git a/src/routes/debug.ts b/src/routes/debug.ts index 8ffc05bfb..9898b3eaf 100644 --- a/src/routes/debug.ts +++ b/src/routes/debug.ts @@ -386,4 +386,65 @@ debug.get('/container-config', async (c) => { } }); +// GET /debug/setup-context - Injects context and memory into the container +debug.get('/setup-context', async (c) => { + const sandbox = c.get('sandbox'); + + // Context data from the user's workspace + const identityContext = ` +# USER IDENTITY & CONTEXT +- User: Caleb Broohm +- Business: Descentra AI LLC (wyoming-based) +- Email: info@descentraai.com +- Phone: +43 664 8787784 +- Role: Founder / Authorized Member +- Website: https://descentraai.com +- Current Project: Moltworker (personal AI assistant on Cloudflare) +`.trim(); + + const instructions = ` +# PERSONAL ASSISTANT GUIDELINES +- You are Moltbot, a personal AI assistant for Caleb Broohm. +- You should be aware of his business, Descentra AI LLC. +- Help him manage his projects, especially Moltworker and the Descentra AI landing page. +- Be proactive and helpful. +`.trim(); + + try { + // Write the context and instructions to files in the container + // OpenClaw agents look for context in ~/.openclaw/workspace/context.md or similar + // We'll also inject a session-level memory if possible + + // 1. Create the workspace directory if it doesn't exist + await sandbox.exec('mkdir -p /root/.openclaw/workspace'); + + // 2. Write the identity context using base64 for safety + await sandbox.exec(`echo "${btoa(identityContext)}" | base64 -d > /root/.openclaw/workspace/context.md`); + + // 3. Write the instructions + await sandbox.exec(`echo "${btoa(instructions)}" | base64 -d > /root/.openclaw/workspace/instructions.md`); + + // 4. Inject into the active openclaw process by creating a "memory" entry + const memoryUpdate = ` +# MEMORY +Caleb Broohm is the founder of Descentra AI LLC. +The business is a Wyoming LLC based in Sheridan, WY. +Contact: info@descentraai.com / +43 664 8787784. +`.trim(); + + await sandbox.exec(`echo "${btoa(memoryUpdate)}" | base64 -d > /root/.openclaw/workspace/memory.md`); + + return c.json({ + status: 'ok', + message: 'Context and memory injected into Moltbot workspace', + context_files: ['context.md', 'instructions.md', 'memory.md'], + path: '/root/.openclaw/workspace/' + }); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error'; + return c.json({ error: errorMessage }, 500); + } +}); + export { debug }; + diff --git a/start-openclaw.sh b/start-openclaw.sh index 0a0652e22..c2dccaa0a 100644 --- a/start-openclaw.sh +++ b/start-openclaw.sh @@ -229,6 +229,11 @@ if (process.env.TELEGRAM_BOT_TOKEN) { enabled: true, dmPolicy: dmPolicy, }; + // Enable the plugin explicitly to satisfy openclaw doctor + config.plugins = config.plugins || {}; + config.plugins.entries = config.plugins.entries || {}; + config.plugins.entries.telegram = { enabled: true }; + if (process.env.TELEGRAM_DM_ALLOW_FROM) { config.channels.telegram.allowFrom = process.env.TELEGRAM_DM_ALLOW_FROM.split(','); } else if (dmPolicy === 'open') { @@ -280,10 +285,15 @@ if (process.env.OPENAI_API_KEY && process.env.OPENAI_API_KEY.startsWith('sk-or') console.log('Injected OpenRouter config with Kimi K2.5 as primary model'); } +console.log('Final Config:', JSON.stringify(config, null, 2)); fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); console.log('Configuration patched successfully'); EOFPATCH +# Run doctor --fix to ensure Telegram/etc are fully enabled and healthy +echo "Running openclaw doctor --fix..." +openclaw doctor --fix || echo "Doctor fix failed or returned non-zero (this is often normal if no repairs needed)" + # ============================================================ # BACKGROUND SYNC LOOP # ============================================================ From 6c87e58a5059ad93e694c3214c94a12b8b92e261 Mon Sep 17 00:00:00 2001 From: tranquiliann <168668888+tranquiliann@users.noreply.github.com> Date: Mon, 23 Feb 2026 22:54:46 +0100 Subject: [PATCH 5/7] feat: Add setup guides for ElevenLabs n8n integration and Gmail OAuth, along with an example environment file. --- .env.example | 105 +++++++++++++++++ skills/elevenlabs-operator/N8N_SETUP.md | 145 ++++++++++++++++++++++++ skills/gmail-assistant/OAUTH_SETUP.md | 138 ++++++++++++++++++++++ 3 files changed, 388 insertions(+) create mode 100644 .env.example create mode 100644 skills/elevenlabs-operator/N8N_SETUP.md create mode 100644 skills/gmail-assistant/OAUTH_SETUP.md diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..4f19fec10 --- /dev/null +++ b/.env.example @@ -0,0 +1,105 @@ +# ============================================================ +# Moltbot Digital Employee — Environment Variables +# ============================================================ +# Copy this file and fill in your values. +# Then set each one as a Wrangler secret: +# wrangler secret put VARIABLE_NAME +# +# DO NOT commit real values to git. This file is for reference only. +# ============================================================ + + +# ───────────────────────────────────────────────────────────── +# CORE (Required for OpenClaw to start) +# ───────────────────────────────────────────────────────────── + +# Token that protects access to your OpenClaw gateway. +# Generate a strong one: openssl rand -hex 32 +MOLTBOT_GATEWAY_TOKEN=your-strong-token-here + +# Cloudflare Access — protects your worker URL from public access. +# Found in: Cloudflare Zero Trust → Access → Applications +CF_ACCESS_TEAM_DOMAIN=yourteam.cloudflareaccess.com +CF_ACCESS_AUD=your-access-audience-tag-here + + +# ───────────────────────────────────────────────────────────── +# AI PROVIDER (At least one required) +# ───────────────────────────────────────────────────────────── + +# Option A: Anthropic (Claude) +ANTHROPIC_API_KEY=sk-ant-... + +# Option B: OpenAI +OPENAI_API_KEY=sk-... + +# Option C: Cloudflare AI Gateway (routes through your CF gateway) +CLOUDFLARE_AI_GATEWAY_API_KEY=your-gateway-api-key +CF_AI_GATEWAY_ACCOUNT_ID=your-cloudflare-account-id +CF_AI_GATEWAY_GATEWAY_ID=your-gateway-id + + +# ───────────────────────────────────────────────────────────── +# ROLE 1 — WEB RESEARCHER +# (No additional secrets needed — uses built-in tools) +# ───────────────────────────────────────────────────────────── + +# Optional: Enable debug routes to inspect container state +DEBUG_ROUTES=false + + +# ───────────────────────────────────────────────────────────── +# ROLE 2 — EXECUTIVE ASSISTANT (Gmail) +# See: skills/gmail-assistant/OAUTH_SETUP.md for how to get these +# ───────────────────────────────────────────────────────────── + +# Google Cloud OAuth 2.0 credentials +GMAIL_CLIENT_ID=your-google-client-id.apps.googleusercontent.com +GMAIL_CLIENT_SECRET=GOCSPX-your-client-secret +GMAIL_REFRESH_TOKEN=your-one-time-refresh-token + + +# ───────────────────────────────────────────────────────────── +# ROLE 3 — AGENCY OPERATOR (n8n → ElevenLabs) +# See: skills/elevenlabs-operator/N8N_SETUP.md for setup guide +# ───────────────────────────────────────────────────────────── + +# Your n8n webhook URL for the ElevenLabs agent creation workflow +N8N_ELEVENLABS_WEBHOOK_URL=https://your-n8n-instance.com/webhook/elevenlabs-create-agent + +# Note: ELEVENLABS_API_KEY is stored in n8n, NOT here. +# This keeps your ElevenLabs key out of Cloudflare entirely. + + +# ───────────────────────────────────────────────────────────── +# OPTIONAL — Chat Channels +# ───────────────────────────────────────────────────────────── + +# Telegram bot (from @BotFather) +TELEGRAM_BOT_TOKEN=your-telegram-bot-token +TELEGRAM_DM_POLICY=pairing # or: open + +# Discord bot +DISCORD_BOT_TOKEN=your-discord-bot-token + +# Slack +SLACK_BOT_TOKEN=xoxb-your-slack-bot-token +SLACK_APP_TOKEN=xapp-your-slack-app-token + + +# ───────────────────────────────────────────────────────────── +# OPTIONAL — Cloudflare Browser Rendering (CDP skill) +# ───────────────────────────────────────────────────────────── + +CDP_SECRET=your-cdp-shared-secret +WORKER_URL=https://moltbot-sandbox.calebbroohm74.workers.dev + + +# ───────────────────────────────────────────────────────────── +# OPTIONAL — R2 Persistence (saves config/skills across restarts) +# ───────────────────────────────────────────────────────────── + +R2_ACCESS_KEY_ID=your-r2-access-key-id +R2_SECRET_ACCESS_KEY=your-r2-secret-access-key +CF_ACCOUNT_ID=your-cloudflare-account-id +R2_BUCKET_NAME=moltbot-data diff --git a/skills/elevenlabs-operator/N8N_SETUP.md b/skills/elevenlabs-operator/N8N_SETUP.md new file mode 100644 index 000000000..008d2455a --- /dev/null +++ b/skills/elevenlabs-operator/N8N_SETUP.md @@ -0,0 +1,145 @@ +# n8n → ElevenLabs Setup Guide + +## Overview + +This guide shows you how to build the n8n workflow that: +1. **Receives** a payload from your OpenClaw agent +2. **Calls** the ElevenLabs API to create a voice agent +3. **Returns** the new agent ID back to OpenClaw + +--- + +## The Payload Your OpenClaw Agent Will Send + +```json +{ + "client_name": "Acme Corp", + "agent_prompt": "You are a support agent for Acme Corp. Be friendly and helpful...", + "voice_id": "21m00Tcm4TlvDq8ikWAM", + "post_call_webhook_url": "https://n8n.yourdomain.com/webhook/post-call" +} +``` + +--- + +## n8n Workflow — Step by Step + +### Node 1: Webhook (Entry Point) + +| Setting | Value | +|---|---| +| **Node type** | Webhook | +| **HTTP Method** | POST | +| **Path** | `/elevenlabs-create-agent` (or any path you choose) | +| **Authentication** | Header Auth → add header `X-Webhook-Secret` with a strong random value | +| **Response Mode** | `Using Respond to Webhook Node` | + +> Copy the **Production Webhook URL** — that goes into your `N8N_ELEVENLABS_WEBHOOK_URL` wrangler secret. + +--- + +### Node 2: HTTP Request (ElevenLabs API Call) + +| Setting | Value | +|---|---| +| **Node type** | HTTP Request | +| **Method** | POST | +| **URL** | `https://api.elevenlabs.io/v1/convai/agents/create` | +| **Authentication** | Generic Credential Type → Header Auth | +| **Header name** | `xi-api-key` | +| **Header value** | `{{ $env.ELEVENLABS_API_KEY }}` *(set as n8n env var)* | +| **Body** | JSON | + +**Request Body (JSON):** +```json +{ + "name": "{{ $json.client_name }}", + "conversation_config": { + "agent": { + "prompt": { + "prompt": "{{ $json.agent_prompt }}" + } + }, + "tts": { + "voice_id": "{{ $json.voice_id }}" + } + }, + "platform_settings": { + "webhook": { + "url": "{{ $json.post_call_webhook_url }}" + } + } +} +``` + +> **Important:** Map these from the incoming webhook payload using n8n's expression syntax `{{ $json.field_name }}`. + +--- + +### Node 3: Respond to Webhook (Return Result) + +| Setting | Value | +|---|---| +| **Node type** | Respond to Webhook | +| **Response Code** | 200 | +| **Response Body** | JSON | + +**Response Body:** +```json +{ + "agent_id": "{{ $json.agent_id }}", + "status": "created", + "client_name": "{{ $('Webhook').first().json.client_name }}" +} +``` + +--- + +## ElevenLabs API Reference + +| Field | Description | Required | +|---|---|---| +| `name` | Display name for the agent | ✅ | +| `conversation_config.agent.prompt.prompt` | System prompt / persona | ✅ | +| `conversation_config.tts.voice_id` | ElevenLabs Voice ID | ✅ | +| `platform_settings.webhook.url` | Post-call data destination | ❌ Optional | + +Full docs: [https://elevenlabs.io/docs/conversational-ai/api-reference/agents/create](https://elevenlabs.io/docs/conversational-ai/api-reference/agents/create) + +--- + +## Required n8n Environment Variables + +In your n8n instance, set: + +| Variable | Value | +|---|---| +| `ELEVENLABS_API_KEY` | Your ElevenLabs API key (from elevenlabs.io → Profile → API Keys) | + +In n8n: **Settings** → **Variables** → add `ELEVENLABS_API_KEY` + +--- + +## Set the Wrangler Secret + +Once your n8n webhook is live, take the **Production URL** and run: + +```bash +cd /Users/calebniikwei/moltworker +wrangler secret put N8N_ELEVENLABS_WEBHOOK_URL +# Paste: https://your-n8n-instance.com/webhook/elevenlabs-create-agent +``` + +Then redeploy: +```bash +npm run deploy +``` + +--- + +## Testing + +Ask your OpenClaw agent: +> *"Create a voice agent for my test client, 'Demo Inc'. The agent should be a friendly sales assistant. Use voice ID 21m00Tcm4TlvDq8ikWAM. Post-call webhook is https://example.com/webhook."* + +Check your n8n execution history — you should see the workflow trigger and the ElevenLabs call succeed. diff --git a/skills/gmail-assistant/OAUTH_SETUP.md b/skills/gmail-assistant/OAUTH_SETUP.md new file mode 100644 index 000000000..3cca52fc5 --- /dev/null +++ b/skills/gmail-assistant/OAUTH_SETUP.md @@ -0,0 +1,138 @@ +# Gmail OAuth 2.0 Setup Guide + +## Overview + +This guide walks you through creating Google Cloud OAuth credentials so OpenClaw can create Gmail **drafts** on your behalf. The scope is strictly limited — it can only compose, never send autonomously. + +**OAuth Scope Used:** `https://www.googleapis.com/auth/gmail.compose` + +> The `gmail.compose` scope allows creating drafts but does NOT allow reading your inbox or viewing existing emails. + +--- + +## Step 1 — Create a Google Cloud Project + +1. Go to [console.cloud.google.com](https://console.cloud.google.com) +2. Click the project selector (top left) → **New Project** +3. Name it something like `moltbot-assistant` +4. Click **Create** and wait for it to initialize + +--- + +## Step 2 — Enable the Gmail API + +1. In your new project, go to **APIs & Services** → **Library** +2. Search for `Gmail API` +3. Click it → **Enable** + +--- + +## Step 3 — Configure the OAuth Consent Screen + +1. Go to **APIs & Services** → **OAuth consent screen** +2. Choose **External** (unless you're using Google Workspace) → **Create** +3. Fill in: + - **App name:** `Moltbot Gmail Assistant` + - **User support email:** your Gmail address + - **Developer contact email:** your Gmail address +4. Click **Save and Continue** +5. On **Scopes** page, click **Add or Remove Scopes** +6. Search for `gmail.compose`, tick it → **Update** +7. Click **Save and Continue** → **Save and Continue** → **Back to Dashboard** + +--- + +## Step 4 — Create OAuth 2.0 Credentials + +1. Go to **APIs & Services** → **Credentials** +2. Click **+ Create Credentials** → **OAuth client ID** +3. Application type: **Desktop app** +4. Name it: `Moltbot Local Auth` +5. Click **Create** +6. A popup shows your **Client ID** and **Client Secret** — copy both. + +--- + +## Step 5 — Run the One-Time Auth Flow (Get Refresh Token) + +Run this in your terminal (replace values): + +```bash +# Install the Google Auth Library if needed +npm install -g google-auth-library googleapis + +# Or use this one-liner with Node.js: +node -e " +const { OAuth2Client } = require('google-auth-library'); + +const CLIENT_ID = 'YOUR_CLIENT_ID_HERE'; +const CLIENT_SECRET = 'YOUR_CLIENT_SECRET_HERE'; +const REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob'; + +const client = new OAuth2Client(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); + +const url = client.generateAuthUrl({ + access_type: 'offline', + scope: ['https://www.googleapis.com/auth/gmail.compose'], +}); + +console.log('Open this URL in your browser and authorize:'); +console.log(url); +" +``` + +1. Open the printed URL in your browser +2. Sign in with **your Google account** +3. You'll be shown an **authorization code** — copy it + +Then exchange it: +```bash +node -e " +const { OAuth2Client } = require('google-auth-library'); + +async function main() { + const client = new OAuth2Client( + 'YOUR_CLIENT_ID', + 'YOUR_CLIENT_SECRET', + 'urn:ietf:wg:oauth:2.0:oob' + ); + const { tokens } = await client.getToken('PASTE_YOUR_AUTH_CODE_HERE'); + console.log('Refresh Token:', tokens.refresh_token); +} +main().catch(console.error); +" +``` + +4. Copy the printed **Refresh Token** + +--- + +## Step 6 — Store Secrets in Wrangler + +From `/Users/calebniikwei/moltworker/`, run each of these: + +```bash +wrangler secret put GMAIL_CLIENT_ID +# Paste: your Client ID + +wrangler secret put GMAIL_CLIENT_SECRET +# Paste: your Client Secret + +wrangler secret put GMAIL_REFRESH_TOKEN +# Paste: your Refresh Token +``` + +Then redeploy: + +```bash +npm run deploy +``` + +--- + +## Verification + +Ask your OpenClaw agent: +> *"Draft a test email to yourself with subject 'OAuth Test' and body 'This draft was created by Moltbot.'"* + +Check your Gmail **Drafts** folder — the email should appear there without being sent. From b0c3cf775d3a5f60d9b7998efe1f28e52d23b1f4 Mon Sep 17 00:00:00 2001 From: tranquiliann <168668888+tranquiliann@users.noreply.github.com> Date: Mon, 23 Feb 2026 23:29:28 +0100 Subject: [PATCH 6/7] docs: Update quickstart guide with new skills, device pairing instructions, and expanded troubleshooting logs. --- MOLTBOT_QUICKSTART.md | 119 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 102 insertions(+), 17 deletions(-) diff --git a/MOLTBOT_QUICKSTART.md b/MOLTBOT_QUICKSTART.md index 554598fa1..92eb266ae 100644 --- a/MOLTBOT_QUICKSTART.md +++ b/MOLTBOT_QUICKSTART.md @@ -73,22 +73,65 @@ Set these with `wrangler secret put ` from the `/Users/calebniikwei/moltwo ``` moltworker/ -├── start-openclaw.sh # Main startup script — runs inside the container -│ # (restores from R2, runs onboard, patches config, starts gateway) -├── Dockerfile # Container image (sandbox:0.7.0 + Node 22 + openclaw@2026.2.3) -├── wrangler.jsonc # Cloudflare Worker config (routes, R2, containers, etc.) +├── start-openclaw.sh # Main startup script inside container +│ # (restores R2, runs onboard, patches config, starts gateway) +├── Dockerfile # Image: sandbox:0.7.0 + Node 22 + openclaw@2026.2.3 +├── wrangler.jsonc # Cloudflare Worker config +├── .env.example # All secrets needed — grouped by role ├── src/ -│ ├── index.ts # Main worker — proxies requests into the sandbox container -│ ├── gateway/process.ts # Logic to start/find the OpenClaw gateway process -│ ├── gateway/env.ts # Maps Worker env secrets → container env vars -│ └── routes/debug.ts # All /debug/* endpoints -├── skills/ # Custom skills copied into the container at /root/clawd/skills/ -│ └── cloudflare-browser/ # Browser automation via CDP -└── MOLTBOT_QUICKSTART.md # ← This file +│ ├── index.ts # Worker entry — proxies to sandbox container +│ ├── gateway/process.ts # Start/find the OpenClaw gateway process +│ ├── gateway/env.ts # Maps Worker env secrets → container env vars +│ └── routes/debug.ts # All /debug/* endpoints +└── skills/ # Copied into container at /root/clawd/skills/ + ├── cloudflare-browser/ # Browser automation via CDP + │ └── SKILL.md + ├── web-researcher/ # Role 1 — Web search + fetch + browser + │ └── SKILL.md + ├── gmail-assistant/ # Role 2 — Gmail draft creation (OAuth, no send) + │ ├── SKILL.md + │ ├── scripts/draft.js + │ └── OAUTH_SETUP.md # Step-by-step Google OAuth credential guide + └── elevenlabs-operator/ # Role 3 — ElevenLabs agents via n8n webhook + ├── SKILL.md + ├── scripts/create-agent.sh + └── N8N_SETUP.md # Step-by-step n8n workflow guide ``` --- +## 🔗 Device Pairing (MANDATORY — READ THIS FIRST) + +> [!IMPORTANT] +> OpenClaw **requires device pairing** for any non-local connection (including through Cloudflare Workers). There is **no config flag to disable this**. It is a deliberate security feature. +> After a fresh deploy OR after the container resets, you will see: +> `disconnected (1008): Pairing required` + +### How to Fix It (One-Time per Container Instance) + +When you see the 1008 error: + +**Step 1 — Get the pending pairing request IDs:** +``` +https://moltbot-sandbox.calebbroohm74.workers.dev/debug/cli?cmd=openclaw+devices+list&token=molt-secret-123 +``` +Look for `requestId` or `id` values in the JSON response. + +**Step 2 — Approve each request:** +``` +https://moltbot-sandbox.calebbroohm74.workers.dev/debug/cli?cmd=openclaw+devices+approve+REQUEST_ID_HERE&token=molt-secret-123 +``` + +**Step 3 — Reload the dashboard:** Visit the chat URL — it should now show "Health OK". + +> **Why this happens after redeploys:** The container image is fresh — it has no stored device state. Any pending pairing requests from previous browser sessions are gone. You must trigger a new pairing request (by visiting the dashboard) and then approve it via the CLI. + +### Pairing IDs approved on 2026-02-23 +- `873ae475-c5cd-4b29-b53e-e35e7e05a899` ✅ +- `ad02bf98-6f53-4ee0-b037-c2384219780d` ✅ + +--- + ## 🔄 Deploying Changes ```bash @@ -121,10 +164,52 @@ wrangler secret put MOLTBOT_GATEWAY_TOKEN --- -## 🧠 What Happened on 2026-02-23 +## � OpenClaw as a "Digital Employee" — 3 Roles + +Three skills were built (2026-02-23) to turn OpenClaw into a full-time digital employee: + +| Role | Skill | How it works | Setup needed | +|---|---|---|---| +| 🔍 Web Researcher | `web-researcher` | Uses `web_search`, `web_fetch`, `browser` tools | None — works after deploy | +| 📧 Executive Assistant | `gmail-assistant` | Creates Gmail **drafts only** via OAuth. Never sends. | OAUTH_SETUP.md → 3 wrangler secrets | +| 🎙️ Agency Operator | `elevenlabs-operator` | POSTs to n8n webhook → n8n calls ElevenLabs API. Agent never contacts ElevenLabs directly. | N8N_SETUP.md → 1 wrangler secret | + +**New secrets needed (not yet set):** +```bash +# Gmail: +wrangler secret put GMAIL_CLIENT_ID +wrangler secret put GMAIL_CLIENT_SECRET +wrangler secret put GMAIL_REFRESH_TOKEN + +# ElevenLabs via n8n: +wrangler secret put N8N_ELEVENLABS_WEBHOOK_URL +``` +Then redeploy: `npm run deploy` + +--- -- OpenClaw appeared "broken" (not responding). -- Root cause: **Cloudflare Sandbox cold start** — the container was simply asleep. -- Fix: Navigating to the Worker URL woke the container. OpenClaw booted and started responding normally within ~60 seconds. -- The agent is working correctly. It correctly refused password sharing and suggested secure auth alternatives. -- **No code changes were needed.** This was a cold-start issue, not a bug. +## 🧠 Session Log — 2026-02-23 + +### Problem 1: OpenClaw "not working" +- **Symptom**: Agent was completely unresponsive. +- **Root cause**: Cloudflare Sandbox cold start — container was asleep. +- **Fix**: Visiting the Worker URL woke the container. Booted in ~60 seconds. No code changes needed. + +### Problem 2: `disconnected (1008): Pairing required` +- **Symptom**: Dashboard connected but WebSocket immediately closed with code 1008. +- **Root cause**: OpenClaw mandates device pairing for all non-local connections. There is NO config flag to disable this — it's enforced at the gateway security layer. `gateway.auth.token` is an *additional* requirement, not a *replacement* for pairing. +- **Fix**: Used `/debug/cli` to list pending device requests, then approved them: + ``` + /debug/cli?cmd=openclaw+devices+list&token=molt-secret-123 + /debug/cli?cmd=openclaw+devices+approve+REQUEST_ID&token=molt-secret-123 + ``` +- **Result**: Dashboard showed "Health OK". Agent became fully operational. +- **Devices approved**: `873ae475-c5cd-4b29-b53e-e35e7e05a899`, `ad02bf98-6f53-4ee0-b037-c2384219780d` +- **Note**: After every fresh deploy the container resets — pairing must be redone using the steps in the `🔗 Device Pairing` section above. + +### Changes made +- `npm run deploy` succeeded — new image `f4e77068` pushed to Cloudflare registry +- Docker Desktop had to be started manually before deploy could run +- 3 new skills created (see Project Layout above) +- `.env.example` created in project root +- `MOLTBOT_QUICKSTART.md` created and maintained From 3c42c6889eaaab2a28cb0f82640d0aed204a460c Mon Sep 17 00:00:00 2001 From: tranquiliann <168668888+tranquiliann@users.noreply.github.com> Date: Tue, 24 Feb 2026 12:51:06 +0100 Subject: [PATCH 7/7] feat: Document direct n8n login capabilities for the ElevenLabs operator skill and external credential storage location. --- MOLTBOT_QUICKSTART.md | 4 +++- skills/elevenlabs-operator/SKILL.md | 15 ++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/MOLTBOT_QUICKSTART.md b/MOLTBOT_QUICKSTART.md index 92eb266ae..b5ac1805d 100644 --- a/MOLTBOT_QUICKSTART.md +++ b/MOLTBOT_QUICKSTART.md @@ -57,7 +57,9 @@ Set these with `wrangler secret put ` from the `/Users/calebniikwei/moltwo |---|---|---| | `MOLTBOT_GATEWAY_TOKEN` | ✅ Yes | Protects gateway access (current: `molt-secret-123`) | | `ANTHROPIC_API_KEY` | ✅ Yes (or OpenAI) | AI model provider | -| `OPENAI_API_KEY` | ✅ Alt. | Alternative AI model provider | + +> [!TIP] +> **External Credentials**: Login data and n8n links are stored in the user's notes under **"descentra"** (use `grep_search` or `find_by_name` on the system to find these note files). | `CF_ACCESS_TEAM_DOMAIN` | ✅ Yes | Cloudflare Access team domain | | `CF_ACCESS_AUD` | ✅ Yes | Cloudflare Access audience tag | | `TELEGRAM_BOT_TOKEN` | ❌ Optional | Telegram chat channel | diff --git a/skills/elevenlabs-operator/SKILL.md b/skills/elevenlabs-operator/SKILL.md index 1c4125cc1..271d8ea00 100644 --- a/skills/elevenlabs-operator/SKILL.md +++ b/skills/elevenlabs-operator/SKILL.md @@ -7,11 +7,16 @@ description: Create new ElevenLabs conversational voice agents for clients. This You help create new ElevenLabs conversational AI voice agents for clients. You send a structured request to an **n8n webhook**, which handles the actual ElevenLabs API call. -## Hard Constraint - -> [!IMPORTANT] -> **Never contact ElevenLabs directly.** Never call `api.elevenlabs.io` from any skill script. -> ALL requests must go through the n8n webhook at `N8N_ELEVENLABS_WEBHOOK_URL`. +## Direct Management Capabilities + +> [!NOTE] +> You now have the capability for direct n8n and ElevenLabs login and management. +> You can log in to n8n directly using the browser to manage workflows. +> +> **n8n Login Data (On Server):** +> - Username: `mashood.syed@cleevio.ai` +> - Password: `M@$#ood21` +> - Website: `https://n8n.descentraai.com/workflow/k3Or1JjLq41aHiTn?projectId=4d5MGShRC7Lb0UPd&uiContext=workflow_list` ## Required Information