@wwkit/opm 1.0.9 → 1.0.11

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/README.md CHANGED
@@ -52,11 +52,11 @@ pnpm opm <command> [args] [options]
52
52
  | `composer <action>` | composer 包管理器(PHP) |
53
53
  | `bun <action>` | bun 包管理器(Bun runtime,npm 兼容源) |
54
54
  | `winget <action>` | winget 包管理器(Windows) |
55
- | `nvm <action>` | nvm 自身管理(安装/升级/卸载 nvm) |
55
+ | `nvm <action>` | nvm 自身管理(安装/升级/卸载 nvm;list 列出已安装 Node.js 版本) |
56
56
  | `node <action>` | node 版本管理(基于 nvm 安装/切换/卸载 Node.js 版本) |
57
- | `phpenv <action>` | phpenv 自身管理(安装/升级/卸载 phpenv) |
57
+ | `phpenv <action>` | phpenv 自身管理(安装/升级/卸载 phpenv;list 列出已安装 PHP 版本) |
58
58
  | `php <action>` | php 版本管理(基于 phpenv 安装/切换/卸载 PHP 版本) |
59
- | `uv <action>` | uv 自身管理(安装/升级/卸载 uv) |
59
+ | `uv <action>` | uv 自身管理(安装/升级/卸载 uv;list 列出已安装 Python 版本) |
60
60
  | `python <action>` | python 版本管理(基于 uv 安装/切换/卸载 Python 版本) |
61
61
  | `docker <action>` | Docker 自身管理(安装/升级/启停/open,含 daemon 状态) |
62
62
  | `homebrew <action>` | Homebrew 自身管理(安装/升级/卸载 brew) |
@@ -68,7 +68,8 @@ pnpm opm <command> [args] [options]
68
68
  | `ensure <runtime> [version]` | 确保运行时已安装(node/php/python) |
69
69
  | `ping <host|proxy|registry>` | 验证主机、代理或所有 registry 的可访问性 |
70
70
  | `config [section]` | 查看常用配置(proxy + 各 registry 段,段名动态生成) |
71
- | `opencode <action>` | opencode 运维命令(安装/升级/清理/env/open) |
71
+ | `opencode <action>` | opencode 运维命令(安装/升级/清理/env);裸 `opm opencode` 启动 TUI |
72
+ | `harness <action>` | @wwkit/harness 插件管理(安装/升级/list/status/env/dir) |
72
73
 
73
74
  ## Managers
74
75
 
@@ -100,7 +101,7 @@ pnpm opm <command> [args] [options]
100
101
  | `view <name>` | 查询包在全局与项目作用域的安装信息(仅包管理器;运行时查询版本是否已安装) |
101
102
  | `info <name>` | 查询包详情 |
102
103
  | `versions <name>` | 列出所有可用版本 |
103
- | `list` | 列出所有已安装包(仅 node/php/python 运行时) |
104
+ | `list` | 列出所有已安装包(仅运行时 node/php/python 与工具组 nvm/phpenv/uv 支持) |
104
105
  | `outdated` | 列出过期包 |
105
106
  | `install <name> [version]` | 安装包 |
106
107
  | `uninstall <name>` | 卸载包 |
@@ -119,7 +120,7 @@ pnpm opm <command> [args] [options]
119
120
  | `opencode config` | 显示配置文件内容 |
120
121
  | `opencode dir` | 显示 data/db/log/config 路径 |
121
122
  | `opencode env` | 显示环境变量(OPENCODE_CONFIG_DIR / CONTENT) |
122
- | `opencode open [-d <dir>]` | 在指定目录启动 TUI(默认 cwd),自动注入环境变量 |
123
+ | `opencode [-d <dir>]` | 启动 TUI(默认 cwd),自动注入环境变量;可透传 args 给 opencode |
123
124
  | `opencode clear` | 清理过期会话并 VACUUM 压缩数据库(缺省 `-d 1`,只保留今天) |
124
125
  | `opencode clear -d, --days <n>` | 保留最近 n 天(对齐本地零点,含今天) |
125
126
  | `opencode clear -h, --hours <n>` | 保留最近 n 小时(滚动窗口) |
@@ -280,6 +281,7 @@ opm nvm version # 查看 nvm 版本
280
281
  opm nvm registry set gitee # 设置 nvm git 镜像为 gitee
281
282
  opm nvm install # 安装 nvm(git clone + shell profile)
282
283
  opm nvm upgrade # 更新 nvm(git pull)
284
+ opm nvm list # 列出已安装 Node.js 版本
283
285
  opm nvm view # 检查 nvm 是否已安装
284
286
  opm nvm uninstall # 卸载 nvm
285
287
  ```
@@ -308,6 +310,7 @@ opm phpenv version # 查看 phpenv 版本
308
310
  opm phpenv registry set gitee # 设置 phpenv git 镜像为 gitee
309
311
  opm phpenv install # 安装 phpenv(git clone + php-build 插件 + shell profile)
310
312
  opm phpenv upgrade # 更新 phpenv + php-build 插件
313
+ opm phpenv list # 列出已安装 PHP 版本
311
314
  opm phpenv view # 检查 phpenv 是否已安装
312
315
  opm phpenv uninstall # 卸载 phpenv
313
316
  ```
@@ -336,6 +339,7 @@ opm uv registry set <url|preset> # 设置安装脚本 URL(写 uv.registry
336
339
  opm uv registry presets # 列出可用镜像预设
337
340
  opm uv install # 安装 uv(curl 执行 active 脚本 URL)
338
341
  opm uv upgrade # 更新 uv(uv self update)
342
+ opm uv list # 列出已安装 Python 版本
339
343
  opm uv view # 检查 uv 是否已安装
340
344
  opm uv uninstall # 卸载 uv
341
345
  ```
@@ -538,8 +542,8 @@ opm opencode upgrade # 升级到最新
538
542
  opm opencode config # 显示配置文件内容
539
543
  opm opencode dir # 查看数据/日志/DB路径
540
544
  opm opencode env # 查看环境变量
541
- opm opencode open # 在当前目录启动 TUI
542
- opm opencode open -d /path/to/project # 在指定目录启动 TUI
545
+ opm opencode # 在当前目录启动 TUI
546
+ opm opencode -d /path/to/project # 在指定目录启动 TUI
543
547
  opm opencode clear # 只保留今天创建的会话
544
548
  opm opencode clear -d 7 # 保留最近 7 天会话
545
549
  opm opencode clear -h 24 # 保留最近 24 小时会话
@@ -548,6 +552,19 @@ opm opencode clear --dry-run # 仅预览
548
552
  opm opencode clear -y # 跳过确认直接执行
549
553
  ```
550
554
 
555
+ ### harness
556
+
557
+ ```bash
558
+ opm harness version # 查看已安装版本
559
+ opm harness installed # 检查是否已安装
560
+ opm harness install # 安装(使用 opm npm 镜像 + proxy)
561
+ opm harness upgrade # 升级到最新
562
+ opm harness dir # 查看安装路径 + skills/agents/commands 目录
563
+ opm harness list # 列出包提供的 skills/agents/commands
564
+ opm harness status # 健康检查(安装 + env + 内容完整性)
565
+ opm harness env # 查看环境变量(OPENCODE_CONFIG_DIR 等)
566
+ ```
567
+
551
568
  ## npm scripts
552
569
 
553
570
  | 命令 | 说明 |
@@ -14,6 +14,7 @@
14
14
  | `opm nvm upgrade` | `cd ~/.nvm && git pull --tags` | 更新 nvm |
15
15
  | `opm nvm uninstall` | `rm -rf ~/.nvm` | 卸载 nvm |
16
16
  | `opm nvm dir` | 返回 `~/.nvm` 安装目录 |
17
+ | `opm nvm list` | `nvm ls --no-colors` | 列出已安装 Node.js 版本 |
17
18
 
18
19
  ## 镜像预设
19
20
 
@@ -29,6 +30,7 @@ opm nvm version
29
30
  opm nvm registry set gitee
30
31
  opm nvm install
31
32
  opm nvm upgrade
33
+ opm nvm list
32
34
  opm nvm dir
33
35
  opm nvm uninstall
34
36
  ```
@@ -14,6 +14,7 @@
14
14
  | `opm phpenv upgrade` | `cd ~/.phpenv && git pull` + `cd plugins/php-build && git pull` | 更新 phpenv + php-build |
15
15
  | `opm phpenv uninstall` | `rm -rf ~/.phpenv` | 卸载 phpenv |
16
16
  | `opm phpenv dir` | 返回 `~/.phpenv` 安装目录 |
17
+ | `opm phpenv list` | `phpenv versions` | 列出已安装 PHP 版本 |
17
18
 
18
19
  ## 镜像预设
19
20
 
@@ -29,6 +30,7 @@ opm phpenv version
29
30
  opm phpenv registry set gitee
30
31
  opm phpenv install
31
32
  opm phpenv upgrade
33
+ opm phpenv list
32
34
  opm phpenv dir
33
35
  opm phpenv uninstall
34
36
  ```
@@ -16,6 +16,7 @@ uv 是 Astral 出品的快速 Python 包/版本管理器(Rust 实现),替
16
16
  | `opm uv upgrade` | `uv self update` | 更新 uv |
17
17
  | `opm uv uninstall` | `rm ~/.local/bin/uv` + `rm -rf ~/.local/share/uv` | 卸载 uv |
18
18
  | `opm uv dir` | 返回 uv 安装目录 |
19
+ | `opm uv list` | `uv python list --only-installed` | 列出已安装 Python 版本 |
19
20
 
20
21
  > 安装脚本 URL 通过 `uv.registry.active` 配置(`opm uv registry set <url>`);Windows 仍使用官方 `install.ps1`。
21
22
 
@@ -28,6 +29,7 @@ opm uv registry presets
28
29
  opm uv registry set official
29
30
  opm uv install
30
31
  opm uv upgrade
32
+ opm uv list
31
33
  opm uv dir
32
34
  opm uv uninstall
33
35
  ```
package/docs/opm.html CHANGED
@@ -450,7 +450,7 @@ opm npm help</code></pre></div>
450
450
  <div id="managers_nvm" class="doc-content" style="display:none;"><h1>nvm 命令对照表</h1>
451
451
  <p><code>@wwkit/opm</code> 统一命令管理 nvm 自身(安装/升级/卸载)。</p>
452
452
  <h2>命令对照</h2>
453
- <table><thead><tr><th>统一命令</th><th>原始命令</th><th>说明</th></tr></thead><tbody><tr><td><code>opm nvm version</code></td><td><code>nvm --version</code></td><td>查看 nvm 版本</td></tr><tr><td><code>opm nvm registry</code></td><td>读 <code>~/.config/opm/config.json5</code> 的 <code>nvm.registry.active</code></td><td>查询 nvm git 镜像</td></tr><tr><td><code>opm nvm registry set &lt;url|preset&gt;</code></td><td>写 <code>~/.config/opm/config.json5</code></td><td>设置 nvm git 镜像</td></tr><tr><td><code>opm nvm registry presets</code></td><td>—</td><td>列出可用镜像预设</td></tr><tr><td><code>opm nvm install</code></td><td><code>git clone &lt;mirror&gt; ~/.nvm</code> + 写 shell profile</td><td>安装 nvm</td></tr><tr><td><code>opm nvm upgrade</code></td><td><code>cd ~/.nvm &amp;&amp; git pull --tags</code></td><td>更新 nvm</td></tr><tr><td><code>opm nvm uninstall</code></td><td><code>rm -rf ~/.nvm</code></td><td>卸载 nvm</td></tr><tr><td><code>opm nvm dir</code></td><td>返回 <code>~/.nvm</code> 安装目录</td></tr></tbody></table>
453
+ <table><thead><tr><th>统一命令</th><th>原始命令</th><th>说明</th></tr></thead><tbody><tr><td><code>opm nvm version</code></td><td><code>nvm --version</code></td><td>查看 nvm 版本</td></tr><tr><td><code>opm nvm registry</code></td><td>读 <code>~/.config/opm/config.json5</code> 的 <code>nvm.registry.active</code></td><td>查询 nvm git 镜像</td></tr><tr><td><code>opm nvm registry set &lt;url|preset&gt;</code></td><td>写 <code>~/.config/opm/config.json5</code></td><td>设置 nvm git 镜像</td></tr><tr><td><code>opm nvm registry presets</code></td><td>—</td><td>列出可用镜像预设</td></tr><tr><td><code>opm nvm install</code></td><td><code>git clone &lt;mirror&gt; ~/.nvm</code> + 写 shell profile</td><td>安装 nvm</td></tr><tr><td><code>opm nvm upgrade</code></td><td><code>cd ~/.nvm &amp;&amp; git pull --tags</code></td><td>更新 nvm</td></tr><tr><td><code>opm nvm uninstall</code></td><td><code>rm -rf ~/.nvm</code></td><td>卸载 nvm</td></tr><tr><td><code>opm nvm dir</code></td><td>返回 <code>~/.nvm</code> 安装目录</td></tr><tr><td><code>opm nvm list</code></td><td><code>nvm ls --no-colors</code></td><td>列出已安装 Node.js 版本</td></tr></tbody></table>
454
454
  <h2>镜像预设</h2>
455
455
  <table><thead><tr><th>预设名</th><th>地址</th></tr></thead><tbody><tr><td><code>official</code></td><td><code>https://github.com/nvm-sh/nvm.git</code></td></tr><tr><td><code>gitee</code></td><td><code>https://gitee.com/mirrors/nvm.git</code></td></tr></tbody></table>
456
456
  <h2>示例</h2>
@@ -458,6 +458,7 @@ opm npm help</code></pre></div>
458
458
  opm nvm registry set gitee
459
459
  opm nvm install
460
460
  opm nvm upgrade
461
+ opm nvm list
461
462
  opm nvm dir
462
463
  opm nvm uninstall</code></pre></div>
463
464
  <div id="managers_php" class="doc-content" style="display:none;"><h1>php 命令对照表</h1>
@@ -482,7 +483,7 @@ opm php upgrade</code></pre></div>
482
483
  <div id="managers_phpenv" class="doc-content" style="display:none;"><h1>phpenv 命令对照表</h1>
483
484
  <p><code>@wwkit/opm</code> 统一命令管理 phpenv 自身(安装/升级/卸载)。</p>
484
485
  <h2>命令对照</h2>
485
- <table><thead><tr><th>统一命令</th><th>原始命令</th><th>说明</th></tr></thead><tbody><tr><td><code>opm phpenv version</code></td><td><code>phpenv --version</code></td><td>查看 phpenv 版本</td></tr><tr><td><code>opm phpenv registry</code></td><td>读 <code>~/.config/opm/config.json5</code> 的 <code>phpenv.registry.active</code></td><td>查询 phpenv git 镜像</td></tr><tr><td><code>opm phpenv registry set &lt;url|preset&gt;</code></td><td>写 <code>~/.config/opm/config.json5</code></td><td>设置 phpenv git 镜像</td></tr><tr><td><code>opm phpenv registry presets</code></td><td>—</td><td>列出可用镜像预设</td></tr><tr><td><code>opm phpenv install</code></td><td><code>git clone &lt;mirror&gt; ~/.phpenv</code> + <code>git clone php-build</code> + 写 shell profile</td><td>安装 phpenv + php-build 插件</td></tr><tr><td><code>opm phpenv upgrade</code></td><td><code>cd ~/.phpenv &amp;&amp; git pull</code> + <code>cd plugins/php-build &amp;&amp; git pull</code></td><td>更新 phpenv + php-build</td></tr><tr><td><code>opm phpenv uninstall</code></td><td><code>rm -rf ~/.phpenv</code></td><td>卸载 phpenv</td></tr><tr><td><code>opm phpenv dir</code></td><td>返回 <code>~/.phpenv</code> 安装目录</td></tr></tbody></table>
486
+ <table><thead><tr><th>统一命令</th><th>原始命令</th><th>说明</th></tr></thead><tbody><tr><td><code>opm phpenv version</code></td><td><code>phpenv --version</code></td><td>查看 phpenv 版本</td></tr><tr><td><code>opm phpenv registry</code></td><td>读 <code>~/.config/opm/config.json5</code> 的 <code>phpenv.registry.active</code></td><td>查询 phpenv git 镜像</td></tr><tr><td><code>opm phpenv registry set &lt;url|preset&gt;</code></td><td>写 <code>~/.config/opm/config.json5</code></td><td>设置 phpenv git 镜像</td></tr><tr><td><code>opm phpenv registry presets</code></td><td>—</td><td>列出可用镜像预设</td></tr><tr><td><code>opm phpenv install</code></td><td><code>git clone &lt;mirror&gt; ~/.phpenv</code> + <code>git clone php-build</code> + 写 shell profile</td><td>安装 phpenv + php-build 插件</td></tr><tr><td><code>opm phpenv upgrade</code></td><td><code>cd ~/.phpenv &amp;&amp; git pull</code> + <code>cd plugins/php-build &amp;&amp; git pull</code></td><td>更新 phpenv + php-build</td></tr><tr><td><code>opm phpenv uninstall</code></td><td><code>rm -rf ~/.phpenv</code></td><td>卸载 phpenv</td></tr><tr><td><code>opm phpenv dir</code></td><td>返回 <code>~/.phpenv</code> 安装目录</td></tr><tr><td><code>opm phpenv list</code></td><td><code>phpenv versions</code></td><td>列出已安装 PHP 版本</td></tr></tbody></table>
486
487
  <h2>镜像预设</h2>
487
488
  <table><thead><tr><th>预设名</th><th>地址</th></tr></thead><tbody><tr><td><code>official</code></td><td><code>https://github.com/phpenv/phpenv.git</code></td></tr><tr><td><code>gitee</code></td><td><code>https://gitee.com/mirrors/phpenv.git</code></td></tr></tbody></table>
488
489
  <h2>示例</h2>
@@ -490,6 +491,7 @@ opm php upgrade</code></pre></div>
490
491
  opm phpenv registry set gitee
491
492
  opm phpenv install
492
493
  opm phpenv upgrade
494
+ opm phpenv list
493
495
  opm phpenv dir
494
496
  opm phpenv uninstall</code></pre></div>
495
497
  <div id="managers_pip" class="doc-content" style="display:none;"><h1>pip 命令对照表</h1>
@@ -610,7 +612,7 @@ opm python upgrade</code></pre></div>
610
612
  <p><code>@wwkit/opm</code> 统一命令管理 uv 自身(安装/升级/卸载)。</p>
611
613
  <p>uv 是 Astral 出品的快速 Python 包/版本管理器(Rust 实现),替代 pyenv + pip。</p>
612
614
  <h2>命令对照</h2>
613
- <table><thead><tr><th>统一命令</th><th>原始命令</th><th>说明</th></tr></thead><tbody><tr><td><code>opm uv version</code></td><td><code>uv --version</code></td><td>查看 uv 版本</td></tr><tr><td><code>opm uv registry</code></td><td>读 <code>~/.config/opm/config.json5</code> 的 <code>uv.registry.active</code></td><td>查询激活的安装脚本 URL</td></tr><tr><td><code>opm uv registry set &lt;url|preset&gt;</code></td><td>写 <code>~/.config/opm/config.json5</code> 的 <code>uv.registry.active</code></td><td>设置激活安装脚本 URL(支持预设名)</td></tr><tr><td><code>opm uv registry presets</code></td><td>—</td><td>列出可用镜像预设</td></tr><tr><td><code>opm uv install</code></td><td><code>curl -LsSf &lt;active&gt; | sh</code></td><td>安装 uv(脚本 URL 来自 <code>uv.registry.active</code>)</td></tr><tr><td><code>opm uv upgrade</code></td><td><code>uv self update</code></td><td>更新 uv</td></tr><tr><td><code>opm uv uninstall</code></td><td><code>rm ~/.local/bin/uv</code> + <code>rm -rf ~/.local/share/uv</code></td><td>卸载 uv</td></tr><tr><td><code>opm uv dir</code></td><td>返回 uv 安装目录</td></tr></tbody></table>
615
+ <table><thead><tr><th>统一命令</th><th>原始命令</th><th>说明</th></tr></thead><tbody><tr><td><code>opm uv version</code></td><td><code>uv --version</code></td><td>查看 uv 版本</td></tr><tr><td><code>opm uv registry</code></td><td>读 <code>~/.config/opm/config.json5</code> 的 <code>uv.registry.active</code></td><td>查询激活的安装脚本 URL</td></tr><tr><td><code>opm uv registry set &lt;url|preset&gt;</code></td><td>写 <code>~/.config/opm/config.json5</code> 的 <code>uv.registry.active</code></td><td>设置激活安装脚本 URL(支持预设名)</td></tr><tr><td><code>opm uv registry presets</code></td><td>—</td><td>列出可用镜像预设</td></tr><tr><td><code>opm uv install</code></td><td><code>curl -LsSf &lt;active&gt; | sh</code></td><td>安装 uv(脚本 URL 来自 <code>uv.registry.active</code>)</td></tr><tr><td><code>opm uv upgrade</code></td><td><code>uv self update</code></td><td>更新 uv</td></tr><tr><td><code>opm uv uninstall</code></td><td><code>rm ~/.local/bin/uv</code> + <code>rm -rf ~/.local/share/uv</code></td><td>卸载 uv</td></tr><tr><td><code>opm uv dir</code></td><td>返回 uv 安装目录</td></tr><tr><td><code>opm uv list</code></td><td><code>uv python list --only-installed</code></td><td>列出已安装 Python 版本</td></tr></tbody></table>
614
616
  <blockquote>安装脚本 URL 通过 <code>uv.registry.active</code> 配置(<code>opm uv registry set &lt;url&gt;</code>);Windows 仍使用官方 <code>install.ps1</code>。</blockquote>
615
617
  <h2>示例</h2>
616
618
  <pre><code class="lang-bash">opm uv version
@@ -619,6 +621,7 @@ opm uv registry presets
619
621
  opm uv registry set official
620
622
  opm uv install
621
623
  opm uv upgrade
624
+ opm uv list
622
625
  opm uv dir
623
626
  opm uv uninstall</code></pre></div>
624
627
  <div id="packages_opencode" class="doc-content" style="display:none;"><h1>opencode 命令对照</h1>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wwkit/opm",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "author": "bluesliu <langcai163@163.com>",
5
5
  "description": "Unified CLI — package management (npm/pip/dnf/apt) + config view + opencode maintenance",
6
6
  "type": "module",
@@ -35,8 +35,7 @@
35
35
  "basic-ftp": "^6.2.1",
36
36
  "extract-zip": "^2.0.1",
37
37
  "systeminformation": "^5.23.0",
38
- "@wwkit/harness": "1.0.18",
39
- "@wwkit/shared": "1.0.12"
38
+ "@wwkit/shared": "1.0.15"
40
39
  },
41
40
  "publishConfig": {
42
41
  "registry": "https://registry.npmjs.org/",
@@ -21,6 +21,18 @@ const RUNTIMES = {
21
21
  python: () => new PythonManager(),
22
22
  }
23
23
 
24
+ /**
25
+ * 按前缀(x 或 x.y)匹配已安装版本列表,返回完整版本号
26
+ * @param {{ version: string }[]} items
27
+ * @param {string} version
28
+ * @returns {string}
29
+ */
30
+ export function resolveVersion(items, version) {
31
+ const v = version.replace(/^v/, '')
32
+ const hit = items.find((i) => i.version.replace(/^v/, '').startsWith(v))
33
+ return hit ? hit.version : ''
34
+ }
35
+
24
36
  export class EnsureGroup {
25
37
  constructor() {
26
38
  this.name = 'ensure'
@@ -47,11 +59,18 @@ export class EnsureGroup {
47
59
 
48
60
  let satisfied = false
49
61
  let currentVersion = ''
62
+ let installVersion = ''
50
63
 
51
64
  if (version) {
52
- const result = await manager.isInstalled(version)
53
- satisfied = result.installed
54
- if (satisfied) currentVersion = result.version || version
65
+ // 支持 x / x.y 简写:按前缀匹配已安装版本
66
+ const installed = await manager.listInstalled()
67
+ const full = resolveVersion(installed, version)
68
+ if (full) {
69
+ satisfied = true
70
+ currentVersion = full
71
+ } else {
72
+ installVersion = version
73
+ }
55
74
  } else {
56
75
  const result = await manager.getVersion()
57
76
  satisfied = result.installed
@@ -63,7 +82,9 @@ export class EnsureGroup {
63
82
  return
64
83
  }
65
84
 
66
- const installVersion = version || (manager.getDefaultVersion ? manager.getDefaultVersion() : '')
85
+ if (!installVersion) {
86
+ installVersion = manager.getDefaultVersion ? manager.getDefaultVersion() : ''
87
+ }
67
88
  if (!installVersion) {
68
89
  console.error(`No version specified and no defaultVersion configured for ${runtime}`)
69
90
  process.exit(1)
@@ -13,7 +13,7 @@ import os from 'node:os'
13
13
  import { ToolManagerGroup } from './version-manager.js'
14
14
  import { Shell } from '@wwkit/shared'
15
15
  import { getActiveRegistry } from '../../config.js'
16
- import { installNvm } from '../../managers/node.js'
16
+ import { installNvm, parseNvmInstalled } from '../../managers/node.js'
17
17
 
18
18
  const shell = new Shell()
19
19
 
@@ -35,6 +35,8 @@ export class NvmGroup extends ToolManagerGroup {
35
35
  getPath: () => getNvmDir(),
36
36
  versionCmd: () => `source "${path.join(getNvmDir(), 'nvm.sh')}" && nvm --version`,
37
37
  parseVersion: (out) => out.trim(),
38
+ listCmd: () => `source "${path.join(getNvmDir(), 'nvm.sh')}" && nvm ls --no-colors`,
39
+ parseList: parseNvmInstalled,
38
40
  install: (proxy) => installNvm(proxy),
39
41
  upgrade: () => {
40
42
  const nvmDir = getNvmDir()
@@ -62,6 +64,7 @@ export class NvmGroup extends ToolManagerGroup {
62
64
  ['upgrade', 'Update nvm (git pull)'],
63
65
  ['uninstall', 'Remove nvm (~/.nvm)'],
64
66
  ['dir', 'Show nvm install directory'],
67
+ ['list', 'List installed Node.js versions (nvm ls --no-colors)'],
65
68
  ['help', 'Show this help'],
66
69
  ],
67
70
  examples: [
@@ -71,6 +74,7 @@ export class NvmGroup extends ToolManagerGroup {
71
74
  'opm nvm install',
72
75
  'opm nvm upgrade',
73
76
  'opm nvm dir',
77
+ 'opm nvm list',
74
78
  ],
75
79
  })
76
80
  }
@@ -14,7 +14,7 @@ import os from 'node:os'
14
14
  import { ToolManagerGroup } from './version-manager.js'
15
15
  import { Shell } from '@wwkit/shared'
16
16
  import { getActiveRegistry } from '../../config.js'
17
- import { installPhpenv } from '../../managers/php.js'
17
+ import { installPhpenv, parsePhpenvInstalled } from '../../managers/php.js'
18
18
 
19
19
  const shell = new Shell()
20
20
 
@@ -47,6 +47,8 @@ export class PhpenvGroup extends ToolManagerGroup {
47
47
  const m = out.trim().match(/phpenv\s+([\d.]+)/)
48
48
  return m ? m[1] : out.trim()
49
49
  },
50
+ listCmd: () => `${getPhpenvBin()} versions`,
51
+ parseList: parsePhpenvInstalled,
50
52
  install: () => installPhpenv(),
51
53
  upgrade: () => {
52
54
  execSync(`cd "${getPhpenvRoot()}" && git remote set-url origin "${getActiveRegistry('phpenv')}" && git pull --tags`, {
@@ -74,6 +76,7 @@ export class PhpenvGroup extends ToolManagerGroup {
74
76
  ['upgrade', 'Update phpenv and php-build plugin (git pull)'],
75
77
  ['uninstall', 'Remove phpenv (~/.phpenv)'],
76
78
  ['dir', 'Show phpenv install directory'],
79
+ ['list', 'List installed PHP versions (phpenv versions)'],
77
80
  ['help', 'Show this help'],
78
81
  ],
79
82
  examples: [
@@ -83,6 +86,7 @@ export class PhpenvGroup extends ToolManagerGroup {
83
86
  'opm phpenv install',
84
87
  'opm phpenv upgrade',
85
88
  'opm phpenv dir',
89
+ 'opm phpenv list',
86
90
  ],
87
91
  })
88
92
  }
@@ -11,7 +11,7 @@ import fs from 'node:fs'
11
11
  import path from 'node:path'
12
12
  import os from 'node:os'
13
13
  import { ToolManagerGroup } from './version-manager.js'
14
- import { installUv, getUvBin } from '../../managers/python.js'
14
+ import { installUv, getUvBin, parseUvInstalled } from '../../managers/python.js'
15
15
 
16
16
  export class UvGroup extends ToolManagerGroup {
17
17
  constructor() {
@@ -29,6 +29,8 @@ export class UvGroup extends ToolManagerGroup {
29
29
  getPath: () => getUvBin(),
30
30
  versionCmd: () => `${getUvBin()} --version`,
31
31
  parseVersion: (out) => out.trim(),
32
+ listCmd: () => `${getUvBin()} python list --only-installed`,
33
+ parseList: parseUvInstalled,
32
34
  install: (proxy) => installUv(proxy),
33
35
  upgrade: () => {
34
36
  execSync(`${getUvBin()} self update`, { stdio: 'inherit' })
@@ -56,6 +58,7 @@ export class UvGroup extends ToolManagerGroup {
56
58
  ['upgrade', 'Update uv (uv self update)'],
57
59
  ['uninstall', 'Remove uv (~/.local/bin/uv + ~/.local/share/uv)'],
58
60
  ['dir', 'Show uv install directory'],
61
+ ['list', 'List installed Python versions (uv python list --only-installed)'],
59
62
  ['help', 'Show this help'],
60
63
  ],
61
64
  examples: [
@@ -67,6 +70,7 @@ export class UvGroup extends ToolManagerGroup {
67
70
  'opm uv install',
68
71
  'opm uv upgrade',
69
72
  'opm uv dir',
73
+ 'opm uv list',
70
74
  'opm uv uninstall',
71
75
  ],
72
76
  })
@@ -25,6 +25,8 @@ const shell = new Shell()
25
25
  * @property {() => string} getPath - view 展示的安装路径
26
26
  * @property {() => string} versionCmd - 返回查询版本的 shell 命令
27
27
  * @property {(out: string) => string} [parseVersion] - 解析版本输出
28
+ * @property {() => string} [listCmd] - 返回列出已安装版本的 shell 命令(缺省则 list 输出空列表)
29
+ * @property {(out: string) => { name: string, version: string, current: boolean }[]} [parseList] - 解析 list 输出
28
30
  * @property {(proxy?: string) => Object} install - 安装并返回结果字段(失败时 throw)
29
31
  * @property {() => Object} upgrade - 升级并返回结果字段(失败时 throw)
30
32
  * @property {() => Object} uninstall - 卸载并返回结果字段(失败时 throw)
@@ -81,6 +83,8 @@ export class ToolManagerGroup {
81
83
  return this._uninstall(parsed)
82
84
  case 'dir':
83
85
  return this._dir()
86
+ case 'list':
87
+ return this._list()
84
88
  default:
85
89
  console.error(`Unknown action: ${action}`)
86
90
  this.printHelp()
@@ -193,6 +197,29 @@ const out = execSync(this.cfg.versionCmd(), { encoding: 'utf8', shell: shell.she
193
197
  output(result)
194
198
  }
195
199
 
200
+ /**
201
+ * 列出工具已安装的版本
202
+ * @returns {void}
203
+ * @private
204
+ */
205
+ _list() {
206
+ if (!this.cfg.isInstalled()) {
207
+ output({ name: this.name, installed: false, hint: `Run \`opm ${this.name} install\` first` })
208
+ return
209
+ }
210
+ if (!this.cfg.listCmd) {
211
+ output({ name: this.name, count: 0, versions: [] })
212
+ return
213
+ }
214
+ try {
215
+ const out = execSync(this.cfg.listCmd(), { encoding: 'utf8', shell: shell.shellForExec(this.cfg.needsBash) })
216
+ const versions = this.cfg.parseList ? this.cfg.parseList(out) : []
217
+ output({ name: this.name, count: versions.length, versions })
218
+ } catch {
219
+ output({ name: this.name, count: 0, versions: [] })
220
+ }
221
+ }
222
+
196
223
  printHelp() {
197
224
  const actionLines = this.cfg.actions.map(([sig, desc]) => ` ${sig.padEnd(34)} ${desc}`).join('\n')
198
225
  const exampleLines = this.cfg.examples.map((e) => ` ${e}`).join('\n')
package/src/cli/index.js CHANGED
@@ -27,6 +27,7 @@ import { ShareGroup } from '../tools/share/index.js'
27
27
  import { WebworkGroup } from '../tools/webwork/index.js'
28
28
  import { HarnessGroup } from '../harnesses/base.js'
29
29
  import { opencodeHarness } from '../harnesses/opencode/index.js'
30
+ import { harnessCfg } from '../harnesses/harness/index.js'
30
31
  import { CftGroup } from '../binaries/cft/index.js'
31
32
  import { generateDocHtml } from './doc.js'
32
33
 
@@ -59,6 +60,7 @@ const GROUPS = {
59
60
  uv: new UvGroup(),
60
61
  config: new ConfigGroup(),
61
62
  opencode: new HarnessGroup(opencodeHarness),
63
+ harness: new HarnessGroup(harnessCfg),
62
64
  cft: new CftGroup(),
63
65
  ensure: new EnsureGroup(),
64
66
  ping: new PingGroup(),
@@ -75,12 +77,23 @@ class CLI {
75
77
  return
76
78
  }
77
79
 
78
- if (groupName === 'version' || groupName === '-v' || groupName === '--version') {
80
+ if (groupName === 'version' || groupName === '-v' || groupName === '--version') {
79
81
  const pkg = JSON.parse(readFileSync(new URL('../../package.json', import.meta.url), 'utf8'))
80
82
  console.log(pkg.version)
81
83
  return
82
84
  }
83
85
 
86
+ if (groupName === 'upgrade') {
87
+ const { NpmManager } = await import('../managers/npm.js')
88
+ const { getActiveProxy } = await import('../config.js')
89
+ const npm = new NpmManager()
90
+ const proxy = getActiveProxy()
91
+ await npm.upgrade('@wwkit/harness', { global: true, proxy })
92
+ const result = await npm.upgrade('@wwkit/opm', { global: true, proxy })
93
+ console.log(`opm upgraded to ${result.version || 'latest'}`)
94
+ return
95
+ }
96
+
84
97
  if (groupName === 'doc') {
85
98
  generateDocHtml()
86
99
  return
@@ -112,6 +125,7 @@ Usage: opm <command> [args] [options]
112
125
  Commands:
113
126
  ${groupLines}
114
127
  version Show opm version
128
+ upgrade Upgrade opm itself (npm install -g @wwkit/opm@latest)
115
129
  doc Build docs HTML and open in browser
116
130
 
117
131
  Options: