-
Notifications
You must be signed in to change notification settings - Fork 2k
fix: standardize messaging integrations with host-side bridge framework #617
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
dda17f2
67cc12b
80afba3
04537f1
ea3fb46
bff2a60
b875742
223b650
c019a7c
2690fab
09bc811
c729c14
44a0fe0
8143bfd
1fa10d3
b970dcf
29a4696
7c97109
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -555,9 +555,15 @@ async function createSandbox(gpu) { | |||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| console.log(` Creating sandbox '${sandboxName}' (this takes a few minutes on first run)...`); | ||||||||||||||||||||||||||||
| const chatUiUrl = process.env.CHAT_UI_URL || 'http://127.0.0.1:18789'; | ||||||||||||||||||||||||||||
| // Pass user-provided secrets into the sandbox as environment variables. | ||||||||||||||||||||||||||||
| // All tokens follow the same pattern: getCredential() checks env first, | ||||||||||||||||||||||||||||
| // then ~/.nemoclaw/credentials.json. OpenClaw auto-enables channels when | ||||||||||||||||||||||||||||
| // it detects the corresponding env var (e.g., DISCORD_BOT_TOKEN). | ||||||||||||||||||||||||||||
| // See docs/reference/architecture.md "Credential Handling" for the full inventory. | ||||||||||||||||||||||||||||
| const envArgs = [`CHAT_UI_URL=${shellQuote(chatUiUrl)}`]; | ||||||||||||||||||||||||||||
| if (process.env.NVIDIA_API_KEY) { | ||||||||||||||||||||||||||||
| envArgs.push(`NVIDIA_API_KEY=${shellQuote(process.env.NVIDIA_API_KEY)}`); | ||||||||||||||||||||||||||||
| const apiKey = getCredential("NVIDIA_API_KEY") || process.env.NVIDIA_API_KEY; | ||||||||||||||||||||||||||||
| if (apiKey) { | ||||||||||||||||||||||||||||
| envArgs.push(`NVIDIA_API_KEY=${shellQuote(apiKey)}`); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| const discordToken = getCredential("DISCORD_BOT_TOKEN") || process.env.DISCORD_BOT_TOKEN; | ||||||||||||||||||||||||||||
| if (discordToken) { | ||||||||||||||||||||||||||||
|
|
@@ -567,6 +573,10 @@ async function createSandbox(gpu) { | |||||||||||||||||||||||||||
| if (slackToken) { | ||||||||||||||||||||||||||||
| envArgs.push(`SLACK_BOT_TOKEN=${shellQuote(slackToken)}`); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| const tgToken = getCredential("TELEGRAM_BOT_TOKEN") || process.env.TELEGRAM_BOT_TOKEN; | ||||||||||||||||||||||||||||
| if (tgToken) { | ||||||||||||||||||||||||||||
| envArgs.push(`TELEGRAM_BOT_TOKEN=${shellQuote(tgToken)}`); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // Run without piping through awk — the pipe masked non-zero exit codes | ||||||||||||||||||||||||||||
| // from openshell because bash returns the status of the last pipeline | ||||||||||||||||||||||||||||
|
|
@@ -1091,9 +1101,43 @@ async function onboard(opts = {}) { | |||||||||||||||||||||||||||
| await setupInference(sandboxName, model, provider); | ||||||||||||||||||||||||||||
| await setupOpenclaw(sandboxName, model, provider); | ||||||||||||||||||||||||||||
| await setupPolicies(sandboxName); | ||||||||||||||||||||||||||||
| startMessagingBridges(sandboxName); | ||||||||||||||||||||||||||||
| printDashboard(sandboxName, model, provider); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| // ── Auto-start messaging bridges ──────────────────────────────── | ||||||||||||||||||||||||||||
| // RISKY CHANGE: This is a migration path to standardize messaging | ||||||||||||||||||||||||||||
| // configuration. We auto-start host-side bridges when tokens are | ||||||||||||||||||||||||||||
| // detected, which takes over from the in-sandbox OpenClaw plugin | ||||||||||||||||||||||||||||
| // (Discord/Slack enforce single gateway connections per token). | ||||||||||||||||||||||||||||
| // The in-sandbox env var passthrough (#601) is kept for backwards | ||||||||||||||||||||||||||||
| // compatibility during this transition. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| function startMessagingBridges(sandboxName) { | ||||||||||||||||||||||||||||
| // Rehydrate file-backed credentials into process.env so start-services.sh | ||||||||||||||||||||||||||||
| // and bridge.js can see them (they only check process.env, not credentials.json). | ||||||||||||||||||||||||||||
| const bridgeTokens = ["TELEGRAM_BOT_TOKEN", "DISCORD_BOT_TOKEN", "SLACK_BOT_TOKEN", "SLACK_APP_TOKEN"]; | ||||||||||||||||||||||||||||
| for (const key of bridgeTokens) { | ||||||||||||||||||||||||||||
| if (!process.env[key]) { | ||||||||||||||||||||||||||||
| const val = getCredential(key); | ||||||||||||||||||||||||||||
| if (val) process.env[key] = val; | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| const hasMessagingToken = | ||||||||||||||||||||||||||||
| process.env.TELEGRAM_BOT_TOKEN || | ||||||||||||||||||||||||||||
| process.env.DISCORD_BOT_TOKEN || | ||||||||||||||||||||||||||||
| process.env.SLACK_BOT_TOKEN; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if (!hasMessagingToken) return; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| console.log(""); | ||||||||||||||||||||||||||||
| console.log(" Starting messaging bridges..."); | ||||||||||||||||||||||||||||
| const safeName = sandboxName && /^[a-zA-Z0-9._-]+$/.test(sandboxName) ? sandboxName : null; | ||||||||||||||||||||||||||||
| const sandboxEnv = safeName ? `SANDBOX_NAME=${shellQuote(safeName)}` : ""; | ||||||||||||||||||||||||||||
| run(`${sandboxEnv} bash "${SCRIPTS}/start-services.sh"`, { ignoreError: true }); | ||||||||||||||||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+1134
to
+1138
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't silently swallow bridge startup failures.
Proposed fix console.log("");
console.log(" Starting messaging bridges...");
const safeName = sandboxName && /^[a-zA-Z0-9._-]+$/.test(sandboxName) ? sandboxName : null;
const sandboxEnv = safeName ? `SANDBOX_NAME=${shellQuote(safeName)}` : "";
-run(`${sandboxEnv} bash "${SCRIPTS}/start-services.sh"`, { ignoreError: true });
+const result = run(`${sandboxEnv} bash "${SCRIPTS}/start-services.sh"`, { ignoreError: true });
+if (result.status !== 0) {
+ console.warn(" Warning: messaging bridge autostart failed.");
+}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| module.exports = { | ||||||||||||||||||||||||||||
| buildSandboxConfigSyncScript, | ||||||||||||||||||||||||||||
| getFutureShellPathHint, | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finish the
NVIDIA_API_KEYmigration beyondenvArgs.These lines resolve the key only for sandbox env injection. Line 701 and Line 728 still read
process.env.NVIDIA_API_KEY, so a key stored only in~/.nemoclaw/credentials.jsonstill breaks the non-interactive cloud path.🤖 Prompt for AI Agents