clawpowers 2.2.5 → 2.2.7
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/CHANGELOG.md +186 -160
- package/COMPATIBILITY.md +48 -13
- package/KNOWN_LIMITATIONS.md +20 -19
- package/LICENSE +44 -44
- package/LICENSING.md +10 -10
- package/README.md +486 -462
- package/SECURITY.md +52 -52
- package/dist/index.d.ts +17 -5
- package/dist/index.js +187 -92
- package/dist/index.js.map +1 -1
- package/native/Cargo.lock +4927 -4927
- package/native/Cargo.toml +73 -73
- package/native/crates/canonical/Cargo.toml +24 -24
- package/native/crates/canonical/src/lib.rs +677 -673
- package/native/crates/compression/Cargo.toml +20 -20
- package/native/crates/compression/benches/compression_bench.rs +42 -42
- package/native/crates/compression/src/lib.rs +393 -393
- package/native/crates/evm-eth/Cargo.toml +13 -13
- package/native/crates/evm-eth/src/lib.rs +105 -105
- package/native/crates/fee/Cargo.toml +15 -15
- package/native/crates/fee/src/lib.rs +281 -281
- package/native/crates/index/Cargo.toml +16 -16
- package/native/crates/index/src/lib.rs +277 -277
- package/native/crates/policy/Cargo.toml +17 -17
- package/native/crates/policy/src/lib.rs +614 -614
- package/native/crates/security/Cargo.toml +22 -22
- package/native/crates/security/src/lib.rs +478 -478
- package/native/crates/tokens/Cargo.toml +13 -13
- package/native/crates/tokens/src/lib.rs +534 -534
- package/native/crates/verification/Cargo.toml +23 -23
- package/native/crates/verification/src/lib.rs +333 -333
- package/native/crates/wallet/Cargo.toml +20 -20
- package/native/crates/wallet/src/lib.rs +261 -261
- package/native/crates/x402/Cargo.toml +30 -30
- package/native/crates/x402/src/lib.rs +423 -423
- package/native/ffi/Cargo.toml +34 -34
- package/native/ffi/build.rs +4 -4
- package/native/ffi/src/lib.rs +352 -352
- package/native/ffi/tests/integration.rs +354 -354
- package/native/pyo3/Cargo.toml +26 -26
- package/native/pyo3/pyproject.toml +16 -16
- package/native/pyo3/src/lib.rs +407 -407
- package/native/pyo3/tests/test_smoke.py +180 -180
- package/native/wasm/Cargo.toml +47 -44
- package/native/wasm/pkg/.gitignore +6 -6
- package/native/wasm/pkg/clawpowers_wasm.d.ts +208 -208
- package/native/wasm/pkg/clawpowers_wasm.js +872 -872
- package/native/wasm/pkg/clawpowers_wasm_bg.wasm.d.ts +40 -40
- package/native/wasm/pkg/package.json +16 -16
- package/native/wasm/pkg-node/clawpowers_wasm.d.ts +143 -143
- package/native/wasm/pkg-node/clawpowers_wasm.js +798 -798
- package/native/wasm/pkg-node/clawpowers_wasm_bg.wasm.d.ts +40 -40
- package/native/wasm/pkg-node/package.json +12 -12
- package/native/wasm/src/lib.rs +433 -433
- package/package.json +13 -8
- package/scripts/build-wasm.mjs +59 -0
- package/scripts/generate_hermes_wrappers.py +211 -0
- package/scripts/hermes_wrapper_overrides.json +184 -0
- package/scripts/run-python-script.mjs +48 -0
- package/scripts/verify-consumer-install.mjs +109 -0
- package/scripts/verify-wasm-artifacts.mjs +26 -3
- package/scripts/verify_hermes_wrappers.py +154 -0
- package/skill.json +20 -0
- package/skills/1password/SKILL.md +34 -0
- package/skills/README.md +44 -0
- package/skills/agent-nexus-2/SKILL.md +34 -0
- package/skills/apple-notes/SKILL.md +34 -0
- package/skills/apple-reminders/SKILL.md +34 -0
- package/skills/autoresearch/SKILL.md +43 -0
- package/skills/bear-notes/SKILL.md +34 -0
- package/skills/blogwatcher/SKILL.md +34 -0
- package/skills/blucli/SKILL.md +34 -0
- package/skills/bluebubbles/SKILL.md +34 -0
- package/skills/business-strategy/SKILL.md +41 -0
- package/skills/camsnap/SKILL.md +34 -0
- package/skills/canvas/SKILL.md +34 -0
- package/skills/clawhub/SKILL.md +34 -0
- package/skills/coding-agent/SKILL.md +34 -0
- package/skills/coding-discipline.skill/SKILL.md +34 -0
- package/skills/content-writer/SKILL.md +41 -0
- package/skills/discord/SKILL.md +34 -0
- package/skills/eightctl/SKILL.md +34 -0
- package/skills/execution-validation.skill/SKILL.md +34 -0
- package/skills/gemini/SKILL.md +34 -0
- package/skills/gh-issues/SKILL.md +34 -0
- package/skills/gifgrep/SKILL.md +34 -0
- package/skills/github/SKILL.md +41 -0
- package/skills/gog/SKILL.md +34 -0
- package/skills/goplaces/SKILL.md +34 -0
- package/skills/healthcheck/SKILL.md +34 -0
- package/skills/himalaya/SKILL.md +34 -0
- package/skills/humanize/SKILL.md +41 -0
- package/skills/imsg/SKILL.md +34 -0
- package/skills/itp/SKILL.md +112 -0
- package/skills/mcporter/SKILL.md +34 -0
- package/skills/model-usage/SKILL.md +34 -0
- package/skills/nano-pdf/SKILL.md +34 -0
- package/skills/node-connect/SKILL.md +34 -0
- package/skills/notion/SKILL.md +34 -0
- package/skills/obsidian/SKILL.md +34 -0
- package/skills/openai-whisper/SKILL.md +34 -0
- package/skills/openai-whisper-api/SKILL.md +34 -0
- package/skills/openhue/SKILL.md +34 -0
- package/skills/oracle/SKILL.md +34 -0
- package/skills/ordercli/SKILL.md +34 -0
- package/skills/peekaboo/SKILL.md +34 -0
- package/skills/polyclaw/SKILL.md +34 -0
- package/skills/prospector/SKILL.md +41 -0
- package/skills/rsi.skill/SKILL.md +34 -0
- package/skills/sag/SKILL.md +34 -0
- package/skills/security/SKILL.md +41 -0
- package/skills/session-logs/SKILL.md +34 -0
- package/skills/sherpa-onnx-tts/SKILL.md +34 -0
- package/skills/skill-creator/SKILL.md +34 -0
- package/skills/slack/SKILL.md +34 -0
- package/skills/songsee/SKILL.md +34 -0
- package/skills/sonoscli/SKILL.md +34 -0
- package/skills/spotify-player/SKILL.md +34 -0
- package/skills/strykr-prism/SKILL.md +41 -0
- package/skills/summarize/SKILL.md +34 -0
- package/skills/taskbridge/SKILL.md +34 -0
- package/skills/things-mac/SKILL.md +34 -0
- package/skills/tmux/SKILL.md +34 -0
- package/skills/trello/SKILL.md +34 -0
- package/skills/validator-agent/SKILL.md +41 -0
- package/skills/video-frames/SKILL.md +34 -0
- package/skills/voice-call/SKILL.md +34 -0
- package/skills/wacli/SKILL.md +34 -0
- package/skills/weather/SKILL.md +34 -0
- package/skills/webmcp-payments/SKILL.md +41 -0
- package/skills/xurl/SKILL.md +34 -0
- package/src/skills/catalog.ts +435 -435
- package/src/skills/executor.ts +56 -56
- package/src/skills/index.ts +3 -3
- package/src/skills/itp/SKILL.md +112 -112
- package/src/skills/loader.ts +262 -193
- package/native/ffi/index.node +0 -0
- package/native/wasm/pkg-node/.gitignore +0 -6
package/src/skills/loader.ts
CHANGED
|
@@ -1,193 +1,262 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ClawPowers Agent — Skill Loader
|
|
3
|
-
* Discovers skills from skill directories, validates SKILL.md frontmatter.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { readdirSync, readFileSync, existsSync, statSync } from 'node:fs';
|
|
7
|
-
import { join } from 'node:path';
|
|
8
|
-
import type { SkillManifest, SkillRequirements, Profile } from '../types.js';
|
|
9
|
-
|
|
10
|
-
// ─── YAML Frontmatter Parser ──────────────────────────────────────────────────
|
|
11
|
-
|
|
12
|
-
interface ParsedFrontmatter {
|
|
13
|
-
name?: string;
|
|
14
|
-
description?: string;
|
|
15
|
-
metadata?: {
|
|
16
|
-
openclaw?: {
|
|
17
|
-
requires?: {
|
|
18
|
-
bins?: string[];
|
|
19
|
-
env?: string[];
|
|
20
|
-
config?: string[];
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* ClawPowers Agent — Skill Loader
|
|
3
|
+
* Discovers skills from skill directories, validates SKILL.md frontmatter.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { readdirSync, readFileSync, existsSync, statSync } from 'node:fs';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
import type { SkillManifest, SkillRequirements, Profile } from '../types.js';
|
|
9
|
+
|
|
10
|
+
// ─── YAML Frontmatter Parser ──────────────────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
interface ParsedFrontmatter {
|
|
13
|
+
name?: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
metadata?: {
|
|
16
|
+
openclaw?: {
|
|
17
|
+
requires?: {
|
|
18
|
+
bins?: string[];
|
|
19
|
+
env?: string[];
|
|
20
|
+
config?: string[];
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function stripQuotes(value: string): string {
|
|
27
|
+
if (value.length >= 2) {
|
|
28
|
+
const first = value[0];
|
|
29
|
+
const last = value[value.length - 1];
|
|
30
|
+
if ((first === '"' && last === '"') || (first === "'" && last === "'")) {
|
|
31
|
+
return value.slice(1, -1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function splitYamlKeyValue(line: string): { key: string; value: string } | null {
|
|
38
|
+
const colonIndex = line.indexOf(':');
|
|
39
|
+
if (colonIndex <= 0) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const key = line.slice(0, colonIndex).trim();
|
|
44
|
+
if (!key) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
for (const char of key) {
|
|
49
|
+
const isAlphaNum =
|
|
50
|
+
(char >= 'a' && char <= 'z')
|
|
51
|
+
|| (char >= 'A' && char <= 'Z')
|
|
52
|
+
|| (char >= '0' && char <= '9')
|
|
53
|
+
|| char === '_';
|
|
54
|
+
if (!isAlphaNum) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
key,
|
|
61
|
+
value: line.slice(colonIndex + 1).trim(),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function parseInlineArray(value: string): string[] | null {
|
|
66
|
+
if (!value.startsWith('[') || !value.endsWith(']')) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const inner = value.slice(1, -1).trim();
|
|
71
|
+
if (!inner) {
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return inner.split(',').map(item => stripQuotes(item.trim())).filter(Boolean);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function parseListItem(line: string): string | null {
|
|
79
|
+
if (!line.startsWith('-')) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const value = line.slice(1).trim();
|
|
84
|
+
if (!value) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return stripQuotes(value);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Parse YAML frontmatter from a SKILL.md file content.
|
|
93
|
+
* Expects format: ---\n<yaml>\n---\n<content>
|
|
94
|
+
*/
|
|
95
|
+
export function parseFrontmatter(content: string): ParsedFrontmatter {
|
|
96
|
+
const normalized = content.replace(/\r\n/g, '\n');
|
|
97
|
+
if (!normalized.startsWith('---\n')) {
|
|
98
|
+
return {};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const endIndex = normalized.indexOf('\n---', 4);
|
|
102
|
+
if (endIndex === -1) {
|
|
103
|
+
return {};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const yamlText = normalized.slice(4, endIndex);
|
|
107
|
+
const result: ParsedFrontmatter = {};
|
|
108
|
+
|
|
109
|
+
// Simple YAML parser for our known structure
|
|
110
|
+
const lines = yamlText.split('\n');
|
|
111
|
+
let currentKey = '';
|
|
112
|
+
let inRequires = false;
|
|
113
|
+
let requiresKey = '';
|
|
114
|
+
const requires: { bins?: string[]; env?: string[]; config?: string[] } = {};
|
|
115
|
+
|
|
116
|
+
for (const line of lines) {
|
|
117
|
+
const trimmed = line.trim();
|
|
118
|
+
if (trimmed === '' || trimmed.startsWith('#')) continue;
|
|
119
|
+
|
|
120
|
+
// Top-level keys
|
|
121
|
+
const topLevel = line === trimmed ? splitYamlKeyValue(trimmed) : null;
|
|
122
|
+
if (topLevel) {
|
|
123
|
+
currentKey = topLevel.key;
|
|
124
|
+
const val = stripQuotes(topLevel.value);
|
|
125
|
+
if (currentKey === 'name' && val) result.name = val;
|
|
126
|
+
if (currentKey === 'description' && val) result.description = val;
|
|
127
|
+
inRequires = false;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// metadata.openclaw.requires detection
|
|
132
|
+
if (trimmed === 'openclaw:') continue;
|
|
133
|
+
if (trimmed === 'requires:') {
|
|
134
|
+
inRequires = true;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (inRequires) {
|
|
139
|
+
const reqKey = splitYamlKeyValue(trimmed);
|
|
140
|
+
if (reqKey) {
|
|
141
|
+
requiresKey = reqKey.key;
|
|
142
|
+
// Inline array: bins: ["node", "git"]
|
|
143
|
+
const items = parseInlineArray(reqKey.value);
|
|
144
|
+
if (items) {
|
|
145
|
+
if (requiresKey === 'bins') requires.bins = items;
|
|
146
|
+
if (requiresKey === 'env') requires.env = items;
|
|
147
|
+
if (requiresKey === 'config') requires.config = items;
|
|
148
|
+
}
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
// List item under requires key
|
|
152
|
+
const listItem = parseListItem(trimmed);
|
|
153
|
+
if (listItem && requiresKey) {
|
|
154
|
+
if (requiresKey === 'bins') {
|
|
155
|
+
requires.bins = requires.bins ?? [];
|
|
156
|
+
requires.bins.push(listItem);
|
|
157
|
+
}
|
|
158
|
+
if (requiresKey === 'env') {
|
|
159
|
+
requires.env = requires.env ?? [];
|
|
160
|
+
requires.env.push(listItem);
|
|
161
|
+
}
|
|
162
|
+
if (requiresKey === 'config') {
|
|
163
|
+
requires.config = requires.config ?? [];
|
|
164
|
+
requires.config.push(listItem);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (Object.keys(requires).length > 0) {
|
|
171
|
+
result.metadata = { openclaw: { requires } };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ─── Skill Discovery ──────────────────────────────────────────────────────────
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Load a single skill manifest from a directory containing SKILL.md
|
|
181
|
+
*/
|
|
182
|
+
export function loadSkillManifest(skillDir: string): SkillManifest | null {
|
|
183
|
+
const skillMdPath = join(skillDir, 'SKILL.md');
|
|
184
|
+
if (!existsSync(skillMdPath)) {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const content = readFileSync(skillMdPath, 'utf-8');
|
|
189
|
+
const frontmatter = parseFrontmatter(content);
|
|
190
|
+
|
|
191
|
+
if (!frontmatter.name || !frontmatter.description) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
let requirements: SkillRequirements | null = null;
|
|
196
|
+
const req = frontmatter.metadata?.openclaw?.requires;
|
|
197
|
+
if (req) {
|
|
198
|
+
requirements = {
|
|
199
|
+
bins: req.bins ?? [],
|
|
200
|
+
env: req.env ?? [],
|
|
201
|
+
config: req.config ?? [],
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return {
|
|
206
|
+
name: frontmatter.name,
|
|
207
|
+
description: frontmatter.description,
|
|
208
|
+
path: skillDir,
|
|
209
|
+
requirements,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Discover all skills in a directory. Each subdirectory with a valid SKILL.md
|
|
215
|
+
* becomes a skill manifest.
|
|
216
|
+
*/
|
|
217
|
+
export function discoverSkills(skillsDir: string): SkillManifest[] {
|
|
218
|
+
if (!existsSync(skillsDir)) {
|
|
219
|
+
return [];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const entries = readdirSync(skillsDir);
|
|
223
|
+
const manifests: SkillManifest[] = [];
|
|
224
|
+
|
|
225
|
+
for (const entry of entries) {
|
|
226
|
+
const fullPath = join(skillsDir, entry);
|
|
227
|
+
if (!statSync(fullPath).isDirectory()) continue;
|
|
228
|
+
|
|
229
|
+
const manifest = loadSkillManifest(fullPath);
|
|
230
|
+
if (manifest) {
|
|
231
|
+
manifests.push(manifest);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return manifests.sort((a, b) => a.name.localeCompare(b.name));
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Filter skills based on active profile.
|
|
240
|
+
* Returns only skills that are listed in the profile's skill list.
|
|
241
|
+
*/
|
|
242
|
+
export function getActiveSkills(
|
|
243
|
+
allSkills: SkillManifest[],
|
|
244
|
+
profile: Profile
|
|
245
|
+
): SkillManifest[] {
|
|
246
|
+
const profileSkillSet = new Set(profile.skills);
|
|
247
|
+
return allSkills.filter(skill => profileSkillSet.has(skill.name));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* List skills with their active/inactive status for a given profile.
|
|
252
|
+
*/
|
|
253
|
+
export function listSkillsWithStatus(
|
|
254
|
+
allSkills: SkillManifest[],
|
|
255
|
+
profile: Profile
|
|
256
|
+
): Array<{ skill: SkillManifest; active: boolean }> {
|
|
257
|
+
const profileSkillSet = new Set(profile.skills);
|
|
258
|
+
return allSkills.map(skill => ({
|
|
259
|
+
skill,
|
|
260
|
+
active: profileSkillSet.has(skill.name),
|
|
261
|
+
}));
|
|
262
|
+
}
|
package/native/ffi/index.node
DELETED
|
Binary file
|