@rynx-ai/skills 0.1.0 → 0.1.1
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/dist/artifact.js +3 -5
- package/dist/install.d.ts +9 -7
- package/dist/install.js +24 -19
- package/package.json +2 -2
package/dist/artifact.js
CHANGED
|
@@ -121,14 +121,12 @@ export function parseSkillRefValue(value) {
|
|
|
121
121
|
...(typeof install.skill === "string" && install.skill ? { skill: install.skill } : {}),
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
|
-
else if (install.tool === "
|
|
125
|
-
if (typeof install.
|
|
126
|
-
return null;
|
|
127
|
-
if (typeof install.version !== "string" || !install.version.trim())
|
|
124
|
+
else if (install.tool === "command") {
|
|
125
|
+
if (typeof install.command !== "string" || !install.command.trim())
|
|
128
126
|
return null;
|
|
129
127
|
if (!Array.isArray(install.args) || install.args.some((a) => typeof a !== "string"))
|
|
130
128
|
return null;
|
|
131
|
-
recipe = { tool: "
|
|
129
|
+
recipe = { tool: "command", command: install.command, args: install.args };
|
|
132
130
|
}
|
|
133
131
|
else {
|
|
134
132
|
return null;
|
package/dist/install.d.ts
CHANGED
|
@@ -7,14 +7,16 @@ export interface InstalledSkill {
|
|
|
7
7
|
dir: string;
|
|
8
8
|
contentHash?: string;
|
|
9
9
|
}
|
|
10
|
-
/** Runs `
|
|
11
|
-
export type
|
|
10
|
+
/** Runs `command args…` with cwd = the temp install dir. Injectable (tests). */
|
|
11
|
+
export type CommandRunner = (command: string, args: string[], opts: {
|
|
12
12
|
cwd: string;
|
|
13
13
|
}) => Promise<void>;
|
|
14
|
-
/** Turn install params into the command
|
|
15
|
-
*
|
|
14
|
+
/** Turn install params into the `{ command, args }` that performs them, run
|
|
15
|
+
* with cwd = the temp install dir. skills-cli shells out through npx; the
|
|
16
|
+
* command recipe runs its executable directly. */
|
|
16
17
|
export declare function buildInstallCommand(recipe: SkillInstallRecipe): {
|
|
17
|
-
|
|
18
|
+
command: string;
|
|
19
|
+
args: string[];
|
|
18
20
|
};
|
|
19
21
|
/**
|
|
20
22
|
* INSTALL ONLY: run `recipe`'s install command in a throwaway temp dir and
|
|
@@ -22,7 +24,7 @@ export declare function buildInstallCommand(recipe: SkillInstallRecipe): {
|
|
|
22
24
|
* observations come back as the return value. Throws on bad input / failure.
|
|
23
25
|
*/
|
|
24
26
|
export declare function installFromRecipe(recipe: SkillInstallRecipe, targetDir: string, opts?: {
|
|
25
|
-
|
|
27
|
+
runCommand?: CommandRunner;
|
|
26
28
|
}): Promise<InstalledSkill[]>;
|
|
27
29
|
/** Write one skill dir's `.rynx-skill.json` v3 install-info file (catalog
|
|
28
30
|
* artifact: the payload IS the SkillRef — declaration ≡ record, literally). */
|
|
@@ -33,5 +35,5 @@ export declare function writeSkillInstallInfo(skillDir: string, ref: SkillRef):
|
|
|
33
35
|
* content hash. Returns the installed skills' catalog metadata.
|
|
34
36
|
*/
|
|
35
37
|
export declare function installIntoCatalog(recipe: SkillInstallRecipe, catalogRoot: string, opts?: {
|
|
36
|
-
|
|
38
|
+
runCommand?: CommandRunner;
|
|
37
39
|
}): Promise<SkillMeta[]>;
|
package/dist/install.js
CHANGED
|
@@ -17,9 +17,11 @@
|
|
|
17
17
|
* write each produced skill an info file recording these exact params +
|
|
18
18
|
* the observed hash.
|
|
19
19
|
*
|
|
20
|
-
* Every install
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* Every install runs a command in a throwaway temp dir that bottoms out at
|
|
21
|
+
* `skills add` (skills-cli shells out through `npx -y skills add …`; the command
|
|
22
|
+
* recipe runs a globally-installed self-installing proxy directly), so both
|
|
23
|
+
* share one pickup path (`.agents/skills/`) and one hash algorithm; they differ
|
|
24
|
+
* only in the command line.
|
|
23
25
|
*/
|
|
24
26
|
import { execFile } from "node:child_process";
|
|
25
27
|
import { cp, mkdir, mkdtemp, readdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
@@ -27,8 +29,11 @@ import { tmpdir } from "node:os";
|
|
|
27
29
|
import path from "node:path";
|
|
28
30
|
import { promisify } from "node:util";
|
|
29
31
|
import { readSkillMeta, SKILL_RECEIPT_FILE } from "./artifact.js";
|
|
30
|
-
const
|
|
31
|
-
await promisify(execFile)(
|
|
32
|
+
const runCommandDefault = async (command, args, opts) => {
|
|
33
|
+
await promisify(execFile)(command, args, { cwd: opts.cwd, timeout: 180_000 }).catch((err) => {
|
|
34
|
+
if (err.code === "ENOENT") {
|
|
35
|
+
throw new Error(`command not found: ${command} — install it (e.g. \`npm i -g @rynx-ai/emulator\` for rynx-emulator)`);
|
|
36
|
+
}
|
|
32
37
|
throw new Error(`skills install failed: ${cliErrorDetail(err)}`);
|
|
33
38
|
});
|
|
34
39
|
};
|
|
@@ -40,8 +45,9 @@ function assertSafeArg(label, value) {
|
|
|
40
45
|
if (/[;&|`$()<>\x00-\x1f]/.test(value))
|
|
41
46
|
throw new Error(`invalid ${label}: ${value}`);
|
|
42
47
|
}
|
|
43
|
-
/** Turn install params into the command
|
|
44
|
-
*
|
|
48
|
+
/** Turn install params into the `{ command, args }` that performs them, run
|
|
49
|
+
* with cwd = the temp install dir. skills-cli shells out through npx; the
|
|
50
|
+
* command recipe runs its executable directly. */
|
|
45
51
|
export function buildInstallCommand(recipe) {
|
|
46
52
|
if (recipe.tool === "skills-cli") {
|
|
47
53
|
const src = recipe.source.trim();
|
|
@@ -63,15 +69,13 @@ export function buildInstallCommand(recipe) {
|
|
|
63
69
|
// predictable pickup location inside the throwaway temp dir. Which agent
|
|
64
70
|
// actually sees a skill is decided downstream, at materialize time.
|
|
65
71
|
args.push("--full-depth", "--agent", "universal", "--copy", "--yes");
|
|
66
|
-
return {
|
|
72
|
+
return { command: "npx", args };
|
|
67
73
|
}
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
assertSafeArg("version", version);
|
|
74
|
-
return { npxArgs: ["-y", `${pkg}@${version}`, ...recipe.args] };
|
|
74
|
+
const command = recipe.command.trim();
|
|
75
|
+
if (!command)
|
|
76
|
+
throw new Error("missing install command");
|
|
77
|
+
assertSafeArg("command", command);
|
|
78
|
+
return { command, args: recipe.args };
|
|
75
79
|
}
|
|
76
80
|
/**
|
|
77
81
|
* INSTALL ONLY: run `recipe`'s install command in a throwaway temp dir and
|
|
@@ -79,7 +83,8 @@ export function buildInstallCommand(recipe) {
|
|
|
79
83
|
* observations come back as the return value. Throws on bad input / failure.
|
|
80
84
|
*/
|
|
81
85
|
export async function installFromRecipe(recipe, targetDir, opts = {}) {
|
|
82
|
-
const
|
|
86
|
+
const { command, args } = buildInstallCommand(recipe);
|
|
87
|
+
const staged = await execStagedInstall(command, args, opts.runCommand);
|
|
83
88
|
try {
|
|
84
89
|
if (staged.names.length === 0)
|
|
85
90
|
throw new Error("no skill was installed — check the source identifier");
|
|
@@ -128,15 +133,15 @@ export async function installIntoCatalog(recipe, catalogRoot, opts = {}) {
|
|
|
128
133
|
return metas;
|
|
129
134
|
}
|
|
130
135
|
/**
|
|
131
|
-
* Run one
|
|
136
|
+
* Run one install command in a throwaway temp dir, list the skill folders it
|
|
132
137
|
* produced under `.agents/skills/`, and pick up the `skills` CLI's per-skill
|
|
133
138
|
* content hashes from its `skills-lock.json`. The caller moves the folders
|
|
134
139
|
* and owns the temp dir's cleanup.
|
|
135
140
|
*/
|
|
136
|
-
async function execStagedInstall(
|
|
141
|
+
async function execStagedInstall(command, args, runCommand = runCommandDefault) {
|
|
137
142
|
const staging = await mkdtemp(path.join(tmpdir(), "rynx-skill-"));
|
|
138
143
|
try {
|
|
139
|
-
await
|
|
144
|
+
await runCommand(command, args, { cwd: staging });
|
|
140
145
|
}
|
|
141
146
|
catch (err) {
|
|
142
147
|
await rm(staging, { recursive: true, force: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rynx-ai/skills",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "The rynx skill artifact domain: discover/parse on-disk skills (SKILL.md), install them from replayable recipes (everything bottoms out at `npx skills add`), and read/write the catalog's `.rynx-skill.json` install-info files. Node built-ins + @rynx-ai/protocol only.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@rynx-ai/protocol": "0.1.
|
|
24
|
+
"@rynx-ai/protocol": "0.1.1"
|
|
25
25
|
},
|
|
26
26
|
"scripts": {
|
|
27
27
|
"build": "rm -rf dist && tsc -p tsconfig.json"
|