create-openclaw-bot 5.6.8 → 5.6.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/setup.js CHANGED
@@ -280,15 +280,26 @@
280
280
  channelConfig: {
281
281
  zalouser: {
282
282
  enabled: true,
283
+ defaultAccount: 'default',
283
284
  accounts: {
284
285
  default: {
285
286
  dmPolicy: 'open',
286
287
  allowFrom: ['*'],
287
288
  groupPolicy: 'allowlist',
289
+ groupAllowFrom: ['*'],
288
290
  },
289
291
  },
290
292
  dmPolicy: 'open',
293
+ allowFrom: ['*'],
291
294
  groupPolicy: 'allowlist',
295
+ groupAllowFrom: ['*'],
296
+ historyLimit: 50,
297
+ groups: {
298
+ '*': {
299
+ enabled: true,
300
+ requireMention: false,
301
+ },
302
+ },
292
303
  },
293
304
  },
294
305
  pluginInstall: '@openclaw/zalouser',
@@ -377,7 +388,6 @@
377
388
  - ✅ Limit exposed ports (only 38789)`,
378
389
  };
379
390
 
380
-
381
391
  // ── PLUGINS list (setup/data/plugins.js) ───────────────────────────
382
392
  // @ts-nocheck
383
393
  /* eslint-disable no-undef, no-unused-vars */
@@ -617,6 +627,39 @@
617
627
  const OPENCLAW_NPM_SPEC = 'openclaw@2026.4.14';
618
628
  const OPENCLAW_RUNTIME_PACKAGES = 'grammy @grammyjs/runner @grammyjs/transformer-throttler @buape/carbon @larksuiteoapi/node-sdk @slack/web-api';
619
629
  const NINE_ROUTER_NPM_SPEC = '9router@latest';
630
+ const NINE_ROUTER_PORT = 20128;
631
+ const NINE_ROUTER_PROXY_API_KEY = 'sk-no-key';
632
+ const NINE_ROUTER_API_BASE_URL = `http://localhost:${NINE_ROUTER_PORT}`;
633
+ const NINE_ROUTER_DOCKER_API_BASE_URL = `http://9router:${NINE_ROUTER_PORT}`;
634
+ const SUPPORTED_CODEX_MODELS = ['cx/gpt-5.4', 'cx/gpt-5.3-codex', 'cx/gpt-5.2', 'cx/gpt-5.4-mini'];
635
+ const SMART_ROUTE_PROVIDER_MODELS = {
636
+ codex: SUPPORTED_CODEX_MODELS,
637
+ 'claude-code': ['cc/claude-opus-4-7', 'cc/claude-opus-4-6', 'cc/claude-sonnet-4-6', 'cc/claude-opus-4-5-20251101', 'cc/claude-sonnet-4-5-20250929', 'cc/claude-haiku-4-5-20251001'],
638
+ github: ['gh/gpt-5.4', 'gh/gpt-5.3-codex', 'gh/gpt-5.2-codex', 'gh/gpt-5.2', 'gh/gpt-5.1-codex-max', 'gh/gpt-5.1-codex', 'gh/gpt-5.1-codex-mini', 'gh/gpt-5.1', 'gh/gpt-5-codex', 'gh/gpt-5', 'gh/gpt-4.1', 'gh/gpt-4o', 'gh/claude-opus-4.6', 'gh/claude-sonnet-4.6', 'gh/claude-sonnet-4.5', 'gh/claude-opus-4.5', 'gh/claude-haiku-4.5', 'gh/gemini-3-pro-preview', 'gh/gemini-3-flash-preview', 'gh/gemini-2.5-pro', 'gh/grok-code-fast-1'],
639
+ cursor: ['cu/default', 'cu/claude-4.6-opus-max', 'cu/claude-4.6-sonnet-medium-thinking', 'cu/claude-4.5-opus-high-thinking', 'cu/claude-4.5-opus-high', 'cu/claude-4.5-sonnet-thinking', 'cu/claude-4.5-sonnet', 'cu/claude-4.5-haiku', 'cu/claude-4.5-opus', 'cu/gpt-5.3-codex', 'cu/gpt-5.2-codex', 'cu/gpt-5.2', 'cu/kimi-k2.5', 'cu/gemini-3-flash-preview'],
640
+ kilo: ['kc/anthropic/claude-sonnet-4-20250514', 'kc/anthropic/claude-opus-4-20250514', 'kc/google/gemini-2.5-pro', 'kc/google/gemini-2.5-flash', 'kc/openai/gpt-4.1', 'kc/openai/o3', 'kc/deepseek/deepseek-chat', 'kc/deepseek/deepseek-reasoner'],
641
+ cline: ['cl/anthropic/claude-opus-4.7', 'cl/anthropic/claude-sonnet-4.6', 'cl/anthropic/claude-opus-4.6', 'cl/openai/gpt-5.4', 'cl/openai/gpt-5.3-codex', 'cl/google/gemini-3.1-pro-preview', 'cl/google/gemini-3.1-flash-lite-preview', 'cl/kwaipilot/kat-coder-pro'],
642
+ 'gemini-cli': ['gc/gemini-3-flash-preview', 'gc/gemini-3-pro-preview'],
643
+ kiro: ['kr/claude-sonnet-4.5', 'kr/claude-haiku-4.5', 'kr/deepseek-3.2', 'kr/deepseek-3.1', 'kr/qwen3-coder-next', 'kr/glm-5', 'kr/MiniMax-M2.5'],
644
+ 'kimi-coding': ['kmc/kimi-k2.5', 'kmc/kimi-k2.5-thinking', 'kmc/kimi-latest'],
645
+ openai: ['openai/gpt-5.4', 'openai/gpt-5.4-mini', 'openai/gpt-5.2', 'openai/gpt-5.1', 'openai/gpt-5', 'openai/gpt-4o', 'openai/gpt-4.1', 'openai/o3', 'openai/o4-mini'],
646
+ anthropic: ['anthropic/claude-sonnet-4-20250514', 'anthropic/claude-opus-4-20250514', 'anthropic/claude-3-5-sonnet-20241022'],
647
+ gemini: ['gemini/gemini-3.1-pro-preview', 'gemini/gemini-3-flash-preview', 'gemini/gemini-2.5-pro', 'gemini/gemini-2.5-flash', 'gemini/gemini-2.5-flash-lite'],
648
+ deepseek: ['deepseek/deepseek-chat', 'deepseek/deepseek-reasoner'],
649
+ xai: ['xai/grok-4', 'xai/grok-4-fast-reasoning', 'xai/grok-code-fast-1', 'xai/grok-3'],
650
+ mistral: ['mistral/mistral-large-latest', 'mistral/codestral-latest', 'mistral/mistral-medium-latest'],
651
+ iflow: ['if/qwen3-coder-plus', 'if/qwen3-max', 'if/qwen3-vl-plus', 'if/qwen3-max-preview', 'if/qwen3-235b', 'if/qwen3-32b', 'if/kimi-k2', 'if/deepseek-v3.2', 'if/deepseek-v3.1', 'if/deepseek-v3', 'if/deepseek-r1', 'if/glm-4.7', 'if/iflow-rome-30ba3b'],
652
+ qwen: ['qw/qwen3-coder-plus', 'qw/qwen3-coder-flash', 'qw/vision-model', 'qw/coder-model'],
653
+ alicode: ['alicode/qwen3.5-plus', 'alicode/kimi-k2.5', 'alicode/glm-5', 'alicode/qwen3-coder-next', 'alicode/qwen3-coder-plus', 'alicode/glm-4.7'],
654
+ groq: ['groq/llama-3.3-70b-versatile', 'groq/openai/gpt-oss-120b', 'groq/qwen/qwen3-32b'],
655
+ cerebras: ['cerebras/gpt-oss-120b', 'cerebras/zai-glm-4.7', 'cerebras/qwen-3-32b'],
656
+ glm: ['glm/glm-5.1', 'glm/glm-5', 'glm/glm-4.7'],
657
+ 'glm-cn': ['glm-cn/glm-5.1', 'glm-cn/glm-5', 'glm-cn/glm-4.7', 'glm-cn/glm-4.6'],
658
+ minimax: ['minimax/MiniMax-M2.7', 'minimax/MiniMax-M2.5', 'minimax/MiniMax-M2.1'],
659
+ kimi: ['kimi/kimi-k2.5', 'kimi/kimi-k2.5-thinking', 'kimi/kimi-latest'],
660
+ ollama: ['ollama/qwen3.5', 'ollama/kimi-k2.5', 'ollama/glm-5', 'ollama/minimax-m2.5', 'ollama/glm-4.7-flash', 'ollama/gpt-oss:120b'],
661
+ };
662
+ const SMART_ROUTE_PROVIDER_ORDER = ['openai', 'anthropic', 'claude-code', 'codex', 'cursor', 'github', 'cline', 'kimi', 'minimax', 'deepseek', 'glm', 'alicode', 'xai', 'mistral', 'kilo', 'kiro', 'iflow', 'qwen', 'gemini-cli', 'gemini', 'ollama'];
620
663
  const TELEGRAM_RELAY_PLUGIN_SPEC = 'openclaw-telegram-multibot-relay';
621
664
  const TELEGRAM_RELAY_PLUGIN_ID = 'telegram-multibot-relay';
622
665
  const TELEGRAM_SETUP_GUIDE_FILENAME = 'TELEGRAM-GROUP-SETUP.md';
@@ -823,10 +866,60 @@
823
866
  return JSON.stringify(buildAuthProfilesJson(options), null, 2);
824
867
  }
825
868
 
869
+ function get9RouterBaseUrl(deployMode = 'native') {
870
+ return deployMode === 'docker' ? `${NINE_ROUTER_DOCKER_API_BASE_URL}/v1` : `${NINE_ROUTER_API_BASE_URL}/v1`;
871
+ }
872
+
873
+ function build9RouterProviderConfig(baseUrl = `${NINE_ROUTER_API_BASE_URL}/v1`) {
874
+ return {
875
+ baseUrl,
876
+ apiKey: NINE_ROUTER_PROXY_API_KEY,
877
+ api: 'openai-completions',
878
+ models: [
879
+ {
880
+ id: 'smart-route',
881
+ name: 'Smart Proxy (Auto Route)',
882
+ contextWindow: 200000,
883
+ maxTokens: 8192,
884
+ },
885
+ ...SUPPORTED_CODEX_MODELS.map((id) => ({
886
+ id,
887
+ name: `Codex ${id.slice(3).replace(/-/g, ' ').replace(/\b\w/g, (char) => char.toUpperCase())}`,
888
+ contextWindow: 200000,
889
+ maxTokens: 8192,
890
+ })),
891
+ ],
892
+ };
893
+ }
894
+
895
+ function buildGatewayConfig(port = 18791, deployMode = 'native', allowedOrigins = []) {
896
+ const normalizedPort = Number(port) || 18791;
897
+ const cfg = {
898
+ port: normalizedPort,
899
+ mode: 'local',
900
+ controlUi: { allowedOrigins },
901
+ auth: { mode: 'token', token: crypto.randomUUID().replace(/-/g, '') },
902
+ };
903
+ if (deployMode === 'docker') {
904
+ cfg.bind = 'custom';
905
+ cfg.customBindHost = '0.0.0.0';
906
+ } else {
907
+ cfg.bind = 'loopback';
908
+ }
909
+ return cfg;
910
+ }
911
+
826
912
  root.__openclawCommon = {
827
913
  OPENCLAW_NPM_SPEC,
828
914
  OPENCLAW_RUNTIME_PACKAGES,
829
915
  NINE_ROUTER_NPM_SPEC,
916
+ NINE_ROUTER_PORT,
917
+ NINE_ROUTER_PROXY_API_KEY,
918
+ NINE_ROUTER_API_BASE_URL,
919
+ NINE_ROUTER_DOCKER_API_BASE_URL,
920
+ SUPPORTED_CODEX_MODELS,
921
+ SMART_ROUTE_PROVIDER_MODELS,
922
+ SMART_ROUTE_PROVIDER_ORDER,
830
923
  TELEGRAM_RELAY_PLUGIN_SPEC,
831
924
  TELEGRAM_RELAY_PLUGIN_ID,
832
925
  TELEGRAM_SETUP_GUIDE_FILENAME,
@@ -835,6 +928,9 @@
835
928
  buildTelegramPostInstallChecklist,
836
929
  buildAuthProfilesJson,
837
930
  buildAuthProfilesString,
931
+ get9RouterBaseUrl,
932
+ build9RouterProviderConfig,
933
+ buildGatewayConfig,
838
934
  };
839
935
 
840
936
  })(typeof globalThis !== 'undefined' ? globalThis : {});
@@ -1367,7 +1463,7 @@
1367
1463
  L.push('set "PATH=%APPDATA%\\npm;%PATH%"');
1368
1464
  L.push('powershell -NoProfile -Command "Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -Force" >nul 2>&1');
1369
1465
  L.push('echo.');
1370
- L.push(isVi ? 'echo ====== OpenClaw Khoi dong lai bot ======' : 'echo ====== OpenClaw Restart Bot ======');
1466
+ L.push(isVi ? 'echo ====== OpenClaw - Khoi dong lai bot ======' : 'echo ====== OpenClaw - Restart Bot ======');
1371
1467
  L.push('echo.');
1372
1468
  L.push(isVi ? 'echo [1] Dung process openclaw cu (neu co)...' : 'echo [1] Stopping existing openclaw process (if any)...');
1373
1469
  L.push('call openclaw gateway stop >nul 2>&1');
@@ -1381,11 +1477,20 @@
1381
1477
  L.push("echo $env:DATA_DIR = '%DATA_DIR%' > \"%TEMP%\\oc-start9r.ps1\"");
1382
1478
  L.push("echo $b = Join-Path $env:APPDATA 'npm\\9router.cmd' >> \"%TEMP%\\oc-start9r.ps1\"");
1383
1479
  L.push("echo if ^(-not ^(Test-Path $b^)^) { $b = Join-Path $env:APPDATA 'npm\\9router' } >> \"%TEMP%\\oc-start9r.ps1\"");
1480
+ L.push(`echo $patch = Join-Path '${projectDir}' '.openclaw\\patch-9router.js' >> "%TEMP%\\oc-start9r.ps1"`);
1481
+ L.push("echo if ^(Test-Path $patch^) { ^& node $patch ^| Out-Null } >> \"%TEMP%\\oc-start9r.ps1\"");
1384
1482
  L.push(`echo Start-Process 'cmd.exe' -WindowStyle Hidden -WorkingDirectory '${projectDir}' -ArgumentList ^('/c "' + $b + '" -n -H 0.0.0.0 -p 20128 --skip-update'^) >> "%TEMP%\\oc-start9r.ps1"`);
1385
1483
  L.push('powershell -NoProfile -ExecutionPolicy Bypass -File "%TEMP%\\oc-start9r.ps1"');
1386
1484
  L.push('del "%TEMP%\\oc-start9r.ps1" >nul 2>&1');
1387
1485
  L.push('timeout /t 5 /nobreak >nul');
1388
1486
  L.push(isVi ? 'echo [OK] 9Router da khoi dong.' : 'echo [OK] 9Router started.');
1487
+ L.push('');
1488
+ L.push(isVi ? 'echo [2b] Khoi dong sync smart-route...' : 'echo [2b] Starting smart-route sync...');
1489
+ L.push(`echo $env:DATA_DIR = '%DATA_DIR%' > "%TEMP%\\oc-syncsmart.ps1"`);
1490
+ L.push(`echo $sync = Join-Path '${projectDir}' '.openclaw\\9router-smart-route-sync.js' >> "%TEMP%\\oc-syncsmart.ps1"`);
1491
+ L.push(`echo if ^(Test-Path $sync^) { Start-Process 'node' -WindowStyle Hidden -ArgumentList $sync } >> "%TEMP%\\oc-syncsmart.ps1"`);
1492
+ L.push('powershell -NoProfile -ExecutionPolicy Bypass -File "%TEMP%\\oc-syncsmart.ps1"');
1493
+ L.push('del "%TEMP%\\oc-syncsmart.ps1" >nul 2>&1');
1389
1494
  }
1390
1495
  L.push('');
1391
1496
  L.push(isVi ? 'echo [3] Khoi dong OpenClaw Gateway...' : 'echo [3] Starting OpenClaw Gateway...');
@@ -1452,7 +1557,7 @@
1452
1557
  L.push(' exit 1');
1453
1558
  L.push('fi');
1454
1559
  L.push('');
1455
- L.push(isVi ? 'echo "====== OpenClaw Khoi dong lai bot qua PM2 ======"' : 'echo "====== OpenClaw Restart Bot via PM2 ======"');
1560
+ L.push(isVi ? 'echo "====== OpenClaw - Khoi dong lai bot qua PM2 ======"' : 'echo "====== OpenClaw - Restart Bot via PM2 ======"');
1456
1561
  L.push('echo ""');
1457
1562
  if (is9Router) {
1458
1563
  L.push(isVi ? 'echo "[1] Khoi dong lai 9Router qua PM2..."' : 'echo "[1] Restarting 9Router via PM2..."');
@@ -1463,6 +1568,9 @@
1463
1568
  L.push(' exit 1');
1464
1569
  L.push('fi');
1465
1570
  L.push('pm2 delete "$APP_NAME-9router" "$APP_NAME-9router-sync" >/dev/null 2>&1 || true');
1571
+ L.push('if [ -f "$PROJECT_DIR/.openclaw/patch-9router.js" ]; then');
1572
+ L.push(' "$NODE_BIN" "$PROJECT_DIR/.openclaw/patch-9router.js" >/dev/null 2>&1 || true');
1573
+ L.push('fi');
1466
1574
  L.push('PORT=20128 HOSTNAME=0.0.0.0 DATA_DIR="$DATA_DIR" pm2 start "$NINE_ROUTER_BIN" --name "$APP_NAME-9router" --interpreter "$NODE_BIN" -- -n -H 0.0.0.0 -p 20128 --skip-update');
1467
1575
  L.push('if [ -f "$PROJECT_DIR/.openclaw/9router-smart-route-sync.js" ]; then');
1468
1576
  L.push(' pm2 start "$NODE_BIN" --name "$APP_NAME-9router-sync" -- "$PROJECT_DIR/.openclaw/9router-smart-route-sync.js"');
@@ -1498,7 +1606,7 @@
1498
1606
  L.push('export DATA_DIR="$PWD/.9router"');
1499
1607
  L.push('if [ -f ".env" ]; then set -a; . ./.env; set +a; fi');
1500
1608
  L.push('');
1501
- L.push(isVi ? 'echo "====== OpenClaw Khoi dong lai bot ======"' : 'echo "====== OpenClaw Restart Bot ======"');
1609
+ L.push(isVi ? 'echo "====== OpenClaw - Khoi dong lai bot ======"' : 'echo "====== OpenClaw - Restart Bot ======"');
1502
1610
  L.push('');
1503
1611
  L.push(isVi ? 'echo "[1] Dung openclaw gateway cu (neu co)..."' : 'echo "[1] Stopping existing openclaw gateway (if any)..."');
1504
1612
  L.push('openclaw gateway stop 2>/dev/null || true');
@@ -1513,9 +1621,17 @@
1513
1621
  L.push(isVi ? ' echo "ERROR: Khong tim thay 9router! Chay: npm install -g 9router"' : ' echo "ERROR: 9router not found! Run: npm install -g 9router"');
1514
1622
  L.push(' exit 1');
1515
1623
  L.push('fi');
1624
+ L.push('if [ -f "$PROJECT_DIR/.openclaw/patch-9router.js" ]; then');
1625
+ L.push(' node "$PROJECT_DIR/.openclaw/patch-9router.js" >/dev/null 2>&1 || true');
1626
+ L.push('fi');
1516
1627
  L.push(`nohup env PORT=20128 HOSTNAME=0.0.0.0 DATA_DIR="$DATA_DIR" "$NINE_ROUTER_BIN" -n -H 0.0.0.0 -p 20128 --skip-update > "${logFile9r}" 2>&1 &`);
1517
1628
  L.push('sleep 3');
1518
1629
  L.push(isVi ? `echo "[OK] 9Router da khoi dong. Log: ${logFile9r}"` : `echo "[OK] 9Router started. Log: ${logFile9r}"`);
1630
+ L.push('');
1631
+ L.push(isVi ? 'echo "[2b] Khoi dong sync smart-route..."' : 'echo "[2b] Starting smart-route sync..."');
1632
+ L.push('if [ -f "$PROJECT_DIR/.openclaw/9router-smart-route-sync.js" ]; then');
1633
+ L.push(' nohup env DATA_DIR="$DATA_DIR" node "$PROJECT_DIR/.openclaw/9router-smart-route-sync.js" > /tmp/9router-sync.log 2>&1 &');
1634
+ L.push('fi');
1519
1635
  }
1520
1636
  L.push('');
1521
1637
  L.push(isVi ? 'echo "[3] Khoi dong OpenClaw Gateway..."' : 'echo "[3] Starting OpenClaw Gateway..."');
@@ -1751,34 +1867,10 @@
1751
1867
  // ── Shared Docker artifact helpers for wizard + CLI (setup/shared/docker-gen.js)
1752
1868
  // @ts-nocheck
1753
1869
  (function (root) {
1754
- const SMART_ROUTE_PROVIDER_MODELS = {
1755
- codex: ['cx/gpt-5.4', 'cx/gpt-5.3-codex', 'cx/gpt-5.3-codex-high', 'cx/gpt-5.2-codex', 'cx/gpt-5.2', 'cx/gpt-5.1-codex-max', 'cx/gpt-5.1-codex', 'cx/gpt-5.1', 'cx/gpt-5-codex'],
1756
- 'claude-code': ['cc/claude-opus-4-6', 'cc/claude-sonnet-4-6', 'cc/claude-opus-4-5-20251101', 'cc/claude-sonnet-4-5-20250929', 'cc/claude-haiku-4-5-20251001'],
1757
- github: ['gh/gpt-5.4', 'gh/gpt-5.3-codex', 'gh/gpt-5.2-codex', 'gh/gpt-5.2', 'gh/gpt-5.1-codex-max', 'gh/gpt-5.1-codex', 'gh/gpt-5.1', 'gh/gpt-5', 'gh/gpt-4.1', 'gh/gpt-4o', 'gh/claude-opus-4.6', 'gh/claude-sonnet-4.6', 'gh/claude-sonnet-4.5', 'gh/claude-opus-4.5', 'gh/claude-haiku-4.5', 'gh/gemini-3-pro-preview', 'gh/gemini-3-flash-preview', 'gh/gemini-2.5-pro'],
1758
- cursor: ['cu/default', 'cu/claude-4.6-opus-max', 'cu/claude-4.5-opus-high-thinking', 'cu/claude-4.5-sonnet-thinking', 'cu/claude-4.5-sonnet', 'cu/gpt-5.3-codex', 'cu/gpt-5.2-codex', 'cu/gemini-3-flash-preview'],
1759
- kilo: ['kc/anthropic/claude-sonnet-4-20250514', 'kc/anthropic/claude-opus-4-20250514', 'kc/google/gemini-2.5-pro', 'kc/google/gemini-2.5-flash', 'kc/openai/gpt-4.1', 'kc/deepseek/deepseek-chat'],
1760
- cline: ['cl/anthropic/claude-sonnet-4.6', 'cl/anthropic/claude-opus-4.6', 'cl/openai/gpt-5.3-codex', 'cl/openai/gpt-5.4', 'cl/google/gemini-3.1-pro-preview'],
1761
- 'gemini-cli': ['gc/gemini-3-flash-preview', 'gc/gemini-3-pro-preview'],
1762
- iflow: ['if/qwen3-coder-plus', 'if/kimi-k2', 'if/kimi-k2-thinking', 'if/glm-4.7', 'if/deepseek-r1', 'if/deepseek-v3.2', 'if/deepseek-v3', 'if/qwen3-max', 'if/qwen3-235b', 'if/iflow-rome-30ba3b'],
1763
- qwen: ['qw/qwen3-coder-plus', 'qw/qwen3-coder-flash', 'qw/vision-model', 'qw/coder-model'],
1764
- kiro: ['kr/claude-sonnet-4.5', 'kr/claude-haiku-4.5', 'kr/deepseek-3.2', 'kr/deepseek-3.1', 'kr/qwen3-coder-next'],
1765
- ollama: ['ollama/gemma4:e2b', 'ollama/gemma4:e4b', 'ollama/gemma4:26b', 'ollama/gemma4:31b', 'ollama/qwen3.5', 'ollama/kimi-k2.5', 'ollama/glm-5', 'ollama/glm-4.7-flash', 'ollama/minimax-m2.5', 'ollama/gpt-oss:120b'],
1766
- 'kimi-coding': ['kmc/kimi-k2.5', 'kmc/kimi-k2.5-thinking', 'kmc/kimi-latest'],
1767
- glm: ['glm/glm-5.1', 'glm/glm-5', 'glm/glm-4.7'],
1768
- 'glm-cn': ['glm/glm-5.1', 'glm/glm-5', 'glm/glm-4.7'],
1769
- minimax: ['minimax/MiniMax-M2.7', 'minimax/MiniMax-M2.5', 'minimax/MiniMax-M2.1'],
1770
- kimi: ['kimi/kimi-k2.5', 'kimi/kimi-k2.5-thinking', 'kimi/kimi-latest'],
1771
- deepseek: ['deepseek/deepseek-chat', 'deepseek/deepseek-reasoner'],
1772
- xai: ['xai/grok-4', 'xai/grok-4-fast-reasoning', 'xai/grok-code-fast-1'],
1773
- mistral: ['mistral/mistral-large-latest', 'mistral/codestral-latest'],
1774
- groq: ['groq/llama-3.3-70b-versatile', 'groq/openai/gpt-oss-120b'],
1775
- cerebras: ['cerebras/gpt-oss-120b'],
1776
- alicode: ['alicode/qwen3.5-plus', 'alicode/qwen3-coder-plus'],
1777
- openai: ['openai/gpt-4o', 'openai/gpt-4.1'],
1778
- anthropic: ['anthropic/claude-sonnet-4', 'anthropic/claude-haiku-3.5'],
1779
- gemini: ['gemini/gemini-2.5-flash', 'gemini/gemini-2.5-pro'],
1780
- };
1781
- const SMART_ROUTE_PROVIDER_ORDER = ['openai', 'anthropic', 'claude-code', 'codex', 'cursor', 'github', 'cline', 'kimi', 'minimax', 'deepseek', 'glm', 'alicode', 'xai', 'mistral', 'kilo', 'kiro', 'iflow', 'qwen', 'gemini-cli', 'ollama'];
1870
+ const common = (typeof globalThis !== 'undefined' && globalThis.__openclawCommon) || {};
1871
+ const SUPPORTED_CODEX_MODELS = common.SUPPORTED_CODEX_MODELS || ['cx/gpt-5.4', 'cx/gpt-5.3-codex', 'cx/gpt-5.2', 'cx/gpt-5.4-mini'];
1872
+ const SMART_ROUTE_PROVIDER_MODELS = common.SMART_ROUTE_PROVIDER_MODELS || { codex: SUPPORTED_CODEX_MODELS };
1873
+ const SMART_ROUTE_PROVIDER_ORDER = common.SMART_ROUTE_PROVIDER_ORDER || ['codex'];
1782
1874
 
1783
1875
  function encodeBase64Utf8(value) {
1784
1876
  if (typeof Buffer !== 'undefined') {
@@ -1838,11 +1930,75 @@
1838
1930
  setInterval(sync, INTERVAL);`;
1839
1931
  }
1840
1932
 
1841
- function build9RouterComposeEntrypointScript(syncScriptBase64) {
1933
+ function build9RouterPatchScript() {
1934
+ return `const fs=require('fs');const path=require('path');const cp=require('child_process');
1935
+ const MODELS=${JSON.stringify(SUPPORTED_CODEX_MODELS.map((model) => model.replace('cx/', '')))};
1936
+ const MODEL_NAMES={"gpt-5.4":"GPT 5.4","gpt-5.4-mini":"GPT 5.4 Mini","gpt-5.3-codex":"GPT 5.3 Codex","gpt-5.2":"GPT 5.2"};
1937
+ const SELF_TEST_BLOCK=[
1938
+ 'codex: {',
1939
+ ' url: "https://chatgpt.com/backend-api/codex/responses",',
1940
+ ' method: "POST",',
1941
+ ' authHeader: "Authorization",',
1942
+ ' authPrefix: "Bearer ",',
1943
+ ' extraHeaders: { "Content-Type": "application/json", "originator": "codex-cli", "User-Agent": "codex-cli/1.0.18 (macOS; arm64)" },',
1944
+ ' body: JSON.stringify({',
1945
+ ' model: "gpt-5.2",',
1946
+ ' instructions: "You are a coding assistant.",',
1947
+ ' input: [{ role: "user", content: [{ type: "input_text", text: "Reply with exactly: ok" }] }],',
1948
+ ' stream: true,',
1949
+ ' store: false,',
1950
+ ' }),',
1951
+ ' acceptStatuses: [200, 400],',
1952
+ ' refreshable: true,',
1953
+ ' },'
1954
+ ].join('\\n');
1955
+ const roots=new Set();
1956
+ function add(p){if(p)roots.add(p);}
1957
+ try{const npmRoot=cp.execSync('npm root -g',{stdio:['ignore','pipe','ignore'],encoding:'utf8'}).trim();if(npmRoot)add(path.join(npmRoot,'9router'));}catch{}
1958
+ add(path.join(process.env.APPDATA||'','npm','node_modules','9router'));
1959
+ add('/usr/local/lib/node_modules/9router');
1960
+ add('/usr/lib/node_modules/9router');
1961
+ add(path.join(process.cwd(),'node_modules','9router'));
1962
+ function patchFile(filePath, transform){if(!fs.existsSync(filePath))return false;const before=fs.readFileSync(filePath,'utf8');const after=transform(before);if(!after||after===before)return false;fs.writeFileSync(filePath,after);return true;}
1963
+ function patchText(text,replacers){let next=text;for(const replacer of replacers){next=replacer(next);}return next===text?null:next;}
1964
+ function patchProviderModels(root){return patchFile(path.join(root,'open-sse','config','providerModels.js'),(text)=>text.replace(/cx:\\s*\\[[\\s\\S]*?\\],/,()=>{const lines=MODELS.map((id)=>' { id: "'+id+'", name: "'+(MODEL_NAMES[id]||id)+'" },');return 'cx: [ // OpenAI Codex\\n'+lines.join('\\n')+'\\n ],';}));}
1965
+ function patchCodexLikeFile(filePath){return patchFile(filePath,(text)=>{if(text.includes('max_output_tokens'))return text;return patchText(text,[
1966
+ (value)=>value.replace(/delete (\\w+)\\.max_tokens,delete \\1\\.user/g,'delete $1.max_tokens,delete $1.max_output_tokens,delete $1.user'),
1967
+ (value)=>value.replace(/delete (\\w+)\\.max_tokens;(\\s*)delete \\1\\.user/g,'delete $1.max_tokens;$2delete $1.max_output_tokens;$2delete $1.user'),
1968
+ (value)=>value.replace(' delete body.max_tokens;\\n',' delete body.max_tokens;\\n delete body.max_output_tokens;\\n')
1969
+ ]);});}
1970
+ function patchCodexExecutor(root){let touched=0;touched+=patchCodexLikeFile(path.join(root,'open-sse','executors','codex.js'))?1:0;const chunksDir=path.join(root,'app','.next','server','chunks');if(fs.existsSync(chunksDir)){for(const entry of fs.readdirSync(chunksDir)){if(!entry.endsWith('.js'))continue;touched+=patchCodexLikeFile(path.join(chunksDir,entry))?1:0;}}return touched;}
1971
+ function patchResponsesNullGuard(root){let touched=0;const chunksDir=path.join(root,'app','.next','server','chunks');if(!fs.existsSync(chunksDir))return touched;for(const entry of fs.readdirSync(chunksDir)){if(!entry.endsWith('.js'))continue;touched+=patchFile(path.join(chunksDir,entry),(text)=>patchText(text,[
1972
+ (value)=>value.replace('let b=a.content.find(a=>"output_text"===a.type);','let b=a.content.find(a=>a&&"output_text"===a.type);'),
1973
+ (value)=>value.replace('let c=a.content.find(a=>"string"==typeof a.text);','let c=a.content.find(a=>a&&"string"==typeof a.text);'),
1974
+ (value)=>value.replace('let b=a.filter(a=>a?.type==="message");','let b=a.filter(a=>a&&a?.type==="message");'),
1975
+ (value)=>value.replace('for(let a of j){let b=a.type||(a.role?"message":null);','for(let a of j){let b=a&&(a.type||(a.role?"message":null));'),
1976
+ (value)=>value.replace('for(let a of b.messages||[]){if("system"===a.role){','for(let a of b.messages||[])if(a){if("system"===a.role){'),
1977
+ (value)=>value.replace('let b=Array.isArray(a.content)?a.content.map(a=>"input_text"===a.type||"output_text"===a.type?{type:"text",text:a.text}:"input_image"===a.type?{type:"image_url",image_url:{url:a.image_url||a.file_id||"",detail:a.detail||"auto"}}:a):a.content;','let b=Array.isArray(a.content)?a.content.map(a=>a&&("input_text"===a.type||"output_text"===a.type)?{type:"text",text:a.text}:a&&"input_image"===a.type?{type:"image_url",image_url:{url:a.image_url||a.file_id||"",detail:a.detail||"auto"}}:a).filter(Boolean):a.content;'),
1978
+ (value)=>value.replace('c="string"==typeof a.content?[{type:b,text:a.content}]:Array.isArray(a.content)?a.content.map(a=>{if("text"===a.type)return{type:b,text:a.text};if("image_url"===a.type)return{type:"input_image",image_url:"string"==typeof a.image_url?a.image_url:a.image_url?.url,detail:a.image_url?.detail||"auto"};if("input_image"===a.type)return a;let c=a.text||a.content||JSON.stringify(a);return{type:b,text:"string"==typeof c?c:JSON.stringify(c)}}):[];','c="string"==typeof a.content?[{type:b,text:a.content}]:Array.isArray(a.content)?a.content.map(a=>{if(!a)return null;if("text"===a.type)return{type:b,text:a.text};if("image_url"===a.type)return{type:"input_image",image_url:"string"==typeof a.image_url?a.image_url:a.image_url?.url,detail:a.image_url?.detail||"auto"};if("input_image"===a.type)return a;let c=a.text||a.content||JSON.stringify(a);return{type:b,text:"string"==typeof c?c:JSON.stringify(c)}}).filter(Boolean):[];'),
1979
+ (value)=>value.replace('b.tools&&Array.isArray(b.tools)&&(e.tools=b.tools.map(a=>{if(a.function)return a;let b=a.name;return b&&"string"==typeof b&&""!==b.trim()?{type:"function",function:{name:b,description:String(a.description||""),parameters:i(a.parameters),strict:a.strict}}:null}).filter(Boolean))','b.tools&&Array.isArray(b.tools)&&(e.tools=b.tools.map(a=>{if(!a)return null;if(a.function)return a;let b=a.name;return b&&"string"==typeof b&&""!==b.trim()?{type:"function",function:{name:b,description:String(a.description||""),parameters:i(a.parameters),strict:a.strict}}:null}).filter(Boolean))'),
1980
+ (value)=>value.replace('b.tools&&Array.isArray(b.tools)&&(e.tools=b.tools.map(a=>"function"===a.type?{type:"function",name:a.function.name,description:String(a.function.description||""),parameters:i(a.function.parameters),strict:a.function.strict}:a)),','b.tools&&Array.isArray(b.tools)&&(e.tools=b.tools.map(a=>a&&"function"===a.type?{type:"function",name:a.function.name,description:String(a.function.description||""),parameters:i(a.function.parameters),strict:a.function.strict}:a).filter(Boolean)),'),
1981
+ (value)=>value.replace('filter(a=>"function_call"===a.type)','filter(a=>a&&"function_call"===a.type)'),
1982
+ (value)=>value.replace(/filter\\(a=>"text"===a\\.type\\)/g,'filter(a=>a&&"text"===a.type)'),
1983
+ (value)=>value.replace(/find\\(a=>"message_stop"===a\\.type\\)/g,'find(a=>a&&"message_stop"===a.type)'),
1984
+ (value)=>value.replace(/find\\(a=>"content_block_delta"===a\\.type\\)/g,'find(a=>a&&"content_block_delta"===a.type)'),
1985
+ (value)=>value.replace(/find\\(a=>"message_delta"===a\\.type\\)/g,'find(a=>a&&"message_delta"===a.type)'),
1986
+ (value)=>value.replace(/find\\(a=>"message_start"===a\\.type\\)/g,'find(a=>a&&"message_start"===a.type)'),
1987
+ (value)=>value.replace(/for\\(let e of a\\.content\\)(?!if\\(e\\))/g,'for(let e of a.content)if(e)')
1988
+ ] ))?1:0;}return touched;}
1989
+ function patchSelfTest(root){return patchFile(path.join(root,'src','app','api','providers','[id]','test','testUtils.js'),(text)=>{if(text.includes('model: "gpt-5.2"')&&text.includes('store: false')&&text.includes('acceptStatuses: [200, 400]'))return text;return text.replace(/codex:\\s*\\{[\\s\\S]*?refreshable:\\s*true,\\s*\\},/,SELF_TEST_BLOCK);});}
1990
+ let touched=0;
1991
+ for(const root of roots){if(!root||!fs.existsSync(root))continue;touched+=patchProviderModels(root)?1:0;touched+=patchCodexExecutor(root)?1:0;touched+=patchResponsesNullGuard(root)?1:0;touched+=patchSelfTest(root)?1:0;}
1992
+ if(touched){console.log('[patch-9router] Applied Codex compatibility patch.');}else{console.log('[patch-9router] No compatible 9router source files found to patch.');}`;
1993
+ }
1994
+
1995
+ function build9RouterComposeEntrypointScript(syncScriptBase64, patchScriptBase64) {
1842
1996
  const nineRouterSpec = (typeof globalThis !== 'undefined' && globalThis.__openclawCommon && globalThis.__openclawCommon.NINE_ROUTER_NPM_SPEC) || '9router@latest';
1843
1997
  return [
1844
1998
  `npm install -g ${nineRouterSpec}`,
1999
+ `node -e "require('fs').writeFileSync('/tmp/patch-9router.js',Buffer.from('${patchScriptBase64}','base64').toString())"`,
1845
2000
  `node -e "require('fs').writeFileSync('/tmp/sync.js',Buffer.from('${syncScriptBase64}','base64').toString())"`,
2001
+ 'node /tmp/patch-9router.js || true',
1846
2002
  'node /tmp/sync.js > /tmp/sync.log 2>&1 &',
1847
2003
  'exec 9router -n -l -H 0.0.0.0 -p 20128 --skip-update'
1848
2004
  ].join('\n');
@@ -1930,7 +2086,9 @@
1930
2086
 
1931
2087
  const syncScript = build9RouterSmartRouteSyncScript('/root/.9router/db.json');
1932
2088
  const syncScriptBase64 = encodeBase64Utf8(syncScript);
1933
- const docker9RouterEntrypointScript = build9RouterComposeEntrypointScript(syncScriptBase64);
2089
+ const patchScript = build9RouterPatchScript();
2090
+ const patchScriptBase64 = encodeBase64Utf8(patchScript);
2091
+ const docker9RouterEntrypointScript = build9RouterComposeEntrypointScript(syncScriptBase64, patchScriptBase64);
1934
2092
  const extraHostsBlock = ` extra_hosts:\n - "host.docker.internal:host-gateway"`;
1935
2093
 
1936
2094
  const appEnvironmentBlock = ' environment:\n - OPENCLAW_HOME=/root/project/.openclaw\n - OPENCLAW_STATE_DIR=/root/project/.openclaw\n';
@@ -2139,6 +2297,7 @@
2139
2297
  encodeBase64Utf8,
2140
2298
  indentBlock,
2141
2299
  build9RouterSmartRouteSyncScript,
2300
+ build9RouterPatchScript,
2142
2301
  build9RouterComposeEntrypointScript,
2143
2302
  buildGatewayPatchCmd,
2144
2303
  buildDockerArtifacts,
@@ -2157,34 +2316,8 @@
2157
2316
  * Do NOT add import/export statements. Edit, then run: node build.mjs
2158
2317
  */
2159
2318
 
2160
- const SMART_ROUTE_PROVIDER_MODELS = {
2161
- codex: ['cx/gpt-5.4', 'cx/gpt-5.3-codex', 'cx/gpt-5.3-codex-high', 'cx/gpt-5.2-codex', 'cx/gpt-5.2', 'cx/gpt-5.1-codex-max', 'cx/gpt-5.1-codex', 'cx/gpt-5.1', 'cx/gpt-5-codex'],
2162
- 'claude-code': ['cc/claude-opus-4-6', 'cc/claude-sonnet-4-6', 'cc/claude-opus-4-5-20251101', 'cc/claude-sonnet-4-5-20250929', 'cc/claude-haiku-4-5-20251001'],
2163
- github: ['gh/gpt-5.4', 'gh/gpt-5.3-codex', 'gh/gpt-5.2-codex', 'gh/gpt-5.2', 'gh/gpt-5.1-codex-max', 'gh/gpt-5.1-codex', 'gh/gpt-5.1', 'gh/gpt-5', 'gh/gpt-4.1', 'gh/gpt-4o', 'gh/claude-opus-4.6', 'gh/claude-sonnet-4.6', 'gh/claude-sonnet-4.5', 'gh/claude-opus-4.5', 'gh/claude-haiku-4.5', 'gh/gemini-3-pro-preview', 'gh/gemini-3-flash-preview', 'gh/gemini-2.5-pro'],
2164
- cursor: ['cu/default', 'cu/claude-4.6-opus-max', 'cu/claude-4.5-opus-high-thinking', 'cu/claude-4.5-sonnet-thinking', 'cu/claude-4.5-sonnet', 'cu/gpt-5.3-codex', 'cu/gpt-5.2-codex', 'cu/gemini-3-flash-preview'],
2165
- kilo: ['kc/anthropic/claude-sonnet-4-20250514', 'kc/anthropic/claude-opus-4-20250514', 'kc/google/gemini-2.5-pro', 'kc/google/gemini-2.5-flash', 'kc/openai/gpt-4.1', 'kc/deepseek/deepseek-chat'],
2166
- cline: ['cl/anthropic/claude-sonnet-4.6', 'cl/anthropic/claude-opus-4.6', 'cl/openai/gpt-5.3-codex', 'cl/openai/gpt-5.4', 'cl/google/gemini-3.1-pro-preview'],
2167
- 'gemini-cli': ['gc/gemini-3-flash-preview', 'gc/gemini-3-pro-preview'],
2168
- iflow: ['if/qwen3-coder-plus', 'if/kimi-k2', 'if/kimi-k2-thinking', 'if/glm-4.7', 'if/deepseek-r1', 'if/deepseek-v3.2', 'if/deepseek-v3', 'if/qwen3-max', 'if/qwen3-235b', 'if/iflow-rome-30ba3b'],
2169
- qwen: ['qw/qwen3-coder-plus', 'qw/qwen3-coder-flash', 'qw/vision-model', 'qw/coder-model'],
2170
- kiro: ['kr/claude-sonnet-4.5', 'kr/claude-haiku-4.5', 'kr/deepseek-3.2', 'kr/deepseek-3.1', 'kr/qwen3-coder-next'],
2171
- ollama: ['ollama/gemma4:e2b', 'ollama/gemma4:e4b', 'ollama/gemma4:26b', 'ollama/gemma4:31b', 'ollama/qwen3.5', 'ollama/kimi-k2.5', 'ollama/glm-5', 'ollama/glm-4.7-flash', 'ollama/minimax-m2.5', 'ollama/gpt-oss:120b'],
2172
- 'kimi-coding': ['kmc/kimi-k2.5', 'kmc/kimi-k2.5-thinking', 'kmc/kimi-latest'],
2173
- glm: ['glm/glm-5.1', 'glm/glm-5', 'glm/glm-4.7'],
2174
- 'glm-cn': ['glm/glm-5.1', 'glm/glm-5', 'glm/glm-4.7'],
2175
- minimax: ['minimax/MiniMax-M2.7', 'minimax/MiniMax-M2.5', 'minimax/MiniMax-M2.1'],
2176
- kimi: ['kimi/kimi-k2.5', 'kimi/kimi-k2.5-thinking', 'kimi/kimi-latest'],
2177
- deepseek: ['deepseek/deepseek-chat', 'deepseek/deepseek-reasoner'],
2178
- xai: ['xai/grok-4', 'xai/grok-4-fast-reasoning', 'xai/grok-code-fast-1'],
2179
- mistral: ['mistral/mistral-large-latest', 'mistral/codestral-latest'],
2180
- groq: ['groq/llama-3.3-70b-versatile', 'groq/openai/gpt-oss-120b'],
2181
- cerebras: ['cerebras/gpt-oss-120b'],
2182
- alicode: ['alicode/qwen3.5-plus', 'alicode/qwen3-coder-plus'],
2183
- openai: ['openai/gpt-4o', 'openai/gpt-4.1'],
2184
- anthropic: ['anthropic/claude-sonnet-4', 'anthropic/claude-haiku-3.5'],
2185
- gemini: ['gemini/gemini-2.5-flash', 'gemini/gemini-2.5-pro'],
2186
- };
2187
- const SMART_ROUTE_PROVIDER_ORDER = ['openai', 'anthropic', 'claude-code', 'codex', 'cursor', 'github', 'cline', 'kimi', 'minimax', 'deepseek', 'glm', 'alicode', 'xai', 'mistral', 'kilo', 'kiro', 'iflow', 'qwen', 'gemini-cli', 'ollama'];
2319
+ const SMART_ROUTE_PROVIDER_MODELS = globalThis.__openclawCommon.SMART_ROUTE_PROVIDER_MODELS;
2320
+ const SMART_ROUTE_PROVIDER_ORDER = globalThis.__openclawCommon.SMART_ROUTE_PROVIDER_ORDER;
2188
2321
 
2189
2322
  function buildNativeScriptCtx(options) {
2190
2323
  const relayPluginSpec = options?.relayPluginSpec || 'openclaw-telegram-multibot-relay';
@@ -2231,7 +2364,7 @@
2231
2364
  const path=require('path');
2232
2365
  const INTERVAL=30000;
2233
2366
  const p=path.join(process.env.DATA_DIR||'.9router','db.json');
2234
- const ROUTER='http://localhost:20128';
2367
+ const ROUTER='${globalThis.__openclawCommon.NINE_ROUTER_API_BASE_URL}';
2235
2368
  const PM=${JSON.stringify(SMART_ROUTE_PROVIDER_MODELS)};
2236
2369
  const PREF=${JSON.stringify(SMART_ROUTE_PROVIDER_ORDER)};
2237
2370
  console.log('[sync-combo] 9Router sync loop started...');
@@ -2426,19 +2559,9 @@
2426
2559
  models: {
2427
2560
  mode: 'merge',
2428
2561
  providers: {
2429
- '9router': {
2430
- baseUrl: 'http://localhost:20128/v1',
2431
- apiKey: 'sk-no-key',
2432
- api: 'openai-completions',
2433
- models: [
2434
- {
2435
- id: 'smart-route',
2436
- name: 'Smart Proxy (Auto Route)',
2437
- contextWindow: 200000,
2438
- maxTokens: 8192,
2439
- }
2440
- ]
2441
- }
2562
+ '9router': globalThis.__openclawCommon.build9RouterProviderConfig(
2563
+ globalThis.__openclawCommon.get9RouterBaseUrl('native')
2564
+ )
2442
2565
  }
2443
2566
  }
2444
2567
  } : {}),
@@ -2575,6 +2698,7 @@
2575
2698
  // Force use global provider if proxy mode is chosen globally, else use bot specific provider
2576
2699
  const botProvider = (provider && provider.isProxy) ? provider : (PROVIDERS[bot.provider] || provider);
2577
2700
  const actualModel = botProvider.isProxy ? provider.models[0].id : (bot.model || state.config.model);
2701
+ const common = globalThis.__openclawCommon;
2578
2702
 
2579
2703
  const cfg = {
2580
2704
  meta: { lastTouchedVersion: '2026.3.24' },
@@ -2596,19 +2720,7 @@
2596
2720
  models: {
2597
2721
  mode: 'merge',
2598
2722
  providers: {
2599
- '9router': {
2600
- baseUrl: state.deployMode === 'docker' ? 'http://9router:20128/v1' : 'http://localhost:20128/v1',
2601
- apiKey: 'sk-no-key',
2602
- api: 'openai-completions',
2603
- models: [
2604
- {
2605
- id: 'smart-route',
2606
- name: 'Smart Proxy (Auto Route)',
2607
- contextWindow: 200000,
2608
- maxTokens: 8192,
2609
- }
2610
- ]
2611
- }
2723
+ '9router': common.build9RouterProviderConfig(common.get9RouterBaseUrl(state.deployMode))
2612
2724
  }
2613
2725
  }
2614
2726
  } : {}),
@@ -2629,17 +2741,7 @@
2629
2741
  commands: { native: 'auto', nativeSkills: 'auto', restart: true, ownerDisplay: 'raw' },
2630
2742
  channels: {},
2631
2743
  tools: { profile: 'full', exec: { host: 'gateway', security: 'full', ask: 'off' } },
2632
- gateway: {
2633
- port: basePort,
2634
- mode: 'local',
2635
- ...(state.deployMode === 'docker'
2636
- ? { bind: 'custom', customBindHost: '0.0.0.0' }
2637
- : { bind: 'loopback' }),
2638
- controlUi: {
2639
- allowedOrigins: getGatewayAllowedOrigins(basePort),
2640
- },
2641
- auth: { mode: 'token', token: crypto.randomUUID().replace(/-/g, '') },
2642
- },
2744
+ gateway: common.buildGatewayConfig(basePort, state.deployMode, getGatewayAllowedOrigins(basePort)),
2643
2745
  };
2644
2746
 
2645
2747
  if (hasBrowser) {
@@ -2705,7 +2807,18 @@
2705
2807
  if (state.channel === 'zalo-personal') {
2706
2808
  cfg.channels.zalouser = {
2707
2809
  enabled: true,
2810
+ defaultAccount: 'default',
2708
2811
  dmPolicy: 'open',
2812
+ allowFrom: ['*'],
2813
+ groupPolicy: 'allowlist',
2814
+ groupAllowFrom: ['*'],
2815
+ historyLimit: 50,
2816
+ groups: {
2817
+ '*': {
2818
+ enabled: true,
2819
+ requireMention: false,
2820
+ },
2821
+ },
2709
2822
  autoReply: true,
2710
2823
  };
2711
2824
  // plugins.entries.zalouser is REQUIRED for gateway to load the Zalo channel provider
@@ -2740,7 +2853,7 @@
2740
2853
  const authProviderName = botProvider.isProxy ? '9router' : (bot.provider || state.config.provider);
2741
2854
  const authProfileId = botProvider.isProxy ? '9router-proxy' : `${authProviderName}:default`;
2742
2855
  const authKeyValue = botProvider.isProxy
2743
- ? 'sk-no-key'
2856
+ ? globalThis.__openclawCommon.NINE_ROUTER_PROXY_API_KEY
2744
2857
  : ((bot.apiKey || state.config.apiKey || '').trim() || `<your_${(botProvider.envKey || 'API_KEY').toLowerCase()}>`);
2745
2858
  authProfilesJson = {
2746
2859
  version: 1,
@@ -4808,6 +4921,7 @@
4808
4921
 
4809
4922
  const buildRelayPluginInstallCommand = globalThis.__openclawCommon.buildRelayPluginInstallCommand;
4810
4923
  const buildRelayPluginInstallCommandWin = globalThis.__openclawCommon.buildRelayPluginInstallCommandWin;
4924
+ const common = globalThis.__openclawCommon;
4811
4925
  const lang = state.config.language || document.getElementById('cfg-language')?.value || 'vi';
4812
4926
 
4813
4927
  function buildTelegramPostInstallChecklist() {
@@ -4955,34 +5069,16 @@
4955
5069
  commands: { native: 'auto', nativeSkills: 'auto', restart: true, ownerDisplay: 'raw' },
4956
5070
  channels: ch.channelConfig,
4957
5071
  tools: { profile: 'full', exec: { host: 'gateway', security: 'full', ask: 'off' } },
4958
- gateway: {
4959
- port: 18791,
4960
- mode: 'local',
4961
- bind: 'loopback',
4962
- controlUi: {
4963
- allowedOrigins: getGatewayAllowedOrigins(18791),
4964
- },
4965
- auth: { mode: 'token', token: crypto.randomUUID().replace(/-/g, '') },
4966
- },
5072
+ gateway: common.buildGatewayConfig(18791, 'native', getGatewayAllowedOrigins(18791)),
4967
5073
  };
4968
5074
 
4969
5075
  // 9Router: add proxy endpoint config under models.providers
4970
5076
  // Native mode: 9router runs on localhost; Docker mode: uses docker service hostname
4971
5077
  if (is9Router) {
4972
- const nineRouterBase = state.deployMode === 'native'
4973
- ? 'http://localhost:20128/v1'
4974
- : 'http://9router:20128/v1';
4975
5078
  clawConfig.models = {
4976
5079
  mode: 'merge',
4977
5080
  providers: {
4978
- '9router': {
4979
- baseUrl: nineRouterBase,
4980
- apiKey: 'sk-no-key',
4981
- api: 'openai-completions',
4982
- models: [
4983
- { id: 'smart-route', name: 'Smart Proxy (Auto Route)', contextWindow: 200000, maxTokens: 8192 }
4984
- ],
4985
- },
5081
+ '9router': common.build9RouterProviderConfig(common.get9RouterBaseUrl(state.deployMode)),
4986
5082
  },
4987
5083
  };
4988
5084
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-openclaw-bot",
3
- "version": "5.6.8",
3
+ "version": "5.6.10",
4
4
  "description": "Interactive CLI installer for OpenClaw Bot",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {