























@@ -12,11 +12,36 @@ bundled_channel_stage_root() {
1212printf "%s/.openclaw/plugin-runtime-deps" "$HOME"
1313}
141415+bundled_channel_stage_dir() {
16+printf "%s" "${OPENCLAW_PLUGIN_STAGE_DIR:-$(bundled_channel_stage_root)}"
17+}
18+19+bundled_channel_install_package() {
20+local log_file="$1"
21+local label="${2:-mounted OpenClaw package}"
22+local package_tgz="${OPENCLAW_CURRENT_PACKAGE_TGZ:?missing OPENCLAW_CURRENT_PACKAGE_TGZ}"
23+echo "Installing $label..."
24+if ! npm install -g "$package_tgz" --no-fund --no-audit >"$log_file" 2>&1; then
25+echo "npm install -g failed for $label" >&2
26+ cat "$log_file" >&2 || true
27+exit 1
28+fi
29+}
30+1531bundled_channel_find_external_dep_package() {
1632local dep_path="$1"
1733 find "$(bundled_channel_stage_root)" -maxdepth 12 -path "*/node_modules/$dep_path/package.json" -type f -print -quit 2>/dev/null || true
1834}
193536+bundled_channel_find_staged_dep_package() {
37+local dep_path="$1"
38+ find "$(bundled_channel_stage_dir)" -maxdepth 12 -path "*/node_modules/$dep_path/package.json" -type f -print -quit 2>/dev/null || true
39+}
40+41+bundled_channel_dump_stage_dir() {
42+ find "$(bundled_channel_stage_dir)" -maxdepth 12 -type f | sort | head -160 >&2 || true
43+}
44+2045bundled_channel_assert_no_package_dep_available() {
2146local channel="$1"
2247local dep_path="$2"
@@ -62,6 +87,91 @@ bundled_channel_assert_no_dep_available() {
6287fi
6388}
648990+bundled_channel_assert_no_staged_dep() {
91+local channel="$1"
92+local dep_path="$2"
93+local message="${3:-$channel unexpectedly staged $dep_path}"
94+if [ -n "$(bundled_channel_find_staged_dep_package "$dep_path")" ]; then
95+echo "$message" >&2
96+ bundled_channel_dump_stage_dir
97+exit 1
98+fi
99+}
100+101+bundled_channel_assert_staged_dep() {
102+local channel="$1"
103+local dep_path="$2"
104+local log_file="${3:-}"
105+if [ -n "$(bundled_channel_find_staged_dep_package "$dep_path")" ]; then
106+return 0
107+fi
108+echo "missing external staged dependency sentinel for $channel: $dep_path" >&2
109+if [ -n "$log_file" ]; then
110+ cat "$log_file" >&2 || true
111+fi
112+ bundled_channel_dump_stage_dir
113+exit 1
114+}
115+116+bundled_channel_assert_no_staged_manifest_spec() {
117+local channel="$1"
118+local dep_path="$2"
119+local log_file="${3:-}"
120+if ! node - <<'NODE' "$(bundled_channel_stage_dir)" "$dep_path"
121+const fs = require("node:fs");
122+const path = require("node:path");
123+124+const stageDir = process.argv[2];
125+const depName = process.argv[3];
126+const manifestName = ".openclaw-runtime-deps.json";
127+const matches = [];
128+129+function visit(dir) {
130+ let entries;
131+ try {
132+ entries = fs.readdirSync(dir, { withFileTypes: true });
133+ } catch {
134+ return;
135+ }
136+ for (const entry of entries) {
137+ const fullPath = path.join(dir, entry.name);
138+ if (entry.isDirectory()) {
139+ visit(fullPath);
140+ continue;
141+ }
142+ if (entry.name !== manifestName) {
143+ continue;
144+ }
145+ let parsed;
146+ try {
147+ parsed = JSON.parse(fs.readFileSync(fullPath, "utf8"));
148+ } catch {
149+ continue;
150+ }
151+ const specs = Array.isArray(parsed.specs) ? parsed.specs : [];
152+ for (const spec of specs) {
153+ if (typeof spec === "string" && spec.startsWith(`${depName}@`)) {
154+ matches.push(`${fullPath}: ${spec}`);
155+ }
156+ }
157+ }
158+}
159+160+visit(stageDir);
161+if (matches.length > 0) {
162+ process.stderr.write(`${matches.join("\n")}\n`);
163+ process.exit(1);
164+}
165+NODE
166+then
167+echo "$channel unexpectedly selected $dep_path for external runtime deps" >&2
168+if [ -n "$log_file" ]; then
169+ cat "$log_file" >&2 || true
170+fi
171+exit 1
172+fi
173+}
174+65175bundled_channel_remove_runtime_dep() {
66176local channel="$1"
67177local dep_path="$2"
@@ -74,18 +184,63 @@ bundled_channel_remove_runtime_dep() {
7418475185bundled_channel_write_config() {
76186local mode="$1"
77- node - <<'NODE' "$mode" "${TOKEN:?missing TOKEN}" "${PORT:?missing PORT}"
187+ node - <<'NODE' "$mode" "${TOKEN:-bundled-channel-config-token}" "${PORT:-18789}"
78188const fs = require("node:fs");
79189const path = require("node:path");
8019081191const mode = process.argv[2];
82192const token = process.argv[3];
83193const port = Number(process.argv[4]);
84-const configPath = path.join(process.env.HOME, ".openclaw", "openclaw.json");
194+const configPath =
195+ process.env.OPENCLAW_BUNDLED_CHANNEL_CONFIG_PATH ||
196+ path.join(process.env.HOME, ".openclaw", "openclaw.json");
85197const config = fs.existsSync(configPath)
86198 ? JSON.parse(fs.readFileSync(configPath, "utf8"))
87199 : {};
88200201+if (mode === "disabled-config") {
202+ const stateDir = path.dirname(configPath);
203+ const disabledConfig = {
204+ gateway: {
205+ mode: "local",
206+ auth: {
207+ mode: "token",
208+ token: "disabled-config-runtime-deps-token",
209+ },
210+ },
211+ plugins: {
212+ enabled: true,
213+ entries: {
214+ discord: { enabled: false },
215+ },
216+ },
217+ channels: {
218+ telegram: {
219+ enabled: false,
220+ botToken: "123456:disabled-config-token",
221+ dmPolicy: "disabled",
222+ groupPolicy: "disabled",
223+ },
224+ slack: {
225+ enabled: false,
226+ botToken: "xoxb-disabled-config-token",
227+ appToken: "xapp-disabled-config-token",
228+ },
229+ discord: {
230+ enabled: true,
231+ token: "disabled-plugin-entry-token",
232+ dmPolicy: "disabled",
233+ groupPolicy: "disabled",
234+ },
235+ },
236+ };
237+ fs.mkdirSync(path.join(stateDir, "agents", "main", "sessions"), { recursive: true });
238+ fs.writeFileSync(configPath, `${JSON.stringify(disabledConfig, null, 2)}\n`, "utf8");
239+ fs.chmodSync(stateDir, 0o700);
240+ fs.chmodSync(configPath, 0o600);
241+ process.exit(0);
242+}
243+89244config.gateway = {
90245 ...(config.gateway || {}),
91246 port,
@@ -120,7 +275,9 @@ config.channels = {
120275 telegram: {
121276 ...(config.channels?.telegram || {}),
122277 enabled: mode === "telegram",
123- botToken: "123456:bundled-channel-update-token",
278+ botToken:
279+ process.env.OPENCLAW_BUNDLED_CHANNEL_TELEGRAM_TOKEN ||
280+ "123456:bundled-channel-update-token",
124281 dmPolicy: "disabled",
125282 groupPolicy: "disabled",
126283 },
@@ -133,8 +290,12 @@ config.channels = {
133290 slack: {
134291 ...(config.channels?.slack || {}),
135292 enabled: mode === "slack",
136- botToken: "xoxb-bundled-channel-update-token",
137- appToken: "xapp-bundled-channel-update-token",
293+ botToken:
294+ process.env.OPENCLAW_BUNDLED_CHANNEL_SLACK_BOT_TOKEN ||
295+ "xoxb-bundled-channel-update-token",
296+ appToken:
297+ process.env.OPENCLAW_BUNDLED_CHANNEL_SLACK_APP_TOKEN ||
298+ "xapp-bundled-channel-update-token",
138299 },
139300 feishu: {
140301 ...(config.channels?.feishu || {}),
@@ -187,6 +348,23 @@ if (mode === "acpx") {
187348 },
188349 };
189350}
351+if (mode === "setup-entry-channels") {
352+ config.plugins = {
353+ ...(config.plugins || {}),
354+ enabled: true,
355+ };
356+ config.channels = {
357+ ...(config.channels || {}),
358+ feishu: {
359+ ...(config.channels?.feishu || {}),
360+ enabled: true,
361+ },
362+ whatsapp: {
363+ ...(config.channels?.whatsapp || {}),
364+ enabled: true,
365+ },
366+ };
367+}
190368191369fs.mkdirSync(path.dirname(configPath), { recursive: true });
192370fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf8");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。