create-openclaw-bot 5.4.1 → 5.5.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,359 @@
1
+ // @ts-nocheck
2
+ (function (root) {
3
+ function encodeBase64Utf8(value) {
4
+ if (typeof Buffer !== 'undefined') {
5
+ return Buffer.from(String(value), 'utf8').toString('base64');
6
+ }
7
+ return btoa(String.fromCharCode(...new TextEncoder().encode(String(value))));
8
+ }
9
+
10
+ function indentBlock(text, spaces) {
11
+ const prefix = ' '.repeat(spaces);
12
+ return String(text).split('\n').map((line) => `${prefix}${line}`).join('\n');
13
+ }
14
+
15
+ function build9RouterSmartRouteSyncScript(dbPath) {
16
+ return `const fs=require('fs');const INTERVAL=30000;const p='${dbPath}';
17
+ const PM={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'],'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'],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'],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'],'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'],'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'],'gemini-cli':['gc/gemini-3-flash-preview','gc/gemini-3-pro-preview'],'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'],'qwen':['qw/qwen3-coder-plus','qw/qwen3-coder-flash','qw/vision-model','qw/coder-model'],'kiro':['kr/claude-sonnet-4.5','kr/claude-haiku-4.5','kr/deepseek-3.2','kr/deepseek-3.1','kr/qwen3-coder-next'],'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'],'kimi-coding':['kmc/kimi-k2.5','kmc/kimi-k2.5-thinking','kmc/kimi-latest'],'glm':['glm/glm-5.1','glm/glm-5','glm/glm-4.7'],'glm-cn':['glm/glm-5.1','glm/glm-5','glm/glm-4.7'],'minimax':['minimax/MiniMax-M2.7','minimax/MiniMax-M2.5','minimax/MiniMax-M2.1'],'kimi':['kimi/kimi-k2.5','kimi/kimi-k2.5-thinking','kimi/kimi-latest'],'deepseek':['deepseek/deepseek-chat','deepseek/deepseek-reasoner'],'xai':['xai/grok-4','xai/grok-4-fast-reasoning','xai/grok-code-fast-1'],'mistral':['mistral/mistral-large-latest','mistral/codestral-latest'],'groq':['groq/llama-3.3-70b-versatile','groq/openai/gpt-oss-120b'],'cerebras':['cerebras/gpt-oss-120b'],'alicode':['alicode/qwen3.5-plus','alicode/qwen3-coder-plus'],'openai':['openai/gpt-4o','openai/gpt-4.1'],'anthropic':['anthropic/claude-sonnet-4','anthropic/claude-haiku-3.5'],'gemini':['gemini/gemini-2.5-flash','gemini/gemini-2.5-pro']};
18
+ console.log('[sync-combo] 9Router sync loop started...');
19
+ const sync = async () => {
20
+ try {
21
+ let db = {};
22
+ try { db = JSON.parse(fs.readFileSync(p, 'utf8')); } catch(e){}
23
+ if (!db.combos) db.combos = [];
24
+ const removeSmartRoute = () => {
25
+ const next = db.combos.filter(x => x.id !== 'smart-route');
26
+ if (next.length !== db.combos.length) {
27
+ db.combos = next;
28
+ fs.writeFileSync(p, JSON.stringify(db, null, 2));
29
+ console.log('[sync-combo] Removed smart-route (no active providers)');
30
+ }
31
+ };
32
+ const res = await fetch('http://localhost:20128/api/providers');
33
+ if (!res.ok) { console.log('[sync-combo] API not ready, retrying...'); return; }
34
+ const d = await res.json();
35
+ const a = (d.connections || []).filter(c => c && c.provider && c.isActive !== false && !c.disabled).map(c => c.provider);
36
+ if (!a.length) { removeSmartRoute(); return; }
37
+ const PREF = ['openai','anthropic','claude-code','codex','cursor','github','cline','kimi','minimax','deepseek','glm','alicode','xai','mistral','kilo','kiro','iflow','qwen','gemini-cli','ollama'];
38
+ a.sort((x, y) => (PREF.indexOf(x) === -1 ? 99 : PREF.indexOf(x)) - (PREF.indexOf(y) === -1 ? 99 : PREF.indexOf(y)));
39
+ const m = a.flatMap(pv => PM[pv] || []);
40
+ if (!m.length) { removeSmartRoute(); return; }
41
+ const c = { id: 'smart-route', name: 'smart-route', alias: 'smart-route', models: m };
42
+ const i = db.combos.findIndex(x => x.id === 'smart-route');
43
+ if (i >= 0) {
44
+ if (JSON.stringify(db.combos[i].models) !== JSON.stringify(c.models)) {
45
+ db.combos[i] = c;
46
+ fs.writeFileSync(p, JSON.stringify(db, null, 2));
47
+ console.log('[sync-combo] Updated smart-route: ' + c.models.length + ' models');
48
+ }
49
+ } else {
50
+ db.combos.push(c);
51
+ fs.writeFileSync(p, JSON.stringify(db, null, 2));
52
+ console.log('[sync-combo] Created smart-route: ' + c.models.length + ' models');
53
+ }
54
+ } catch (e) {}
55
+ };
56
+ setTimeout(sync, 5000);
57
+ setInterval(sync, INTERVAL);`;
58
+ }
59
+
60
+ function build9RouterComposeEntrypointScript(syncScriptBase64) {
61
+ return [
62
+ 'npm install -g 9router',
63
+ `node -e "require('fs').writeFileSync('/tmp/sync.js',Buffer.from('${syncScriptBase64}','base64').toString())"`,
64
+ 'node /tmp/sync.js > /tmp/sync.log 2>&1 &',
65
+ 'exec 9router -n -l -H 0.0.0.0 -p 20128 --skip-update'
66
+ ].join('\n');
67
+ }
68
+
69
+ function buildGatewayPatchCmd() {
70
+ return `node -e \\"const fs=require('fs'),os=require('os'),p='/root/.openclaw/openclaw.json';if(fs.existsSync(p)){const c=JSON.parse(fs.readFileSync(p,'utf8'));const a=new Set(['http://localhost:18791','http://127.0.0.1:18791','http://0.0.0.0:18791']);for(const entries of Object.values(os.networkInterfaces()||{})){for(const entry of entries||[]){if(!entry||entry.internal||entry.family!=='IPv4'||!entry.address)continue;a.add('http://' + entry.address + ':18791');}}c.tools=Object.assign({},c.tools,{profile:'full',exec:{host:'gateway',security:'full',ask:'off'}});c.gateway=Object.assign({},c.gateway,{port:18791,bind:'custom',customBindHost:'0.0.0.0',controlUi:Object.assign({},c.gateway?.controlUi,{allowedOrigins:Array.from(a).filter(Boolean)})});fs.writeFileSync(p,JSON.stringify(c,null,2));}\\"`;
71
+ }
72
+
73
+ function buildDockerArtifacts(options) {
74
+ const {
75
+ openClawNpmSpec,
76
+ openClawRuntimePackages,
77
+ is9Router,
78
+ isLocal,
79
+ isMultiBot,
80
+ hasBrowser,
81
+ selectedModel,
82
+ agentId,
83
+ allSkills = [],
84
+ dockerfileSkillInstallMode = 'none',
85
+ runtimeCommandParts = [],
86
+ volumeMount = '../../.openclaw:/root/.openclaw',
87
+ singleComposeName = 'oc-bot',
88
+ multiComposeName = 'oc-multibot',
89
+ singleAppContainerName = 'openclaw-bot',
90
+ multiAppContainerName = 'openclaw-multibot',
91
+ singleRouterContainerName = '9router',
92
+ multiRouterContainerName = '9router-multibot',
93
+ singleOllamaContainerName = 'ollama',
94
+ multiOllamaContainerName = 'ollama-multibot',
95
+ plainSingleExtraHosts = false,
96
+ multiOllamaNumParallel = 1,
97
+ singleOllamaNumParallel = 1,
98
+ emitBrowserInstall = true,
99
+ } = options;
100
+
101
+ const browserAptExtra = hasBrowser ? ' xvfb' : '';
102
+ const browserInstallLines = hasBrowser && emitBrowserInstall
103
+ ? [
104
+ '',
105
+ '# Browser Automation: Playwright engine (needed for native CDP)',
106
+ 'RUN npm install -g agent-browser playwright \\',
107
+ ' && npx playwright install chromium --with-deps \\',
108
+ ' && ln -f -s /root/.cache/ms-playwright/chromium-*/chrome-linux*/chrome /usr/bin/google-chrome',
109
+ '',
110
+ ''
111
+ ].join('\n')
112
+ : '';
113
+ const skillLines = dockerfileSkillInstallMode === 'build' && allSkills.length > 0
114
+ ? `\n# Install skills (ClawHub)\n${allSkills.map((skill) => `RUN openclaw skills install ${skill} || echo "Warning: Failed to install ${skill} due to rate limits."`).join('\n')}\n`
115
+ : '';
116
+ const patchLine = `RUN node -e "const fs=require('fs');const path=require('path');const dir='/usr/local/lib/node_modules/openclaw/dist';const from='\\t\\t\\t\\t\\tonAgentRunStart: (runId) => {';const to='\\t\\t\\t\\t\\ttimeoutOverrideSeconds: Math.max(1, Math.ceil(timeoutMs / 1e3)),\\n\\t\\t\\t\\t\\tonAgentRunStart: (runId) => {';const files=fs.readdirSync(dir).filter(n=>/\\.js$/.test(n));let patched=0;for(const file of files){const p=path.join(dir,file);let s='';try{s=fs.readFileSync(p,'utf8');}catch{continue;}if(s.includes(to)||!s.includes(from))continue;s=s.replace(from,to);fs.writeFileSync(p,s);patched++;}if(!patched){process.exit(0);}"`;
117
+
118
+ // Dynamic runtime configuration injection for container internal IPs
119
+ const setupInternalIpScript = `const fs=require('fs'),os=require('os'),p='/root/.openclaw/openclaw.json';if(fs.existsSync(p)){const c=JSON.parse(fs.readFileSync(p,'utf8'));const a=new Set(['http://localhost:18791','http://127.0.0.1:18791','http://0.0.0.0:18791']);for(const entries of Object.values(os.networkInterfaces()||{})){for(const entry of entries||[]){if(!entry||entry.internal||entry.family!=='IPv4'||!entry.address)continue;a.add('http://' + entry.address + ':18791');}}c.tools=Object.assign({},c.tools,{profile:'full',exec:{host:'gateway',security:'full',ask:'off'}});c.gateway=Object.assign({},c.gateway,{port:18791,bind:'custom',customBindHost:'0.0.0.0',controlUi:Object.assign({},c.gateway?.controlUi,{allowedOrigins:Array.from(a).filter(Boolean)})});fs.writeFileSync(p,JSON.stringify(c,null,2));}`;
120
+ const setupInternalIpB64 = encodeBase64Utf8(setupInternalIpScript);
121
+
122
+ const runtimeParts = runtimeCommandParts.filter(Boolean);
123
+ runtimeParts.unshift(`node -e "eval(Buffer.from('${setupInternalIpB64}','base64').toString())" &&`);
124
+ if (hasBrowser) {
125
+ runtimeParts.push('(Xvfb :99 -screen 0 1280x720x24 > /dev/null 2>&1 &) && export DISPLAY=:99 && openclaw gateway run');
126
+ } else {
127
+ runtimeParts.push('openclaw gateway run');
128
+ }
129
+ const dockerfile = `FROM node:22-slim
130
+
131
+ RUN apt-get update && apt-get install -y git curl${browserAptExtra} && rm -rf /var/lib/apt/lists/*
132
+ ${browserInstallLines}
133
+ ARG OPENCLAW_VER="${openClawNpmSpec}"
134
+ RUN npm install -g ${openClawNpmSpec} ${openClawRuntimePackages}${skillLines}
135
+ ${patchLine}
136
+ WORKDIR /root/.openclaw
137
+
138
+ EXPOSE 18791
139
+
140
+ CMD sh -c "${runtimeParts.join(' ')}"`;
141
+
142
+ const syncScript = build9RouterSmartRouteSyncScript('/root/.9router/db.json');
143
+ const syncScriptBase64 = encodeBase64Utf8(syncScript);
144
+ const docker9RouterEntrypointScript = build9RouterComposeEntrypointScript(syncScriptBase64);
145
+ const extraHostsBlock = ` extra_hosts:\n - "host.docker.internal:host-gateway"`;
146
+
147
+ let compose;
148
+ if (isMultiBot) {
149
+ const dependsOn = is9Router
150
+ ? ' depends_on:\n - 9router\n'
151
+ : isLocal
152
+ ? ' depends_on:\n ollama:\n condition: service_healthy\n'
153
+ : '';
154
+ const extraHosts = hasBrowser ? `${extraHostsBlock}\n` : '';
155
+ if (is9Router) {
156
+ compose = `name: ${multiComposeName}
157
+ services:
158
+ ai-bot:
159
+ build: .
160
+ container_name: ${multiAppContainerName}
161
+ restart: always
162
+ env_file:
163
+ - .env
164
+ ${dependsOn}${extraHosts} volumes:
165
+ - ${volumeMount}
166
+ ports:
167
+ - "18791:18791"
168
+
169
+ 9router:
170
+ image: node:22-slim
171
+ container_name: ${multiRouterContainerName}
172
+ restart: always
173
+ entrypoint:
174
+ - /bin/sh
175
+ - -c
176
+ - |
177
+ ${indentBlock(docker9RouterEntrypointScript, 8)}
178
+ environment:
179
+ - PORT=20128
180
+ - HOSTNAME=0.0.0.0
181
+ - CI=true
182
+ volumes:
183
+ - 9router-data:/root/.9router
184
+ ports:
185
+ - "20128:20128"
186
+
187
+ volumes:
188
+ 9router-data:`;
189
+ } else if (isLocal) {
190
+ const ollamaModelTag = String(selectedModel || 'ollama/gemma4:e2b').replace('ollama/', '');
191
+ compose = `name: ${multiComposeName}
192
+ services:
193
+ ai-bot:
194
+ build: .
195
+ container_name: ${multiAppContainerName}
196
+ restart: always
197
+ env_file:
198
+ - .env
199
+ ${dependsOn}${extraHosts} volumes:
200
+ - ${volumeMount}
201
+ ports:
202
+ - "18791:18791"
203
+
204
+ ollama:
205
+ image: ollama/ollama:latest
206
+ container_name: ${multiOllamaContainerName}
207
+ restart: always
208
+ environment:
209
+ - OLLAMA_KEEP_ALIVE=24h
210
+ - OLLAMA_NUM_PARALLEL=${multiOllamaNumParallel}
211
+ volumes:
212
+ - ollama-data:/root/.ollama
213
+ entrypoint:
214
+ - /bin/sh
215
+ - -c
216
+ - |
217
+ ollama serve &
218
+ until ollama list > /dev/null 2>&1; do sleep 1; done
219
+ ollama pull ${ollamaModelTag}
220
+ wait
221
+ healthcheck:
222
+ test: ["CMD-SHELL", "ollama list > /dev/null 2>&1"]
223
+ interval: 10s
224
+ timeout: 5s
225
+ retries: 10
226
+ start_period: 30s
227
+
228
+ volumes:
229
+ ollama-data:`;
230
+ } else {
231
+ compose = `name: ${multiComposeName}
232
+ services:
233
+ ai-bot:
234
+ build: .
235
+ container_name: ${multiAppContainerName}
236
+ restart: always
237
+ env_file:
238
+ - .env
239
+ ${extraHosts} volumes:
240
+ - ${volumeMount}
241
+ ports:
242
+ - "18791:18791"`;
243
+ }
244
+ } else if (is9Router) {
245
+ compose = `name: ${singleComposeName}
246
+ services:
247
+ ai-bot:
248
+ build: .
249
+ container_name: ${singleAppContainerName}
250
+ restart: always
251
+ env_file:
252
+ - .env
253
+ depends_on:
254
+ - 9router
255
+ ${hasBrowser ? `${extraHostsBlock}\n` : ''} volumes:
256
+ - ${volumeMount}
257
+ ports:
258
+ - "18791:18791"
259
+
260
+ 9router:
261
+ image: node:22-slim
262
+ container_name: ${singleRouterContainerName}
263
+ restart: always
264
+ entrypoint:
265
+ - /bin/sh
266
+ - -c
267
+ - |
268
+ ${indentBlock(docker9RouterEntrypointScript, 8)}
269
+ environment:
270
+ - PORT=20128
271
+ - HOSTNAME=0.0.0.0
272
+ - CI=true
273
+ volumes:
274
+ - 9router-data:/root/.9router
275
+ ports:
276
+ - "20128:20128"
277
+
278
+ volumes:
279
+ 9router-data:`;
280
+ } else if (isLocal) {
281
+ const ollamaModelTag = String(selectedModel || 'ollama/gemma4:e2b').replace('ollama/', '');
282
+ compose = `name: ${singleComposeName}
283
+ services:
284
+ ai-bot:
285
+ build: .
286
+ container_name: ${singleAppContainerName}
287
+ restart: always
288
+ env_file: .env
289
+ depends_on:
290
+ ollama:
291
+ condition: service_healthy
292
+ ${hasBrowser ? `${extraHostsBlock}\n` : ''} ports:
293
+ - "18791:18791"
294
+ volumes:
295
+ - ${volumeMount}
296
+
297
+ ollama:
298
+ image: ollama/ollama:latest
299
+ container_name: ${singleOllamaContainerName}
300
+ restart: always
301
+ environment:
302
+ - OLLAMA_KEEP_ALIVE=24h
303
+ - OLLAMA_NUM_PARALLEL=${singleOllamaNumParallel}
304
+ volumes:
305
+ - ollama-data:/root/.ollama
306
+ entrypoint:
307
+ - /bin/sh
308
+ - -c
309
+ - |
310
+ ollama serve &
311
+ until ollama list > /dev/null 2>&1; do sleep 1; done
312
+ ollama pull ${ollamaModelTag}
313
+ wait
314
+ healthcheck:
315
+ test: ["CMD-SHELL", "ollama list > /dev/null 2>&1"]
316
+ interval: 10s
317
+ timeout: 5s
318
+ retries: 10
319
+ start_period: 30s
320
+
321
+ volumes:
322
+ ollama-data:`;
323
+ } else {
324
+ compose = `name: ${singleComposeName}
325
+ services:
326
+ ai-bot:
327
+ build: .
328
+ container_name: ${singleAppContainerName}
329
+ restart: always
330
+ env_file:
331
+ - .env
332
+ ${plainSingleExtraHosts ? `${extraHostsBlock}\n` : ''} volumes:
333
+ - ${volumeMount}
334
+ ports:
335
+ - "18791:18791"`;
336
+ }
337
+
338
+ return {
339
+ dockerfile,
340
+ compose,
341
+ syncScript,
342
+ docker9RouterEntrypointScript,
343
+ gatewayPatchCmd: buildGatewayPatchCmd(),
344
+ };
345
+ }
346
+
347
+ root.__openclawDockerGen = {
348
+ encodeBase64Utf8,
349
+ indentBlock,
350
+ build9RouterSmartRouteSyncScript,
351
+ build9RouterComposeEntrypointScript,
352
+ buildGatewayPatchCmd,
353
+ buildDockerArtifacts,
354
+ };
355
+
356
+ })(typeof globalThis !== 'undefined' ? globalThis : {});
357
+ if (typeof exports !== 'undefined' && typeof globalThis !== 'undefined' && globalThis.__openclawDockerGen) {
358
+ Object.assign(exports, globalThis.__openclawDockerGen);
359
+ }