rainskills 0.1.28 → 0.1.30
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 +19 -3
- package/SKILL.md +4 -2
- package/bin/rainskills-tools.js +52 -2
- package/bin/rainskills.js +7 -4
- package/install.sh +392 -12
- package/marketplace/rainskills/.claude-plugin/plugin.json +3 -1
- package/marketplace/rainskills/.codex-plugin/plugin.json +3 -1
- package/marketplace/rainskills/skills/rainskills/SKILL.md +5 -3
- package/package.json +5 -3
- package/rainbond-app-assistant/SKILL.md +2 -1
- package/rainbond-app-assistant/references/runtime-gate.md +3 -1
- package/rainbond-app-version-assistant/SKILL.md +3 -1
- package/rainbond-delivery-verifier/SKILL.md +3 -1
- package/rainbond-env-sync/SKILL.md +3 -1
- package/rainbond-fullstack-bootstrap/SKILL.md +3 -1
- package/rainbond-fullstack-troubleshooter/SKILL.md +3 -1
- package/rainbond-opensource-app-deploy/references/runtime-gate.md +3 -1
- package/rainbond-platform-installer/SKILL.md +1 -1
- package/rainbond-platform-installer/scripts/auto-update.js +7 -10
- package/rainbond-platform-installer/scripts/host-targets.js +61 -0
- package/rainbond-platform-installer/scripts/installed-version.js +1 -1
- package/rainbond-platform-installer/scripts/platform-installer.js +2 -1
- package/rainbond-platform-installer/scripts/result-telemetry.js +285 -0
- package/rainbond-platform-installer/scripts/runtime-state.js +2 -1
- package/rainbond-platform-installer/scripts/telemetry.js +6 -1
- package/rainbond-platform-installer/scripts/windows-client-config.js +0 -1
- package/rainbond-platform-installer/scripts/windows-onboarding.js +127 -36
- package/rainbond-platform-query/SKILL.md +3 -1
- package/rainbond-project-init/SKILL.md +3 -1
- package/rainbond-template-installer/SKILL.md +3 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Rainskills
|
|
2
2
|
|
|
3
|
-
Rainskills 是一组面向应用识别、部署、排障和交付的 AI Skills,支持 Codex、Claude Code 和
|
|
3
|
+
Rainskills 是一组面向应用识别、部署、排障和交付的 AI Skills,支持 Codex、Claude Code、Pi Agent、DeepSeek Harness 和 WorkBuddy。用户在市场中只会看到一个 `Rainskills` 产品,安装后 11 个 `rainbond-*` Skill 仍会独立触发。
|
|
4
4
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
@@ -41,7 +41,23 @@ Claude Code:
|
|
|
41
41
|
/reload-plugins
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
DeepSeek Harness:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx --yes rainskills dsh
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
默认安装到 `${DSH_HOME:-~/.dsh}/skills`。DeepSeek Harness 使用原生 Skill catalog 和 `skill` loader 加载,不配置客户端 MCP。
|
|
51
|
+
|
|
52
|
+
WorkBuddy:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx --yes rainskills workbuddy
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
默认安装到 `${WORKBUDDY_CONFIG_DIR:-~/.workbuddy-ai}/skills`。如果安装发生在一个已经打开的 WorkBuddy 任务中,先刷新 Skill 列表或新建任务;部署时明确指定 Rainbond/Rainskills,或让项目保留 `rainbond.app.json`、`.rainbond/local.json` 标记,以避免被内置 Sites 路由抢占。
|
|
59
|
+
|
|
60
|
+
安装流程支持 Codex、Claude Code、Pi Agent、DeepSeek Harness 和 WorkBuddy;所有 Agent 共用同一组 Skills 和本地 Rainskills CLI,不提供单独的客户端 MCP adapter。macOS、Linux 和 WSL 不支持 OpenClaw 安装。不要手工复制 Skill、拼接凭据或修改 Agent 配置。
|
|
45
61
|
|
|
46
62
|
## 安装完成时用户会看到什么
|
|
47
63
|
|
|
@@ -223,7 +239,7 @@ node ~/.rainbond/lib/rainskills/bin/rainskills.js platform install --onboarding-
|
|
|
223
239
|
|
|
224
240
|
Rainskills 会在用户下一次发起业务动作时,由本地运行时立即返回环境查询结果,并另行启动后台任务静默检查更新。更新只跟随 npm `latest` 指向的正式版。当前版本是 RC 或其他预发布版本时不会查询、不会自动升级;npm 上的新 RC 版本也不参与正式版自动升级。
|
|
225
241
|
|
|
226
|
-
发现更高的正式版后,后台任务只委托到经过校验的精确版本,例如 `rainskills@0.1.
|
|
242
|
+
发现更高的正式版后,后台任务只委托到经过校验的精确版本,例如 `rainskills@0.1.30`,不会执行浮动的 `@latest` 业务代码。新版本原子刷新已经安装的 Rainskills Skills;当前业务继续使用启动时已经加载的版本,最迟从下一条新任务开始使用新版。npm 超时、版本检查失败、安装位置不安全或文件迁移失败时会保留旧版本,且不会阻塞或改变当前操作。
|
|
227
243
|
|
|
228
244
|
升级只更新 Rainskills 自身,不触发 Rainbond 安装、运行环境选择、登录授权或重新对接,也不会新增 Agent MCP 配置。更新内容仅包括 Skills 和本地 CLI。原始业务操作会继续执行;只有该业务操作本身需要运行环境时,才按既有门禁检查当前连接。可用连接直接复用,401 只重新授权一次,403 立即停止,从未连接过运行环境时才进入环境选择。
|
|
229
245
|
|
package/SKILL.md
CHANGED
|
@@ -9,7 +9,7 @@ This is the single marketplace entry for the complete Rainskills product. The in
|
|
|
9
9
|
|
|
10
10
|
## Initialize
|
|
11
11
|
|
|
12
|
-
1. Detect the current host client and map it to exactly one supported installer target: Codex=`codex`, Claude Code=`claude`,
|
|
12
|
+
1. Detect the current host client and map it to exactly one supported installer target: Codex=`codex`, Claude Code=`claude`, Pi Agent=`pi`, DeepSeek Harness=`dsh`, or WorkBuddy=`workbuddy`. All five use the same installed Skills and protected local Rainskills CLI; Pi and DeepSeek Harness have no separate MCP adapter or generated extension. DeepSeek Harness installs to `$DSH_HOME/skills` (default `~/.dsh/skills`). WorkBuddy installs to `$WORKBUDDY_CONFIG_DIR/skills` (default `~/.workbuddy-ai/skills`). The macOS, Linux, and WSL installer intentionally does not support OpenClaw; report that limitation instead of invoking an unsupported target. Do not ask the user which supported client they are currently using. If the host cannot be determined reliably, omit the target and let the installer ask.
|
|
13
13
|
2. Resolve the directory containing this `SKILL.md`. On native Windows, if the adjacent `bin/rainskills.js` exists, run it by absolute path with the detected target in an attached interactive terminal: `node <skill-directory>/bin/rainskills.js <target>`. On macOS, Linux, or WSL, if the adjacent `install.sh` exists, run `bash <skill-directory>/install.sh <target>` the same way. Do not replace the installer with manual file copies.
|
|
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.
|
|
@@ -48,7 +48,9 @@ Rainskills 安装完成,下一条消息即可直接使用。
|
|
|
48
48
|
|
|
49
49
|
Codex 中命令工具一旦返回 `session_id`,必须立即对该 `session_id` 反复调用 `write_stdin`(空输入轮询),直到工具返回 `exit_code`。连接器输出 `[RAINSKILLS_AGENT_WAIT_REQUIRED:runtime-connect]` 后进入上述轮询;看到 `[RAINSKILLS_AGENT_WAIT_COMPLETE:runtime-connect]` 后仍须继续轮询,直到取得退出码和最终 JSON。
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
DeepSeek Harness 和 WorkBuddy 也必须保持原命令附着直到退出;如果宿主把长命令转成持久终端或后台任务,只能轮询该原始命令句柄,不得另起 `runtime status` 推测授权结果。WorkBuddy 安装后若当前任务的 Skill 清单尚未刷新,在下一条业务动作前先刷新 Skill 列表或新建任务,不得退回内置 Sites 代替 Rainbond 部署。
|
|
52
|
+
|
|
53
|
+
Rainskills 只保存一个全局运行环境,不维护环境列表、名称、默认值或环境 ID。使用固定 launcher `node <home>/.rainbond/lib/rainskills/bin/rainskills.js`(运行包版本 `rainskills@0.1.30`):
|
|
52
54
|
|
|
53
55
|
- 状态:执行 `runtime status --json`。
|
|
54
56
|
- 首次连接:执行 `runtime connect <target> --saas` 或 `runtime connect <target> --rainbond-url <Console origin>`。
|
package/bin/rainskills-tools.js
CHANGED
|
@@ -449,6 +449,56 @@ function skillManifestPath(config) {
|
|
|
449
449
|
return path.join(config.homeDir || os.homedir(), CONFIG_DIRECTORY, "bin", SKILL_MANIFEST_FILENAME);
|
|
450
450
|
}
|
|
451
451
|
|
|
452
|
+
function loadTelemetryPackageVersion(config) {
|
|
453
|
+
try {
|
|
454
|
+
const manifest = JSON.parse(fs.readFileSync(skillManifestPath(config), "utf8"));
|
|
455
|
+
return typeof manifest.package_version === "string" && manifest.package_version
|
|
456
|
+
? manifest.package_version
|
|
457
|
+
: "unknown";
|
|
458
|
+
} catch {
|
|
459
|
+
return "unknown";
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function createBridgeTelemetry(config) {
|
|
464
|
+
try {
|
|
465
|
+
const directory = path.join(config.homeDir || os.homedir(), CONFIG_DIRECTORY, "rainskills", "telemetry");
|
|
466
|
+
const { createResultTelemetry } = requireRuntimeModule("result-telemetry.js");
|
|
467
|
+
return createResultTelemetry({
|
|
468
|
+
directory,
|
|
469
|
+
packageVersion: loadTelemetryPackageVersion(config),
|
|
470
|
+
});
|
|
471
|
+
} catch {
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
async function executeWithUsageTelemetry(command, config) {
|
|
477
|
+
const tracksUsage = command.command === "read" || command.command === "call";
|
|
478
|
+
const telemetry = tracksUsage ? createBridgeTelemetry(config) : null;
|
|
479
|
+
if (telemetry) await telemetry.flushPending(3).catch(() => {});
|
|
480
|
+
try {
|
|
481
|
+
const output = await execute(command, config);
|
|
482
|
+
if (telemetry) {
|
|
483
|
+
const firstUse = telemetry.recordFirstUse("success");
|
|
484
|
+
const active = telemetry.recordActiveDaily();
|
|
485
|
+
await Promise.allSettled([firstUse.delivery, active.delivery]);
|
|
486
|
+
}
|
|
487
|
+
return output;
|
|
488
|
+
} catch (error) {
|
|
489
|
+
if (telemetry) {
|
|
490
|
+
const firstUse = telemetry.recordFirstUse("failed", {
|
|
491
|
+
error_stage: "first_use",
|
|
492
|
+
error_code: error instanceof BridgeError && error.exitCode === EXIT.TRANSPORT
|
|
493
|
+
? "transport_failed"
|
|
494
|
+
: "tool_call_failed",
|
|
495
|
+
});
|
|
496
|
+
await firstUse.delivery.catch(() => false);
|
|
497
|
+
}
|
|
498
|
+
throw error;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
452
502
|
function loadSkillBinding(config, skillId, rootSkillId) {
|
|
453
503
|
const target = skillManifestPath(config);
|
|
454
504
|
let manifest;
|
|
@@ -1370,7 +1420,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
1370
1420
|
if (config.isInsecureHttp) {
|
|
1371
1421
|
process.stderr.write('{"warning":"using insecure HTTP transport"}\n');
|
|
1372
1422
|
}
|
|
1373
|
-
const output = await
|
|
1423
|
+
const output = await executeWithUsageTelemetry(command, config);
|
|
1374
1424
|
process.stdout.write(`${JSON.stringify(fitOutput(output))}\n`);
|
|
1375
1425
|
return;
|
|
1376
1426
|
}
|
|
@@ -1380,7 +1430,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
1380
1430
|
if (config.isInsecureHttp) {
|
|
1381
1431
|
process.stderr.write('{"warning":"using insecure HTTP transport"}\n');
|
|
1382
1432
|
}
|
|
1383
|
-
const output = await
|
|
1433
|
+
const output = await executeWithUsageTelemetry(command, config);
|
|
1384
1434
|
process.stdout.write(`${JSON.stringify(fitOutput(output))}\n`);
|
|
1385
1435
|
} catch (error) {
|
|
1386
1436
|
const bridgeError = error instanceof BridgeError
|
package/bin/rainskills.js
CHANGED
|
@@ -13,6 +13,9 @@ const {
|
|
|
13
13
|
const {
|
|
14
14
|
renderCatalogUserMessage,
|
|
15
15
|
} = require("../rainbond-platform-installer/scripts/user-message.js");
|
|
16
|
+
const {
|
|
17
|
+
isHostTarget,
|
|
18
|
+
} = require("../rainbond-platform-installer/scripts/host-targets.js");
|
|
16
19
|
|
|
17
20
|
const AUTO_UPDATE_FALLBACK_EXIT_CODE = 75;
|
|
18
21
|
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
@@ -67,7 +70,7 @@ function parseRuntimeAssertConnectArgs(args) {
|
|
|
67
70
|
throw new Error("runtime connect 内部门禁参数无效");
|
|
68
71
|
}
|
|
69
72
|
if (!UUID_PATTERN.test(args[3] || "")) throw new Error("runtime connect operation 无效");
|
|
70
|
-
if (!
|
|
73
|
+
if (!isHostTarget(args[5])) throw new Error("runtime connect target 无效");
|
|
71
74
|
if (!["saas", "private"].includes(args[7])) throw new Error("runtime connect environment kind 无效");
|
|
72
75
|
return {
|
|
73
76
|
operationId: args[3],
|
|
@@ -95,8 +98,8 @@ function parseRuntimeConnectArgs(args) {
|
|
|
95
98
|
throw new Error("不是 runtime connect 命令");
|
|
96
99
|
}
|
|
97
100
|
const targetClient = args[2];
|
|
98
|
-
if (!
|
|
99
|
-
throw new Error("runtime connect
|
|
101
|
+
if (!isHostTarget(targetClient)) {
|
|
102
|
+
throw new Error("runtime connect 需要固定的受支持宿主目标");
|
|
100
103
|
}
|
|
101
104
|
let environmentChoice = "";
|
|
102
105
|
let rainbondUrl = "";
|
|
@@ -319,7 +322,7 @@ async function runBuiltin(args, {
|
|
|
319
322
|
return true;
|
|
320
323
|
}
|
|
321
324
|
if (args[0] === "runtime" && args[1] === "reconnect") {
|
|
322
|
-
if (args.length !== 3 || !
|
|
325
|
+
if (args.length !== 3 || !isHostTarget(args[2])) {
|
|
323
326
|
throw new Error("runtime reconnect 参数无效");
|
|
324
327
|
}
|
|
325
328
|
const current = getSingleRuntimeStore().read();
|