create-openclaw-bot 5.1.0 → 5.1.2

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.
@@ -38,6 +38,30 @@ checks.push(() => expectMatch(
38
38
  'Docker branch must still auto-install Docker when missing'
39
39
  ));
40
40
 
41
+ checks.push(() => expectMatch(
42
+ cli,
43
+ /function shouldReuseInstalledGlobals\(\) \{[\s\S]*OPENCLAW_SETUP_REUSE_GLOBALS[\s\S]*trim\(\)\.toLowerCase\(\)/,
44
+ 'CLI must expose an env-flag helper for fast test runs that reuse installed global packages'
45
+ ));
46
+
47
+ checks.push(() => expectMatch(
48
+ cli,
49
+ /function installLatestOpenClaw\(\{ isVi, osChoice \}\) \{[\s\S]*installGlobalPackage\('openclaw@latest', \{ isVi, osChoice, displayName: 'openclaw' \}\)[\s\S]*process\.exit\(1\)/,
50
+ 'CLI must provide a shared helper that always installs or upgrades openclaw@latest'
51
+ ));
52
+
53
+ checks.push(() => expectMatch(
54
+ cli,
55
+ /function installLatestOpenClaw\(\{ isVi, osChoice \}\) \{[\s\S]*shouldReuseInstalledGlobals\(\) && isOpenClawInstalled\(\)[\s\S]*Reusing the installed openclaw/s,
56
+ 'CLI fast-test mode must be able to reuse an existing openclaw install'
57
+ ));
58
+
59
+ checks.push(() => expectMatch(
60
+ cli,
61
+ /installLatestOpenClaw\(\{ isVi, osChoice \}\);\s*if \(deployMode === 'docker'\) \{/,
62
+ 'CLI must install or upgrade openclaw before entering the Docker/native branches'
63
+ ));
64
+
41
65
  checks.push(() => expectMatch(
42
66
  cli,
43
67
  /if \(!isOpenClawInstalled\(\)\) \{[\s\S]*installGlobalPackage\('openclaw@latest', \{ isVi, osChoice, displayName: 'openclaw' \}\)/,
@@ -52,19 +76,32 @@ checks.push(() => expectMatch(
52
76
 
53
77
  checks.push(() => expectMatch(
54
78
  cli,
55
- /if \(providerKey === '9router' && !is9RouterInstalled\(\)\) \{[\s\S]*installGlobalPackage\('9router@latest', \{ isVi, osChoice, displayName: '9Router' \}\)/,
79
+ /if \(providerKey === '9router'\) \{[\s\S]*else if \(!is9RouterInstalled\(\)\) \{[\s\S]*installGlobalPackage\('9router@latest', \{ isVi, osChoice, displayName: '9Router' \}\)/,
56
80
  'Native 9Router flow must auto-install 9Router'
57
81
  ));
58
82
 
59
83
  checks.push(() => expectMatch(
60
84
  cli,
61
- /async function writeNative9RouterSyncScript\(projectDir\) \{[\s\S]*9router-smart-route-sync\.js[\s\S]*providerConnections[\s\S]*smart-route/s,
62
- 'Native 9Router flow must write a smart-route sync script based on ~/.9router/db.json'
85
+ /if \(providerKey === '9router'\) \{[\s\S]*shouldReuseInstalledGlobals\(\) && is9RouterInstalled\(\)[\s\S]*Reusing the installed 9Router[\s\S]*else if \(!is9RouterInstalled\(\)\)/s,
86
+ 'CLI fast-test mode must be able to reuse an existing 9Router install'
87
+ ));
88
+
89
+ checks.push(() => expectMatch(
90
+ cli,
91
+ /function build9RouterSmartRouteSyncScript\(dbPath\) \{[\s\S]*safeDbPath[\s\S]*providerConnections[\s\S]*smart-route[\s\S]*async function writeNative9RouterSyncScript\(projectDir\) \{[\s\S]*getNative9RouterDataDir\(\), 'db\.json'/s,
92
+ 'Native 9Router flow must write a smart-route sync script based on the platform-specific 9Router data directory'
63
93
  ));
64
94
 
65
95
  checks.push(() => expectMatch(
66
96
  cli,
67
- /Removed smart-route \(no active providers\)[\s\S]*if \(!a\.length\) \{[\s\S]*removeSmartRoute\(\)[\s\S]*if \(!m\.length\) \{[\s\S]*removeSmartRoute\(\)/s,
97
+ /function getNative9RouterDataDir\(\) \{[\s\S]*process\.platform === 'win32'[\s\S]*AppData[\s\S]*Roaming[\s\S]*9router[\s\S]*os\.homedir\(\)[\s\S]*\.9router/s,
98
+ 'CLI must resolve the correct native 9Router data directory on both Windows and Unix'
99
+ ));
100
+
101
+ checks.push(() => expect(
102
+ cli.includes("Removed smart-route (no active providers)")
103
+ && cli.includes("if(!a.length){removeSmartRoute();return;}")
104
+ && cli.includes("if(!m.length){removeSmartRoute();return;}"),
68
105
  '9Router sync logic in CLI must remove stale smart-route combos when providers are disabled'
69
106
  ));
70
107
 
@@ -94,10 +131,46 @@ checks.push(() => expectMatch(
94
131
 
95
132
  checks.push(() => expectMatch(
96
133
  cli,
97
- /function printZaloPersonalLoginInfo\(\{ isVi, deployMode, projectDir \}\) \{[\s\S]*docker compose exec -it ai-bot openclaw channels login --channel zalouser --verbose[\s\S]*const copyCmd = deployMode === 'native'[\s\S]*docker compose cp ai-bot:\$\{qrPath\} \.\/zalo-login-qr\.png/s,
134
+ /function printZaloPersonalLoginInfo\(\{ isVi, deployMode, projectDir \}\) \{[\s\S]*docker compose exec -it ai-bot openclaw channels login --channel zalouser --verbose[\s\S]*openclaw-zalouser-qr-default\.png[\s\S]*Copy-Item[\s\S]*docker compose cp ai-bot:\$\{qrPath\} \.\/zalo-login-qr\.png/s,
98
135
  'CLI must print the dedicated Docker/native Zalo Personal login commands and QR copy path instead of onboarding'
99
136
  ));
100
137
 
138
+ checks.push(() => expectMatch(
139
+ cli,
140
+ /function extractZaloPairingCode\(text\) \{[\s\S]*openclaw pairing approve zalouser[\s\S]*Pairing code:/s,
141
+ 'CLI must be able to extract a Zalo pairing code from the login output'
142
+ ));
143
+
144
+ checks.push(() => expectMatch(
145
+ cli,
146
+ /function approveZaloPairingCode\(\{ pairingCode, projectDir, isVi \}\) \{[\s\S]*openclaw pairing approve zalouser \$\{pairingCode\}/s,
147
+ 'CLI must be able to auto-approve a detected Zalo pairing code'
148
+ ));
149
+
150
+ checks.push(() => expectMatch(
151
+ cli,
152
+ /async function runNativeZaloPersonalLoginFlow\(\{ isVi, projectDir \}\) \{[\s\S]*spawn\('openclaw', \['channels', 'login', '--channel', 'zalouser', '--verbose'\]/s,
153
+ 'Native Zalo flow must run the zalouser login command'
154
+ ));
155
+
156
+ checks.push(() => expectMatch(
157
+ cli,
158
+ /async function runNativeZaloPersonalLoginFlow\(\{ isVi, projectDir \}\) \{[\s\S]*fs\.remove\(qrSourcePath\)[\s\S]*fs\.remove\(qrProjectPath\)[\s\S]*fs\.copy\(qrSourcePath, qrProjectPath, \{ overwrite: true \}\)/s,
159
+ 'Native Zalo flow must clear stale QR files and copy the fresh QR into the project folder'
160
+ ));
161
+
162
+ checks.push(() => expectMatch(
163
+ cli,
164
+ /async function runNativeZaloPersonalLoginFlow\(\{ isVi, projectDir \}\) \{[\s\S]*outputBuffer[\s\S]*extractZaloPairingCode\(outputBuffer\)[\s\S]*approveZaloPairingCode\(\{ pairingCode, projectDir, isVi \}\)/s,
165
+ 'Native Zalo flow must auto-approve pairing when the login command emits a pairing code'
166
+ ));
167
+
168
+ checks.push(() => expectMatch(
169
+ cli,
170
+ /async function runNativeZaloPersonalLoginFlow\(\{ isVi, projectDir \}\) \{[\s\S]*let loginSucceeded = false[\s\S]*successPattern[\s\S]*if \(exitCode !== 0 && !loginSucceeded\)[\s\S]*else if \(loginSucceeded && exitCode !== 0\)/s,
171
+ 'Native Zalo flow must tolerate non-standard exit codes when the login output already reports success'
172
+ ));
173
+
101
174
  checks.push(() => expectMatch(
102
175
  cli,
103
176
  /baseUrl: deployMode === 'native' \? 'http:\/\/localhost:20128\/v1' : 'http:\/\/9router:20128\/v1'/,
@@ -116,6 +189,36 @@ checks.push(() => expectMatch(
116
189
  'VPS native 9Router flow must start a standalone 9Router dashboard on port 20128 via PM2'
117
190
  ));
118
191
 
192
+ checks.push(() => expectMatch(
193
+ cli,
194
+ /function spawnBackgroundProcess\(command, args, options = \{\}\) \{[\s\S]*if \(process\.platform === 'win32'\)[\s\S]*resolveWindowsCommand[\s\S]*Start-Process -WindowStyle Hidden[\s\S]*powershell\.exe/s,
195
+ 'Native desktop background helpers must use hidden Start-Process launches on Windows'
196
+ ));
197
+
198
+ checks.push(() => expectMatch(
199
+ cli,
200
+ /function resolveNative9RouterDesktopLaunch\(\) \{[\s\S]*process\.platform === 'win32'[\s\S]*npm root -g[\s\S]*9router', 'app', 'server\.js'[\s\S]*PORT: '20128'[\s\S]*HOSTNAME: '0\.0\.0\.0'[\s\S]*command: '9router'[\s\S]*\['-n', '-t', '-l', '-H', '0\.0\.0\.0', '-p', '20128', '--skip-update'\]/s,
201
+ 'Native desktop 9Router launch must bypass the interactive CLI menu on Windows while preserving the standard CLI launch elsewhere'
202
+ ));
203
+
204
+ checks.push(() => expectMatch(
205
+ cli,
206
+ /const native9RouterLaunch = resolveNative9RouterDesktopLaunch\(\);[\s\S]*spawnBackgroundProcess\(native9RouterLaunch\.command, native9RouterLaunch\.args, \{[\s\S]*env: native9RouterLaunch\.env/s,
207
+ 'Native desktop 9Router flow must launch through the background helper with the resolved launch spec'
208
+ ));
209
+
210
+ checks.push(() => expectMatch(
211
+ cli,
212
+ /const routerHealth = await waitFor9RouterApiReady\(\);[\s\S]*admin API chua san sang[\s\S]*admin API is not ready yet/s,
213
+ 'Native desktop 9Router flow must warn when the dashboard port opens but the admin API never becomes ready'
214
+ ));
215
+
216
+ checks.push(() => expectMatch(
217
+ cli,
218
+ /spawnBackgroundProcess\(process\.execPath, \[native9RouterSyncScriptPath\]/,
219
+ 'Native desktop 9Router sync loop must launch through the background helper'
220
+ ));
221
+
119
222
  checks.push(() => expectMatch(
120
223
  cli,
121
224
  /function runPm2Save\(\{ projectDir, isVi \}\) \{[\s\S]*execSync\('pm2 save'[\s\S]*PM2 save did not complete/s,
@@ -124,8 +227,8 @@ checks.push(() => expectMatch(
124
227
 
125
228
  checks.push(() => expectMatch(
126
229
  cli,
127
- /const child = spawn\('openclaw', \['gateway', 'run'\], \{/,
128
- 'Native desktop flows must start openclaw in foreground'
230
+ /if \(channelKey === 'zalo-personal'\) \{\s*await runNativeZaloPersonalLoginFlow\(\{ isVi, projectDir \}\);\s*\}[\s\S]*const child = spawn\('openclaw', \['gateway', 'run'\], \{/s,
231
+ 'Native desktop flows must finish the Zalo login flow before starting openclaw in foreground'
129
232
  ));
130
233
 
131
234
  checks.push(() => expectOrder(
@@ -179,19 +282,20 @@ checks.push(() => expectMatch(
179
282
 
180
283
  checks.push(() => expectMatch(
181
284
  setup,
182
- /function providerLines\(arr, shell\) \{[\s\S]*npm install -g 9router[\s\S]*9router -n -t -l -H 0\.0\.0\.0 -p 20128 --skip-update/s,
285
+ /function providerLines\(arr, shell\) \{[\s\S]*npm install -g 9router[\s\S]*npm root -g[\s\S]*Join-Path \$npmRoot[\s\S]*Start-Process -WindowStyle Hidden -FilePath ''node\.exe''[\s\S]*9router-smart-route-sync\.js/s,
183
286
  'Native script generation must install and start a standalone 9Router dashboard on port 20128'
184
287
  ));
185
288
 
186
289
  checks.push(() => expectMatch(
187
290
  setup,
188
- /function native9RouterSyncScriptContent\(\) \{[\s\S]*providerConnections[\s\S]*smart-route/s,
189
- 'Native script generation must embed a 9Router smart-route sync script'
291
+ /function native9RouterSyncScriptContent\(\) \{[\s\S]*process\.platform==='win32'[\s\S]*AppData[\s\S]*Roaming[\s\S]*providerConnections[\s\S]*smart-route/s,
292
+ 'Native script generation must embed a 9Router smart-route sync script with the correct Windows data directory'
190
293
  ));
191
294
 
192
- checks.push(() => expectMatch(
193
- setup,
194
- /Removed smart-route \(no active providers\)[\s\S]*if \(!a\.length\) \{[\s\S]*removeSmartRoute\(\)[\s\S]*if \(!m\.length\) \{[\s\S]*removeSmartRoute\(\)/s,
295
+ checks.push(() => expect(
296
+ setup.includes("Removed smart-route (no active providers)")
297
+ && setup.includes("if(!a.length){removeSmartRoute();return;}")
298
+ && setup.includes("if(!m.length){removeSmartRoute();return;}"),
195
299
  '9Router sync logic in setup.js must remove stale smart-route combos when providers are disabled'
196
300
  ));
197
301
 
@@ -245,8 +349,8 @@ checks.push(() => expectMatch(
245
349
 
246
350
  checks.push(() => expectMatch(
247
351
  setup,
248
- /docker compose exec -it ai-bot openclaw channels login --channel zalouser --verbose[\s\S]*docker compose cp ai-bot:\/tmp\/openclaw\/openclaw-zalouser-qr-default\.png \.\/zalo-login-qr\.png/s,
249
- 'Wizard copy must use the dedicated zalouser login command and Docker QR copy path'
352
+ /Native setup now auto-runs the login flow and copies the QR into the project folder[\s\S]*docker compose exec -it ai-bot openclaw channels login --channel zalouser --verbose[\s\S]*docker compose cp ai-bot:\/tmp\/openclaw\/openclaw-zalouser-qr-default\.png \.\/zalo-login-qr\.png/s,
353
+ 'Wizard copy must mention native auto-login and still show the dedicated Docker QR login command'
250
354
  ));
251
355
 
252
356
  for (const check of checks) {
@@ -1,20 +0,0 @@
1
- const fs = require('fs');
2
-
3
- const configPath = process.argv[2];
4
-
5
- if (!configPath) {
6
- console.error('Usage: node live-enable-zalouser.cjs <configPath>');
7
- process.exit(1);
8
- }
9
-
10
- const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
11
- config.channels = config.channels || {};
12
- config.channels.zalouser = {
13
- ...(config.channels.zalouser || {}),
14
- enabled: true,
15
- dmPolicy: 'pairing',
16
- autoReply: true
17
- };
18
-
19
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
20
- console.log(`Enabled channels.zalouser in ${configPath}`);
@@ -1,20 +0,0 @@
1
- const fs = require('fs');
2
-
3
- const configPath = process.argv[2];
4
-
5
- if (!configPath) {
6
- console.error('Usage: node live-enable-zalouser.js <configPath>');
7
- process.exit(1);
8
- }
9
-
10
- const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
11
- config.channels = config.channels || {};
12
- config.channels.zalouser = {
13
- ...(config.channels.zalouser || {}),
14
- enabled: true,
15
- dmPolicy: 'pairing',
16
- autoReply: true
17
- };
18
-
19
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
20
- console.log(`Enabled channels.zalouser in ${configPath}`);
@@ -1,40 +0,0 @@
1
- const fs = require('fs');
2
-
3
- const dbPath = process.argv[2];
4
-
5
- if (!dbPath) {
6
- console.error('Usage: node live-patch-9router.cjs <dbPath>');
7
- process.exit(1);
8
- }
9
-
10
- const models = [
11
- 'cx/gpt-5.4',
12
- 'cx/gpt-5.3-codex',
13
- 'cx/gpt-5.3-codex-high',
14
- 'cx/gpt-5.2-codex',
15
- 'cx/gpt-5.2',
16
- 'cx/gpt-5.1-codex-max',
17
- 'cx/gpt-5.1-codex',
18
- 'cx/gpt-5.1',
19
- 'cx/gpt-5-codex'
20
- ];
21
-
22
- const db = JSON.parse(fs.readFileSync(dbPath, 'utf8'));
23
- db.combos = db.combos || [];
24
-
25
- const combo = {
26
- id: 'smart-route',
27
- name: 'smart-route',
28
- alias: 'smart-route',
29
- models
30
- };
31
-
32
- const index = db.combos.findIndex((entry) => entry && entry.id === 'smart-route');
33
- if (index >= 0) {
34
- db.combos[index] = combo;
35
- } else {
36
- db.combos.push(combo);
37
- }
38
-
39
- fs.writeFileSync(dbPath, JSON.stringify(db, null, 2));
40
- console.log(`Patched smart-route in ${dbPath}`);
@@ -1,40 +0,0 @@
1
- const fs = require('fs');
2
-
3
- const dbPath = process.argv[2];
4
-
5
- if (!dbPath) {
6
- console.error('Usage: node live-patch-9router.js <dbPath>');
7
- process.exit(1);
8
- }
9
-
10
- const models = [
11
- 'cx/gpt-5.4',
12
- 'cx/gpt-5.3-codex',
13
- 'cx/gpt-5.3-codex-high',
14
- 'cx/gpt-5.2-codex',
15
- 'cx/gpt-5.2',
16
- 'cx/gpt-5.1-codex-max',
17
- 'cx/gpt-5.1-codex',
18
- 'cx/gpt-5.1',
19
- 'cx/gpt-5-codex'
20
- ];
21
-
22
- const db = JSON.parse(fs.readFileSync(dbPath, 'utf8'));
23
- db.combos = db.combos || [];
24
-
25
- const combo = {
26
- id: 'smart-route',
27
- name: 'smart-route',
28
- alias: 'smart-route',
29
- models
30
- };
31
-
32
- const index = db.combos.findIndex((entry) => entry && entry.id === 'smart-route');
33
- if (index >= 0) {
34
- db.combos[index] = combo;
35
- } else {
36
- db.combos.push(combo);
37
- }
38
-
39
- fs.writeFileSync(dbPath, JSON.stringify(db, null, 2));
40
- console.log(`Patched smart-route in ${dbPath}`);