@qingchencloud/openclaw-zh 2026.1.29-nightly.202601301956 → 2026.1.29-nightly.202601302059
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/CHANGELOG.md +10 -9
- package/README.md +86 -20
- package/dist/agents/system-prompt.js +1 -1
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/cli/cli-utils.js +10 -0
- package/dist/cli/models-cli.js +20 -8
- package/dist/cli/skills-cli.js +7 -7
- package/dist/commands/models/auth-order.js +2 -2
- package/dist/commands/models/list.status-command.js +37 -17
- package/dist/commands/models/shared.js +14 -0
- package/dist/control-ui/assets/{index-CNKLKKXX.js → index-Bpe27rQF.js} +2 -2
- package/dist/control-ui/assets/{index-CNKLKKXX.js.map → index-Bpe27rQF.js.map} +1 -1
- package/dist/control-ui/index.html +1 -1
- package/docs/cli/index.md +1 -1
- package/docs/cli/models.md +4 -0
- package/docs/cli/skills.md +1 -2
- package/docs/concepts/agent.md +2 -2
- package/docs/concepts/system-prompt.md +1 -1
- package/docs/docs.json +10 -2
- package/docs/help/faq.md +16 -16
- package/docs/install/installer.md +2 -2
- package/docs/providers/github-copilot.md +1 -1
- package/docs/start/hubs.md +1 -1
- package/docs/start/lore.md +1 -1
- package/docs/start/showcase.md +14 -14
- package/docs/start/wizard.md +8 -8
- package/docs/tools/{clawdhub.md → clawhub.md} +39 -39
- package/docs/tools/creating-skills.md +1 -1
- package/docs/tools/skills.md +9 -9
- package/package.json +1 -1
- package/skills/1password/SKILL.md +1 -1
- package/skills/bluebubbles/SKILL.md +1 -1
- package/skills/canvas/SKILL.md +3 -3
- package/skills/clawhub/SKILL.md +53 -0
- package/skills/nano-banana-pro/SKILL.md +1 -1
- package/skills/openai-whisper-api/SKILL.md +1 -1
- package/skills/session-logs/SKILL.md +6 -6
- package/skills/sherpa-onnx-tts/SKILL.md +6 -6
- package/skills/tmux/SKILL.md +4 -4
- package/skills/tmux/scripts/find-sessions.sh +2 -2
- package/skills/clawdhub/SKILL.md +0 -53
package/CHANGELOG.md
CHANGED
|
@@ -41,11 +41,12 @@ Status: stable.
|
|
|
41
41
|
- Routing: add per-account DM session scope and document multi-account isolation. (#3095) Thanks @jarvis-sam.
|
|
42
42
|
- Routing: precompile session key regexes. (#1697) Thanks @Ray0907.
|
|
43
43
|
- CLI: use Node's module compile cache for faster startup. (#2808) Thanks @pi0.
|
|
44
|
+
- CLI: add per-agent model status and auth order scoping. (#4780) Thanks @jlowin.
|
|
44
45
|
- Auth: show copyable Google auth URL after ASCII prompt. (#1787) Thanks @robbyczgw-cla.
|
|
45
46
|
- Agents: add Kimi K2.5 to the synthetic model catalog. (#4407) Thanks @manikv12.
|
|
46
47
|
- TUI: avoid width overflow when rendering selection lists. (#1686) Thanks @mossein.
|
|
47
48
|
- macOS: finish OpenClaw app rename for macOS sources, bundle identifiers, and shared kit paths. (#2844) Thanks @fal3.
|
|
48
|
-
- Branding: update launchd labels, mobile bundle IDs, and logging subsystems to bot.molt (legacy
|
|
49
|
+
- Branding: update launchd labels, mobile bundle IDs, and logging subsystems to bot.molt (legacy bundle ID migrations). Thanks @thewilloftheshadow.
|
|
49
50
|
- macOS: limit project-local `node_modules/.bin` PATH preference to debug builds (reduce PATH hijacking risk).
|
|
50
51
|
- macOS: keep custom SSH usernames in remote target. (#2046) Thanks @algal.
|
|
51
52
|
- macOS: avoid crash when rendering code blocks by bumping Textual to 0.3.1. (#2033) Thanks @garricn.
|
|
@@ -417,7 +418,7 @@ Status: stable.
|
|
|
417
418
|
- Security: warn when <=300B models run without sandboxing while web tools are enabled. https://docs.openclaw.ai/cli/security
|
|
418
419
|
- Exec: add host/security/ask routing for gateway + node exec. https://docs.openclaw.ai/tools/exec
|
|
419
420
|
- Exec: add `/exec` directive for per-session exec defaults (host/security/ask/node). https://docs.openclaw.ai/tools/exec
|
|
420
|
-
- Exec approvals: migrate approvals to `~/.
|
|
421
|
+
- Exec approvals: migrate approvals to `~/.openclaw/exec-approvals.json` with per-agent allowlists + skill auto-allow toggle, and add approvals UI + node exec lifecycle events. https://docs.openclaw.ai/tools/exec-approvals
|
|
421
422
|
- Nodes: add headless node host (`openclaw node start`) for `system.run`/`system.which`. https://docs.openclaw.ai/cli/node
|
|
422
423
|
- Nodes: add node daemon service install/status/start/stop/restart. https://docs.openclaw.ai/cli/node
|
|
423
424
|
- Bridge: add `skills.bins` RPC to support node host auto-allow skill bins.
|
|
@@ -441,7 +442,7 @@ Status: stable.
|
|
|
441
442
|
- Android: remove legacy bridge transport code now that nodes use the gateway protocol.
|
|
442
443
|
- Android: bump okhttp + dnsjava to satisfy lint dependency checks.
|
|
443
444
|
- Build: update workspace + core/plugin deps.
|
|
444
|
-
- Build: use tsgo for dev/watch builds by default (opt out with `
|
|
445
|
+
- Build: use tsgo for dev/watch builds by default (opt out with `OPENCLAW_TS_COMPILER=tsc`).
|
|
445
446
|
- Repo: remove the Peekaboo git submodule now that the SPM release is used.
|
|
446
447
|
- macOS: switch PeekabooBridge integration to the tagged Swift Package Manager release.
|
|
447
448
|
- macOS: stop syncing Peekaboo in postinstall.
|
|
@@ -569,7 +570,7 @@ Thanks @AlexMikhalev, @CoreyH, @John-Rood, @KrauseFx, @MaudeBot, @Nachx639, @Nic
|
|
|
569
570
|
- **BREAKING:** Drop legacy `chatType: "room"` support; use `chatType: "channel"`.
|
|
570
571
|
- **BREAKING:** remove legacy provider-specific target resolution fallbacks; target resolution is centralized with plugin hints + directory lookups.
|
|
571
572
|
- **BREAKING:** `openclaw hooks` is now `openclaw webhooks`; hooks live under `openclaw hooks`. https://docs.openclaw.ai/cli/webhooks
|
|
572
|
-
- **BREAKING:** `openclaw plugins install <path>` now copies into `~/.
|
|
573
|
+
- **BREAKING:** `openclaw plugins install <path>` now copies into `~/.openclaw/extensions` (use `--link` to keep path-based loading).
|
|
573
574
|
|
|
574
575
|
### Changes
|
|
575
576
|
- Plugins: ship bundled plugins disabled by default and allow overrides by installed versions. (#1066) — thanks @ItzR3NO.
|
|
@@ -804,7 +805,7 @@ Thanks @AlexMikhalev, @CoreyH, @John-Rood, @KrauseFx, @MaudeBot, @Nachx639, @Nic
|
|
|
804
805
|
- TUI: render picker overlays via the overlay stack so /models and /settings display. (#921) — thanks @grizzdank.
|
|
805
806
|
- TUI: add a bright spinner + elapsed time in the status line for send/stream/run states.
|
|
806
807
|
- TUI: show LLM error messages (rate limits, auth, etc.) instead of `(no output)`.
|
|
807
|
-
- Gateway/Dev: ensure `pnpm gateway:dev` always uses the dev profile config + state (`~/.
|
|
808
|
+
- Gateway/Dev: ensure `pnpm gateway:dev` always uses the dev profile config + state (`~/.openclaw-dev`).
|
|
808
809
|
|
|
809
810
|
#### Agents / Auth / Tools / Sandbox
|
|
810
811
|
- Agents: make user time zone and 24-hour time explicit in the system prompt. (#859) — thanks @CashWilliams.
|
|
@@ -865,7 +866,7 @@ Thanks @AlexMikhalev, @CoreyH, @John-Rood, @KrauseFx, @MaudeBot, @Nachx639, @Nic
|
|
|
865
866
|
|
|
866
867
|
### New & Improved
|
|
867
868
|
- Memory: add custom OpenAI-compatible embedding endpoints; support OpenAI/local `node-llama-cpp` embeddings with per-agent overrides and provider metadata in tools/CLI. (#819) — thanks @mukhtharcm.
|
|
868
|
-
- Memory: new `openclaw memory` CLI plus `memory_search`/`memory_get` tools with snippets + line ranges; index stored under `~/.
|
|
869
|
+
- Memory: new `openclaw memory` CLI plus `memory_search`/`memory_get` tools with snippets + line ranges; index stored under `~/.openclaw/memory/{agentId}.sqlite` with watch-on-by-default.
|
|
869
870
|
- Agents: strengthen memory recall guidance; make workspace bootstrap truncation configurable (default 20k) with warnings; add default sub-agent model config.
|
|
870
871
|
- Tools/Sandbox: add tool profiles + group shorthands; support tool-policy groups in `tools.sandbox.tools`; drop legacy `memory` shorthand; allow Docker bind mounts via `docker.binds`. (#790) — thanks @akonyer.
|
|
871
872
|
- Tools: add provider/model-specific tool policy overrides (`tools.byProvider`) to trim tool exposure per provider.
|
|
@@ -1113,7 +1114,7 @@ Thanks @AlexMikhalev, @CoreyH, @John-Rood, @KrauseFx, @MaudeBot, @Nachx639, @Nic
|
|
|
1113
1114
|
- CLI UX: logs output modes (pretty/plain/JSONL) + colorized health/daemon output; global `--no-color`; lobster palette in onboarding/config.
|
|
1114
1115
|
- Dev ergonomics: gateway `--dev/--reset` + dev profile auto-config; C-3PO dev templates; dev gateway/TUI helper scripts.
|
|
1115
1116
|
- Sandbox/Workspace: sandbox list/recreate commands; sync skills into sandbox workspace; sandbox browser auto-start.
|
|
1116
|
-
- Config/Onboarding: inline env vars; OpenAI API key flow to shared `~/.
|
|
1117
|
+
- Config/Onboarding: inline env vars; OpenAI API key flow to shared `~/.openclaw/.env`; Opus 4.5 default prompt for Anthropic auth; QuickStart auto-install gateway (Node-only) + provider picker tweaks + skip-systemd flags; TUI bootstrap prompt (`tui --message`); remove Bun runtime choice.
|
|
1117
1118
|
- Providers: Microsoft Teams provider (polling, attachments, outbound sends, requireMention, config reload/DM policy). (#404) — thanks @onutc
|
|
1118
1119
|
- Providers: WhatsApp broadcast groups for multi-agent replies (#547) — thanks @pasogott; inbound media size cap configurable (#505) — thanks @koala73; identity-based message prefixes (#578) — thanks @p6l-richard.
|
|
1119
1120
|
- Providers: Telegram inline keyboard buttons + callback payload routing (#491) — thanks @azade-c; cron topic delivery targets (#474/#478) — thanks @mitschabaude-bot, @nachoiacovino; `[[audio_as_voice]]` tag support (#490) — thanks @jarvis-medmatic.
|
|
@@ -1182,7 +1183,7 @@ Thanks @AlexMikhalev, @CoreyH, @John-Rood, @KrauseFx, @MaudeBot, @Nachx639, @Nic
|
|
|
1182
1183
|
- **Control UI/Web:** logs tab, focus mode polish, config form resilience, streaming stability, tool output caps, windowed chat history, and reconnect/password URL auth.
|
|
1183
1184
|
- **macOS/Android/TUI/Build:** macOS gateway races, QR bundling, JSON5 config safety, Voice Wake hardening; Android EXIF rotation + APK naming/versioning; TUI key handling; tooling/bundling fixes.
|
|
1184
1185
|
- **Packaging/compat:** npm dist folder coverage, Node 25 qrcode-terminal import fixes, Bun/Playwright/WebSocket patches, and Docker Bun install.
|
|
1185
|
-
- **Docs:** new FAQ/
|
|
1186
|
+
- **Docs:** new FAQ/ClawHub/config examples/showcase entries and clarified auth, sandbox, and systemd docs.
|
|
1186
1187
|
|
|
1187
1188
|
### Maintenance
|
|
1188
1189
|
- Skills additions (Himalaya email, CodexBar, 1Password).
|
|
@@ -1212,7 +1213,7 @@ Thanks @AlexMikhalev, @CoreyH, @John-Rood, @KrauseFx, @MaudeBot, @Nachx639, @Nic
|
|
|
1212
1213
|
- WhatsApp: mark offline history sync messages as read without auto-reply. (#193) — thanks @mcinteerj
|
|
1213
1214
|
- Discord: avoid duplicate replies when a provider emits late streaming `text_end` events (OpenAI/GPT).
|
|
1214
1215
|
- CLI: use tailnet IP for local gateway calls when bind is tailnet/auto (fixes #176).
|
|
1215
|
-
- Env: load global `$
|
|
1216
|
+
- Env: load global `$OPENCLAW_STATE_DIR/.env` (`~/.openclaw/.env`) as a fallback after CWD `.env`.
|
|
1216
1217
|
- Env: optional login-shell env fallback (opt-in; imports expected keys without overriding existing env).
|
|
1217
1218
|
- Agent tools: OpenAI-compatible tool JSON Schemas (fix `browser`, normalize union schemas).
|
|
1218
1219
|
- Onboarding: when running from source, auto-build missing Control UI assets (`bun run ui:build`).
|
package/README.md
CHANGED
|
@@ -270,26 +270,99 @@ openclaw --help # 查看帮助
|
|
|
270
270
|
|
|
271
271
|
## 🐳 Docker 部署指南
|
|
272
272
|
|
|
273
|
-
###
|
|
273
|
+
### 方式 1:一键部署脚本(推荐)
|
|
274
|
+
|
|
275
|
+
自动完成初始化、配置远程访问、启动容器:
|
|
274
276
|
|
|
275
277
|
```bash
|
|
276
|
-
#
|
|
278
|
+
# Linux / macOS
|
|
279
|
+
curl -fsSL https://cdn.jsdelivr.net/gh/1186258278/OpenClawChineseTranslation@main/docker-deploy.sh | bash
|
|
280
|
+
|
|
281
|
+
# Windows PowerShell
|
|
282
|
+
irm https://cdn.jsdelivr.net/gh/1186258278/OpenClawChineseTranslation@main/docker-deploy.ps1 | iex
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### 方式 2:快速启动(本地访问)
|
|
286
|
+
|
|
287
|
+
适用于在本机运行并通过 `localhost` 访问:
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
# 基础运行(数据不持久化)
|
|
277
291
|
docker run -d \
|
|
278
292
|
--name openclaw \
|
|
279
293
|
-p 18789:18789 \
|
|
280
294
|
ghcr.io/qingchencloud/openclaw-zh:latest
|
|
281
295
|
|
|
282
|
-
#
|
|
296
|
+
# 带数据持久化(推荐)
|
|
283
297
|
docker run -d \
|
|
284
298
|
--name openclaw \
|
|
285
299
|
-p 18789:18789 \
|
|
286
|
-
-v openclaw-data:/
|
|
300
|
+
-v openclaw-data:/root/.openclaw \
|
|
287
301
|
ghcr.io/qingchencloud/openclaw-zh:latest
|
|
288
302
|
```
|
|
289
303
|
|
|
304
|
+
访问:`http://localhost:18789`
|
|
305
|
+
|
|
306
|
+
### 方式 3:服务器部署(远程访问)
|
|
307
|
+
|
|
308
|
+
部署到服务器并从其他设备访问时,需要额外配置。
|
|
309
|
+
|
|
310
|
+
**手动配置步骤:**
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
# 1. 创建数据卷
|
|
314
|
+
docker volume create openclaw-data
|
|
315
|
+
|
|
316
|
+
# 2. 初始化配置
|
|
317
|
+
docker run --rm -v openclaw-data:/root/.openclaw \
|
|
318
|
+
ghcr.io/qingchencloud/openclaw-zh:latest openclaw setup
|
|
319
|
+
|
|
320
|
+
# 3. 配置远程访问参数
|
|
321
|
+
docker run --rm -v openclaw-data:/root/.openclaw \
|
|
322
|
+
ghcr.io/qingchencloud/openclaw-zh:latest openclaw config set gateway.mode local
|
|
323
|
+
|
|
324
|
+
docker run --rm -v openclaw-data:/root/.openclaw \
|
|
325
|
+
ghcr.io/qingchencloud/openclaw-zh:latest openclaw config set gateway.bind lan
|
|
326
|
+
|
|
327
|
+
docker run --rm -v openclaw-data:/root/.openclaw \
|
|
328
|
+
ghcr.io/qingchencloud/openclaw-zh:latest openclaw config set gateway.controlUi.allowInsecureAuth true
|
|
329
|
+
|
|
330
|
+
# 4. 启动容器
|
|
331
|
+
docker run -d \
|
|
332
|
+
--name openclaw \
|
|
333
|
+
-p 18789:18789 \
|
|
334
|
+
-v openclaw-data:/root/.openclaw \
|
|
335
|
+
-e OPENCLAW_GATEWAY_TOKEN=your-secure-token \
|
|
336
|
+
--restart unless-stopped \
|
|
337
|
+
ghcr.io/qingchencloud/openclaw-zh:latest \
|
|
338
|
+
openclaw gateway run
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
访问:`http://服务器IP:18789?token=your-secure-token`
|
|
342
|
+
|
|
343
|
+
### 远程访问注意事项
|
|
344
|
+
|
|
345
|
+
通过 HTTP 从非 localhost 访问时,浏览器会限制某些安全功能(设备身份验证)。
|
|
346
|
+
|
|
347
|
+
| 方案 | 说明 | 适用场景 |
|
|
348
|
+
|------|------|----------|
|
|
349
|
+
| **启用 allowInsecureAuth** | 仅使用 Token 认证 | 内网/测试环境 |
|
|
350
|
+
| **使用 HTTPS** | Tailscale Serve 或 Nginx 反向代理 | 生产环境(推荐) |
|
|
351
|
+
| **SSH 端口转发** | `ssh -L 18789:127.0.0.1:18789 user@server` | 临时访问 |
|
|
352
|
+
|
|
290
353
|
### 使用 Docker Compose
|
|
291
354
|
|
|
292
|
-
|
|
355
|
+
项目提供了开箱即用的 `docker-compose.yml`:
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
# 下载配置文件
|
|
359
|
+
curl -fsSL https://cdn.jsdelivr.net/gh/1186258278/OpenClawChineseTranslation@main/docker-compose.yml -o docker-compose.yml
|
|
360
|
+
|
|
361
|
+
# 启动(首次会自动初始化)
|
|
362
|
+
docker-compose up -d
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
或手动创建 `docker-compose.yml`:
|
|
293
366
|
|
|
294
367
|
```yaml
|
|
295
368
|
version: '3.8'
|
|
@@ -300,21 +373,17 @@ services:
|
|
|
300
373
|
ports:
|
|
301
374
|
- "18789:18789"
|
|
302
375
|
volumes:
|
|
303
|
-
- openclaw-data:/
|
|
376
|
+
- openclaw-data:/root/.openclaw
|
|
304
377
|
environment:
|
|
305
|
-
- OPENCLAW_GATEWAY_TOKEN=your-secure-token #
|
|
378
|
+
- OPENCLAW_GATEWAY_TOKEN=your-secure-token # 设置访问令牌
|
|
306
379
|
restart: unless-stopped
|
|
380
|
+
# 远程访问时使用以下命令(需先手动初始化配置)
|
|
381
|
+
# command: openclaw gateway run
|
|
307
382
|
|
|
308
383
|
volumes:
|
|
309
384
|
openclaw-data:
|
|
310
385
|
```
|
|
311
386
|
|
|
312
|
-
启动:
|
|
313
|
-
|
|
314
|
-
```bash
|
|
315
|
-
docker-compose up -d
|
|
316
|
-
```
|
|
317
|
-
|
|
318
387
|
### 自行构建 Docker 镜像
|
|
319
388
|
|
|
320
389
|
如果需要自定义或使用最新代码:
|
|
@@ -335,7 +404,7 @@ cd openclaw
|
|
|
335
404
|
docker build -t openclaw-zh:local .
|
|
336
405
|
|
|
337
406
|
# 5. 运行
|
|
338
|
-
docker run -d --name openclaw -p 18789:18789 openclaw-zh:local
|
|
407
|
+
docker run -d --name openclaw -p 18789:18789 -v openclaw-data:/root/.openclaw openclaw-zh:local
|
|
339
408
|
```
|
|
340
409
|
|
|
341
410
|
### 常用 Docker 命令
|
|
@@ -355,13 +424,10 @@ docker exec -it openclaw sh
|
|
|
355
424
|
|
|
356
425
|
# 删除容器
|
|
357
426
|
docker stop openclaw && docker rm openclaw
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
### 访问 Dashboard
|
|
361
427
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
428
|
+
# 查看配置
|
|
429
|
+
docker run --rm -v openclaw-data:/root/.openclaw alpine cat /root/.openclaw/openclaw.json
|
|
430
|
+
```
|
|
365
431
|
|
|
366
432
|
---
|
|
367
433
|
|
|
@@ -99,7 +99,7 @@ function buildDocsSection(params) {
|
|
|
99
99
|
"Mirror: https://docs.openclaw.ai",
|
|
100
100
|
"Source: https://github.com/openclaw/openclaw",
|
|
101
101
|
"Community: https://discord.com/invite/clawd",
|
|
102
|
-
"Find new skills: https://
|
|
102
|
+
"Find new skills: https://clawhub.com",
|
|
103
103
|
"For OpenClaw behavior, commands, config, or architecture: consult local docs first.",
|
|
104
104
|
"When diagnosing issues, run `openclaw status` yourself when possible; only ask the user if you lack access (e.g., sandboxed).",
|
|
105
105
|
"",
|
package/dist/build-info.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2026.1.29-nightly.
|
|
3
|
-
"commit": "
|
|
4
|
-
"builtAt": "2026-01-
|
|
2
|
+
"version": "2026.1.29-nightly.202601302059",
|
|
3
|
+
"commit": "7c96bde3b3db74dcf57bff0138eefd5d03ba1d08",
|
|
4
|
+
"builtAt": "2026-01-30T21:00:23.151Z"
|
|
5
5
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
9f71946c42dd48cbf433eb302e8b0824f989785de8f9750671ce2f34c097396d
|
package/dist/cli/cli-utils.js
CHANGED
|
@@ -32,3 +32,13 @@ export async function runCommandWithRuntime(runtime, action, onError) {
|
|
|
32
32
|
runtime.exit(1);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
export function resolveOptionFromCommand(command, key) {
|
|
36
|
+
let current = command;
|
|
37
|
+
while (current) {
|
|
38
|
+
const opts = (current.opts?.() ?? {});
|
|
39
|
+
if (opts[key] !== undefined)
|
|
40
|
+
return opts[key];
|
|
41
|
+
current = current.parent ?? undefined;
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
package/dist/cli/models-cli.js
CHANGED
|
@@ -2,7 +2,7 @@ import { githubCopilotLoginCommand, modelsAliasesAddCommand, modelsAliasesListCo
|
|
|
2
2
|
import { defaultRuntime } from "../runtime.js";
|
|
3
3
|
import { formatDocsLink } from "../terminal/links.js";
|
|
4
4
|
import { theme } from "../terminal/theme.js";
|
|
5
|
-
import { runCommandWithRuntime } from "./cli-utils.js";
|
|
5
|
+
import { resolveOptionFromCommand, runCommandWithRuntime } from "./cli-utils.js";
|
|
6
6
|
function runModelsCommand(action) {
|
|
7
7
|
return runCommandWithRuntime(defaultRuntime, action);
|
|
8
8
|
}
|
|
@@ -12,6 +12,7 @@ export function registerModelsCli(program) {
|
|
|
12
12
|
.description("Model discovery, scanning, and configuration")
|
|
13
13
|
.option("--status-json", "Output JSON (alias for `models status --json`)", false)
|
|
14
14
|
.option("--status-plain", "Plain output (alias for `models status --plain`)", false)
|
|
15
|
+
.option("--agent <id>", "Agent id to inspect (overrides OPENCLAW_AGENT_DIR/PI_CODING_AGENT_DIR)")
|
|
15
16
|
.addHelpText("after", () => `\n${theme.muted("Docs:")} ${formatDocsLink("/cli/models", "docs.openclaw.ai/cli/models")}\n`);
|
|
16
17
|
models
|
|
17
18
|
.command("list")
|
|
@@ -42,7 +43,9 @@ export function registerModelsCli(program) {
|
|
|
42
43
|
.option("--probe-timeout <ms>", "Per-probe timeout in ms")
|
|
43
44
|
.option("--probe-concurrency <n>", "Concurrent probes")
|
|
44
45
|
.option("--probe-max-tokens <n>", "Probe max tokens (best-effort)")
|
|
45
|
-
.
|
|
46
|
+
.option("--agent <id>", "Agent id to inspect (overrides OPENCLAW_AGENT_DIR/PI_CODING_AGENT_DIR)")
|
|
47
|
+
.action(async (opts, command) => {
|
|
48
|
+
const agent = resolveOptionFromCommand(command, "agent") ?? opts.agent;
|
|
46
49
|
await runModelsCommand(async () => {
|
|
47
50
|
await modelsStatusCommand({
|
|
48
51
|
json: Boolean(opts.json),
|
|
@@ -54,6 +57,7 @@ export function registerModelsCli(program) {
|
|
|
54
57
|
probeTimeout: opts.probeTimeout,
|
|
55
58
|
probeConcurrency: opts.probeConcurrency,
|
|
56
59
|
probeMaxTokens: opts.probeMaxTokens,
|
|
60
|
+
agent,
|
|
57
61
|
}, defaultRuntime);
|
|
58
62
|
});
|
|
59
63
|
});
|
|
@@ -206,10 +210,15 @@ export function registerModelsCli(program) {
|
|
|
206
210
|
await modelsStatusCommand({
|
|
207
211
|
json: Boolean(opts?.statusJson),
|
|
208
212
|
plain: Boolean(opts?.statusPlain),
|
|
213
|
+
agent: opts?.agent,
|
|
209
214
|
}, defaultRuntime);
|
|
210
215
|
});
|
|
211
216
|
});
|
|
212
217
|
const auth = models.command("auth").description("Manage model auth profiles");
|
|
218
|
+
auth.option("--agent <id>", "Agent id for auth order get/set/clear");
|
|
219
|
+
auth.action(() => {
|
|
220
|
+
auth.help();
|
|
221
|
+
});
|
|
213
222
|
auth
|
|
214
223
|
.command("add")
|
|
215
224
|
.description("Interactive auth helper (setup-token or paste token)")
|
|
@@ -281,11 +290,12 @@ export function registerModelsCli(program) {
|
|
|
281
290
|
.requiredOption("--provider <name>", "Provider id (e.g. anthropic)")
|
|
282
291
|
.option("--agent <id>", "Agent id (default: configured default agent)")
|
|
283
292
|
.option("--json", "Output JSON", false)
|
|
284
|
-
.action(async (opts) => {
|
|
293
|
+
.action(async (opts, command) => {
|
|
294
|
+
const agent = resolveOptionFromCommand(command, "agent") ?? opts.agent;
|
|
285
295
|
await runModelsCommand(async () => {
|
|
286
296
|
await modelsAuthOrderGetCommand({
|
|
287
297
|
provider: opts.provider,
|
|
288
|
-
agent
|
|
298
|
+
agent,
|
|
289
299
|
json: Boolean(opts.json),
|
|
290
300
|
}, defaultRuntime);
|
|
291
301
|
});
|
|
@@ -296,11 +306,12 @@ export function registerModelsCli(program) {
|
|
|
296
306
|
.requiredOption("--provider <name>", "Provider id (e.g. anthropic)")
|
|
297
307
|
.option("--agent <id>", "Agent id (default: configured default agent)")
|
|
298
308
|
.argument("<profileIds...>", "Auth profile ids (e.g. anthropic:default)")
|
|
299
|
-
.action(async (profileIds, opts) => {
|
|
309
|
+
.action(async (profileIds, opts, command) => {
|
|
310
|
+
const agent = resolveOptionFromCommand(command, "agent") ?? opts.agent;
|
|
300
311
|
await runModelsCommand(async () => {
|
|
301
312
|
await modelsAuthOrderSetCommand({
|
|
302
313
|
provider: opts.provider,
|
|
303
|
-
agent
|
|
314
|
+
agent,
|
|
304
315
|
order: profileIds,
|
|
305
316
|
}, defaultRuntime);
|
|
306
317
|
});
|
|
@@ -310,11 +321,12 @@ export function registerModelsCli(program) {
|
|
|
310
321
|
.description("Clear per-agent auth order override (fall back to config/round-robin)")
|
|
311
322
|
.requiredOption("--provider <name>", "Provider id (e.g. anthropic)")
|
|
312
323
|
.option("--agent <id>", "Agent id (default: configured default agent)")
|
|
313
|
-
.action(async (opts) => {
|
|
324
|
+
.action(async (opts, command) => {
|
|
325
|
+
const agent = resolveOptionFromCommand(command, "agent") ?? opts.agent;
|
|
314
326
|
await runModelsCommand(async () => {
|
|
315
327
|
await modelsAuthOrderClearCommand({
|
|
316
328
|
provider: opts.provider,
|
|
317
|
-
agent
|
|
329
|
+
agent,
|
|
318
330
|
}, defaultRuntime);
|
|
319
331
|
});
|
|
320
332
|
});
|
package/dist/cli/skills-cli.js
CHANGED
|
@@ -7,10 +7,10 @@ import { renderTable } from "../terminal/table.js";
|
|
|
7
7
|
import { theme } from "../terminal/theme.js";
|
|
8
8
|
import { shortenHomePath } from "../utils.js";
|
|
9
9
|
import { formatCliCommand } from "./command-format.js";
|
|
10
|
-
function
|
|
10
|
+
function appendClawHubHint(output, json) {
|
|
11
11
|
if (json)
|
|
12
12
|
return output;
|
|
13
|
-
return `${output}\n\nTip: use \`npx
|
|
13
|
+
return `${output}\n\nTip: use \`npx clawhub\` to search, install, and sync skills.`;
|
|
14
14
|
}
|
|
15
15
|
function formatSkillStatus(skill) {
|
|
16
16
|
if (skill.eligible)
|
|
@@ -72,7 +72,7 @@ export function formatSkillsList(report, opts) {
|
|
|
72
72
|
const message = opts.eligible
|
|
73
73
|
? `No eligible skills found. Run \`${formatCliCommand("openclaw skills list")}\` to see all skills.`
|
|
74
74
|
: "No skills found.";
|
|
75
|
-
return
|
|
75
|
+
return appendClawHubHint(message, opts.json);
|
|
76
76
|
}
|
|
77
77
|
const eligible = skills.filter((s) => s.eligible);
|
|
78
78
|
const tableWidth = Math.max(60, (process.stdout.columns ?? 120) - 1);
|
|
@@ -102,7 +102,7 @@ export function formatSkillsList(report, opts) {
|
|
|
102
102
|
columns,
|
|
103
103
|
rows,
|
|
104
104
|
}).trimEnd());
|
|
105
|
-
return
|
|
105
|
+
return appendClawHubHint(lines.join("\n"), opts.json);
|
|
106
106
|
}
|
|
107
107
|
/**
|
|
108
108
|
* Format detailed info for a single skill
|
|
@@ -113,7 +113,7 @@ export function formatSkillInfo(report, skillName, opts) {
|
|
|
113
113
|
if (opts.json) {
|
|
114
114
|
return JSON.stringify({ error: "not found", skill: skillName }, null, 2);
|
|
115
115
|
}
|
|
116
|
-
return
|
|
116
|
+
return appendClawHubHint(`Skill "${skillName}" not found. Run \`${formatCliCommand("openclaw skills list")}\` to see available skills.`, opts.json);
|
|
117
117
|
}
|
|
118
118
|
if (opts.json) {
|
|
119
119
|
return JSON.stringify(skill, null, 2);
|
|
@@ -195,7 +195,7 @@ export function formatSkillInfo(report, skillName, opts) {
|
|
|
195
195
|
lines.push(` ${theme.warn("→")} ${inst.label}`);
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
|
-
return
|
|
198
|
+
return appendClawHubHint(lines.join("\n"), opts.json);
|
|
199
199
|
}
|
|
200
200
|
/**
|
|
201
201
|
* Format a check/summary of all skills status
|
|
@@ -264,7 +264,7 @@ export function formatSkillsCheck(report, opts) {
|
|
|
264
264
|
lines.push(` ${emoji} ${skill.name} ${theme.muted(`(${missing.join("; ")})`)}`);
|
|
265
265
|
}
|
|
266
266
|
}
|
|
267
|
-
return
|
|
267
|
+
return appendClawHubHint(lines.join("\n"), opts.json);
|
|
268
268
|
}
|
|
269
269
|
/**
|
|
270
270
|
* Register the skills CLI commands
|
|
@@ -2,10 +2,10 @@ import { resolveAgentDir, resolveDefaultAgentId } from "../../agents/agent-scope
|
|
|
2
2
|
import { ensureAuthProfileStore, setAuthProfileOrder, } from "../../agents/auth-profiles.js";
|
|
3
3
|
import { normalizeProviderId } from "../../agents/model-selection.js";
|
|
4
4
|
import { loadConfig } from "../../config/config.js";
|
|
5
|
-
import { normalizeAgentId } from "../../routing/session-key.js";
|
|
6
5
|
import { shortenHomePath } from "../../utils.js";
|
|
6
|
+
import { resolveKnownAgentId } from "./shared.js";
|
|
7
7
|
function resolveTargetAgent(cfg, raw) {
|
|
8
|
-
const agentId =
|
|
8
|
+
const agentId = resolveKnownAgentId({ cfg, rawAgentId: raw }) ?? resolveDefaultAgentId(cfg);
|
|
9
9
|
const agentDir = resolveAgentDir(cfg, agentId);
|
|
10
10
|
return { agentId, agentDir };
|
|
11
11
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { resolveOpenClawAgentDir } from "../../agents/agent-paths.js";
|
|
3
|
+
import { resolveAgentDir, resolveAgentModelFallbacksOverride, resolveAgentModelPrimary, } from "../../agents/agent-scope.js";
|
|
3
4
|
import { buildAuthHealthSummary, DEFAULT_OAUTH_WARN_MS, formatRemainingShort, } from "../../agents/auth-health.js";
|
|
4
5
|
import { ensureAuthProfileStore, resolveAuthStorePathForDisplay, resolveProfileUnusableUntilForDisplay, } from "../../agents/auth-profiles.js";
|
|
5
6
|
import { resolveEnvApiKey } from "../../agents/model-auth.js";
|
|
6
|
-
import { buildModelAliasIndex, parseModelRef, resolveConfiguredModelRef, resolveModelRefFromString, } from "../../agents/model-selection.js";
|
|
7
|
+
import { buildModelAliasIndex, parseModelRef, resolveConfiguredModelRef, resolveDefaultModelForAgent, resolveModelRefFromString, } from "../../agents/model-selection.js";
|
|
7
8
|
import { CONFIG_PATH, loadConfig } from "../../config/config.js";
|
|
8
9
|
import { getShellEnvAppliedKeys, shouldEnableShellEnvFallback } from "../../infra/shell-env.js";
|
|
9
10
|
import { withProgressTotals } from "../../cli/progress.js";
|
|
@@ -15,24 +16,34 @@ import { shortenHomePath } from "../../utils.js";
|
|
|
15
16
|
import { resolveProviderAuthOverview } from "./list.auth-overview.js";
|
|
16
17
|
import { isRich } from "./list.format.js";
|
|
17
18
|
import { describeProbeSummary, formatProbeLatency, runAuthProbes, sortProbeResults, } from "./list.probe.js";
|
|
18
|
-
import { DEFAULT_MODEL, DEFAULT_PROVIDER, ensureFlagCompatibility } from "./shared.js";
|
|
19
|
+
import { DEFAULT_MODEL, DEFAULT_PROVIDER, ensureFlagCompatibility, resolveKnownAgentId, } from "./shared.js";
|
|
19
20
|
export async function modelsStatusCommand(opts, runtime) {
|
|
20
21
|
ensureFlagCompatibility(opts);
|
|
21
22
|
if (opts.plain && opts.probe) {
|
|
22
23
|
throw new Error("--probe cannot be used with --plain output.");
|
|
23
24
|
}
|
|
24
25
|
const cfg = loadConfig();
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
const agentId = resolveKnownAgentId({ cfg, rawAgentId: opts.agent });
|
|
27
|
+
const agentDir = agentId ? resolveAgentDir(cfg, agentId) : resolveOpenClawAgentDir();
|
|
28
|
+
const agentModelPrimary = agentId ? resolveAgentModelPrimary(cfg, agentId) : undefined;
|
|
29
|
+
const agentFallbacksOverride = agentId
|
|
30
|
+
? resolveAgentModelFallbacksOverride(cfg, agentId)
|
|
31
|
+
: undefined;
|
|
32
|
+
const resolved = agentId
|
|
33
|
+
? resolveDefaultModelForAgent({ cfg, agentId })
|
|
34
|
+
: resolveConfiguredModelRef({
|
|
35
|
+
cfg,
|
|
36
|
+
defaultProvider: DEFAULT_PROVIDER,
|
|
37
|
+
defaultModel: DEFAULT_MODEL,
|
|
38
|
+
});
|
|
30
39
|
const modelConfig = cfg.agents?.defaults?.model;
|
|
31
40
|
const imageConfig = cfg.agents?.defaults?.imageModel;
|
|
32
|
-
const
|
|
41
|
+
const rawDefaultsModel = typeof modelConfig === "string" ? modelConfig.trim() : (modelConfig?.primary?.trim() ?? "");
|
|
42
|
+
const rawModel = agentModelPrimary ?? rawDefaultsModel;
|
|
33
43
|
const resolvedLabel = `${resolved.provider}/${resolved.model}`;
|
|
34
44
|
const defaultLabel = rawModel || resolvedLabel;
|
|
35
|
-
const
|
|
45
|
+
const defaultsFallbacks = typeof modelConfig === "object" ? (modelConfig?.fallbacks ?? []) : [];
|
|
46
|
+
const fallbacks = agentFallbacksOverride ?? defaultsFallbacks;
|
|
36
47
|
const imageModel = typeof imageConfig === "string" ? imageConfig.trim() : (imageConfig?.primary?.trim() ?? "");
|
|
37
48
|
const imageFallbacks = typeof imageConfig === "object" ? (imageConfig?.fallbacks ?? []) : [];
|
|
38
49
|
const aliases = Object.entries(cfg.agents?.defaults?.models ?? {}).reduce((acc, [key, entry]) => {
|
|
@@ -42,8 +53,7 @@ export async function modelsStatusCommand(opts, runtime) {
|
|
|
42
53
|
return acc;
|
|
43
54
|
}, {});
|
|
44
55
|
const allowed = Object.keys(cfg.agents?.defaults?.models ?? {});
|
|
45
|
-
const
|
|
46
|
-
const store = ensureAuthProfileStore();
|
|
56
|
+
const store = ensureAuthProfileStore(agentDir);
|
|
47
57
|
const modelsPath = path.join(agentDir, "models.json");
|
|
48
58
|
const providersFromStore = new Set(Object.values(store.profiles)
|
|
49
59
|
.map((profile) => profile.provider)
|
|
@@ -208,16 +218,25 @@ export async function modelsStatusCommand(opts, runtime) {
|
|
|
208
218
|
if (opts.json) {
|
|
209
219
|
runtime.log(JSON.stringify({
|
|
210
220
|
configPath: CONFIG_PATH,
|
|
221
|
+
...(agentId ? { agentId } : {}),
|
|
211
222
|
agentDir,
|
|
212
223
|
defaultModel: defaultLabel,
|
|
213
224
|
resolvedDefault: resolvedLabel,
|
|
214
225
|
fallbacks,
|
|
215
226
|
imageModel: imageModel || null,
|
|
216
227
|
imageFallbacks,
|
|
228
|
+
...(agentId
|
|
229
|
+
? {
|
|
230
|
+
modelConfig: {
|
|
231
|
+
defaultSource: agentModelPrimary ? "agent" : "defaults",
|
|
232
|
+
fallbacksSource: agentFallbacksOverride !== undefined ? "agent" : "defaults",
|
|
233
|
+
},
|
|
234
|
+
}
|
|
235
|
+
: {}),
|
|
217
236
|
aliases,
|
|
218
237
|
allowed,
|
|
219
238
|
auth: {
|
|
220
|
-
storePath: resolveAuthStorePathForDisplay(),
|
|
239
|
+
storePath: resolveAuthStorePathForDisplay(agentDir),
|
|
221
240
|
shellEnvFallback: {
|
|
222
241
|
enabled: shellFallbackEnabled,
|
|
223
242
|
appliedKeys: applied,
|
|
@@ -246,13 +265,14 @@ export async function modelsStatusCommand(opts, runtime) {
|
|
|
246
265
|
}
|
|
247
266
|
const rich = isRich(opts);
|
|
248
267
|
const label = (value) => colorize(rich, theme.accent, value.padEnd(14));
|
|
268
|
+
const labelWithSource = (value, source) => label(source ? `${value} (${source})` : value);
|
|
249
269
|
const displayDefault = rawModel && rawModel !== resolvedLabel ? `${resolvedLabel} (from ${rawModel})` : resolvedLabel;
|
|
250
270
|
runtime.log(`${label("Config")}${colorize(rich, theme.muted, ":")} ${colorize(rich, theme.info, shortenHomePath(CONFIG_PATH))}`);
|
|
251
271
|
runtime.log(`${label("Agent dir")}${colorize(rich, theme.muted, ":")} ${colorize(rich, theme.info, shortenHomePath(agentDir))}`);
|
|
252
|
-
runtime.log(`${
|
|
253
|
-
runtime.log(`${
|
|
254
|
-
runtime.log(`${
|
|
255
|
-
runtime.log(`${
|
|
272
|
+
runtime.log(`${labelWithSource("Default", agentId ? (agentModelPrimary ? "agent" : "defaults") : undefined)}${colorize(rich, theme.muted, ":")} ${colorize(rich, theme.success, displayDefault)}`);
|
|
273
|
+
runtime.log(`${labelWithSource(`Fallbacks (${fallbacks.length || 0})`, agentId ? (agentFallbacksOverride !== undefined ? "agent" : "defaults") : undefined)}${colorize(rich, theme.muted, ":")} ${colorize(rich, fallbacks.length ? theme.warn : theme.muted, fallbacks.length ? fallbacks.join(", ") : "-")}`);
|
|
274
|
+
runtime.log(`${labelWithSource("Image model", agentId ? "defaults" : undefined)}${colorize(rich, theme.muted, ":")} ${colorize(rich, imageModel ? theme.accentBright : theme.muted, imageModel || "-")}`);
|
|
275
|
+
runtime.log(`${labelWithSource(`Image fallbacks (${imageFallbacks.length || 0})`, agentId ? "defaults" : undefined)}${colorize(rich, theme.muted, ":")} ${colorize(rich, imageFallbacks.length ? theme.accentBright : theme.muted, imageFallbacks.length ? imageFallbacks.join(", ") : "-")}`);
|
|
256
276
|
runtime.log(`${label(`Aliases (${Object.keys(aliases).length || 0})`)}${colorize(rich, theme.muted, ":")} ${colorize(rich, Object.keys(aliases).length ? theme.accent : theme.muted, Object.keys(aliases).length
|
|
257
277
|
? Object.entries(aliases)
|
|
258
278
|
.map(([alias, target]) => rich
|
|
@@ -263,7 +283,7 @@ export async function modelsStatusCommand(opts, runtime) {
|
|
|
263
283
|
runtime.log(`${label(`Configured models (${allowed.length || 0})`)}${colorize(rich, theme.muted, ":")} ${colorize(rich, allowed.length ? theme.info : theme.muted, allowed.length ? allowed.join(", ") : "all")}`);
|
|
264
284
|
runtime.log("");
|
|
265
285
|
runtime.log(colorize(rich, theme.heading, "Auth overview"));
|
|
266
|
-
runtime.log(`${label("Auth store")}${colorize(rich, theme.muted, ":")} ${colorize(rich, theme.info, shortenHomePath(resolveAuthStorePathForDisplay()))}`);
|
|
286
|
+
runtime.log(`${label("Auth store")}${colorize(rich, theme.muted, ":")} ${colorize(rich, theme.info, shortenHomePath(resolveAuthStorePathForDisplay(agentDir)))}`);
|
|
267
287
|
runtime.log(`${label("Shell env")}${colorize(rich, theme.muted, ":")} ${colorize(rich, shellFallbackEnabled ? theme.success : theme.muted, shellFallbackEnabled ? "on" : "off")}${applied.length ? colorize(rich, theme.muted, ` (applied: ${applied.join(", ")})`) : ""}`);
|
|
268
288
|
runtime.log(`${label(`Providers w/ OAuth/tokens (${providersWithOauth.length || 0})`)}${colorize(rich, theme.muted, ":")} ${colorize(rich, providersWithOauth.length ? theme.info : theme.muted, providersWithOauth.length ? providersWithOauth.join(", ") : "-")}`);
|
|
269
289
|
const formatKey = (key) => colorize(rich, theme.warn, key);
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../../agents/defaults.js";
|
|
2
2
|
import { buildModelAliasIndex, modelKey, parseModelRef, resolveModelRefFromString, } from "../../agents/model-selection.js";
|
|
3
|
+
import { listAgentIds } from "../../agents/agent-scope.js";
|
|
4
|
+
import { formatCliCommand } from "../../cli/command-format.js";
|
|
3
5
|
import { readConfigFileSnapshot, writeConfigFile, } from "../../config/config.js";
|
|
6
|
+
import { normalizeAgentId } from "../../routing/session-key.js";
|
|
4
7
|
export const ensureFlagCompatibility = (opts) => {
|
|
5
8
|
if (opts.json && opts.plain) {
|
|
6
9
|
throw new Error("Choose either --json or --plain, not both.");
|
|
@@ -67,6 +70,17 @@ export function normalizeAlias(alias) {
|
|
|
67
70
|
}
|
|
68
71
|
return trimmed;
|
|
69
72
|
}
|
|
73
|
+
export function resolveKnownAgentId(params) {
|
|
74
|
+
const raw = params.rawAgentId?.trim();
|
|
75
|
+
if (!raw)
|
|
76
|
+
return undefined;
|
|
77
|
+
const agentId = normalizeAgentId(raw);
|
|
78
|
+
const knownAgents = listAgentIds(params.cfg);
|
|
79
|
+
if (!knownAgents.includes(agentId)) {
|
|
80
|
+
throw new Error(`Unknown agent id "${raw}". Use "${formatCliCommand("openclaw agents list")}" to see configured agents.`);
|
|
81
|
+
}
|
|
82
|
+
return agentId;
|
|
83
|
+
}
|
|
70
84
|
export { modelKey };
|
|
71
85
|
export { DEFAULT_MODEL, DEFAULT_PROVIDER };
|
|
72
86
|
/**
|