rainskills 0.1.2 → 0.1.4

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
@@ -72,7 +72,7 @@ Rainskills 安装完成,下一条消息即可直接使用。
72
72
  固定 launcher 来自当前 `package.json` 版本:
73
73
 
74
74
  ```json
75
- ["npx", "--yes", "rainskills@0.1.2"]
75
+ ["npx", "--yes", "rainskills@0.1.4"]
76
76
  ```
77
77
 
78
78
  所有调用都把 launcher 与参数合并成 argv 数组后直接执行;不得使用 `rainskills@latest`,不得把参数拼成 shell 字符串。
@@ -192,21 +192,21 @@ Windows 本地安装是预览能力,也可以改选 Linux 服务器。它要
192
192
 
193
193
  ```bash
194
194
  # 本地单机
195
- npx --yes rainskills@0.1.2 platform install --onboarding-id <id> \
195
+ npx --yes rainskills@0.1.4 platform install --onboarding-id <id> \
196
196
  --location local --mode single-node
197
197
 
198
198
  # Linux 服务器单机
199
- npx --yes rainskills@0.1.2 platform install --onboarding-id <id> \
199
+ npx --yes rainskills@0.1.4 platform install --onboarding-id <id> \
200
200
  --location server --mode single-node --ssh <user@host>
201
201
 
202
202
  # 服务器主机集群(自动生成受保护示例文件)
203
- npx --yes rainskills@0.1.2 platform install --onboarding-id <id> \
203
+ npx --yes rainskills@0.1.4 platform install --onboarding-id <id> \
204
204
  --location server --mode host-cluster
205
205
 
206
206
  # 已有高级 ROI cluster.yaml 才追加:--cluster-config <path>
207
207
 
208
208
  # 已有 Kubernetes
209
- npx --yes rainskills@0.1.2 platform install --onboarding-id <id> \
209
+ npx --yes rainskills@0.1.4 platform install --onboarding-id <id> \
210
210
  --location server --mode existing-kubernetes \
211
211
  --kubeconfig <path> --kube-context <name> --chart-version <version>
212
212
  ```
@@ -226,13 +226,13 @@ npx --yes rainskills@0.1.2 platform install --onboarding-id <id> \
226
226
 
227
227
  ## 更新
228
228
 
229
- Rainskills 会在用户下一次发起业务动作时静默检查更新,且只跟随 npm `latest` 指向的正式版。当前版本是 RC 或其他预发布版本时不会查询、不会自动升级;npm 上的新 RC 版本也不参与正式版自动升级。
229
+ Rainskills 会在用户下一次发起业务动作时,由本地运行时立即返回环境查询结果,并另行启动后台任务静默检查更新。更新只跟随 npm `latest` 指向的正式版。当前版本是 RC 或其他预发布版本时不会查询、不会自动升级;npm 上的新 RC 版本也不参与正式版自动升级。
230
230
 
231
- 发现更高的正式版后,当前 launcher 只委托到经过校验的精确版本,例如 `rainskills@1.2.3`,不会执行浮动的 `@latest` 业务代码。新版本先原子刷新已经安装的 Rainskills Skills,再继续原业务操作。版本检查失败、安装位置不安全或文件迁移失败时会保留旧版本继续,不要求用户处理。
231
+ 发现更高的正式版后,后台任务只委托到经过校验的精确版本,例如 `rainskills@1.2.3`,不会执行浮动的 `@latest` 业务代码。新版本原子刷新已经安装的 Rainskills Skills;当前业务继续使用启动时已经加载的版本,最迟从下一条新任务开始使用新版。npm 超时、版本检查失败、安装位置不安全或文件迁移失败时会保留旧版本,且不会阻塞或改变当前操作。
232
232
 
233
233
  升级只更新 Rainskills 自身,不触发 Rainbond 安装、运行环境选择、登录授权、MCP 配置或重新对接。原始业务操作会继续执行;只有该业务操作本身需要运行环境时,才按既有门禁检查当前连接。可用连接直接复用,401 只重新授权一次,403 立即停止,从未连接过运行环境时才进入环境选择。
234
234
 
235
- 正在执行或等待恢复的部署、私有平台安装和授权流程继续使用启动时锁定的旧版本,自动升级不会插入这些流程。操作结束后的下一次普通业务请求才会再次检查正式版。
235
+ 正在执行的部署、私有平台安装和授权流程继续使用启动时锁定的旧版本,自动升级不会插入这些流程。操作完成后会再次静默调度更新检查;检查进程有固定超时且不向用户输出远程 npx 命令。
236
236
 
237
237
  如需手工恢复安装,可执行 `npx --yes rainskills@latest --force`;正常使用不需要主动运行更新命令。
238
238
 
package/SKILL.md CHANGED
@@ -38,7 +38,7 @@ Rainskills 安装完成,下一条消息即可直接使用。
38
38
 
39
39
  ## Manage Runtime Environments
40
40
 
41
- 环境是全局列表,不是项目绑定。本地状态命令必须定位已安装的同级 `rainbond-platform-installer/scripts/local-runtime.js`,解析为绝对路径后通过 `node` 以 argv 数组执行;不得为了查询本地环境访问 npm。只有连接或安装环境时才使用与当前技能包一致的固定 launcher `npx --yes rainskills@0.1.2`。
41
+ 环境是全局列表,不是项目绑定。本地状态命令必须定位已安装的同级 `rainbond-platform-installer/scripts/local-runtime.js`,解析为绝对路径后通过 `node` 以 argv 数组执行;不得为了查询本地环境访问 npm。只有连接或安装环境时才使用与当前技能包一致的固定 launcher `npx --yes rainskills@0.1.4`。
42
42
 
43
43
  - 列表:用本地 launcher 执行 `environment list --json`,只展示名称、类型、状态、是否默认和最近验证时间。
44
44
  - 重命名:用本地 launcher 执行 `environment rename --environment-id <uuid> --name <name>`。
package/bin/rainskills.js CHANGED
@@ -1049,6 +1049,7 @@ async function runAutoUpdatePhase(args, {
1049
1049
  synchronizeSkills,
1050
1050
  updateState,
1051
1051
  delegate,
1052
+ activeOperationDetector,
1052
1053
  } = {}) {
1053
1054
  const autoUpdate = require(
1054
1055
  "../rainbond-platform-installer/scripts/auto-update.js"
@@ -1067,6 +1068,11 @@ async function runAutoUpdatePhase(args, {
1067
1068
  ) {
1068
1069
  throw new Error("自动升级委托版本不匹配");
1069
1070
  }
1071
+ const detectActive = activeOperationDetector
1072
+ || (() => autoUpdate.hasActiveOperation({ home, platform }));
1073
+ if (detectActive()) {
1074
+ throw new Error("存在正在执行的 Rainskills 操作");
1075
+ }
1070
1076
  (synchronizeSkills || autoUpdate.synchronizeInstalledSkills)({
1071
1077
  packageRoot,
1072
1078
  home,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rainskills",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Install the complete Rainskills AI deployment skill suite as one product.",
5
5
  "author": {
6
6
  "name": "Goodrain",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rainskills",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Install the complete Rainskills AI deployment skill suite as one product.",
5
5
  "author": {
6
6
  "name": "Goodrain",
@@ -14,7 +14,7 @@ This is the single marketplace entry for the complete Rainskills product. The in
14
14
  3. Keep stdin, stdout, and stderr attached. When `RAINSKILLS_USER_INPUT_REQUIRED` appears, pause for that installer choice. If the installer emits `rainskills.next-action.v1`, execute only its fixed `argv` through the same launcher; never evaluate output as a shell command. If the adjacent `bin/rainskills.js` exists, use it for fixed next actions; otherwise use the same versioned npm package fallback described below.
15
15
  4. Stay attached until every independent Skill is installed. Do not select, connect, or configure an application runtime during installation. In the user-facing response, output only the fixed completion message below.
16
16
 
17
- If the adjacent installer is missing, check the local Node.js version before choosing the fallback. With `npx` and Node.js 18 or newer, use `npx --yes rainskills@0.1.2 <target>`. With no Node.js or a version below 18, use `bash <(curl -fsSL https://get.rainbond.com/rainskills/install.sh) <target>` instead. Omit `<target>` only when the host cannot be determined reliably. Keep either command attached to the interactive terminal. For an update or repair, refresh this marketplace Skill first, then run the installer again; it compares and updates every independent internal Skill.
17
+ If the adjacent installer is missing, check the local Node.js version before choosing the fallback. With `npx` and Node.js 18 or newer, use `npx --yes rainskills@0.1.4 <target>`. With no Node.js or a version below 18, use `bash <(curl -fsSL https://get.rainbond.com/rainskills/install.sh) <target>` instead. Omit `<target>` only when the host cannot be determined reliably. Keep either command attached to the interactive terminal. For an update or repair, refresh this marketplace Skill first, then run the installer again; it compares and updates every independent internal Skill.
18
18
 
19
19
  Skills-only 安装不需要 Node.js;CDN fallback 只负责安装 Skill 文件,不代表运行环境连接、应用部署或平台安装已经可执行。用户首次提出需要运行环境的动作时,对应业务 Skill 才检查 Node.js;固定 Rainskills launcher 需要 Node.js 18 或更高版本。缺失或版本过低时保留原始 intent 并停止,等待用户或 agent 明确同意安装或升级 Node.js,安装完成消息不得提前提示 Node.js。
20
20
 
@@ -38,7 +38,7 @@ Rainskills 安装完成,下一条消息即可直接使用。
38
38
 
39
39
  ## Manage Runtime Environments
40
40
 
41
- 环境是全局列表,不是项目绑定。本地状态命令必须定位已安装的同级 `rainbond-platform-installer/scripts/local-runtime.js`,解析为绝对路径后通过 `node` 以 argv 数组执行;不得为了查询本地环境访问 npm。只有连接或安装环境时才使用与当前技能包一致的固定 launcher `npx --yes rainskills@0.1.2`。
41
+ 环境是全局列表,不是项目绑定。本地状态命令必须定位已安装的同级 `rainbond-platform-installer/scripts/local-runtime.js`,解析为绝对路径后通过 `node` 以 argv 数组执行;不得为了查询本地环境访问 npm。只有连接或安装环境时才使用与当前技能包一致的固定 launcher `npx --yes rainskills@0.1.4`。
42
42
 
43
43
  - 列表:用本地 launcher 执行 `environment list --json`,只展示名称、类型、状态、是否默认和最近验证时间。
44
44
  - 重命名:用本地 launcher 执行 `environment rename --environment-id <uuid> --name <name>`。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rainskills",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Interactive Rainbond skill installer for Codex and Claude Code",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/goodrain/rainskills#readme",
@@ -15500,7 +15500,7 @@ function serializeMessage(message) {
15500
15500
  // package.json
15501
15501
  var package_default = {
15502
15502
  name: "rainskills",
15503
- version: "0.1.2",
15503
+ version: "0.1.4",
15504
15504
  description: "Interactive Rainbond skill installer for Codex and Claude Code",
15505
15505
  license: "Apache-2.0",
15506
15506
  homepage: "https://github.com/goodrain/rainskills#readme",
@@ -98,7 +98,7 @@ description: "Use whenever a user asks to deploy, run, deliver, publish, inspect
98
98
 
99
99
  第一步检查 Node.js 是否存在且主版本不低于 18。Node.js 缺失或低于 18 时,只说明“Rainskills 执行组件需要 Node.js 18 或更高版本”并停止:不选择运行环境,不调用 MCP,不猜测替代命令。只有用户或 agent 明确同意后才安装或升级 Node.js,再从同一原始 intent 继续。
100
100
 
101
- 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.2"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止使用 `rainskills@latest`,禁止拼接或执行 shell 字符串。
101
+ 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.4"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止使用 `rainskills@latest`,禁止拼接或执行 shell 字符串。
102
102
 
103
103
  本地 launcher 必须从当前 Skill 所在目录的同级目录定位 `rainbond-platform-installer/scripts/local-runtime.js`,解析为绝对路径后使用 `["node", "<绝对路径>"]` 执行。`environment list`、`operation begin`、`operation complete` 和 `runtime message` 只能使用本地 launcher;本地 launcher 只读取已安装文件和本机受保护状态,不得访问 npm 或其它网络。只有用户选定连接或安装运行环境后,才使用上面的固定 npx launcher。
104
104
 
@@ -106,7 +106,7 @@ description: "Use whenever a user asks to deploy, run, deliver, publish, inspect
106
106
  ```json
107
107
  {
108
108
  "schema": "rainskills.skill-runtime-contract.v1",
109
- "launcher": ["npx", "--yes", "rainskills@0.1.2"],
109
+ "launcher": ["npx", "--yes", "rainskills@0.1.4"],
110
110
  "local_launcher": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js"],
111
111
  "local_argv": {
112
112
  "environment-list": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js", "environment", "list", "--json"],
@@ -126,9 +126,9 @@ description: "Use whenever a user asks to deploy, run, deliver, publish, inspect
126
126
  "existing": ["saas", "private-existing"]
127
127
  },
128
128
  "connect_argv": {
129
- "saas": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
130
- "private-existing": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"],
131
- "install-private": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--install-private", "--location", "<private-location>", "--intent-json", "<intent-json>"]
129
+ "saas": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
130
+ "private-existing": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"],
131
+ "install-private": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--install-private", "--location", "<private-location>", "--intent-json", "<intent-json>"]
132
132
  }
133
133
  }
134
134
  ```
@@ -14,7 +14,7 @@ description: "Use when a user explicitly asks for an existing Rainbond app versi
14
14
 
15
15
  第一步检查 Node.js 是否存在且主版本不低于 18。Node.js 缺失或低于 18 时,只说明“Rainskills 执行组件需要 Node.js 18 或更高版本”并停止:不选择运行环境,不调用 MCP,不猜测替代命令。只有用户或 agent 明确同意后才安装或升级 Node.js,再从同一原始 intent 继续。
16
16
 
17
- 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.2"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
17
+ 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.4"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
18
18
 
19
19
  本地 launcher 必须从当前 Skill 所在目录的同级目录定位 `rainbond-platform-installer/scripts/local-runtime.js`,解析为绝对路径后使用 `["node", "<绝对路径>"]` 执行。`environment list`、`operation begin`、`operation complete` 和 `runtime message` 只能使用本地 launcher;本地 launcher 只读取已安装文件和本机受保护状态,不得访问 npm 或其它网络。只有用户选定连接运行环境后,才使用上面的固定 npx launcher。
20
20
 
@@ -22,7 +22,7 @@ description: "Use when a user explicitly asks for an existing Rainbond app versi
22
22
  ```json
23
23
  {
24
24
  "schema": "rainskills.skill-runtime-contract.v1",
25
- "launcher": ["npx", "--yes", "rainskills@0.1.2"],
25
+ "launcher": ["npx", "--yes", "rainskills@0.1.4"],
26
26
  "local_launcher": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js"],
27
27
  "local_argv": {
28
28
  "environment-list": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js", "environment", "list", "--json"],
@@ -37,8 +37,8 @@ description: "Use when a user explicitly asks for an existing Rainbond app versi
37
37
  },
38
38
  "routes": {"existing": ["saas", "private-existing"]},
39
39
  "connect_argv": {
40
- "saas": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
41
- "private-existing": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"]
40
+ "saas": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
41
+ "private-existing": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"]
42
42
  }
43
43
  }
44
44
  ```
@@ -46,7 +46,7 @@ description: "Use only when the user explicitly asks for final delivery or acces
46
46
 
47
47
  第一步检查 Node.js 是否存在且主版本不低于 18。Node.js 缺失或低于 18 时,只说明“Rainskills 执行组件需要 Node.js 18 或更高版本”并停止:不选择运行环境,不调用 MCP,不猜测替代命令。只有用户或 agent 明确同意后才安装或升级 Node.js,再从同一原始 intent 继续。
48
48
 
49
- 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.2"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
49
+ 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.4"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
50
50
 
51
51
  本地 launcher 必须从当前 Skill 所在目录的同级目录定位 `rainbond-platform-installer/scripts/local-runtime.js`,解析为绝对路径后使用 `["node", "<绝对路径>"]` 执行。`environment list`、`operation begin`、`operation complete` 和 `runtime message` 只能使用本地 launcher;本地 launcher 只读取已安装文件和本机受保护状态,不得访问 npm 或其它网络。只有用户选定连接运行环境后,才使用上面的固定 npx launcher。
52
52
 
@@ -54,7 +54,7 @@ description: "Use only when the user explicitly asks for final delivery or acces
54
54
  ```json
55
55
  {
56
56
  "schema": "rainskills.skill-runtime-contract.v1",
57
- "launcher": ["npx", "--yes", "rainskills@0.1.2"],
57
+ "launcher": ["npx", "--yes", "rainskills@0.1.4"],
58
58
  "local_launcher": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js"],
59
59
  "local_argv": {
60
60
  "environment-list": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js", "environment", "list", "--json"],
@@ -67,8 +67,8 @@ description: "Use only when the user explicitly asks for final delivery or acces
67
67
  },
68
68
  "routes": {"existing": ["saas", "private-existing"]},
69
69
  "connect_argv": {
70
- "saas": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
71
- "private-existing": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"]
70
+ "saas": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
71
+ "private-existing": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"]
72
72
  }
73
73
  }
74
74
  ```
@@ -14,7 +14,7 @@ description: "Use when a user explicitly asks to sync non-sensitive preview or p
14
14
 
15
15
  第一步检查 Node.js 是否存在且主版本不低于 18。Node.js 缺失或低于 18 时,只说明“Rainskills 执行组件需要 Node.js 18 或更高版本”并停止:不选择运行环境,不调用 MCP,不猜测替代命令。只有用户或 agent 明确同意后才安装或升级 Node.js,再从同一原始 intent 继续。
16
16
 
17
- 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.2"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
17
+ 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.4"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
18
18
 
19
19
  本地 launcher 必须从当前 Skill 所在目录的同级目录定位 `rainbond-platform-installer/scripts/local-runtime.js`,解析为绝对路径后使用 `["node", "<绝对路径>"]` 执行。`environment list`、`operation begin`、`operation complete` 和 `runtime message` 只能使用本地 launcher;本地 launcher 只读取已安装文件和本机受保护状态,不得访问 npm 或其它网络。只有用户选定连接运行环境后,才使用上面的固定 npx launcher。
20
20
 
@@ -22,7 +22,7 @@ description: "Use when a user explicitly asks to sync non-sensitive preview or p
22
22
  ```json
23
23
  {
24
24
  "schema": "rainskills.skill-runtime-contract.v1",
25
- "launcher": ["npx", "--yes", "rainskills@0.1.2"],
25
+ "launcher": ["npx", "--yes", "rainskills@0.1.4"],
26
26
  "local_launcher": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js"],
27
27
  "local_argv": {
28
28
  "environment-list": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js", "environment", "list", "--json"],
@@ -35,8 +35,8 @@ description: "Use when a user explicitly asks to sync non-sensitive preview or p
35
35
  },
36
36
  "routes": {"existing": ["saas", "private-existing"]},
37
37
  "connect_argv": {
38
- "saas": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
39
- "private-existing": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"]
38
+ "saas": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
39
+ "private-existing": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"]
40
40
  }
41
41
  }
42
42
  ```
@@ -14,7 +14,7 @@ description: "Use only when the user explicitly asks to create the Rainbond app
14
14
 
15
15
  第一步检查 Node.js 是否存在且主版本不低于 18。Node.js 缺失或低于 18 时,只说明“Rainskills 执行组件需要 Node.js 18 或更高版本”并停止:不选择运行环境,不调用 MCP,不猜测替代命令。只有用户或 agent 明确同意后才安装或升级 Node.js,再从同一原始 intent 继续。
16
16
 
17
- 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.2"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
17
+ 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.4"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
18
18
 
19
19
  本地 launcher 必须从当前 Skill 所在目录的同级目录定位 `rainbond-platform-installer/scripts/local-runtime.js`,解析为绝对路径后使用 `["node", "<绝对路径>"]` 执行。`environment list`、`operation begin`、`operation complete` 和 `runtime message` 只能使用本地 launcher;本地 launcher 只读取已安装文件和本机受保护状态,不得访问 npm 或其它网络。只有用户选定连接或安装运行环境后,才使用上面的固定 npx launcher。
20
20
 
@@ -22,7 +22,7 @@ description: "Use only when the user explicitly asks to create the Rainbond app
22
22
  ```json
23
23
  {
24
24
  "schema": "rainskills.skill-runtime-contract.v1",
25
- "launcher": ["npx", "--yes", "rainskills@0.1.2"],
25
+ "launcher": ["npx", "--yes", "rainskills@0.1.4"],
26
26
  "local_launcher": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js"],
27
27
  "local_argv": {
28
28
  "environment-list": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js", "environment", "list", "--json"],
@@ -42,9 +42,9 @@ description: "Use only when the user explicitly asks to create the Rainbond app
42
42
  "existing": ["saas", "private-existing"]
43
43
  },
44
44
  "connect_argv": {
45
- "saas": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
46
- "private-existing": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"],
47
- "install-private": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--install-private", "--location", "<private-location>", "--intent-json", "<intent-json>"]
45
+ "saas": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
46
+ "private-existing": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"],
47
+ "install-private": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--install-private", "--location", "<private-location>", "--intent-json", "<intent-json>"]
48
48
  }
49
49
  }
50
50
  ```
@@ -46,7 +46,7 @@ description: "Use only when the user explicitly asks for a bounded build, runtim
46
46
 
47
47
  第一步检查 Node.js 是否存在且主版本不低于 18。Node.js 缺失或低于 18 时,只说明“Rainskills 执行组件需要 Node.js 18 或更高版本”并停止:不选择运行环境,不调用 MCP,不猜测替代命令。只有用户或 agent 明确同意后才安装或升级 Node.js,再从同一原始 intent 继续。
48
48
 
49
- 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.2"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
49
+ 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.4"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
50
50
 
51
51
  本地 launcher 必须从当前 Skill 所在目录的同级目录定位 `rainbond-platform-installer/scripts/local-runtime.js`,解析为绝对路径后使用 `["node", "<绝对路径>"]` 执行。`environment list`、`operation begin`、`operation complete` 和 `runtime message` 只能使用本地 launcher;本地 launcher 只读取已安装文件和本机受保护状态,不得访问 npm 或其它网络。只有用户选定连接运行环境后,才使用上面的固定 npx launcher。
52
52
 
@@ -54,7 +54,7 @@ description: "Use only when the user explicitly asks for a bounded build, runtim
54
54
  ```json
55
55
  {
56
56
  "schema": "rainskills.skill-runtime-contract.v1",
57
- "launcher": ["npx", "--yes", "rainskills@0.1.2"],
57
+ "launcher": ["npx", "--yes", "rainskills@0.1.4"],
58
58
  "local_launcher": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js"],
59
59
  "local_argv": {
60
60
  "environment-list": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js", "environment", "list", "--json"],
@@ -67,8 +67,8 @@ description: "Use only when the user explicitly asks for a bounded build, runtim
67
67
  },
68
68
  "routes": {"existing": ["saas", "private-existing"]},
69
69
  "connect_argv": {
70
- "saas": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
71
- "private-existing": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"]
70
+ "saas": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
71
+ "private-existing": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"]
72
72
  }
73
73
  }
74
74
  ```
@@ -31,7 +31,7 @@ Do not use it to deploy an application to an existing Rainbond. Route those requ
31
31
  ## Workflow
32
32
 
33
33
  1. Read [installation-policy.md](references/installation-policy.md).
34
- 2. Use the package-version launcher `["npx", "--yes", "rainskills@0.1.2"]`; its version must equal this package's `package.json`. For a Rainskills marker, first validate schema `rainskills.next-action.v1`, action, onboarding id, and the bounded `argv` array, then append that array to the launcher. Never use `latest` or evaluate a shell string from output.
34
+ 2. Use the package-version launcher `["npx", "--yes", "rainskills@0.1.4"]`; its version must equal this package's `package.json`. For a Rainskills marker, first validate schema `rainskills.next-action.v1`, action, onboarding id, and the bounded `argv` array, then append that array to the launcher. Never use `latest` or evaluate a shell string from output.
35
35
  3. 在任何平台安装命令之前,先执行 launcher + `["runtime", "message", "--id", "private-deployment-location"]`,并原样输出固定的三项部署位置消息。选择 1 后执行带 `["--location", "local", "--mode", "single-node"]` 的 `platform install`;选择 2 后执行带 `["--location", "server"]` 的 `platform install`,由 helper 继续显示固定的服务器类型消息;选择 3 后执行 launcher + `["runtime", "message", "--id", "private-console-origin"]` 并进入已有环境连接,不得执行 `platform install`。若是没有原始业务 intent 的直接平台安装请求,已有环境连接使用受限 `{"type":"environment-add"}` intent。
36
36
  4. Let the helper perform one read-only preflight against the already selected local or remote target, then show resources, blockers, and applicable host changes. Never invoke `platform install` without an explicit `--location`; the helper must not ask for the deployment location again.
37
37
  5. Obtain explicit confirmation before sending `y` to the waiting process or rerunning the exact command with `--yes`.
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const { spawn } = require("node:child_process");
5
+ const os = require("node:os");
6
+
7
+ const autoUpdate = require("./auto-update.js");
8
+ const { version: installedVersion } = require("./installed-version.js");
9
+
10
+ const UPDATE_ENTRY = Object.freeze(["runtime", "status", "--json"]);
11
+ const DEFAULT_DELEGATE_TIMEOUT_MS = 30_000;
12
+ const SAFE_ENVIRONMENT_KEYS = Object.freeze([
13
+ "HOME", "USERPROFILE", "PATH", "Path", "SystemRoot", "ComSpec",
14
+ "TMPDIR", "TMP", "TEMP", "LANG", "LC_ALL", "HTTP_PROXY",
15
+ "HTTPS_PROXY", "NO_PROXY", "http_proxy", "https_proxy", "no_proxy",
16
+ ]);
17
+
18
+ function backgroundUpdateEnvironment(source = process.env) {
19
+ const result = {};
20
+ for (const key of SAFE_ENVIRONMENT_KEYS) {
21
+ if (typeof source[key] === "string") result[key] = source[key];
22
+ }
23
+ return result;
24
+ }
25
+
26
+ function terminateChild(child, platform, signal = "SIGTERM") {
27
+ try {
28
+ if (platform !== "win32" && Number.isInteger(child.pid)) {
29
+ process.kill(-child.pid, signal);
30
+ } else {
31
+ child.kill(signal);
32
+ }
33
+ } catch {
34
+ try { child.kill(signal); } catch { /* already stopped */ }
35
+ }
36
+ }
37
+
38
+ function runBoundedChild(invocation, environment, {
39
+ platform = process.platform,
40
+ timeoutMs = DEFAULT_DELEGATE_TIMEOUT_MS,
41
+ spawnFn = spawn,
42
+ } = {}) {
43
+ return new Promise((resolve) => {
44
+ let settled = false;
45
+ let timedOut = false;
46
+ let forceTimer = null;
47
+ const finish = (result) => {
48
+ if (settled) return;
49
+ settled = true;
50
+ clearTimeout(timer);
51
+ if (forceTimer) clearTimeout(forceTimer);
52
+ resolve(result);
53
+ };
54
+ let child;
55
+ try {
56
+ child = spawnFn(invocation.executable, invocation.args, {
57
+ detached: platform !== "win32",
58
+ env: environment,
59
+ shell: false,
60
+ stdio: "ignore",
61
+ windowsHide: true,
62
+ });
63
+ } catch {
64
+ resolve({ code: 1, signal: null });
65
+ return;
66
+ }
67
+ const timer = setTimeout(() => {
68
+ timedOut = true;
69
+ terminateChild(child, platform);
70
+ forceTimer = setTimeout(() => {
71
+ terminateChild(child, platform, "SIGKILL");
72
+ finish({ code: 1, signal: "TIMEOUT" });
73
+ }, 1000);
74
+ }, timeoutMs);
75
+ child.once("error", () => finish({ code: 1, signal: null }));
76
+ child.once("close", (code, signal) => finish({
77
+ code: timedOut ? 1 : (code ?? 1),
78
+ signal: timedOut ? "TIMEOUT" : (signal || null),
79
+ }));
80
+ });
81
+ }
82
+
83
+ async function runBackgroundAutoUpdate({
84
+ currentVersion = installedVersion,
85
+ env = backgroundUpdateEnvironment(),
86
+ home = os.homedir(),
87
+ platform = process.platform,
88
+ updateState = autoUpdate.createAutoUpdateState({ home, platform }),
89
+ checkForUpdate = autoUpdate.checkForStableUpdate,
90
+ activeOperationDetector = () => autoUpdate.hasActiveOperation({ home, platform }),
91
+ runDelegated = (invocation, environment) => runBoundedChild(
92
+ invocation,
93
+ environment,
94
+ { platform }
95
+ ),
96
+ } = {}) {
97
+ let lease;
98
+ try {
99
+ lease = updateState.acquireLease?.() || null;
100
+ } catch {
101
+ return { action: "continue", reason: "update-busy" };
102
+ }
103
+ try {
104
+ const decision = await checkForUpdate({
105
+ args: UPDATE_ENTRY,
106
+ currentVersion,
107
+ env,
108
+ home,
109
+ platform,
110
+ activeOperationDetector,
111
+ updateState,
112
+ });
113
+ if (decision.action !== "delegate") return decision;
114
+ if (activeOperationDetector()) {
115
+ return { action: "continue", reason: "active-operation" };
116
+ }
117
+ const invocation = autoUpdate.buildStableUpdateInvocation(
118
+ decision.version,
119
+ UPDATE_ENTRY,
120
+ { platform }
121
+ );
122
+ const environment = autoUpdate.buildStableUpdateEnvironment(env, {
123
+ fromVersion: currentVersion,
124
+ targetVersion: decision.version,
125
+ });
126
+ const result = await runDelegated(invocation, environment);
127
+ if (result.code !== 0 || result.signal) {
128
+ try { updateState.recordFailure?.(); } catch { /* best effort */ }
129
+ return { action: "continue", reason: "delegated-update-failed" };
130
+ }
131
+ return { action: "continue", reason: "updated" };
132
+ } catch {
133
+ try { updateState.recordFailure?.(); } catch { /* best effort */ }
134
+ return { action: "continue", reason: "update-failed" };
135
+ } finally {
136
+ lease?.release();
137
+ }
138
+ }
139
+
140
+ async function main() {
141
+ await runBackgroundAutoUpdate();
142
+ }
143
+
144
+ if (require.main === module) {
145
+ main().catch(() => {
146
+ process.exitCode = 0;
147
+ });
148
+ }
149
+
150
+ module.exports = {
151
+ backgroundUpdateEnvironment,
152
+ main,
153
+ runBackgroundAutoUpdate,
154
+ runBoundedChild,
155
+ };
@@ -75,13 +75,18 @@ function fetchOfficialLatest({
75
75
  } = {}) {
76
76
  return new Promise((resolve, reject) => {
77
77
  let settled = false;
78
+ let req;
79
+ const deadline = setTimeout(() => {
80
+ req?.destroy(new Error("npm latest 请求超时"));
81
+ }, timeoutMs);
78
82
  const finish = (error, value) => {
79
83
  if (settled) return;
80
84
  settled = true;
85
+ clearTimeout(deadline);
81
86
  if (error) reject(error);
82
87
  else resolve(value);
83
88
  };
84
- const req = request(OFFICIAL_LATEST_URL, {
89
+ req = request(OFFICIAL_LATEST_URL, {
85
90
  headers: { accept: "application/json" },
86
91
  }, (response) => {
87
92
  if (response.statusCode !== 200 || response.headers.location) {
@@ -247,7 +252,17 @@ function hasActiveOperation({
247
252
  path.join(home, ".rainbond", "rainskills-onboarding-v1.json"),
248
253
  stateStore
249
254
  );
250
- return Boolean(onboarding && onboarding.stage !== "configured");
255
+ if (onboarding && onboarding.stage !== "configured") return true;
256
+ const operationsDirectory = path.join(home, ".rainbond", "rainskills", "operations");
257
+ if (!fs.existsSync(operationsDirectory)) return false;
258
+ const directoryInfo = fs.lstatSync(operationsDirectory);
259
+ if (directoryInfo.isSymbolicLink() || !directoryInfo.isDirectory()) return true;
260
+ for (const entry of fs.readdirSync(operationsDirectory, { withFileTypes: true })) {
261
+ if (!entry.isFile() || !entry.name.endsWith(".json")) return true;
262
+ const operation = stateStore.readProtectedJson(path.join(operationsDirectory, entry.name));
263
+ if (["awaiting-environment", "active"].includes(operation?.stage)) return true;
264
+ }
265
+ return false;
251
266
  } catch {
252
267
  return true;
253
268
  }
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ module.exports = Object.freeze({
4
+ version: "0.1.4",
5
+ });
@@ -1,11 +1,51 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
 
4
+ const path = require("node:path");
5
+ const { spawn } = require("node:child_process");
4
6
  const { runLocalRuntimeCommand } = require("./local-runtime-commands.js");
7
+ const { backgroundUpdateEnvironment } = require("./auto-update-worker.js");
5
8
 
6
- async function main() {
7
- const handled = runLocalRuntimeCommand(process.argv.slice(2));
9
+ function shouldScheduleUpdate(args, env = process.env) {
10
+ if (env.RAINSKILLS_DISABLE_AUTO_UPDATE === "1") return false;
11
+ return (
12
+ args[0] === "environment"
13
+ && args[1] === "list"
14
+ && args[2] === "--json"
15
+ ) || (
16
+ args[0] === "operation"
17
+ && args[1] === "complete"
18
+ );
19
+ }
20
+
21
+ function spawnBackgroundUpdate({
22
+ spawnFn = spawn,
23
+ env = process.env,
24
+ execPath = process.execPath,
25
+ } = {}) {
26
+ try {
27
+ const child = spawnFn(execPath, [path.join(__dirname, "auto-update-worker.js")], {
28
+ detached: true,
29
+ env: backgroundUpdateEnvironment(env),
30
+ shell: false,
31
+ stdio: "ignore",
32
+ windowsHide: true,
33
+ });
34
+ child.unref();
35
+ } catch {
36
+ // Automatic updates are best-effort and never affect the local command.
37
+ }
38
+ }
39
+
40
+ async function main({
41
+ args = process.argv.slice(2),
42
+ runCommand = runLocalRuntimeCommand,
43
+ scheduleUpdate = spawnBackgroundUpdate,
44
+ env = process.env,
45
+ } = {}) {
46
+ const handled = runCommand(args);
8
47
  if (!handled) throw new Error("不支持的本地运行环境命令");
48
+ if (shouldScheduleUpdate(args, env)) scheduleUpdate({ env });
9
49
  }
10
50
 
11
51
  if (require.main === module) {
@@ -15,4 +55,4 @@ if (require.main === module) {
15
55
  });
16
56
  }
17
57
 
18
- module.exports = { main };
58
+ module.exports = { main, shouldScheduleUpdate, spawnBackgroundUpdate };
@@ -14,7 +14,7 @@ Node.js 前置检查通过后,每次请求先执行本地 launcher + `["enviro
14
14
 
15
15
  第一步检查 Node.js 是否存在且主版本不低于 18。Node.js 缺失或低于 18 时,只说明“Rainskills 执行组件需要 Node.js 18 或更高版本”并停止:不选择运行环境,不调用 MCP,不猜测替代命令。只有用户或 agent 明确同意后才安装或升级 Node.js,再从同一原始 intent 继续。
16
16
 
17
- 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.2"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
17
+ 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.4"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
18
18
 
19
19
  本地 launcher 必须从当前 Skill 所在目录的同级目录定位 `rainbond-platform-installer/scripts/local-runtime.js`,解析为绝对路径后使用 `["node", "<绝对路径>"]` 执行。`environment list`、`operation begin`、`operation complete` 和 `runtime message` 只能使用本地 launcher;本地 launcher 只读取已安装文件和本机受保护状态,不得访问 npm 或其它网络。只有用户选定连接运行环境后,才使用上面的固定 npx launcher。
20
20
 
@@ -22,7 +22,7 @@ Node.js 前置检查通过后,每次请求先执行本地 launcher + `["enviro
22
22
  ```json
23
23
  {
24
24
  "schema": "rainskills.skill-runtime-contract.v1",
25
- "launcher": ["npx", "--yes", "rainskills@0.1.2"],
25
+ "launcher": ["npx", "--yes", "rainskills@0.1.4"],
26
26
  "local_launcher": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js"],
27
27
  "local_argv": {
28
28
  "environment-list": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js", "environment", "list", "--json"],
@@ -35,8 +35,8 @@ Node.js 前置检查通过后,每次请求先执行本地 launcher + `["enviro
35
35
  },
36
36
  "routes": {"existing": ["saas", "private-existing"]},
37
37
  "connect_argv": {
38
- "saas": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
39
- "private-existing": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"]
38
+ "saas": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
39
+ "private-existing": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"]
40
40
  }
41
41
  }
42
42
  ```
@@ -14,7 +14,7 @@ description: "Use only when the user explicitly asks to initialize or link a loc
14
14
 
15
15
  第一步检查 Node.js 是否存在且主版本不低于 18。Node.js 缺失或低于 18 时,只说明“Rainskills 执行组件需要 Node.js 18 或更高版本”并停止:不选择运行环境,不调用 MCP,不猜测替代命令。只有用户或 agent 明确同意后才安装或升级 Node.js,再从同一原始 intent 继续。
16
16
 
17
- 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.2"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
17
+ 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.4"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
18
18
 
19
19
  本地 launcher 必须从当前 Skill 所在目录的同级目录定位 `rainbond-platform-installer/scripts/local-runtime.js`,解析为绝对路径后使用 `["node", "<绝对路径>"]` 执行。`environment list`、`operation begin`、`operation complete` 和 `runtime message` 只能使用本地 launcher;本地 launcher 只读取已安装文件和本机受保护状态,不得访问 npm 或其它网络。只有用户选定连接或安装运行环境后,才使用上面的固定 npx launcher。
20
20
 
@@ -22,7 +22,7 @@ description: "Use only when the user explicitly asks to initialize or link a loc
22
22
  ```json
23
23
  {
24
24
  "schema": "rainskills.skill-runtime-contract.v1",
25
- "launcher": ["npx", "--yes", "rainskills@0.1.2"],
25
+ "launcher": ["npx", "--yes", "rainskills@0.1.4"],
26
26
  "local_launcher": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js"],
27
27
  "local_argv": {
28
28
  "environment-list": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js", "environment", "list", "--json"],
@@ -35,9 +35,9 @@ description: "Use only when the user explicitly asks to initialize or link a loc
35
35
  },
36
36
  "routes": {"new": ["saas", "private-existing", "install-private"]},
37
37
  "connect_argv": {
38
- "saas": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
39
- "private-existing": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"],
40
- "install-private": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--install-private", "--location", "<private-location>", "--intent-json", "<intent-json>"]
38
+ "saas": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
39
+ "private-existing": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"],
40
+ "install-private": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--install-private", "--location", "<private-location>", "--intent-json", "<intent-json>"]
41
41
  }
42
42
  }
43
43
  ```
@@ -14,7 +14,7 @@ description: "Use when the user explicitly asks to install a local or cloud Rain
14
14
 
15
15
  第一步检查 Node.js 是否存在且主版本不低于 18。Node.js 缺失或低于 18 时,只说明“Rainskills 执行组件需要 Node.js 18 或更高版本”并停止:不选择运行环境,不调用 MCP,不猜测替代命令。只有用户或 agent 明确同意后才安装或升级 Node.js,再从同一原始 intent 继续。
16
16
 
17
- 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.2"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
17
+ 固定 launcher 是 `["npx", "--yes", "rainskills@0.1.4"]`;版本必须与本技能包 `package.json` 一致。把 launcher 与参数拼成 argv 数组直接执行,禁止 `rainskills@latest` 或执行 shell 字符串。
18
18
 
19
19
  本地 launcher 必须从当前 Skill 所在目录的同级目录定位 `rainbond-platform-installer/scripts/local-runtime.js`,解析为绝对路径后使用 `["node", "<绝对路径>"]` 执行。`environment list`、`operation begin`、`operation complete` 和 `runtime message` 只能使用本地 launcher;本地 launcher 只读取已安装文件和本机受保护状态,不得访问 npm 或其它网络。只有用户选定连接或安装运行环境后,才使用上面的固定 npx launcher。
20
20
 
@@ -22,7 +22,7 @@ description: "Use when the user explicitly asks to install a local or cloud Rain
22
22
  ```json
23
23
  {
24
24
  "schema": "rainskills.skill-runtime-contract.v1",
25
- "launcher": ["npx", "--yes", "rainskills@0.1.2"],
25
+ "launcher": ["npx", "--yes", "rainskills@0.1.4"],
26
26
  "local_launcher": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js"],
27
27
  "local_argv": {
28
28
  "environment-list": ["node", "<installed-skills-root>/rainbond-platform-installer/scripts/local-runtime.js", "environment", "list", "--json"],
@@ -38,9 +38,9 @@ description: "Use when the user explicitly asks to install a local or cloud Rain
38
38
  "existing": ["saas", "private-existing"]
39
39
  },
40
40
  "connect_argv": {
41
- "saas": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
42
- "private-existing": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"],
43
- "install-private": ["npx", "--yes", "rainskills@0.1.2", "runtime", "connect", "<target>", "--install-private", "--location", "<private-location>", "--intent-json", "<intent-json>"]
41
+ "saas": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--saas", "--intent-json", "<intent-json>"],
42
+ "private-existing": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--rainbond-url", "<rainbond-url>", "--intent-json", "<intent-json>"],
43
+ "install-private": ["npx", "--yes", "rainskills@0.1.4", "runtime", "connect", "<target>", "--install-private", "--location", "<private-location>", "--intent-json", "<intent-json>"]
44
44
  }
45
45
  }
46
46
  ```