skill-tree 0.0.1 → 0.1.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.
- package/README.md +324 -1
- package/dist/chunk-5QGJJCVX.mjs +15392 -0
- package/dist/cli/index.d.mts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +15285 -0
- package/dist/cli/index.mjs +3569 -0
- package/dist/index.d.mts +6805 -4
- package/dist/index.d.ts +6805 -4
- package/dist/index.js +15521 -3
- package/dist/index.mjs +244 -3
- package/package.json +28 -5
package/README.md
CHANGED
|
@@ -1 +1,324 @@
|
|
|
1
|
-
# skill-
|
|
1
|
+
# skill-tree
|
|
2
|
+
|
|
3
|
+
A TypeScript library for managing agent skill versions and evolution. Extract, iterate, and adapt skills from agent trajectories.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
skill-tree helps you build and maintain a library of reusable skills for AI agents by:
|
|
8
|
+
|
|
9
|
+
- **Extracting skills** from agent sessions/trajectories (manual or automatic)
|
|
10
|
+
- **Storing skills** in a versioned, searchable format (OpenSkills-compatible)
|
|
11
|
+
- **Evolving skills** through versioning, forking, and merging
|
|
12
|
+
- **Quality gates** to ensure extracted skills are reusable and non-trivial
|
|
13
|
+
|
|
14
|
+
Inspired by research on skill libraries ([arXiv:2512.17102](https://arxiv.org/abs/2512.17102)), [Claudeception](https://github.com/blader/Claudeception), and [OpenSkills](https://github.com/numman-ali/openskills).
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install skill-tree
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { createSkillBank } from 'skill-tree';
|
|
26
|
+
|
|
27
|
+
// Create a skill bank with filesystem storage
|
|
28
|
+
const skillBank = createSkillBank({
|
|
29
|
+
storage: {
|
|
30
|
+
type: 'filesystem',
|
|
31
|
+
basePath: './skills',
|
|
32
|
+
openSkillsCompatible: true,
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
await skillBank.initialize();
|
|
37
|
+
|
|
38
|
+
// Parse a Claude Code session
|
|
39
|
+
const trajectory = await skillBank.parseSession(sessionContent);
|
|
40
|
+
|
|
41
|
+
// Extract a skill manually
|
|
42
|
+
const result = await skillBank.extractManual(trajectory, {
|
|
43
|
+
suggestedName: 'typescript-import-fix',
|
|
44
|
+
description: 'Fix TypeScript ES module import errors',
|
|
45
|
+
tags: ['typescript', 'imports'],
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
if (result.success) {
|
|
49
|
+
console.log('Extracted skill:', result.skill.name);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Search for skills
|
|
53
|
+
const skills = await skillBank.searchSkills('typescript error');
|
|
54
|
+
|
|
55
|
+
// Create a new version
|
|
56
|
+
const updated = await skillBank.createVersion('typescript-import-fix', {
|
|
57
|
+
solution: 'Updated solution...',
|
|
58
|
+
}, { bumpType: 'minor' });
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Core Concepts
|
|
62
|
+
|
|
63
|
+
### Skills
|
|
64
|
+
|
|
65
|
+
A skill represents a reusable piece of knowledge extracted from agent interactions:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
interface Skill {
|
|
69
|
+
id: string; // Unique identifier
|
|
70
|
+
name: string; // Human-readable name
|
|
71
|
+
version: string; // Semantic version
|
|
72
|
+
description: string; // For semantic matching
|
|
73
|
+
problem: string; // What problem this solves
|
|
74
|
+
triggerConditions: TriggerCondition[]; // When to apply
|
|
75
|
+
solution: string; // Step-by-step solution
|
|
76
|
+
verification: string; // How to verify it worked
|
|
77
|
+
examples: SkillExample[]; // Usage examples
|
|
78
|
+
// ... metadata, metrics, lineage
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Trajectories
|
|
83
|
+
|
|
84
|
+
Agent sessions are parsed into trajectories:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
interface Trajectory {
|
|
88
|
+
sessionId: string;
|
|
89
|
+
turns: Turn[]; // User/assistant/tool interactions
|
|
90
|
+
metadata: TrajectoryMetadata;
|
|
91
|
+
outcome?: TrajectoryOutcome;
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Quality Gates
|
|
96
|
+
|
|
97
|
+
Extraction includes quality gates (inspired by Claudeception) to ensure skills are:
|
|
98
|
+
|
|
99
|
+
- **Reusable**: Applicable across multiple future tasks
|
|
100
|
+
- **Non-trivial**: Involves discovery beyond documentation lookup
|
|
101
|
+
- **Specific**: Has clear trigger conditions
|
|
102
|
+
- **Verified**: Solution demonstrably works
|
|
103
|
+
|
|
104
|
+
## Features
|
|
105
|
+
|
|
106
|
+
### Session Adapters
|
|
107
|
+
|
|
108
|
+
Parse different agent session formats:
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
// Built-in: Claude Code JSONL
|
|
112
|
+
const trajectory = await skillBank.parseSession(jsonlContent);
|
|
113
|
+
|
|
114
|
+
// Register custom adapters
|
|
115
|
+
skillBank.registerAdapter(myCustomAdapter);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Extraction Modes
|
|
119
|
+
|
|
120
|
+
**Manual extraction** with user guidance:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
const result = await skillBank.extractManual(trajectory, {
|
|
124
|
+
turnRange: [5, 15], // Extract specific turns
|
|
125
|
+
suggestedName: 'my-skill',
|
|
126
|
+
tags: ['debugging'],
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Automatic extraction** using LLM:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
skillBank.setLLMProvider(myLLMProvider);
|
|
134
|
+
|
|
135
|
+
const results = await skillBank.extractAutomatic(trajectory, {
|
|
136
|
+
minConfidence: 0.7,
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Storage
|
|
141
|
+
|
|
142
|
+
**Filesystem storage** (OpenSkills-compatible):
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
const skillBank = createSkillBank({
|
|
146
|
+
storage: {
|
|
147
|
+
type: 'filesystem',
|
|
148
|
+
basePath: '~/.skills',
|
|
149
|
+
openSkillsCompatible: true, // YAML frontmatter + Markdown
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Memory storage** (for testing):
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
const skillBank = createSkillBank({
|
|
158
|
+
storage: { type: 'memory' },
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Skills are stored in the OpenSkills format:
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
skills/
|
|
166
|
+
├── my-skill/
|
|
167
|
+
│ ├── SKILL.md # Skill content (YAML + Markdown)
|
|
168
|
+
│ └── .skilltree.json # Metadata and lineage
|
|
169
|
+
└── .versions/
|
|
170
|
+
└── my-skill/
|
|
171
|
+
├── 1.0.0.json # Version snapshots
|
|
172
|
+
└── 1.1.0.json
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Versioning
|
|
176
|
+
|
|
177
|
+
Semantic versioning with full lineage tracking:
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
// Create new version
|
|
181
|
+
const v2 = await skillBank.createVersion('my-skill', updates, {
|
|
182
|
+
bumpType: 'minor',
|
|
183
|
+
changelog: 'Added alternative solution',
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Get version history
|
|
187
|
+
const history = await skillBank.getVersionHistory('my-skill');
|
|
188
|
+
|
|
189
|
+
// Rollback to previous version
|
|
190
|
+
const restored = await skillBank.rollbackSkill('my-skill', '1.0.0');
|
|
191
|
+
|
|
192
|
+
// Compare versions
|
|
193
|
+
const diff = await skillBank.compareVersions('my-skill', '1.0.0', '2.0.0');
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Skill Evolution
|
|
197
|
+
|
|
198
|
+
Fork and merge skills:
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
// Fork for a specialized use case
|
|
202
|
+
const forked = await skillBank.forkSkill('my-skill', {
|
|
203
|
+
newId: 'my-skill-react',
|
|
204
|
+
newName: 'My Skill (React variant)',
|
|
205
|
+
reason: 'Specialized for React projects',
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Merge improvements back
|
|
209
|
+
const merged = await skillBank.lineageTracker.mergeSkill(
|
|
210
|
+
'my-skill',
|
|
211
|
+
'my-skill-react',
|
|
212
|
+
{ fields: ['solution', 'examples'] }
|
|
213
|
+
);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Events
|
|
217
|
+
|
|
218
|
+
Subscribe to skill bank events:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
const unsubscribe = skillBank.on((event) => {
|
|
222
|
+
switch (event.type) {
|
|
223
|
+
case 'skill:created':
|
|
224
|
+
console.log('New skill:', event.skill.name);
|
|
225
|
+
break;
|
|
226
|
+
case 'extraction:completed':
|
|
227
|
+
console.log('Extraction confidence:', event.result.confidence);
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## API Reference
|
|
234
|
+
|
|
235
|
+
### SkillBank
|
|
236
|
+
|
|
237
|
+
Main orchestrator class.
|
|
238
|
+
|
|
239
|
+
| Method | Description |
|
|
240
|
+
|--------|-------------|
|
|
241
|
+
| `initialize()` | Initialize storage (required before use) |
|
|
242
|
+
| `parseSession(content, adapter?)` | Parse session into trajectory |
|
|
243
|
+
| `extractManual(trajectory, options?)` | Extract skill with guidance |
|
|
244
|
+
| `extractAutomatic(trajectory, options?)` | Extract skills using LLM |
|
|
245
|
+
| `getSkill(id, version?)` | Get skill by ID |
|
|
246
|
+
| `listSkills(filter?)` | List skills with optional filter |
|
|
247
|
+
| `searchSkills(query)` | Search skills by text |
|
|
248
|
+
| `saveSkill(skill)` | Save or update a skill |
|
|
249
|
+
| `deleteSkill(id, version?)` | Delete a skill |
|
|
250
|
+
| `createVersion(id, updates, options?)` | Create new version |
|
|
251
|
+
| `forkSkill(id, options)` | Fork a skill |
|
|
252
|
+
| `getVersionHistory(id)` | Get version history |
|
|
253
|
+
| `rollbackSkill(id, version)` | Rollback to version |
|
|
254
|
+
| `on(handler)` | Subscribe to events |
|
|
255
|
+
|
|
256
|
+
### Versioning Utilities
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
import {
|
|
260
|
+
parseVersion,
|
|
261
|
+
compareVersions,
|
|
262
|
+
bumpVersion,
|
|
263
|
+
satisfiesRange,
|
|
264
|
+
} from 'skill-tree';
|
|
265
|
+
|
|
266
|
+
bumpVersion('1.2.3', 'minor'); // '1.3.0'
|
|
267
|
+
satisfiesRange('1.5.0', '^1.2.0'); // true
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Skill Format
|
|
271
|
+
|
|
272
|
+
Skills use YAML frontmatter + Markdown (OpenSkills-compatible):
|
|
273
|
+
|
|
274
|
+
```markdown
|
|
275
|
+
---
|
|
276
|
+
name: typescript-esm-import-fix
|
|
277
|
+
description: |
|
|
278
|
+
Fix TypeScript ES module import errors by adding .js extension
|
|
279
|
+
version: 1.0.0
|
|
280
|
+
author: extracted
|
|
281
|
+
status: active
|
|
282
|
+
date: 2024-01-15
|
|
283
|
+
tags:
|
|
284
|
+
- typescript
|
|
285
|
+
- esm
|
|
286
|
+
- imports
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Problem
|
|
290
|
+
|
|
291
|
+
TypeScript with ES modules requires explicit .js extensions in imports.
|
|
292
|
+
|
|
293
|
+
## Trigger Conditions
|
|
294
|
+
|
|
295
|
+
- **error**: `Cannot find module './utils'`
|
|
296
|
+
- **pattern**: `import .* from '\./[^']+(?<!\.js)'`
|
|
297
|
+
|
|
298
|
+
## Solution
|
|
299
|
+
|
|
300
|
+
1. Add `.js` extension to relative imports
|
|
301
|
+
2. Even for `.ts` files, use `.js` in the import path
|
|
302
|
+
|
|
303
|
+
## Verification
|
|
304
|
+
|
|
305
|
+
Run `tsc` and verify no module resolution errors.
|
|
306
|
+
|
|
307
|
+
## Examples
|
|
308
|
+
|
|
309
|
+
### Basic import fix
|
|
310
|
+
|
|
311
|
+
**Before:**
|
|
312
|
+
```typescript
|
|
313
|
+
import { helper } from './utils'
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**After:**
|
|
317
|
+
```typescript
|
|
318
|
+
import { helper } from './utils.js'
|
|
319
|
+
```
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## License
|
|
323
|
+
|
|
324
|
+
MIT
|