aliyun-codex-bridge 0.1.0

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.
@@ -0,0 +1,96 @@
1
+ # Diff Record vs DioNanos/zai-codex-bridge
2
+
3
+ Generated on: 2026-03-04
4
+ Baseline: `https://github.com/DioNanos/zai-codex-bridge` `main` @ `e1a5392`
5
+
6
+ ## Summary
7
+
8
+ - Modified files: 8
9
+ - Added local files (not in baseline): 2
10
+ - `git diff --stat dionanos/main`: 139 insertions, 303 deletions
11
+
12
+ ## Modified Files
13
+
14
+ ### `src/server.js`
15
+
16
+ - Rebranded header/log text from `zai-codex-bridge` to `aliyun-codex-bridge`.
17
+ - Replaced single upstream env var with prioritized base URL chain:
18
+ `AI_BASE` -> `AI_BASE_URL` -> `ZAI_BASE_URL`.
19
+ - Changed role toggle default:
20
+ `ALLOW_SYSTEM` now defaults to enabled (`!== '0'`).
21
+ - Added `FORCE_ENV_AUTH` (default enabled) to avoid forwarding caller auth unless explicitly allowed.
22
+ - Added `extractToolCallsFromChoice()`:
23
+ supports `delta.tool_calls`, `choice.message.tool_calls`, `choice.tool_calls`.
24
+ - Added `normalizeToolName()` and broadened tool normalization:
25
+ accepts non-function shapes, normalizes names, bridges `input_schema`.
26
+ - Changed `developer` role mapping:
27
+ now maps to `system` when `ALLOW_SYSTEM` is enabled.
28
+ - Added `status` to function-call output items:
29
+ `in_progress` for `response.output_item.added`,
30
+ `completed` for `response.output_item.done` and non-streaming output.
31
+ - Auth env var family switched from `ZAI_API_KEY*` to `AI_API_KEY*` (+ fallback `OPENAI_API_KEY`).
32
+ - If no env auth and forwarding disabled, now fails fast with explicit missing-key error.
33
+ - Startup logging now prints `AI_BASE_URL`.
34
+ - File mode changed from `100755` to `100644`.
35
+
36
+ ### `package.json`
37
+
38
+ - Package name changed:
39
+ `@mmmbuto/zai-codex-bridge` -> `aliyun-codex-bridge`.
40
+ - Added second bin entry:
41
+ `aliyun-codex-bridge` -> `bin/aliyun-codex-bridge`.
42
+ - Repository URL changed to:
43
+ `https://github.com/sea-monsters/aliyun-codex-bridge.git`.
44
+
45
+ ### `bin/zai-codex-bridge`
46
+
47
+ - Replaced full CLI implementation with thin wrapper:
48
+ now only `require('./aliyun-codex-bridge')`.
49
+ - Previous in-file argument parser/help/update logic removed from this file and moved to shared/new CLI entry.
50
+
51
+ ### `README.md`
52
+
53
+ - Project/package/repo names rebranded to `aliyun-codex-bridge`.
54
+ - Install/command examples switched from `zai-codex-bridge` to `aliyun-codex-bridge`.
55
+ - CLI option docs changed from `--zai-base-url` to `--ai-base-url` (with alias support noted elsewhere).
56
+ - Environment examples changed:
57
+ `ZAI_BASE_URL` -> `AI_BASE`,
58
+ `ZAI_API_KEY*` -> `AI_API_KEY*`.
59
+ - `ALLOW_SYSTEM` guidance inverted to disable on incompat providers (`ALLOW_SYSTEM=0`).
60
+
61
+ ### `docs/guide.md`
62
+
63
+ - Rebranded all path/command references to `aliyun-codex-bridge`.
64
+ - Env var examples changed from `ZAI_API_KEY_*` to `AI_API_KEY_*`.
65
+ - Log file names and troubleshooting commands renamed accordingly.
66
+
67
+ ### `scripts/test-curl.js`
68
+
69
+ - Rebranded script banner and comments to `aliyun-codex-bridge`.
70
+ - Switched auth env var lookup and messaging:
71
+ `ZAI_API_KEY*` -> `AI_API_KEY*`.
72
+ - Authorization header now uses `AI_API_KEY` variable.
73
+
74
+ ### `RELEASING.md`
75
+
76
+ - Rebranded package name in release docs.
77
+ - API key export sample changed to `AI_API_KEY`.
78
+ - Version policy examples changed to align with `0.1.0`.
79
+
80
+ ### `CHANGELOG.md`
81
+
82
+ - Added unreleased fix notes for:
83
+ 1) stream tool-call extraction from multiple chunk shapes,
84
+ 2) `function_call` status fields for Responses API compatibility.
85
+
86
+ ## Added Local Files (Not in Baseline)
87
+
88
+ ### `bin/aliyun-codex-bridge`
89
+
90
+ - New primary CLI entry containing:
91
+ argument parsing, help text, config loading, optional auto-update, and server bootstrap.
92
+ - Supports `--ai-base-url` and compatibility alias `--zai-base-url`.
93
+
94
+ ### `package-lock.json`
95
+
96
+ - New npm lockfile (lockfileVersion 3) matching package metadata and bin entries.
package/docs/guide.md ADDED
@@ -0,0 +1,406 @@
1
+ # Coding Plan Dashscope Proxy - Complete Guide
2
+
3
+ **Purpose**: Practical guide for using Coding Plan Dashscope with Codex CLI through the `aliyun-codex-bridge` proxy.
4
+
5
+ ---
6
+
7
+ ## Quick Start
8
+
9
+ ### First Time Setup
10
+
11
+ ```bash
12
+ # 1. Install the proxy globally
13
+ cd ~/Dev/aliyun-codex-bridge
14
+ npm install -g .
15
+
16
+ # 2. Reload .zshrc for the new functions
17
+ source ~/.zshrc
18
+
19
+ # 3. Start Codex with GLM-4.7
20
+ codex-glm-a
21
+ ```
22
+
23
+ ### Daily Usage
24
+
25
+ ```bash
26
+ # Start with account A
27
+ codex-glm-a
28
+
29
+ # Start with account P
30
+ codex-glm-p
31
+
32
+ # Exit Codex
33
+ Ctrl+D
34
+ # Proxy is automatically terminated
35
+ ```
36
+
37
+ ---
38
+
39
+ ## Prerequisites
40
+
41
+ ### 1. Environment Variables
42
+
43
+ Ensure you have API keys in your `.zshrc` or `.zshenv`:
44
+
45
+ ```bash
46
+ # Coding Plan Dashscope API Key
47
+ export AI_API_KEY="sk-your-key"
48
+ ```
49
+
50
+ ### 2. Proxy Installed
51
+
52
+ ```bash
53
+ # Global installation (recommended)
54
+ cd ~/Dev/aliyun-codex-bridge
55
+ npm install -g .
56
+
57
+ # Verify installation
58
+ which aliyun-codex-bridge
59
+ ```
60
+
61
+ ### 3. Codex Configuration
62
+
63
+ The file `~/.codex/config.toml` must contain:
64
+
65
+ ```toml
66
+ [model_providers.ai_proxy]
67
+ name = "Coding Plan Dashscope via local proxy"
68
+ base_url = "http://127.0.0.1:31415/v1"
69
+ env_key = "AI_API_KEY"
70
+ wire_api = "responses"
71
+ stream_idle_timeout_ms = 3000000
72
+ ```
73
+
74
+ ---
75
+
76
+ ## How It Works
77
+
78
+ ### Architecture
79
+
80
+ ```
81
+ .zshrc → _codex_glm_with_proxy() → Codex → Proxy (port 31415) → Coding Plan Dashscope API
82
+
83
+ Translates:
84
+ Responses → Chat
85
+ Chat → Responses
86
+ ```
87
+
88
+ ### Execution Flow
89
+
90
+ 1. User runs `codex-glm-a`
91
+ 2. Function checks if proxy is active on port 31415
92
+ 3. If NO:
93
+ - Starts proxy in background
94
+ - Saves PID
95
+ - Sets trap for cleanup
96
+ - Waits up to 2 seconds for proxy to be ready
97
+ 4. Codex starts with provider `ai_proxy`
98
+ 5. Request: Codex → Proxy → Translated to Chat → Coding Plan Dashscope
99
+ 6. Response: Coding Plan Dashscope → Chat → Proxy → Translated to Responses → Codex
100
+ 7. User exits Codex (Ctrl+D)
101
+ 8. Trap kills the proxy (only if this function started it)
102
+
103
+ ---
104
+
105
+ ## Usage Examples
106
+
107
+ ### Example 1: Simple Conversation
108
+
109
+ ```bash
110
+ # Start
111
+ codex-glm-a
112
+
113
+ # In Codex prompt:
114
+ > What is 23 * 47?
115
+
116
+ # GLM-4.7 responds:
117
+ > The result of 23 * 47 is 1081.
118
+
119
+ # Exit
120
+ Ctrl+D
121
+ # Proxy automatically terminated
122
+ ```
123
+
124
+ ### Example 2: Code Analysis
125
+
126
+ ```bash
127
+ # Start with additional arguments
128
+ codex-glm-a -s workspace-write
129
+
130
+ # In Codex prompt:
131
+ > Read main.py and tell me what it does
132
+
133
+ # Codex will read the file and GLM-4.7 will analyze the code
134
+ ```
135
+
136
+ ### Example 3: Multi-Session
137
+
138
+ ```bash
139
+ # Terminal 1
140
+ codex-glm-a
141
+ # Proxy starts (PID 12345)
142
+
143
+ # Terminal 2 (while terminal 1 is still open)
144
+ codex-glm-a
145
+ # Proxy ALREADY ACTIVE, gets reused
146
+ # No new process spawned
147
+
148
+ # Terminal 1: Ctrl+D
149
+ # Codex exits but proxy STAYS active (for terminal 2)
150
+
151
+ # Terminal 2: Ctrl+D
152
+ # Codex exits but proxy STAYS active (didn't start it)
153
+ ```
154
+
155
+ ### Example 4: Debug Proxy
156
+
157
+ ```bash
158
+ # Start proxy manually with debug
159
+ aliyun-codex-bridge --log-level debug --port 31415
160
+
161
+ # In another terminal, test
162
+ curl http://127.0.0.1:31415/health
163
+ # {"ok":true}
164
+
165
+ # Now start codex manually
166
+ AI_API_KEY="$AI_API_KEY" \
167
+ codex -m "GLM-4.7" -c model_provider="ai_proxy"
168
+ ```
169
+
170
+ ---
171
+
172
+ ## Troubleshooting
173
+
174
+ ### Proxy Won't Start
175
+
176
+ **Symptom**: `codex-glm-a` hangs or errors
177
+
178
+ **Solution**:
179
+ ```bash
180
+ # Verify installation
181
+ which aliyun-codex-bridge
182
+
183
+ # If not found, reinstall
184
+ cd ~/Dev/aliyun-codex-bridge
185
+ npm install -g .
186
+ ```
187
+
188
+ ### Port Already in Use
189
+
190
+ **Symptom**: `Error: listen EADDRINUSE: address already in use :::31415`
191
+
192
+ **Solution**:
193
+ ```bash
194
+ # Find process
195
+ lsof -i :31415
196
+ # or
197
+ netstat -tulpn | grep 31415
198
+
199
+ # If it's an old proxy, kill it
200
+ kill -9 <PID>
201
+
202
+ # Or use different port - just use:
203
+ codex-glm-a # will use existing proxy
204
+ ```
205
+
206
+ ### Coding Plan Dashscope Error 1214
207
+
208
+ **Symptom**: `{"error":{"code":"1214","message":"Incorrect role information"}}`
209
+
210
+ **Cause**: Using wrong provider
211
+
212
+ **Solution**:
213
+ ```bash
214
+ # VERIFY in ~/.codex/config.toml
215
+ # You must use: model_provider="ai_proxy"
216
+ # NOT: deprecated provider aliases
217
+ ```
218
+
219
+ ### Proxy Won't Stop
220
+
221
+ **Symptom**: Proxy remains active after closing Codex
222
+
223
+ **Solution**:
224
+ ```bash
225
+ # Find and kill manually
226
+ ps aux | grep aliyun-codex-bridge
227
+ kill <PID>
228
+
229
+ # Or use dedicated command
230
+ pkill -f aliyun-codex-bridge
231
+ ```
232
+
233
+ ### Debug Logging
234
+
235
+ ```bash
236
+ # Proxy logs are in:
237
+ cat /tmp/aliyun-codex-bridge.log
238
+
239
+ # For real-time logs:
240
+ tail -f /tmp/aliyun-codex-bridge.log
241
+
242
+ # Restart with debug:
243
+ codex-glm-a # proxy will write detailed logs
244
+ ```
245
+
246
+ ---
247
+
248
+ ## Health Checks
249
+
250
+ ### Health Check
251
+
252
+ ```bash
253
+ # Verify proxy is active
254
+ curl http://127.0.0.1:31415/health
255
+ # Expected: {"ok":true}
256
+ ```
257
+
258
+ ### Verify Configuration
259
+
260
+ ```bash
261
+ # Check provider in config
262
+ grep -A 5 "ai_proxy" ~/.codex/config.toml
263
+
264
+ # Check functions in .zshrc
265
+ grep -A 30 "_codex_glm_with_proxy" ~/.zshrc
266
+ ```
267
+
268
+ ### Full Test
269
+
270
+ ```bash
271
+ # 1. Test proxy
272
+ aliyun-codex-bridge --help
273
+
274
+ # 2. Test health
275
+ curl http://127.0.0.1:31415/health
276
+
277
+ # 3. Test Codex
278
+ codex-glm-a --help
279
+
280
+ # 4. Interactive test
281
+ codex-glm-a
282
+ # > Tell me 2+2
283
+ # Ctrl+D
284
+ ```
285
+
286
+ ---
287
+
288
+ ## Function Reference
289
+
290
+ ### `_codex_glm_with_proxy()`
291
+
292
+ **Parameters**:
293
+ - `$1` - API key to use (`$AI_API_KEY`)
294
+ - `$@` - Additional arguments passed to Codex
295
+
296
+ **Behavior**:
297
+ 1. Checks health at `http://127.0.0.1:31415/health`
298
+ 2. If fails:
299
+ - Starts `aliyun-codex-bridge` in background
300
+ - Redirects log to `/tmp/aliyun-codex-bridge.log`
301
+ - Saves PID in `$PROXY_PID`
302
+ - Sets trap to kill proxy on EXIT
303
+ - Waits up to 2 seconds for proxy to be ready
304
+ 3. Executes `codex` with provider `ai_proxy`
305
+
306
+ ### `codex-glm-a()`
307
+
308
+ **Usage**: Account A
309
+ ```bash
310
+ codex-glm-a [codex options]
311
+ ```
312
+
313
+ **Example**:
314
+ ```bash
315
+ codex-glm-a -s workspace-write
316
+ codex-glm-a --help
317
+ ```
318
+
319
+ ### `codex-glm-p()`
320
+
321
+ **Usage**: Account P
322
+ ```bash
323
+ codex-glm-p [codex options]
324
+ ```
325
+
326
+ ---
327
+
328
+ ## Advanced Configuration
329
+
330
+ ### Change Port
331
+
332
+ Modify the function in `~/.zshrc`:
333
+
334
+ ```bash
335
+ _codex_glm_with_proxy () {
336
+ local KEY="$1"; shift
337
+ local HOST="127.0.0.1"
338
+ local PORT="8080" # ← Change here
339
+ # ...
340
+ }
341
+ ```
342
+
343
+ And update `~/.codex/config.toml`:
344
+
345
+ ```toml
346
+ [model_providers.ai_proxy]
347
+ base_url = "http://127.0.0.1:8080/v1"
348
+ ```
349
+
350
+ ### Verbose Logging
351
+
352
+ Modify the log level in the proxy command:
353
+
354
+ ```bash
355
+ aliyun-codex-bridge --host "$HOST" --port "$PORT" --log-level debug >"$LOGFILE" 2>&1 &
356
+ ```
357
+
358
+ ---
359
+
360
+ ## Performance
361
+
362
+ ### Startup Times
363
+
364
+ | Operation | Time |
365
+ |-----------|------|
366
+ | Health check (proxy running) | ~50ms |
367
+ | Health check (proxy not running) | ~2s |
368
+ | Proxy startup | ~500ms |
369
+ | Codex startup | ~1s |
370
+ | **Total (first time)** | **~3.5s** |
371
+ | **Total (proxy already up)** | **~1.5s** |
372
+
373
+ ### Memory
374
+
375
+ | Process | RAM |
376
+ |----------|-----|
377
+ | aliyun-codex-bridge | ~30-50MB |
378
+ | codex CLI | ~100-200MB |
379
+ | **Total** | **~130-250MB** |
380
+
381
+ ---
382
+
383
+ ## Setup Checklist
384
+
385
+ - [ ] Proxy installed: `npm install -g aliyun-codex-bridge`
386
+ - [ ] API key set: `export AI_API_KEY=...`
387
+ - [ ] Provider configured: `[model_providers.ai_proxy]` in config.toml
388
+ - [ ] Functions updated: `source ~/.zshrc`
389
+ - [ ] Test health: `curl http://127.0.0.1:31415/health`
390
+ - [ ] Full test: `codex-glm-a`
391
+
392
+ ---
393
+
394
+ ## Related Files
395
+
396
+ - **Proxy Code**: `~/Dev/aliyun-codex-bridge/`
397
+ - **Codex Config**: `~/.codex/config.toml`
398
+ - **ZSH Functions**: `~/.zshrc`
399
+
400
+ ---
401
+
402
+ ## License
403
+
404
+ MIT
405
+
406
+
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "aliyun-codex-bridge",
3
+ "version": "0.1.0",
4
+ "description": "Local proxy that translates OpenAI Responses API format to Coding Plan Dashscope Chat Completions format for Codex",
5
+ "main": "src/server.js",
6
+ "bin": {
7
+ "aliyun-codex-bridge": "bin/aliyun-codex-bridge",
8
+ "zai-codex-bridge": "bin/zai-codex-bridge"
9
+ },
10
+ "scripts": {
11
+ "start": "node src/server.js",
12
+ "test": "node scripts/test-curl.js",
13
+ "test:curl": "node scripts/test-curl.js",
14
+ "release:patch": "node scripts/release-patch.js"
15
+ },
16
+ "keywords": [
17
+ "codex",
18
+ "zai",
19
+ "glm",
20
+ "proxy",
21
+ "openai",
22
+ "responses-api",
23
+ "chat-completions"
24
+ ],
25
+ "author": "Davide A. Guglielmi",
26
+ "license": "MIT",
27
+ "engines": {
28
+ "node": ">=18.0.0"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/sea-monsters/aliyun-codex-bridge.git"
33
+ }
34
+ }
@@ -0,0 +1,32 @@
1
+ Param(
2
+ [switch]$WhatIfOnly
3
+ )
4
+
5
+ Set-StrictMode -Version Latest
6
+ $ErrorActionPreference = "Stop"
7
+
8
+ $root = Split-Path -Parent $PSScriptRoot
9
+
10
+ $patterns = @(
11
+ "response.log",
12
+ "logs\*.log",
13
+ "*.tmp",
14
+ "tmp\*"
15
+ )
16
+
17
+ Write-Host "[clean] root=$root"
18
+ foreach ($pattern in $patterns) {
19
+ $path = Join-Path $root $pattern
20
+ $items = Get-ChildItem -Path $path -Force -ErrorAction SilentlyContinue
21
+ foreach ($item in $items) {
22
+ if ($WhatIfOnly) {
23
+ Write-Host "[clean] would remove $($item.FullName)"
24
+ } else {
25
+ Remove-Item -Path $item.FullName -Force -Recurse -ErrorAction SilentlyContinue
26
+ Write-Host "[clean] removed $($item.FullName)"
27
+ }
28
+ }
29
+ }
30
+
31
+ Write-Host "[clean] done"
32
+
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Safe patch version bumper
5
+ * Only allows patch releases from 0.1.0 base line
6
+ * Refuses minor/major bumps
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+
12
+ const PACKAGE_PATH = path.join(__dirname, '..', 'package.json');
13
+
14
+ function bumpPatch(version) {
15
+ const parts = version.split('.').map(Number);
16
+
17
+ if (parts.length !== 3) {
18
+ throw new Error(`Invalid version format: ${version}`);
19
+ }
20
+
21
+ const [major, minor, patch] = parts;
22
+
23
+ // Only allow 0.1.x versions
24
+ if (major !== 0 || minor !== 1) {
25
+ console.error(`ERROR: Current version is ${version}`);
26
+ console.error('This script only supports patch releases for 0.1.x versions.');
27
+ console.error('For other version changes, edit package.json manually.');
28
+ process.exit(1);
29
+ }
30
+
31
+ const newVersion = `0.1.${patch + 1}`;
32
+ return newVersion;
33
+ }
34
+
35
+ function main() {
36
+ // Read package.json
37
+ const pkg = JSON.parse(fs.readFileSync(PACKAGE_PATH, 'utf8'));
38
+ const currentVersion = pkg.version;
39
+
40
+ console.log(`Current version: ${currentVersion}`);
41
+
42
+ // Bump patch
43
+ const newVersion = bumpPatch(currentVersion);
44
+ console.log(`Bumping to: ${newVersion}`);
45
+
46
+ // Update package.json
47
+ pkg.version = newVersion;
48
+
49
+ // Write back
50
+ fs.writeFileSync(PACKAGE_PATH, JSON.stringify(pkg, null, 2) + '\n');
51
+
52
+ console.log('Updated package.json');
53
+ console.log('\nNext steps:');
54
+ console.log(' 1. Update CHANGELOG.md');
55
+ console.log(' 2. Commit: git add package.json CHANGELOG.md && git commit -m "chore: release v' + newVersion + '"');
56
+ console.log(' 3. Tag: git tag v' + newVersion);
57
+ console.log(' 4. Publish: npm publish');
58
+ }
59
+
60
+ main();
@@ -0,0 +1,68 @@
1
+ Option Explicit
2
+
3
+ ' Windows autostart launcher for aliyun-codex-bridge
4
+ ' Usage:
5
+ ' wscript scripts\start-aliyun-codex-bridge.vbs [host] [port] [ai_base] [log_level]
6
+ ' Example:
7
+ ' wscript scripts\start-aliyun-codex-bridge.vbs 127.0.0.1 31415 https://coding.dashscope.aliyuncs.com/v1 info
8
+
9
+ Const DEFAULT_HOST = "127.0.0.1"
10
+ Const DEFAULT_PORT = "4000"
11
+ Const DEFAULT_LOG_LEVEL = "info"
12
+
13
+ Dim shell, fso, args
14
+ Dim host, port, aiBase, logLevel
15
+ Dim scriptPath, scriptsDir, repoDir, logsDir, logFile
16
+ Dim checkCmd, startCmd, rc, aiBasePart
17
+
18
+ Set shell = CreateObject("WScript.Shell")
19
+ Set fso = CreateObject("Scripting.FileSystemObject")
20
+ Set args = WScript.Arguments
21
+
22
+ host = DEFAULT_HOST
23
+ port = DEFAULT_PORT
24
+ aiBase = ""
25
+ logLevel = DEFAULT_LOG_LEVEL
26
+
27
+ If args.Count >= 1 Then host = args(0)
28
+ If args.Count >= 2 Then port = args(1)
29
+ If args.Count >= 3 Then aiBase = args(2)
30
+ If args.Count >= 4 Then logLevel = args(3)
31
+
32
+ scriptPath = WScript.ScriptFullName
33
+ scriptsDir = fso.GetParentFolderName(scriptPath)
34
+ repoDir = fso.GetParentFolderName(scriptsDir)
35
+
36
+ logsDir = repoDir & "\logs"
37
+ If Not fso.FolderExists(logsDir) Then
38
+ fso.CreateFolder logsDir
39
+ End If
40
+ logFile = logsDir & "\bridge.log"
41
+
42
+ ' If port already listening, skip startup.
43
+ checkCmd = "powershell -NoProfile -ExecutionPolicy Bypass -Command " & Q("$p=" & port & "; if (Get-NetTCPConnection -LocalPort $p -State Listen -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }")
44
+ rc = shell.Run(checkCmd, 0, True)
45
+ If rc = 0 Then
46
+ WScript.Quit 0
47
+ End If
48
+
49
+ aiBasePart = ""
50
+ If Len(aiBase) > 0 Then
51
+ aiBasePart = " && set " & Q("AI_API_BASE=" & aiBase)
52
+ End If
53
+
54
+ startCmd = "cmd.exe /c " & Q( _
55
+ "cd /d " & Q(repoDir) & _
56
+ " && set " & Q("HOST=" & host) & _
57
+ " && set " & Q("PORT=" & port) & _
58
+ aiBasePart & _
59
+ " && set " & Q("LOG_LEVEL=" & logLevel) & _
60
+ " && node src\server.js >> " & Q(logFile) & " 2>&1")
61
+
62
+ ' Hidden window, do not wait
63
+ shell.Run startCmd, 0, False
64
+ WScript.Quit 0
65
+
66
+ Function Q(ByVal s)
67
+ Q = Chr(34) & s & Chr(34)
68
+ End Function