@majkapp/plugin-kit 3.7.2 → 3.7.4

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/docs/SKILLS.md ADDED
@@ -0,0 +1,514 @@
1
+ # Skills API - Task Instructions with Tools
2
+
3
+ The Skills API provides a way to manage skills - instructions on how to accomplish tasks using tools. Skills can be database-persisted or runtime-registered with optional setup/teardown functions.
4
+
5
+ ## Quick Start
6
+
7
+ ```typescript
8
+ import { definePlugin } from '@majkapp/plugin-kit';
9
+
10
+ // Access skills from plugin context
11
+ .function('enableCodeReview', {
12
+ description: 'Enable code review mode',
13
+ input: { type: 'object', properties: {}, additionalProperties: false },
14
+ output: { type: 'object', properties: { instructions: { type: 'string' } } },
15
+ handler: async (input, ctx) => {
16
+ const result = await ctx.majk.skills.enable(ctx, {
17
+ skill: 'code-review-mode'
18
+ });
19
+ return { instructions: result.instructions };
20
+ }
21
+ })
22
+ ```
23
+
24
+ ## Interface Overview
25
+
26
+ ```typescript
27
+ export interface SkillsAPI {
28
+ // Discovery
29
+ list(conversationId?: string, includeDisabled?: boolean): Promise<ListSkillsResult>;
30
+ search(conversationId: string | undefined, input: SearchSkillsInput): Promise<SearchSkillsResult>;
31
+ getById(skillId: string): Promise<Skill | null>;
32
+
33
+ // Database skills
34
+ add(conversationId: string | undefined, input: AddSkillInput): Promise<AddSkillResult>;
35
+ update(input: UpdateSkillInput): Promise<UpdateSkillResult>;
36
+ delete(input: DeleteSkillInput): Promise<boolean>;
37
+
38
+ // Activation
39
+ enable(context: SkillContext, input: EnableSkillInput): Promise<EnableSkillResult>;
40
+ disable(conversationId: string, input: DisableSkillInput): Promise<boolean>;
41
+
42
+ // Runtime skills
43
+ registerRuntime(skill: RuntimeSkill): Promise<void>;
44
+ unregisterRuntime(skillId: string): Promise<boolean>;
45
+ getRuntime(skillId: string): Promise<RuntimeSkill | undefined>;
46
+
47
+ // Events
48
+ on(eventType: SkillEventType, handler: (event: SkillEvent) => void): Promise<Unsubscribe>;
49
+ }
50
+ ```
51
+
52
+ ## Core Concepts
53
+
54
+ ### Skill Types
55
+
56
+ 1. **Database Skills** - Persisted skills created via `add()`
57
+ 2. **Runtime Skills** - Memory-only skills with setup/teardown functions
58
+
59
+ ### Skill Definition
60
+
61
+ ```typescript
62
+ interface SkillDefinition {
63
+ id: string; // Unique identifier
64
+ name: string; // Display name
65
+ description: string; // One-sentence description
66
+ instructions: string; // Full task instructions
67
+ tags?: string[]; // Optional categorization
68
+ enabled: boolean; // Whether currently active
69
+ }
70
+ ```
71
+
72
+ ## Discovery Operations
73
+
74
+ ### List Skills
75
+
76
+ ```typescript
77
+ // List all skills
78
+ const { skills, total } = await ctx.majk.skills.list();
79
+
80
+ // Include disabled skills
81
+ const all = await ctx.majk.skills.list(undefined, true);
82
+
83
+ // List conversation-specific skills
84
+ const conversationSkills = await ctx.majk.skills.list(conversationId);
85
+
86
+ console.log(`Found ${skills.length} skills out of ${total} total`);
87
+ ```
88
+
89
+ ### Search Skills
90
+
91
+ ```typescript
92
+ const results = await ctx.majk.skills.search(conversationId, {
93
+ query: 'code review',
94
+ limit: 10,
95
+ includeDisabled: false
96
+ });
97
+
98
+ console.log('Well-matching skills:', results.matching);
99
+ console.log('Related skills:', results.related);
100
+ console.log('Total found:', results.total);
101
+ ```
102
+
103
+ ### Get Skill by ID
104
+
105
+ ```typescript
106
+ const skill = await ctx.majk.skills.getById('code-review-mode');
107
+ if (skill) {
108
+ console.log('Skill:', skill.name);
109
+ console.log('Instructions:', skill.instructions);
110
+ console.log('Source:', skill.source); // 'database' | 'runtime'
111
+ }
112
+ ```
113
+
114
+ ## Database Skills Management
115
+
116
+ ### Adding Skills
117
+
118
+ ```typescript
119
+ const result = await ctx.majk.skills.add(conversationId, {
120
+ id: 'custom-reviewer', // Optional - auto-generated if not provided
121
+ name: 'Custom Code Reviewer',
122
+ description: 'Reviews code with custom standards',
123
+ instructions: `You are now in Custom Code Review Mode.
124
+
125
+ When reviewing code:
126
+ 1. Check for our company coding standards
127
+ 2. Look for security vulnerabilities
128
+ 3. Suggest performance improvements
129
+ 4. Verify test coverage
130
+
131
+ Use these tools:
132
+ - Static analysis tools
133
+ - Security scanners
134
+ - Test coverage reports`,
135
+ tags: ['review', 'code-quality', 'security'],
136
+ enabled: true
137
+ });
138
+
139
+ console.log(`Created skill: ${result.name} (${result.id})`);
140
+ ```
141
+
142
+ ### Updating Skills
143
+
144
+ ```typescript
145
+ const result = await ctx.majk.skills.update({
146
+ id: 'custom-reviewer',
147
+ name: 'Enhanced Code Reviewer',
148
+ description: 'Reviews code with enhanced AI analysis',
149
+ instructions: 'Updated instructions here...',
150
+ tags: ['review', 'ai', 'enhanced']
151
+ });
152
+
153
+ console.log(`Updated: ${result.name}, Success: ${result.updated}`);
154
+ ```
155
+
156
+ ### Deleting Skills
157
+
158
+ ```typescript
159
+ const deleted = await ctx.majk.skills.delete({ id: 'custom-reviewer' });
160
+ console.log('Skill deleted:', deleted);
161
+ ```
162
+
163
+ ## Skill Activation
164
+
165
+ ### Enabling Skills
166
+
167
+ ```typescript
168
+ // Basic skill enablement
169
+ const result = await ctx.majk.skills.enable(ctx, { skill: 'code-review-mode' });
170
+ console.log('Skill enabled:', result.name);
171
+ console.log('Instructions to follow:', result.instructions);
172
+
173
+ // The instructions returned include:
174
+ // - Base skill instructions
175
+ // - Additional context from setup function (if any)
176
+ ```
177
+
178
+ ### Disabling Skills
179
+
180
+ ```typescript
181
+ const disabled = await ctx.majk.skills.disable(conversationId, {
182
+ skill: 'code-review-mode'
183
+ });
184
+ console.log('Skill disabled:', disabled);
185
+ ```
186
+
187
+ ## Runtime Skills
188
+
189
+ Runtime skills exist only in memory and can have setup/teardown functions for dynamic behavior.
190
+
191
+ ### Registering Runtime Skills
192
+
193
+ ```typescript
194
+ await ctx.majk.skills.registerRuntime({
195
+ id: 'dynamic-analyzer',
196
+ name: 'Dynamic Code Analyzer',
197
+ description: 'Analyzes code with runtime context',
198
+ instructions: 'Base instructions for dynamic analysis...',
199
+ enabled: true,
200
+
201
+ // Optional setup function - called when skill is enabled
202
+ setup: async (context: SkillContext) => {
203
+ // Perform setup logic
204
+ console.log(`Setting up for teammate: ${context.teammateId}`);
205
+ console.log(`In conversation: ${context.conversationId}`);
206
+
207
+ // Initialize tools, connect to services, etc.
208
+ const projectPath = process.cwd();
209
+ const config = await loadProjectConfig(projectPath);
210
+
211
+ // Return additional instructions to prepend
212
+ return `Project configuration loaded from ${projectPath}.
213
+ Using ${config.language} with ${config.framework} framework.`;
214
+ },
215
+
216
+ // Optional teardown function - called when skill is disabled
217
+ teardown: async (context: SkillContext) => {
218
+ // Cleanup logic
219
+ console.log(`Cleaning up dynamic analyzer for ${context.teammateId}`);
220
+ await cleanupTempFiles();
221
+ await disconnectServices();
222
+ }
223
+ });
224
+ ```
225
+
226
+ ### Managing Runtime Skills
227
+
228
+ ```typescript
229
+ // Get runtime skill
230
+ const runtimeSkill = await ctx.majk.skills.getRuntime('dynamic-analyzer');
231
+ if (runtimeSkill) {
232
+ console.log('Runtime skill found:', runtimeSkill.name);
233
+ }
234
+
235
+ // Unregister runtime skill
236
+ const removed = await ctx.majk.skills.unregisterRuntime('dynamic-analyzer');
237
+ console.log('Runtime skill removed:', removed);
238
+ ```
239
+
240
+ ## Event Handling
241
+
242
+ Subscribe to skill-related events:
243
+
244
+ ```typescript
245
+ // Subscribe to all skill events
246
+ const unsubscribe = await ctx.majk.skills.on('skill_enabled', (event) => {
247
+ console.log(`Skill ${event.skillId} enabled at ${event.timestamp}`);
248
+ console.log('Event data:', event.data);
249
+ });
250
+
251
+ // Subscribe to specific events
252
+ await ctx.majk.skills.on('skill_added', (event) => {
253
+ console.log('New skill added:', event.skillId);
254
+ });
255
+
256
+ await ctx.majk.skills.on('skill_deleted', (event) => {
257
+ console.log('Skill deleted:', event.skillId);
258
+ });
259
+
260
+ // Clean up subscription
261
+ await unsubscribe();
262
+ ```
263
+
264
+ Event types:
265
+ - `skill_added` - New skill created
266
+ - `skill_updated` - Skill modified
267
+ - `skill_deleted` - Skill removed
268
+ - `skill_enabled` - Skill activated
269
+ - `skill_disabled` - Skill deactivated
270
+
271
+ ## Plugin Integration
272
+
273
+ ### Declaring Skills in Plugins
274
+
275
+ ```typescript
276
+ import { definePlugin } from '@majkapp/plugin-kit';
277
+
278
+ const plugin = definePlugin('code-tools', 'Code Analysis Tools', '1.0.0')
279
+
280
+ // Declare a skill capability
281
+ .skill({
282
+ id: 'advanced-reviewer',
283
+ name: 'Advanced Code Reviewer',
284
+ description: 'Performs deep code analysis with AI',
285
+ instructions: `You are now in Advanced Code Review Mode.
286
+
287
+ Perform comprehensive analysis including:
288
+ - Architecture patterns
289
+ - Performance bottlenecks
290
+ - Security vulnerabilities
291
+ - Maintainability issues`,
292
+ tags: ['review', 'ai', 'advanced']
293
+ })
294
+
295
+ .build();
296
+ ```
297
+
298
+ ## Complete Example
299
+
300
+ Here's a comprehensive example showing database skills, runtime skills, and event handling:
301
+
302
+ ```typescript
303
+ .function('setupCodeReviewWorkflow', {
304
+ description: 'Set up complete code review workflow',
305
+ input: {
306
+ type: 'object',
307
+ properties: {
308
+ projectType: { type: 'string', enum: ['web', 'api', 'mobile'] }
309
+ },
310
+ required: ['projectType'],
311
+ additionalProperties: false
312
+ },
313
+ output: {
314
+ type: 'object',
315
+ properties: {
316
+ skillsEnabled: { type: 'array', items: { type: 'string' } },
317
+ instructions: { type: 'string' }
318
+ }
319
+ },
320
+ handler: async (input, ctx) => {
321
+ const skillsEnabled = [];
322
+
323
+ // 1. Add a persistent skill for this project type
324
+ const projectSkill = await ctx.majk.skills.add(ctx.conversationId, {
325
+ name: `${input.projectType.toUpperCase()} Code Reviewer`,
326
+ description: `Specialized reviewer for ${input.projectType} projects`,
327
+ instructions: `You are reviewing ${input.projectType} code.
328
+ Focus on ${input.projectType}-specific best practices and patterns.`,
329
+ tags: ['review', input.projectType],
330
+ enabled: false
331
+ });
332
+
333
+ // 2. Register a runtime skill with dynamic setup
334
+ await ctx.majk.skills.registerRuntime({
335
+ id: 'project-context-analyzer',
336
+ name: 'Project Context Analyzer',
337
+ description: 'Analyzes project-specific context',
338
+ instructions: 'Analyze code within project context...',
339
+ enabled: true,
340
+
341
+ setup: async (context) => {
342
+ // Analyze project structure
343
+ const analysis = await analyzeProjectStructure(input.projectType);
344
+ return `Project analysis complete: ${analysis.summary}`;
345
+ },
346
+
347
+ teardown: async (context) => {
348
+ await cleanupAnalysisCache();
349
+ }
350
+ });
351
+
352
+ // 3. Enable both skills
353
+ const result1 = await ctx.majk.skills.enable(ctx, {
354
+ skill: projectSkill.id
355
+ });
356
+ skillsEnabled.push(result1.name);
357
+
358
+ const result2 = await ctx.majk.skills.enable(ctx, {
359
+ skill: 'project-context-analyzer'
360
+ });
361
+ skillsEnabled.push(result2.name);
362
+
363
+ // 4. Subscribe to skill events
364
+ await ctx.majk.skills.on('skill_disabled', async (event) => {
365
+ ctx.logger.info(`Skill disabled: ${event.skillId}`);
366
+ // Cleanup if needed
367
+ });
368
+
369
+ return {
370
+ skillsEnabled,
371
+ instructions: `Code review workflow active for ${input.projectType} project.
372
+ ${result1.instructions}
373
+
374
+ ${result2.instructions}`
375
+ };
376
+ }
377
+ })
378
+ ```
379
+
380
+ ## Types Reference
381
+
382
+ ### Input Types
383
+
384
+ ```typescript
385
+ interface AddSkillInput {
386
+ id?: string; // Auto-generated if not provided
387
+ name: string;
388
+ description: string;
389
+ instructions: string;
390
+ tags?: string[];
391
+ enabled: boolean;
392
+ }
393
+
394
+ interface UpdateSkillInput {
395
+ id: string;
396
+ name?: string;
397
+ description?: string;
398
+ instructions?: string;
399
+ tags?: string[];
400
+ enabled?: boolean;
401
+ }
402
+
403
+ interface SearchSkillsInput {
404
+ query: string;
405
+ limit?: number;
406
+ includeDisabled?: boolean;
407
+ }
408
+
409
+ interface EnableSkillInput {
410
+ skill: string; // ID or name
411
+ }
412
+
413
+ interface DisableSkillInput {
414
+ skill: string; // ID or name
415
+ }
416
+ ```
417
+
418
+ ### Output Types
419
+
420
+ ```typescript
421
+ interface ListSkillsResult {
422
+ skills: SkillSummary[];
423
+ total: number;
424
+ }
425
+
426
+ interface SearchSkillsResult {
427
+ matching: SkillSummary[];
428
+ related: SkillSummary[];
429
+ total: number;
430
+ }
431
+
432
+ interface EnableSkillResult {
433
+ id: string;
434
+ name: string;
435
+ instructions: string; // Includes setup additions
436
+ }
437
+
438
+ interface SkillSummary {
439
+ id: string;
440
+ name: string;
441
+ description: string;
442
+ enabled: boolean;
443
+ source: 'database' | 'runtime';
444
+ tags?: string[];
445
+ }
446
+
447
+ interface Skill extends SkillDefinition {
448
+ persisted: boolean;
449
+ hasSetup: boolean;
450
+ hasTeardown: boolean;
451
+ source: 'database' | 'runtime';
452
+ }
453
+ ```
454
+
455
+ ### Context and Functions
456
+
457
+ ```typescript
458
+ interface SkillContext {
459
+ teammateId: string;
460
+ conversationId: string;
461
+ projectRoot: string;
462
+ }
463
+
464
+ type SkillSetupFn = (context: SkillContext) => Promise<string | void>;
465
+ type SkillTeardownFn = (context: SkillContext) => Promise<void>;
466
+
467
+ interface RuntimeSkill extends SkillDefinition {
468
+ setup?: SkillSetupFn;
469
+ teardown?: SkillTeardownFn;
470
+ }
471
+ ```
472
+
473
+ ## Best Practices
474
+
475
+ 1. **Use descriptive IDs** - Make skill IDs meaningful and unique
476
+ 2. **Write clear instructions** - Provide step-by-step guidance
477
+ 3. **Tag appropriately** - Use consistent tags for discoverability
478
+ 4. **Handle setup/teardown** - Clean up resources in teardown functions
479
+ 5. **Subscribe to events** - Monitor skill state changes
480
+ 6. **Conversation scoping** - Use conversation IDs when appropriate
481
+ 7. **Error handling** - Skills operations can fail, handle gracefully
482
+
483
+ ## Common Patterns
484
+
485
+ ### Conditional Skills
486
+
487
+ ```typescript
488
+ // Enable different skills based on context
489
+ const projectType = await detectProjectType();
490
+ const skillId = `${projectType}-expert`;
491
+ await ctx.majk.skills.enable(ctx, { skill: skillId });
492
+ ```
493
+
494
+ ### Skill Chains
495
+
496
+ ```typescript
497
+ // Enable multiple related skills in sequence
498
+ const skills = ['basic-reviewer', 'security-scanner', 'performance-analyzer'];
499
+ for (const skillId of skills) {
500
+ await ctx.majk.skills.enable(ctx, { skill: skillId });
501
+ }
502
+ ```
503
+
504
+ ### Dynamic Instructions
505
+
506
+ ```typescript
507
+ // Use setup to provide context-aware instructions
508
+ setup: async (context) => {
509
+ const codebase = await analyzeCodebase(context.projectRoot);
510
+ return `Codebase uses ${codebase.languages.join(', ')}.
511
+ Primary framework: ${codebase.framework}.
512
+ Focus on ${codebase.framework}-specific patterns.`;
513
+ }
514
+ ```