@framers/agentos-skills 0.2.0 → 0.3.0

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.
Files changed (42) hide show
  1. package/README.md +64 -94
  2. package/dist/SkillLoader.d.ts +50 -0
  3. package/dist/SkillLoader.d.ts.map +1 -0
  4. package/dist/SkillLoader.js +291 -0
  5. package/dist/SkillLoader.js.map +1 -0
  6. package/dist/SkillRegistry.d.ts +135 -0
  7. package/dist/SkillRegistry.d.ts.map +1 -0
  8. package/dist/SkillRegistry.js +455 -0
  9. package/dist/SkillRegistry.js.map +1 -0
  10. package/dist/index.d.ts +13 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +13 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/paths.d.ts +35 -0
  15. package/dist/paths.d.ts.map +1 -0
  16. package/dist/paths.js +71 -0
  17. package/dist/paths.js.map +1 -0
  18. package/dist/types.d.ts +231 -0
  19. package/dist/types.d.ts.map +1 -0
  20. package/dist/types.js +21 -0
  21. package/dist/types.js.map +1 -0
  22. package/package.json +31 -13
  23. package/registry/community/.gitkeep +0 -0
  24. package/registry/curated/1password/SKILL.md +0 -53
  25. package/registry/curated/apple-notes/SKILL.md +0 -45
  26. package/registry/curated/apple-reminders/SKILL.md +0 -46
  27. package/registry/curated/coding-agent/SKILL.md +0 -40
  28. package/registry/curated/discord-helper/SKILL.md +0 -43
  29. package/registry/curated/git/SKILL.md +0 -39
  30. package/registry/curated/github/SKILL.md +0 -54
  31. package/registry/curated/healthcheck/SKILL.md +0 -43
  32. package/registry/curated/image-gen/SKILL.md +0 -44
  33. package/registry/curated/notion/SKILL.md +0 -43
  34. package/registry/curated/obsidian/SKILL.md +0 -42
  35. package/registry/curated/slack-helper/SKILL.md +0 -42
  36. package/registry/curated/spotify-player/SKILL.md +0 -44
  37. package/registry/curated/summarize/SKILL.md +0 -40
  38. package/registry/curated/trello/SKILL.md +0 -43
  39. package/registry/curated/weather/SKILL.md +0 -37
  40. package/registry/curated/whisper-transcribe/SKILL.md +0 -58
  41. package/registry.json +0 -363
  42. package/types.d.ts +0 -77
package/README.md CHANGED
@@ -1,6 +1,12 @@
1
+ <p align="center">
2
+ <a href="https://agentos.sh"><img src="logos/agentos-primary-no-tagline-transparent-2x.png" alt="AgentOS" height="56" /></a>
3
+ &nbsp;&nbsp;&nbsp;
4
+ <a href="https://frame.dev"><img src="logos/frame-logo-green-no-tagline.svg" alt="Frame.dev" height="36" /></a>
5
+ </p>
6
+
1
7
  # @framers/agentos-skills
2
8
 
3
- Curated catalog of **skills** for the [AgentOS](https://github.com/framersai/agentos) ecosystem.
9
+ Skills runtime for the [AgentOS](https://github.com/framersai/agentos) ecosystem -- loads, parses, and manages SKILL.md prompt modules.
4
10
 
5
11
  [![npm](https://img.shields.io/npm/v/@framers/agentos-skills?logo=npm&color=cb3837)](https://www.npmjs.com/package/@framers/agentos-skills)
6
12
 
@@ -10,117 +16,81 @@ npm install @framers/agentos-skills
10
16
 
11
17
  ## What's Inside
12
18
 
13
- This package is **data only** no runtime code, no heavy dependencies. It ships:
19
+ This package is the **runtime** for the AgentOS skills system. It provides:
14
20
 
15
- | File | Description |
16
- | ----------------------------- | -------------------------------------------------------------------- |
17
- | `registry/curated/*/SKILL.md` | 16+ curated skill definitions (weather, github, slack, notion, etc.) |
18
- | `registry.json` | Flat JSON index of every skill with metadata |
19
- | `types.d.ts` | TypeScript type declarations for the registry schema |
21
+ | Module | Description |
22
+ | ------------------- | ------------------------------------------------------------------------ |
23
+ | `SkillLoader` | Loads and parses SKILL.md files with YAML frontmatter |
24
+ | `SkillRegistry` | Runtime registry for managing, querying, and filtering loaded skills |
25
+ | `paths` | Path resolution utilities for discovering default skill directories |
26
+ | `types` | Full TypeScript type definitions for skills, metadata, and configuration |
20
27
 
21
- Each skill is a directory containing a `SKILL.md` file with **YAML frontmatter** (metadata, requirements, install specs) and a **markdown body** (instructions injected into an agent's system prompt).
28
+ ## Usage
22
29
 
23
- ## Available Skills
30
+ ```typescript
31
+ import {
32
+ SkillRegistry,
33
+ loadSkillFromDir,
34
+ loadSkillsFromDir,
35
+ resolveDefaultSkillsDirs,
36
+ } from '@framers/agentos-skills';
24
37
 
25
- | Category | Skills |
26
- | ------------------- | ------------------------------------------------------ |
27
- | **Information** | weather, summarize |
28
- | **Developer Tools** | github, coding-agent |
29
- | **Communication** | slack-helper, discord-helper |
30
- | **Productivity** | notion, obsidian, trello, apple-notes, apple-reminders |
31
- | **DevOps** | healthcheck |
32
- | **Media** | spotify-player, whisper-transcribe |
33
- | **Security** | 1password |
34
- | **Creative** | image-gen |
38
+ // Discover default skill directories
39
+ const dirs = resolveDefaultSkillsDirs();
35
40
 
36
- ## Usage
41
+ // Create a registry and load skills
42
+ const registry = new SkillRegistry();
43
+ await registry.loadFromDirs(dirs);
37
44
 
38
- ### Raw data (no dependencies needed)
45
+ console.log(`Loaded ${registry.size} skills`);
39
46
 
40
- ```typescript
41
- import registry from '@framers/agentos-skills';
47
+ // Build a snapshot for LLM context
48
+ const snapshot = registry.buildSnapshot({ platform: 'darwin', strict: true });
49
+ console.log(snapshot.prompt);
50
+ ```
51
+
52
+ ## Relationship to Other Packages
42
53
 
43
- // registry.json is the full catalog
44
- console.log(registry.skills.curated.length); // 16+
54
+ ```
55
+ @framers/agentos-skills <-- You are here (runtime: SkillLoader, SkillRegistry, types)
56
+ @framers/agentos-skills-registry (catalog: 40+ curated SKILL.md files + JSON index)
57
+ @framers/agentos (full cognitive runtime, re-exports skills from here)
45
58
  ```
46
59
 
47
- ### With the typed SDK
60
+ | Package | What | Runtime Code | Dependencies |
61
+ | ------------------------------------ | ----------------------------------------- | :----------: | --------------- |
62
+ | **@framers/agentos-skills** | SkillLoader, SkillRegistry, path utils | Yes | `yaml` |
63
+ | **@framers/agentos-skills-registry** | 40+ SKILL.md files + JSON index + catalog | No | `yaml` |
64
+ | **@framers/agentos** | Full cognitive runtime | Yes | Many |
48
65
 
49
- For programmatic queries, filtering, and runtime loading, use [`@framers/agentos-skills-registry`](https://www.npmjs.com/package/@framers/agentos-skills-registry):
66
+ ## API
50
67
 
51
- ```bash
52
- npm install @framers/agentos-skills-registry
53
- ```
68
+ ### SkillLoader
54
69
 
55
- ```typescript
56
- import { searchSkills, getSkillsByCategory } from '@framers/agentos-skills-registry/catalog';
70
+ - `parseSkillFrontmatter(content)` -- Parse YAML frontmatter from SKILL.md content
71
+ - `extractMetadata(frontmatter)` -- Extract typed SkillMetadata from parsed frontmatter
72
+ - `loadSkillFromDir(dir)` -- Load a single skill from a directory containing SKILL.md
73
+ - `loadSkillsFromDir(dir)` -- Load all skills from a parent directory
74
+ - `filterByPlatform(entries, platform)` -- Filter skill entries by OS platform
75
+ - `filterByEligibility(entries, context)` -- Filter by full eligibility context
76
+ - `checkBinaryRequirements(entry, hasBin)` -- Check if binary requirements are met
57
77
 
58
- const devTools = getSkillsByCategory('developer-tools');
59
- const matches = searchSkills('github');
60
- ```
78
+ ### SkillRegistry
61
79
 
62
- ## Relationship to Other Packages
80
+ - `register(entry)` / `unregister(name)` -- Add/remove skills
81
+ - `loadFromDir(dir)` / `loadFromDirs(dirs)` / `reload(options)` -- Bulk loading
82
+ - `getByName(name)` / `listAll()` / `has(name)` / `size` -- Queries
83
+ - `filterByPlatform(platform)` / `filterByEligibility(context)` -- Filtering
84
+ - `getUserInvocableSkills()` / `getModelInvocableSkills()` -- Invocation filtering
85
+ - `buildSnapshot(options)` -- Build LLM context snapshot
86
+ - `buildPrompt(entries)` -- Format skills into prompt text
87
+ - `buildCommandSpecs(options)` -- Generate CLI command specs
63
88
 
64
- ```
65
- @framers/agentos-skills ← You are here (data: SKILL.md files + JSON index)
66
- └── @framers/agentos-skills-registry (SDK: typed catalog, query helpers, registry factories)
67
- └── @framers/agentos (optional peer: live SkillRegistry + snapshots)
68
- ```
89
+ ### Path Utilities
69
90
 
70
- | Package | What | Runtime Code | Dependencies |
71
- | ------------------------------------ | ----------------------------------------- | :----------: | -------------------------------------- |
72
- | **@framers/agentos-skills** | Raw SKILL.md files + JSON index | No | Zero |
73
- | **@framers/agentos-skills-registry** | Typed catalog + query helpers + factories | Yes | `agentos-skills`, optionally `agentos` |
74
- | **@framers/agentos** | Full cognitive runtime with SkillRegistry | Yes | Many |
75
-
76
- ## Contributing a Skill
77
-
78
- 1. **Fork** the [agentos-skills](https://github.com/framersai/agentos-skills) repository.
79
- 2. **Create** a `SKILL.md` file in `registry/community/<your-skill>/`.
80
- 3. **Open a PR** against `main`.
81
-
82
- See [`CONTRIBUTING.md`](https://github.com/framersai/agentos-skills/blob/main/CONTRIBUTING.md) for the full SKILL.md format spec and submission process.
83
-
84
- ## Community vs Curated
85
-
86
- Skills ship in two tiers, all bundled in this single package:
87
-
88
- | Tier | Namespace | Maintained By | Verified |
89
- | ------------- | ------------ | ------------- | :------: |
90
- | **Curated** | `wunderland` | Core staff | Yes |
91
- | **Community** | `community` | PR contributors | No |
92
-
93
- Curated skills live in `registry/curated/` and are maintained and tested by the AgentOS team. Community skills live in `registry/community/` and are submitted via pull request from the community.
94
-
95
- ## Skill Format Quick Reference
96
-
97
- ```yaml
98
- ---
99
- name: my-skill
100
- description: Short description of what this skill does
101
- namespace: community # or 'wunderland' for curated
102
- category: productivity # information | developer-tools | communication | productivity | devops | media | security | creative
103
- tags: [example, template]
104
- metadata:
105
- openclaw:
106
- emoji: "\U0001F4A1"
107
- primaryEnv: MY_API_KEY # optional
108
- os: [darwin, linux] # optional platform restriction
109
- requires:
110
- bins: [my-tool] # all must exist
111
- install:
112
- - id: brew
113
- kind: brew
114
- formula: my-tool
115
- bins: [my-tool]
116
- label: "Install via Homebrew"
117
- ---
118
-
119
- # My Skill
120
-
121
- Instructions injected into the agent's system prompt go here.
122
- ```
91
+ - `resolveDefaultSkillsDirs(options)` -- Resolve default skill directories to scan
123
92
 
124
93
  ## License
125
94
 
126
95
  MIT
96
+
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @fileoverview Skill Loader for AgentOS
3
+ * @module @framers/agentos-skills/SkillLoader
4
+ *
5
+ * Loads skills from directories by parsing SKILL.md files with YAML frontmatter.
6
+ * Skills are modular capabilities that extend agent functionality.
7
+ */
8
+ import type { SkillEntry, SkillMetadata, SkillEligibilityContext, ParsedSkillFrontmatter } from './types.js';
9
+ /**
10
+ * Parse YAML frontmatter from SKILL.md content.
11
+ * Supports the standard `---` delimited format.
12
+ */
13
+ export declare function parseSkillFrontmatter(content: string): {
14
+ frontmatter: ParsedSkillFrontmatter;
15
+ body: string;
16
+ };
17
+ /**
18
+ * Extract SkillMetadata from parsed frontmatter.
19
+ */
20
+ export declare function extractMetadata(frontmatter: ParsedSkillFrontmatter): SkillMetadata | undefined;
21
+ /**
22
+ * Load a single skill from a directory.
23
+ *
24
+ * @param skillDir - Path to skill directory (should contain SKILL.md)
25
+ * @returns SkillEntry or null if invalid
26
+ */
27
+ export declare function loadSkillFromDir(skillDir: string): Promise<SkillEntry | null>;
28
+ /**
29
+ * Load all skills from a directory.
30
+ *
31
+ * @param dir - Parent directory containing skill subdirectories
32
+ * @returns Array of SkillEntry objects
33
+ */
34
+ export declare function loadSkillsFromDir(dir: string): Promise<SkillEntry[]>;
35
+ /**
36
+ * Filter skill entries by platform.
37
+ */
38
+ export declare function filterByPlatform(entries: SkillEntry[], platform: string): SkillEntry[];
39
+ /**
40
+ * Filter skill entries by eligibility context.
41
+ */
42
+ export declare function filterByEligibility(entries: SkillEntry[], context: SkillEligibilityContext): SkillEntry[];
43
+ /**
44
+ * Check if all binary requirements for a skill are met.
45
+ */
46
+ export declare function checkBinaryRequirements(entry: SkillEntry, hasBin: (bin: string) => boolean): {
47
+ met: boolean;
48
+ missing: string[];
49
+ };
50
+ //# sourceMappingURL=SkillLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillLoader.d.ts","sourceRoot":"","sources":["../src/SkillLoader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAEV,UAAU,EACV,aAAa,EACb,uBAAuB,EACvB,sBAAsB,EAEvB,MAAM,YAAY,CAAC;AAQpB;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG;IACtD,WAAW,EAAE,sBAAsB,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;CACd,CAkCA;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,sBAAsB,GAAG,aAAa,GAAG,SAAS,CAoC9F;AAiED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAyCnF;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAuB1E;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE,CAStF;AAaD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,UAAU,EAAE,EACrB,OAAO,EAAE,uBAAuB,GAC/B,UAAU,EAAE,CA+Bd;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,GAC/B;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAgBrC"}
@@ -0,0 +1,291 @@
1
+ /**
2
+ * @fileoverview Skill Loader for AgentOS
3
+ * @module @framers/agentos-skills/SkillLoader
4
+ *
5
+ * Loads skills from directories by parsing SKILL.md files with YAML frontmatter.
6
+ * Skills are modular capabilities that extend agent functionality.
7
+ */
8
+ import * as fs from 'fs';
9
+ import * as path from 'path';
10
+ import YAML from 'yaml';
11
+ const fsp = fs.promises;
12
+ // ============================================================================
13
+ // FRONTMATTER PARSING
14
+ // ============================================================================
15
+ /**
16
+ * Parse YAML frontmatter from SKILL.md content.
17
+ * Supports the standard `---` delimited format.
18
+ */
19
+ export function parseSkillFrontmatter(content) {
20
+ const normalized = content.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
21
+ const lines = normalized.split('\n');
22
+ // Check for frontmatter start
23
+ if (lines[0]?.trim() !== '---') {
24
+ return { frontmatter: {}, body: normalized.trim() };
25
+ }
26
+ // Find frontmatter end
27
+ let endIndex = -1;
28
+ for (let i = 1; i < lines.length; i++) {
29
+ if (lines[i]?.trim() === '---') {
30
+ endIndex = i;
31
+ break;
32
+ }
33
+ }
34
+ if (endIndex === -1) {
35
+ return { frontmatter: {}, body: normalized.trim() };
36
+ }
37
+ const frontmatterBlock = lines.slice(1, endIndex).join('\n');
38
+ const body = lines.slice(endIndex + 1).join('\n').trim();
39
+ try {
40
+ const parsed = YAML.parse(frontmatterBlock);
41
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
42
+ return { frontmatter: {}, body };
43
+ }
44
+ return { frontmatter: parsed, body };
45
+ }
46
+ catch {
47
+ return { frontmatter: {}, body };
48
+ }
49
+ }
50
+ /**
51
+ * Extract SkillMetadata from parsed frontmatter.
52
+ */
53
+ export function extractMetadata(frontmatter) {
54
+ const metadataValue = frontmatter.metadata;
55
+ let meta = undefined;
56
+ if (metadataValue && typeof metadataValue === 'object') {
57
+ const mObj = metadataValue;
58
+ meta = mObj.openclaw ?? mObj.wunderland ?? mObj.agentos ?? mObj;
59
+ }
60
+ else if (typeof metadataValue === 'string' && metadataValue.trim()) {
61
+ // Support OpenClaw-style metadata serialization (JSON-ish string in YAML).
62
+ try {
63
+ meta = JSON.parse(metadataValue);
64
+ }
65
+ catch {
66
+ meta = undefined;
67
+ }
68
+ }
69
+ if (!meta) {
70
+ meta = frontmatter;
71
+ }
72
+ if (!meta || typeof meta !== 'object') {
73
+ return undefined;
74
+ }
75
+ const m = meta;
76
+ return {
77
+ always: m.always === true,
78
+ skillKey: typeof m.skillKey === 'string' ? m.skillKey : undefined,
79
+ primaryEnv: typeof m.primaryEnv === 'string' ? m.primaryEnv : undefined,
80
+ emoji: typeof m.emoji === 'string' ? m.emoji : undefined,
81
+ homepage: typeof m.homepage === 'string' ? m.homepage : undefined,
82
+ os: Array.isArray(m.os) ? m.os : undefined,
83
+ requires: m.requires,
84
+ install: Array.isArray(m.install) ? m.install : undefined,
85
+ };
86
+ }
87
+ /**
88
+ * Extract skill description from body content.
89
+ */
90
+ function extractDescription(body) {
91
+ // Skip markdown title and get first paragraph
92
+ const lines = body.split('\n');
93
+ let inParagraph = false;
94
+ const paragraphLines = [];
95
+ for (const line of lines) {
96
+ const trimmed = line.trim();
97
+ // Skip headings
98
+ if (trimmed.startsWith('#')) {
99
+ if (inParagraph)
100
+ break;
101
+ continue;
102
+ }
103
+ // Skip empty lines before paragraph
104
+ if (!trimmed && !inParagraph) {
105
+ continue;
106
+ }
107
+ // Empty line ends paragraph
108
+ if (!trimmed && inParagraph) {
109
+ break;
110
+ }
111
+ inParagraph = true;
112
+ paragraphLines.push(trimmed);
113
+ }
114
+ return paragraphLines.join(' ').slice(0, 200);
115
+ }
116
+ function coerceBoolean(value) {
117
+ if (typeof value === 'boolean')
118
+ return value;
119
+ if (typeof value === 'string') {
120
+ const lowered = value.trim().toLowerCase();
121
+ if (lowered === 'true')
122
+ return true;
123
+ if (lowered === 'false')
124
+ return false;
125
+ }
126
+ return undefined;
127
+ }
128
+ function resolveSkillInvocationPolicy(frontmatter) {
129
+ const userInvocable = coerceBoolean(frontmatter['user-invocable']) ??
130
+ coerceBoolean(frontmatter.userInvocable) ??
131
+ true;
132
+ const disableModelInvocation = coerceBoolean(frontmatter['disable-model-invocation']) ??
133
+ coerceBoolean(frontmatter.disableModelInvocation) ??
134
+ false;
135
+ return { userInvocable, disableModelInvocation };
136
+ }
137
+ // ============================================================================
138
+ // SKILL LOADING
139
+ // ============================================================================
140
+ /**
141
+ * Load a single skill from a directory.
142
+ *
143
+ * @param skillDir - Path to skill directory (should contain SKILL.md)
144
+ * @returns SkillEntry or null if invalid
145
+ */
146
+ export async function loadSkillFromDir(skillDir) {
147
+ const skillPath = path.join(skillDir, 'SKILL.md');
148
+ try {
149
+ const stat = await fsp.stat(skillPath);
150
+ if (!stat.isFile()) {
151
+ return null;
152
+ }
153
+ const content = await fsp.readFile(skillPath, 'utf-8');
154
+ const { frontmatter, body } = parseSkillFrontmatter(content);
155
+ const name = (typeof frontmatter.name === 'string' && frontmatter.name.trim())
156
+ ? frontmatter.name.trim()
157
+ : path.basename(skillDir);
158
+ const description = (typeof frontmatter.description === 'string' && frontmatter.description.trim())
159
+ ? frontmatter.description.trim()
160
+ : extractDescription(body);
161
+ const skill = {
162
+ name,
163
+ description,
164
+ content: body,
165
+ };
166
+ const metadata = extractMetadata(frontmatter);
167
+ const invocation = resolveSkillInvocationPolicy(frontmatter);
168
+ return {
169
+ skill,
170
+ frontmatter,
171
+ metadata,
172
+ invocation,
173
+ sourcePath: skillDir,
174
+ };
175
+ }
176
+ catch {
177
+ // Skill doesn't exist or is invalid
178
+ return null;
179
+ }
180
+ }
181
+ /**
182
+ * Load all skills from a directory.
183
+ *
184
+ * @param dir - Parent directory containing skill subdirectories
185
+ * @returns Array of SkillEntry objects
186
+ */
187
+ export async function loadSkillsFromDir(dir) {
188
+ const entries = [];
189
+ try {
190
+ const items = await fsp.readdir(dir, { withFileTypes: true });
191
+ for (const item of items) {
192
+ if (!item.isDirectory())
193
+ continue;
194
+ if (item.name.startsWith('.'))
195
+ continue;
196
+ const skillDir = path.join(dir, item.name);
197
+ const entry = await loadSkillFromDir(skillDir);
198
+ if (entry) {
199
+ entries.push(entry);
200
+ }
201
+ }
202
+ }
203
+ catch (err) {
204
+ // Directory doesn't exist or is inaccessible
205
+ console.warn(`[SkillLoader] Failed to load skills from ${dir}:`, err);
206
+ }
207
+ return entries;
208
+ }
209
+ // ============================================================================
210
+ // FILTERING
211
+ // ============================================================================
212
+ /**
213
+ * Filter skill entries by platform.
214
+ */
215
+ export function filterByPlatform(entries, platform) {
216
+ return entries.filter((entry) => {
217
+ const os = entry.metadata?.os;
218
+ if (!os || os.length === 0)
219
+ return true;
220
+ // Normalize platform names
221
+ const normalizedPlatform = normalizeOSName(platform);
222
+ return os.some((p) => normalizeOSName(p) === normalizedPlatform);
223
+ });
224
+ }
225
+ /**
226
+ * Normalize OS name for comparison.
227
+ */
228
+ function normalizeOSName(name) {
229
+ const lower = name.toLowerCase();
230
+ if (lower === 'darwin' || lower === 'macos' || lower === 'mac')
231
+ return 'darwin';
232
+ if (lower === 'win32' || lower === 'windows')
233
+ return 'win32';
234
+ if (lower === 'linux')
235
+ return 'linux';
236
+ return lower;
237
+ }
238
+ /**
239
+ * Filter skill entries by eligibility context.
240
+ */
241
+ export function filterByEligibility(entries, context) {
242
+ return entries.filter((entry) => {
243
+ const requires = entry.metadata?.requires;
244
+ if (!requires)
245
+ return true;
246
+ // Check required binaries
247
+ if (requires.bins && requires.bins.length > 0) {
248
+ const allBins = requires.bins.every((bin) => context.hasBin(bin));
249
+ if (!allBins)
250
+ return false;
251
+ }
252
+ // Check any-of binaries
253
+ if (requires.anyBins && requires.anyBins.length > 0) {
254
+ const anyBin = context.hasAnyBin(requires.anyBins);
255
+ if (!anyBin)
256
+ return false;
257
+ }
258
+ // Check environment variables
259
+ if (requires.env && requires.env.length > 0 && context.hasEnv) {
260
+ const allEnv = requires.env.every((env) => context.hasEnv(env));
261
+ if (!allEnv)
262
+ return false;
263
+ }
264
+ // Platform check
265
+ for (const platform of context.platforms) {
266
+ const filtered = filterByPlatform([entry], platform);
267
+ if (filtered.length === 0)
268
+ return false;
269
+ }
270
+ return true;
271
+ });
272
+ }
273
+ /**
274
+ * Check if all binary requirements for a skill are met.
275
+ */
276
+ export function checkBinaryRequirements(entry, hasBin) {
277
+ const requires = entry.metadata?.requires;
278
+ const missing = [];
279
+ if (requires?.bins) {
280
+ for (const bin of requires.bins) {
281
+ if (!hasBin(bin)) {
282
+ missing.push(bin);
283
+ }
284
+ }
285
+ }
286
+ return {
287
+ met: missing.length === 0,
288
+ missing,
289
+ };
290
+ }
291
+ //# sourceMappingURL=SkillLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillLoader.js","sourceRoot":"","sources":["../src/SkillLoader.ts"],"names":[],"mappings":"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"}