@devxiyang/agent-skill 0.0.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/LICENSE +21 -0
- package/README.md +187 -0
- package/dist/builtin.d.ts +20 -0
- package/dist/builtin.d.ts.map +1 -0
- package/dist/builtin.js +25 -0
- package/dist/builtin.js.map +1 -0
- package/dist/copy.d.ts +30 -0
- package/dist/copy.d.ts.map +1 -0
- package/dist/copy.js +73 -0
- package/dist/copy.js.map +1 -0
- package/dist/discovery/discovery.d.ts +40 -0
- package/dist/discovery/discovery.d.ts.map +1 -0
- package/dist/discovery/discovery.js +111 -0
- package/dist/discovery/discovery.js.map +1 -0
- package/dist/discovery/frontmatter.d.ts +27 -0
- package/dist/discovery/frontmatter.d.ts.map +1 -0
- package/dist/discovery/frontmatter.js +123 -0
- package/dist/discovery/frontmatter.js.map +1 -0
- package/dist/discovery/index.d.ts +4 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +3 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +38 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/validator.d.ts +14 -0
- package/dist/validator.d.ts.map +1 -0
- package/dist/validator.js +2 -0
- package/dist/validator.js.map +1 -0
- package/dist/validators/index.d.ts +2 -0
- package/dist/validators/index.d.ts.map +1 -0
- package/dist/validators/index.js +2 -0
- package/dist/validators/index.js.map +1 -0
- package/dist/validators/node.d.ts +9 -0
- package/dist/validators/node.d.ts.map +1 -0
- package/dist/validators/node.js +43 -0
- package/dist/validators/node.js.map +1 -0
- package/package.json +58 -0
- package/skills/git/SKILL.md +87 -0
- package/skills/github/SKILL.md +54 -0
- package/skills/skill-creator/SKILL.md +73 -0
- package/skills/tmux/SKILL.md +76 -0
- package/skills/weather/SKILL.md +39 -0
- package/skills/web/SKILL.md +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dev.xiyang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# agent.skill
|
|
2
|
+
|
|
3
|
+
SDK for skill discovery and registration — integrates into any agent.
|
|
4
|
+
|
|
5
|
+
A **skill** is a folder containing a `SKILL.md` file (with YAML frontmatter + instructions) and optional resources (scripts, references, assets). This SDK provides the tooling to discover, validate, and load skills into an agent's context.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @devxiyang/agent-skill
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Concepts
|
|
14
|
+
|
|
15
|
+
### Skill folder structure
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
skill-name/
|
|
19
|
+
├── SKILL.md # required — frontmatter metadata + instructions
|
|
20
|
+
├── scripts/ # optional — executable scripts
|
|
21
|
+
├── references/ # optional — docs loaded on demand
|
|
22
|
+
└── assets/ # optional — files used in output
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### SKILL.md frontmatter
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
---
|
|
29
|
+
name: github
|
|
30
|
+
description: Interact with GitHub using the gh CLI.
|
|
31
|
+
requires: bin:gh,env:GITHUB_TOKEN
|
|
32
|
+
os: darwin,linux
|
|
33
|
+
---
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
| Field | Required | Description |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `name` | yes | Skill identifier |
|
|
39
|
+
| `description` | yes | What the skill does and when to use it |
|
|
40
|
+
| `requires` | no | `bin:<name>` and/or `env:<NAME>` comma-separated |
|
|
41
|
+
| `os` | no | Allowed platforms: `darwin`, `linux`, `win32` |
|
|
42
|
+
| `always` | no | Load into agent context on every run |
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { SkillDiscovery, builtinSkillsRoot } from '@devxiyang/agent-skill';
|
|
48
|
+
|
|
49
|
+
const discovery = new SkillDiscovery([
|
|
50
|
+
{ path: '/my/workspace/skills', scope: 'user' }, // checked first — higher priority
|
|
51
|
+
{ path: builtinSkillsRoot(), scope: 'system' }, // fallback
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
// Discover all skills with eligibility info
|
|
55
|
+
const entries = await discovery.list();
|
|
56
|
+
|
|
57
|
+
// Load the body of a SKILL.md (frontmatter stripped)
|
|
58
|
+
const content = await discovery.load(entries[0].filePath);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Priority is determined by roots array order** — the first root that contains a skill with a given name wins; later roots are skipped for that name. The `scope` field is metadata only and does not affect priority.
|
|
62
|
+
|
|
63
|
+
To override a built-in skill, place a skill folder with the same name in an earlier root:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
/my/workspace/skills/
|
|
67
|
+
└── git/ ← overrides the built-in git skill
|
|
68
|
+
└── SKILL.md
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Built-in skills
|
|
72
|
+
|
|
73
|
+
| Skill | Requires | Description |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| `git` | `git` | Local git operations |
|
|
76
|
+
| `github` | `gh` | GitHub issues, PRs, CI via gh CLI |
|
|
77
|
+
| `tmux` | `tmux` (macOS/Linux) | Remote-control interactive terminal sessions |
|
|
78
|
+
| `weather` | `curl` | Current weather and forecasts, no API key |
|
|
79
|
+
| `web` | `curl` | Fetch pages, call REST APIs, download files |
|
|
80
|
+
| `skill-creator` | — | Guide for creating and structuring new skills |
|
|
81
|
+
|
|
82
|
+
## Copying skills
|
|
83
|
+
|
|
84
|
+
Copy skill folders from any source root into a target directory. Useful for seeding a workspace with built-in or third-party skill sets.
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { copySkills, builtinSkillsRoot } from '@devxiyang/agent-skill';
|
|
88
|
+
|
|
89
|
+
// Copy all built-in skills
|
|
90
|
+
await copySkills({
|
|
91
|
+
from: builtinSkillsRoot(),
|
|
92
|
+
to: '/my/workspace/skills',
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Copy a subset
|
|
96
|
+
await copySkills({
|
|
97
|
+
from: builtinSkillsRoot(),
|
|
98
|
+
to: '/my/workspace/skills',
|
|
99
|
+
skills: ['git', 'github'],
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Overwrite existing
|
|
103
|
+
await copySkills({
|
|
104
|
+
from: builtinSkillsRoot(),
|
|
105
|
+
to: '/my/workspace/skills',
|
|
106
|
+
overwrite: true,
|
|
107
|
+
});
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Returns `{ copied: string[], skipped: string[] }`. Existing skills are skipped by default (`overwrite: false`). Directories without a `SKILL.md` are ignored.
|
|
111
|
+
|
|
112
|
+
## Custom validator
|
|
113
|
+
|
|
114
|
+
By default, dependency checks use the built-in `defaultValidator` (Node.js PATH lookup, `process.env`, `process.platform`). You can provide your own:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { SkillDiscovery, SkillValidator } from '@devxiyang/agent-skill';
|
|
118
|
+
|
|
119
|
+
const myValidator: SkillValidator = {
|
|
120
|
+
async checkBin(name) { /* custom bin check */ return true; },
|
|
121
|
+
checkEnv(name) { return !!process.env[name]; },
|
|
122
|
+
checkOs(platforms) { return platforms.includes(process.platform); },
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const discovery = new SkillDiscovery([{ path: myRoot, scope: 'user' }], myValidator);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## API
|
|
129
|
+
|
|
130
|
+
### `SkillDiscovery`
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
new SkillDiscovery(roots: SkillRoot[], validator?: SkillValidator)
|
|
134
|
+
|
|
135
|
+
discovery.list(): Promise<SkillEntry[]>
|
|
136
|
+
discovery.load(filePath: string): Promise<string>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### `copySkills(options): Promise<CopySkillsResult>`
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
type CopySkillsOptions = {
|
|
143
|
+
from: string; // source skills root
|
|
144
|
+
to: string; // target directory
|
|
145
|
+
skills?: string[]; // filter by skill name (default: all)
|
|
146
|
+
overwrite?: boolean; // overwrite existing (default: false)
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
type CopySkillsResult = {
|
|
150
|
+
copied: string[];
|
|
151
|
+
skipped: string[];
|
|
152
|
+
};
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### `builtinSkillsRoot(): string`
|
|
156
|
+
|
|
157
|
+
Returns the absolute path to the built-in skills directory bundled with this package.
|
|
158
|
+
|
|
159
|
+
### `defaultValidator`
|
|
160
|
+
|
|
161
|
+
The built-in `SkillValidator` implementation for Node.js environments.
|
|
162
|
+
|
|
163
|
+
### Types
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
type SkillEntry = {
|
|
167
|
+
name: string;
|
|
168
|
+
description: string | null;
|
|
169
|
+
path: string; // skill folder path
|
|
170
|
+
filePath: string; // SKILL.md path
|
|
171
|
+
scope: 'user' | 'system';
|
|
172
|
+
eligible: boolean; // all dependencies satisfied
|
|
173
|
+
always: boolean;
|
|
174
|
+
tags: string[];
|
|
175
|
+
missing: SkillMissingReason[];
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
type SkillMissingReason = {
|
|
179
|
+
kind: 'bin' | 'env' | 'os' | 'invalid';
|
|
180
|
+
value: string;
|
|
181
|
+
message: string;
|
|
182
|
+
};
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## License
|
|
186
|
+
|
|
187
|
+
MIT
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the absolute path to the built-in skills directory bundled with this package.
|
|
3
|
+
*
|
|
4
|
+
* Resolves relative to this file's location so the path remains correct regardless
|
|
5
|
+
* of where the consuming project is installed. Pass the result to SkillDiscovery
|
|
6
|
+
* as a system-scoped root:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* new SkillDiscovery([
|
|
10
|
+
* { path: userSkillsDir, scope: 'user' },
|
|
11
|
+
* { path: builtinSkillsRoot(), scope: 'system' },
|
|
12
|
+
* ])
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Note for Electron apps: if the app is packaged with asar, add
|
|
16
|
+
* `node_modules/@devxiyang/agent-skill/skills` to `asarUnpack` in
|
|
17
|
+
* electron-builder config so the directory is accessible via the filesystem.
|
|
18
|
+
*/
|
|
19
|
+
export declare function builtinSkillsRoot(): string;
|
|
20
|
+
//# sourceMappingURL=builtin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtin.d.ts","sourceRoot":"","sources":["../src/builtin.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C"}
|
package/dist/builtin.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
/**
|
|
4
|
+
* Returns the absolute path to the built-in skills directory bundled with this package.
|
|
5
|
+
*
|
|
6
|
+
* Resolves relative to this file's location so the path remains correct regardless
|
|
7
|
+
* of where the consuming project is installed. Pass the result to SkillDiscovery
|
|
8
|
+
* as a system-scoped root:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* new SkillDiscovery([
|
|
12
|
+
* { path: userSkillsDir, scope: 'user' },
|
|
13
|
+
* { path: builtinSkillsRoot(), scope: 'system' },
|
|
14
|
+
* ])
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* Note for Electron apps: if the app is packaged with asar, add
|
|
18
|
+
* `node_modules/@devxiyang/agent-skill/skills` to `asarUnpack` in
|
|
19
|
+
* electron-builder config so the directory is accessible via the filesystem.
|
|
20
|
+
*/
|
|
21
|
+
export function builtinSkillsRoot() {
|
|
22
|
+
const dir = path.dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
return path.resolve(dir, '..', 'skills');
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=builtin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtin.js","sourceRoot":"","sources":["../src/builtin.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACzD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC"}
|
package/dist/copy.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type CopySkillsOptions = {
|
|
2
|
+
/** Source skills root directory (e.g. builtinSkillsRoot()). */
|
|
3
|
+
from: string;
|
|
4
|
+
/** Target directory to copy skills into. Created if it does not exist. */
|
|
5
|
+
to: string;
|
|
6
|
+
/** Only copy these skill names. Copies all if omitted. */
|
|
7
|
+
skills?: string[];
|
|
8
|
+
/** Overwrite existing skill folders. Default: false. */
|
|
9
|
+
overwrite?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export type CopySkillsResult = {
|
|
12
|
+
/** Names of skills that were successfully copied. */
|
|
13
|
+
copied: string[];
|
|
14
|
+
/** Names of skills that were skipped because they already exist and overwrite is false. */
|
|
15
|
+
skipped: string[];
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Copy skill folders from a source root into a target directory.
|
|
19
|
+
*
|
|
20
|
+
* Only directories that contain a SKILL.md are treated as valid skills;
|
|
21
|
+
* everything else is silently ignored.
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { copySkills, builtinSkillsRoot } from '@devxiyang/agent-skill';
|
|
25
|
+
*
|
|
26
|
+
* await copySkills({ from: builtinSkillsRoot(), to: '/my/workspace/skills' });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function copySkills(options: CopySkillsOptions): Promise<CopySkillsResult>;
|
|
30
|
+
//# sourceMappingURL=copy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy.d.ts","sourceRoot":"","sources":["../src/copy.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,EAAE,EAAE,MAAM,CAAC;IACX,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,qDAAqD;IACrD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,2FAA2F;IAC3F,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4CtF"}
|
package/dist/copy.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Copy skill folders from a source root into a target directory.
|
|
5
|
+
*
|
|
6
|
+
* Only directories that contain a SKILL.md are treated as valid skills;
|
|
7
|
+
* everything else is silently ignored.
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { copySkills, builtinSkillsRoot } from '@devxiyang/agent-skill';
|
|
11
|
+
*
|
|
12
|
+
* await copySkills({ from: builtinSkillsRoot(), to: '/my/workspace/skills' });
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export async function copySkills(options) {
|
|
16
|
+
const { from, to, skills, overwrite = false } = options;
|
|
17
|
+
await fs.mkdir(to, { recursive: true });
|
|
18
|
+
const dirents = await fs.readdir(from, { withFileTypes: true });
|
|
19
|
+
const candidates = dirents.filter((d) => d.isDirectory() && !d.name.startsWith('.'));
|
|
20
|
+
// Apply optional name filter.
|
|
21
|
+
const targets = skills
|
|
22
|
+
? candidates.filter((d) => skills.includes(d.name))
|
|
23
|
+
: candidates;
|
|
24
|
+
const copied = [];
|
|
25
|
+
const skipped = [];
|
|
26
|
+
for (const dirent of targets) {
|
|
27
|
+
const srcPath = path.join(from, dirent.name);
|
|
28
|
+
const destPath = path.join(to, dirent.name);
|
|
29
|
+
// Validate: must contain a SKILL.md to be considered a skill folder.
|
|
30
|
+
try {
|
|
31
|
+
await fs.access(path.join(srcPath, 'SKILL.md'));
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const destExists = await exists(destPath);
|
|
37
|
+
if (destExists && !overwrite) {
|
|
38
|
+
skipped.push(dirent.name);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (destExists) {
|
|
42
|
+
await fs.rm(destPath, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
await copyDir(srcPath, destPath);
|
|
45
|
+
copied.push(dirent.name);
|
|
46
|
+
}
|
|
47
|
+
return { copied, skipped };
|
|
48
|
+
}
|
|
49
|
+
/** Recursively copies a directory tree from src to dest. */
|
|
50
|
+
async function copyDir(src, dest) {
|
|
51
|
+
await fs.mkdir(dest, { recursive: true });
|
|
52
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
53
|
+
for (const entry of entries) {
|
|
54
|
+
const srcEntry = path.join(src, entry.name);
|
|
55
|
+
const destEntry = path.join(dest, entry.name);
|
|
56
|
+
if (entry.isDirectory()) {
|
|
57
|
+
await copyDir(srcEntry, destEntry);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
await fs.copyFile(srcEntry, destEntry);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function exists(p) {
|
|
65
|
+
try {
|
|
66
|
+
await fs.access(p);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=copy.js.map
|
package/dist/copy.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy.js","sourceRoot":"","sources":["../src/copy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAoB7B;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAA0B;IACzD,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAExD,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAExC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAC/B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAClD,CAAC;IAEF,8BAA8B;IAC9B,MAAM,OAAO,GAAG,MAAM;QACpB,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC,CAAC,UAAU,CAAC;IAEf,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAE5C,qEAAqE;QACrE,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,UAAU,IAAI,CAAC,SAAS,EAAE,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC1B,SAAS;QACX,CAAC;QAED,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC;AAED,4DAA4D;AAC5D,KAAK,UAAU,OAAO,CAAC,GAAW,EAAE,IAAY;IAC9C,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,OAAO,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACrC,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,CAAS;IAC7B,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { SkillEntry, SkillRoot } from '../types.js';
|
|
2
|
+
import type { SkillValidator } from '../validator.js';
|
|
3
|
+
/**
|
|
4
|
+
* Discovers and loads skills from one or more root directories.
|
|
5
|
+
*
|
|
6
|
+
* Priority is determined by the order of the `roots` array — the first root
|
|
7
|
+
* that contains a skill folder with a given name wins; subsequent roots are
|
|
8
|
+
* skipped for that name. Place higher-priority roots (e.g. user overrides)
|
|
9
|
+
* before lower-priority ones (e.g. built-in skills).
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* const discovery = new SkillDiscovery([
|
|
13
|
+
* { path: userSkillsDir, scope: 'user' }, // checked first
|
|
14
|
+
* { path: builtinSkillsRoot(), scope: 'system' }, // fallback
|
|
15
|
+
* ]);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare class SkillDiscovery {
|
|
19
|
+
private readonly roots;
|
|
20
|
+
private readonly validator;
|
|
21
|
+
constructor(roots: SkillRoot[], validator?: SkillValidator);
|
|
22
|
+
/**
|
|
23
|
+
* Scans all roots and returns every discovered skill with its eligibility status.
|
|
24
|
+
*
|
|
25
|
+
* Skills are deduplicated by folder name (first-root-wins). The returned array
|
|
26
|
+
* is sorted alphabetically by skill name.
|
|
27
|
+
*/
|
|
28
|
+
list(): Promise<SkillEntry[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Reads a SKILL.md file and returns its body with the frontmatter block stripped.
|
|
31
|
+
* This is the content suitable for injecting into an agent's context.
|
|
32
|
+
*/
|
|
33
|
+
load(filePath: string): Promise<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Checks all requires/os constraints declared in the frontmatter against the
|
|
36
|
+
* current environment and returns a list of unmet requirements.
|
|
37
|
+
*/
|
|
38
|
+
private resolveMissing;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/discovery/discovery.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAsB,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAItD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,cAAc;IAIvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAHxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;gBAGxB,KAAK,EAAE,SAAS,EAAE,EACnC,SAAS,CAAC,EAAE,cAAc;IAK5B;;;;;OAKG;IACG,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAqCnC;;;OAGG;IACG,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO7C;;;OAGG;YACW,cAAc;CAyB7B"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { defaultValidator } from '../validators/index.js';
|
|
4
|
+
import { parseFrontmatter, stripFrontmatter } from './frontmatter.js';
|
|
5
|
+
/**
|
|
6
|
+
* Discovers and loads skills from one or more root directories.
|
|
7
|
+
*
|
|
8
|
+
* Priority is determined by the order of the `roots` array — the first root
|
|
9
|
+
* that contains a skill folder with a given name wins; subsequent roots are
|
|
10
|
+
* skipped for that name. Place higher-priority roots (e.g. user overrides)
|
|
11
|
+
* before lower-priority ones (e.g. built-in skills).
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* const discovery = new SkillDiscovery([
|
|
15
|
+
* { path: userSkillsDir, scope: 'user' }, // checked first
|
|
16
|
+
* { path: builtinSkillsRoot(), scope: 'system' }, // fallback
|
|
17
|
+
* ]);
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export class SkillDiscovery {
|
|
21
|
+
roots;
|
|
22
|
+
validator;
|
|
23
|
+
constructor(roots, validator) {
|
|
24
|
+
this.roots = roots;
|
|
25
|
+
this.validator = validator ?? defaultValidator;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Scans all roots and returns every discovered skill with its eligibility status.
|
|
29
|
+
*
|
|
30
|
+
* Skills are deduplicated by folder name (first-root-wins). The returned array
|
|
31
|
+
* is sorted alphabetically by skill name.
|
|
32
|
+
*/
|
|
33
|
+
async list() {
|
|
34
|
+
const byName = new Map();
|
|
35
|
+
for (const root of this.roots) {
|
|
36
|
+
if (!(await exists(root.path)))
|
|
37
|
+
continue;
|
|
38
|
+
const dirents = await fs.readdir(root.path, { withFileTypes: true });
|
|
39
|
+
for (const dirent of dirents) {
|
|
40
|
+
if (!dirent.isDirectory() || dirent.name.startsWith('.'))
|
|
41
|
+
continue;
|
|
42
|
+
// First root wins — skip if already discovered from a higher-priority root.
|
|
43
|
+
if (byName.has(dirent.name))
|
|
44
|
+
continue;
|
|
45
|
+
const skillPath = path.join(root.path, dirent.name);
|
|
46
|
+
const filePath = path.join(skillPath, 'SKILL.md');
|
|
47
|
+
if (!(await exists(filePath)))
|
|
48
|
+
continue;
|
|
49
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
50
|
+
const fm = parseFrontmatter(content);
|
|
51
|
+
const missing = await this.resolveMissing(fm);
|
|
52
|
+
byName.set(dirent.name, {
|
|
53
|
+
name: fm.name ?? dirent.name,
|
|
54
|
+
description: fm.description,
|
|
55
|
+
path: skillPath,
|
|
56
|
+
filePath,
|
|
57
|
+
scope: root.scope,
|
|
58
|
+
eligible: missing.length === 0,
|
|
59
|
+
always: fm.always,
|
|
60
|
+
tags: fm.tags,
|
|
61
|
+
missing,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Reads a SKILL.md file and returns its body with the frontmatter block stripped.
|
|
69
|
+
* This is the content suitable for injecting into an agent's context.
|
|
70
|
+
*/
|
|
71
|
+
async load(filePath) {
|
|
72
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
73
|
+
return stripFrontmatter(content);
|
|
74
|
+
}
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
/**
|
|
77
|
+
* Checks all requires/os constraints declared in the frontmatter against the
|
|
78
|
+
* current environment and returns a list of unmet requirements.
|
|
79
|
+
*/
|
|
80
|
+
async resolveMissing(fm) {
|
|
81
|
+
const missing = [];
|
|
82
|
+
for (const bin of fm.requiresBins) {
|
|
83
|
+
if (!(await this.validator.checkBin(bin))) {
|
|
84
|
+
missing.push({ kind: 'bin', value: bin, message: `Missing executable: ${bin}` });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
for (const env of fm.requiresEnvs) {
|
|
88
|
+
if (!this.validator.checkEnv(env)) {
|
|
89
|
+
missing.push({ kind: 'env', value: env, message: `Missing env var: ${env}` });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (fm.requiresOs.length > 0 && !this.validator.checkOs(fm.requiresOs)) {
|
|
93
|
+
missing.push({
|
|
94
|
+
kind: 'os',
|
|
95
|
+
value: fm.requiresOs.join(','),
|
|
96
|
+
message: `Requires OS: ${fm.requiresOs.join(' or ')}`,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return missing;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async function exists(p) {
|
|
103
|
+
try {
|
|
104
|
+
await fs.access(p);
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/discovery/discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Parsed and normalized representation of a SKILL.md frontmatter block. */
|
|
2
|
+
export type SkillFrontmatter = {
|
|
3
|
+
name: string | null;
|
|
4
|
+
description: string | null;
|
|
5
|
+
always: boolean;
|
|
6
|
+
tags: string[];
|
|
7
|
+
requiresBins: string[];
|
|
8
|
+
requiresEnvs: string[];
|
|
9
|
+
requiresOs: string[];
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Parses the YAML frontmatter of a SKILL.md file into a normalized structure.
|
|
13
|
+
*
|
|
14
|
+
* Supports two requirement sources:
|
|
15
|
+
* 1. Top-level `requires` field: `bin:git,env:GITHUB_TOKEN`
|
|
16
|
+
* 2. `metadata` field: a JSON string with a namespaced object (`octoii` or `openclaw`)
|
|
17
|
+
* containing `requires`, `bins`, `env`, and `os` keys.
|
|
18
|
+
*
|
|
19
|
+
* Values from both sources are merged and deduplicated.
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseFrontmatter(content: string): SkillFrontmatter;
|
|
22
|
+
/**
|
|
23
|
+
* Strips the frontmatter block from a SKILL.md file and returns the trimmed body.
|
|
24
|
+
* This is the markdown content passed to the agent as skill instructions.
|
|
25
|
+
*/
|
|
26
|
+
export declare function stripFrontmatter(content: string): string;
|
|
27
|
+
//# sourceMappingURL=frontmatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/discovery/frontmatter.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAgBlE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD"}
|