@majkapp/plugin-kit 3.5.3 → 3.5.5

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.
@@ -0,0 +1,585 @@
1
+ # Teammates - AI Agents for Your Plugin
2
+
3
+ Every MAJK plugin can provide AI teammates (agents) that users can interact with. These teammates have access to your plugin's functions and provide natural language interfaces to your plugin's capabilities.
4
+
5
+ ## Quick Start
6
+
7
+ ```typescript
8
+ import { definePlugin } from '@majkapp/plugin-kit';
9
+
10
+ const plugin = definePlugin('my-plugin', 'My Plugin', '1.0.0')
11
+ .pluginRoot(__dirname)
12
+
13
+ .function('getData', {
14
+ description: 'Get data from the system',
15
+ input: { type: 'object', properties: {}, additionalProperties: false },
16
+ output: { type: 'object', properties: { data: { type: 'array' } } },
17
+ handler: async (_, ctx) => ({ data: [] })
18
+ })
19
+
20
+ // Customize the auto-generated teammate's instructions
21
+ .instructions(`You are an expert assistant for My Plugin.
22
+ Help users retrieve and analyze data efficiently.`)
23
+
24
+ .build();
25
+ ```
26
+
27
+ ## Auto-Generated Default Teammate
28
+
29
+ **Every plugin automatically gets a default teammate** with these characteristics:
30
+
31
+ - **Name**: `"<Plugin Name> Expert"` (e.g., "Task Manager Expert")
32
+ - **ID**: Same as your package name (e.g., `"@majk/task-manager"`)
33
+ - **Functions**: ALL plugin functions automatically included
34
+ - **System Prompt**: Generic or customized via `.instructions()`
35
+
36
+ ### How It Works
37
+
38
+ When you define functions in your plugin:
39
+
40
+ ```typescript
41
+ .function('searchTasks', { /* ... */ })
42
+ .function('createTask', { /* ... */ })
43
+ .function('updateTask', { /* ... */ })
44
+ ```
45
+
46
+ MAJK automatically creates a teammate that can call all three functions. Users can then interact with your plugin through natural conversation:
47
+
48
+ > **User**: "Show me all tasks due this week"
49
+ >
50
+ > **Task Manager Expert**: *calls searchTasks({ dueDate: '2024-11-17' })*
51
+ >
52
+ > "Here are your tasks due this week: ..."
53
+
54
+ ### Customizing Instructions
55
+
56
+ Use `.instructions()` to customize the auto-generated teammate's system prompt:
57
+
58
+ ```typescript
59
+ .instructions(`You are an expert assistant for the Weather Plugin.
60
+
61
+ Your capabilities:
62
+ - Get current weather conditions using getCurrentWeather
63
+ - Retrieve 7-day forecasts using getWeeklyForecast
64
+ - Search historical weather data using searchHistory
65
+
66
+ When helping users:
67
+ 1. Always ask for location if not provided
68
+ 2. Present weather data in a clear, formatted way
69
+ 3. Proactively suggest relevant queries (e.g., "Would you like the extended forecast?")
70
+ 4. Use appropriate units based on user's region
71
+
72
+ Be concise but informative. Focus on actionable weather insights.`)
73
+ ```
74
+
75
+ **Best Practices for Instructions**:
76
+ - Clearly list available functions and their purpose
77
+ - Provide guidance on how to interact with users
78
+ - Set expectations for response format
79
+ - Include domain-specific knowledge relevant to your plugin
80
+
81
+ ### Disabling Auto-Generated Teammate
82
+
83
+ If you want complete control over teammates (no default):
84
+
85
+ ```typescript
86
+ .noDefaultTeammate()
87
+ ```
88
+
89
+ Use this when:
90
+ - You want to define all teammates manually
91
+ - Your plugin is purely infrastructure (no user-facing agent needed)
92
+ - You have multiple specialized teammates and don't want a general-purpose one
93
+
94
+ ## Custom Teammates
95
+
96
+ In addition to (or instead of) the auto-generated teammate, you can define custom teammates with specialized roles and limited function access.
97
+
98
+ ### Basic Custom Teammate
99
+
100
+ ```typescript
101
+ .teamMember([
102
+ {
103
+ id: 'weather-viewer',
104
+ name: 'Weather Viewer (Read-Only)',
105
+ systemPrompt: 'You are a read-only assistant for viewing weather data. You can query and display information but cannot modify settings or create alerts.',
106
+ expertise: ['Weather Data', 'Read-Only Operations'],
107
+ skills: {
108
+ primary: ['Data Query', 'Weather Display'],
109
+ secondary: ['Data Analysis'],
110
+ languages: [],
111
+ frameworks: [],
112
+ tools: []
113
+ },
114
+ personality: {
115
+ workStyle: 'methodical',
116
+ codeStyle: 'concise',
117
+ reviewStyle: 'pragmatic',
118
+ communicationStyle: 'explanatory'
119
+ },
120
+ metadata: {
121
+ totalTasks: 0,
122
+ successfulTasks: 0,
123
+ projectHistory: [],
124
+ codeStats: {
125
+ linesWritten: 0,
126
+ filesModified: 0,
127
+ testsWritten: 0,
128
+ reviewsPassed: 0,
129
+ commitsCreated: 0
130
+ }
131
+ },
132
+ mcpServerIds: [],
133
+
134
+ // Specify which functions this teammate can access
135
+ functions: [
136
+ 'getCurrentWeather',
137
+ 'getWeeklyForecast',
138
+ 'searchHistory'
139
+ // NOT included: 'createAlert', 'updateSettings'
140
+ ]
141
+ }
142
+ ])
143
+ ```
144
+
145
+ ### Function Access Control
146
+
147
+ The `functions` field controls which plugin functions a teammate can call:
148
+
149
+ #### Simple Mode (String Array)
150
+
151
+ Just list function names from your plugin:
152
+
153
+ ```typescript
154
+ functions: [
155
+ 'searchTasks', // ✅ Can search
156
+ 'getTasks', // ✅ Can view
157
+ 'uiLog' // ✅ Can debug
158
+ // ❌ Cannot use 'deleteTask' - not included
159
+ ]
160
+ ```
161
+
162
+ **How it works**:
163
+ - Each string is automatically expanded to reference the current plugin
164
+ - Example: `'searchTasks'` becomes `{ pluginId: '@myorg/my-plugin', serviceName: '@myorg/my-plugin:all', functionName: 'searchTasks' }`
165
+
166
+ #### Advanced Mode (Cross-Plugin Functions)
167
+
168
+ Reference functions from other plugins:
169
+
170
+ ```typescript
171
+ functions: [
172
+ // Current plugin functions (simple)
173
+ 'searchTasks',
174
+ 'getTasks',
175
+
176
+ // Other plugin functions (explicit)
177
+ {
178
+ pluginId: '@majk/calendar',
179
+ serviceName: '@majk/calendar:all',
180
+ functionName: 'getEvents'
181
+ },
182
+ {
183
+ pluginId: '@majk/notifications',
184
+ serviceName: '@majk/notifications:all',
185
+ functionName: 'sendAlert'
186
+ }
187
+ ]
188
+ ```
189
+
190
+ **Use cases for cross-plugin access**:
191
+ - Coordinator teammates that orchestrate multiple plugins
192
+ - Integration teammates that bridge different systems
193
+ - Specialized workflows that span multiple domains
194
+
195
+ ### Multiple Specialized Teammates
196
+
197
+ Define teammates for different roles or expertise levels:
198
+
199
+ ```typescript
200
+ .teamMember([
201
+ {
202
+ id: 'task-viewer',
203
+ name: 'Task Viewer (Beginner-Friendly)',
204
+ systemPrompt: 'You are a friendly assistant for viewing tasks. Explain everything clearly and guide users step-by-step.',
205
+ functions: ['getTasks', 'searchTasks'],
206
+ // ... full teammate config
207
+ },
208
+ {
209
+ id: 'task-manager',
210
+ name: 'Task Manager (Power User)',
211
+ systemPrompt: 'You are an advanced task management assistant. Assume users are familiar with the system and want concise, powerful operations.',
212
+ functions: ['getTasks', 'searchTasks', 'createTask', 'updateTask', 'deleteTask', 'bulkUpdate'],
213
+ // ... full teammate config
214
+ },
215
+ {
216
+ id: 'task-reporter',
217
+ name: 'Task Reporter (Analytics)',
218
+ systemPrompt: 'You specialize in task analytics and reporting. Generate insights, trends, and actionable recommendations.',
219
+ functions: ['getTasks', 'searchTasks', 'generateReport', 'getStatistics'],
220
+ // ... full teammate config
221
+ }
222
+ ])
223
+ ```
224
+
225
+ ## Complete Example from Quickstart
226
+
227
+ ```typescript
228
+ const plugin = definePlugin('sample-plugin', 'Sample Plugin', '1.0.0')
229
+ .pluginRoot(path.join(__dirname, '..'))
230
+
231
+ .function('getSampleItems', {
232
+ description: 'Get sample items from the API',
233
+ input: { type: 'object', properties: {}, additionalProperties: false },
234
+ output: {
235
+ type: 'array',
236
+ items: {
237
+ type: 'object',
238
+ properties: {
239
+ id: { type: 'string' },
240
+ name: { type: 'string' },
241
+ value: { type: 'number' }
242
+ }
243
+ }
244
+ },
245
+ handler: async (_, ctx) => [
246
+ { id: '1', name: 'Item 1', value: 100 }
247
+ ],
248
+ tags: ['sample', 'query']
249
+ })
250
+
251
+ .function('doSampleAction', {
252
+ description: 'Perform a sample action via the API',
253
+ input: {
254
+ type: 'object',
255
+ properties: {
256
+ name: { type: 'string' },
257
+ value: { type: 'number' }
258
+ },
259
+ required: ['name', 'value']
260
+ },
261
+ output: {
262
+ type: 'object',
263
+ properties: {
264
+ id: { type: 'string' },
265
+ success: { type: 'boolean' }
266
+ }
267
+ },
268
+ handler: async (input, ctx) => ({
269
+ id: 'action-1',
270
+ success: true
271
+ }),
272
+ tags: ['sample', 'action']
273
+ })
274
+
275
+ /**
276
+ * ============================================================
277
+ * AUTO-GENERATED TEAMMATE (AI AGENT)
278
+ * ============================================================
279
+ *
280
+ * Every plugin automatically gets a default teammate (AI agent) that:
281
+ * - Is named "<Plugin Name> Expert" (e.g., "Sample Plugin Expert")
282
+ * - Has access to ALL plugin functions automatically
283
+ * - Gets a default system prompt (can be customized below)
284
+ * - Is identified by ID: same as package name (e.g., "@majk/sample-plugin")
285
+ *
286
+ * This auto-teammate appears in MAJK's teammate selector and can be
287
+ * invoked by users to interact with your plugin's capabilities through
288
+ * natural conversation.
289
+ *
290
+ * You can customize the system prompt using .instructions(), or disable
291
+ * the auto-teammate entirely with .noDefaultTeammate().
292
+ *
293
+ * ============================================================
294
+ */
295
+ .instructions(`You are an expert assistant for the Sample Plugin. Your role is to help users work with sample data and perform sample actions efficiently.
296
+
297
+ Your capabilities:
298
+ - Query sample items from the API using getSampleItems
299
+ - Perform sample actions using doSampleAction
300
+ - Access UI debugging logs when needed
301
+
302
+ When helping users:
303
+ 1. Proactively suggest relevant actions based on their requests
304
+ 2. Explain what each function does before using it
305
+ 3. Present results in a clear, organized format
306
+ 4. Guide users through multi-step workflows when appropriate
307
+
308
+ Remember: This is a template plugin - in production, you would have domain-specific knowledge and capabilities!`)
309
+
310
+ /**
311
+ * ============================================================
312
+ * CUSTOM TEAMMATES (OPTIONAL)
313
+ * ============================================================
314
+ *
315
+ * In addition to the auto-generated teammate, you can define custom
316
+ * teammates with specialized roles and limited function access.
317
+ *
318
+ * This is useful for:
319
+ * - Role-based access (e.g., read-only teammates)
320
+ * - Specialized assistants (e.g., reporting vs. data entry)
321
+ * - Different expertise levels (e.g., beginner-friendly vs. expert)
322
+ *
323
+ * Custom teammates use the `functions` field to specify which
324
+ * functions they can access. Use simple strings for current plugin
325
+ * functions, or full objects for cross-plugin capabilities.
326
+ *
327
+ * ============================================================
328
+ */
329
+ .teamMember([
330
+ {
331
+ id: 'sample-viewer',
332
+ name: 'Sample Viewer (Read-Only)',
333
+ systemPrompt: 'You are a read-only assistant for viewing sample data. You can query and display information but cannot perform actions or modifications. Help users explore and understand their sample data.',
334
+ expertise: ['Data Viewing', 'Read-Only Operations', 'Sample Plugin'],
335
+ skills: {
336
+ primary: ['Data Query', 'Information Display'],
337
+ secondary: ['Data Analysis', 'Reporting'],
338
+ languages: [],
339
+ frameworks: [],
340
+ tools: []
341
+ },
342
+ personality: {
343
+ workStyle: 'methodical',
344
+ codeStyle: 'concise',
345
+ reviewStyle: 'pragmatic',
346
+ communicationStyle: 'explanatory'
347
+ },
348
+ metadata: {
349
+ totalTasks: 0,
350
+ successfulTasks: 0,
351
+ projectHistory: [],
352
+ codeStats: {
353
+ linesWritten: 0,
354
+ filesModified: 0,
355
+ testsWritten: 0,
356
+ reviewsPassed: 0,
357
+ commitsCreated: 0
358
+ }
359
+ },
360
+ mcpServerIds: [],
361
+
362
+ // SIMPLE MODE: Just list function names!
363
+ // This teammate only has access to query functions, not action functions.
364
+ // Compare this to the auto-generated teammate which gets ALL functions.
365
+ functions: [
366
+ 'getSampleItems', // ✅ Can view data
367
+ 'uiLog' // ✅ Can log for debugging
368
+ // ❌ Cannot use 'doSampleAction' - not included!
369
+ ]
370
+ }
371
+ ])
372
+
373
+ .build();
374
+ ```
375
+
376
+ ## API Reference
377
+
378
+ ### .instructions(text: string)
379
+
380
+ Customize the auto-generated default teammate's system prompt.
381
+
382
+ **Parameters**:
383
+ - `text` (string): The system prompt for the teammate
384
+
385
+ **Returns**: FluentBuilder (chainable)
386
+
387
+ **Example**:
388
+ ```typescript
389
+ .instructions(`You are an expert in X. Your capabilities: ...`)
390
+ ```
391
+
392
+ ### .noDefaultTeammate()
393
+
394
+ Disable automatic default teammate generation.
395
+
396
+ **Parameters**: None
397
+
398
+ **Returns**: FluentBuilder (chainable)
399
+
400
+ **Example**:
401
+ ```typescript
402
+ .noDefaultTeammate()
403
+ ```
404
+
405
+ ### .teamMember(members: TeamMemberEntity[])
406
+
407
+ Define custom teammates with specialized roles and function access.
408
+
409
+ **Parameters**:
410
+ - `members` (TeamMemberEntity[]): Array of teammate definitions
411
+
412
+ **TeamMemberEntity Structure**:
413
+ ```typescript
414
+ {
415
+ id: string; // Unique identifier
416
+ name: string; // Display name
417
+ systemPrompt: string; // AI instructions
418
+ expertise: string[]; // Areas of expertise
419
+ skills: {
420
+ primary: string[];
421
+ secondary: string[];
422
+ languages: string[];
423
+ frameworks: string[];
424
+ tools: string[];
425
+ };
426
+ personality: {
427
+ workStyle: 'methodical' | 'agile' | 'exploratory';
428
+ codeStyle: 'concise' | 'verbose' | 'documented';
429
+ reviewStyle: 'pragmatic' | 'thorough' | 'nitpicky';
430
+ communicationStyle: 'concise' | 'explanatory' | 'socratic';
431
+ };
432
+ metadata: {
433
+ totalTasks: number;
434
+ successfulTasks: number;
435
+ projectHistory: any[];
436
+ codeStats: {
437
+ linesWritten: number;
438
+ filesModified: number;
439
+ testsWritten: number;
440
+ reviewsPassed: number;
441
+ commitsCreated: number;
442
+ };
443
+ };
444
+ mcpServerIds: string[]; // MCP servers this teammate can access
445
+ functions?: Array<string | { // Functions this teammate can call
446
+ pluginId: string;
447
+ serviceName: string;
448
+ functionName: string;
449
+ }>;
450
+ }
451
+ ```
452
+
453
+ **Returns**: FluentBuilder (chainable)
454
+
455
+ **Example**:
456
+ ```typescript
457
+ .teamMember([{
458
+ id: 'my-teammate',
459
+ name: 'My Teammate',
460
+ systemPrompt: '...',
461
+ functions: ['func1', 'func2'],
462
+ // ... other fields
463
+ }])
464
+ ```
465
+
466
+ ## Use Cases
467
+
468
+ ### 1. Read-Only vs Full-Access
469
+
470
+ Create separate teammates for viewing vs. modifying data:
471
+
472
+ ```typescript
473
+ .teamMember([
474
+ {
475
+ id: 'viewer',
476
+ name: 'Data Viewer',
477
+ functions: ['getData', 'searchData', 'exportData']
478
+ },
479
+ {
480
+ id: 'editor',
481
+ name: 'Data Editor',
482
+ functions: ['getData', 'searchData', 'createData', 'updateData', 'deleteData']
483
+ }
484
+ ])
485
+ ```
486
+
487
+ ### 2. Beginner vs Expert
488
+
489
+ Different interaction styles for different user levels:
490
+
491
+ ```typescript
492
+ .instructions(`You are a beginner-friendly assistant. Always explain concepts clearly and guide users step-by-step.`)
493
+
494
+ .teamMember([
495
+ {
496
+ id: 'expert',
497
+ name: 'Expert Mode',
498
+ systemPrompt: 'You are an advanced assistant for power users. Be concise and assume technical knowledge.',
499
+ functions: ['all', 'advanced', 'functions']
500
+ }
501
+ ])
502
+ ```
503
+
504
+ ### 3. Specialized Workflows
505
+
506
+ Create teammates for specific tasks:
507
+
508
+ ```typescript
509
+ .teamMember([
510
+ {
511
+ id: 'reporter',
512
+ name: 'Report Generator',
513
+ systemPrompt: 'You specialize in generating reports and analytics.',
514
+ functions: ['getData', 'aggregateData', 'generateReport', 'exportReport']
515
+ },
516
+ {
517
+ id: 'importer',
518
+ name: 'Data Importer',
519
+ systemPrompt: 'You specialize in importing and validating data.',
520
+ functions: ['validateData', 'importData', 'verifyImport']
521
+ }
522
+ ])
523
+ ```
524
+
525
+ ### 4. Cross-Plugin Orchestration
526
+
527
+ Create a coordinator that uses multiple plugins:
528
+
529
+ ```typescript
530
+ .teamMember([
531
+ {
532
+ id: 'workflow-coordinator',
533
+ name: 'Workflow Coordinator',
534
+ systemPrompt: 'You orchestrate complex workflows across multiple systems.',
535
+ functions: [
536
+ 'triggerWorkflow', // Current plugin
537
+ { pluginId: '@majk/tasks', serviceName: '@majk/tasks:all', functionName: 'createTask' },
538
+ { pluginId: '@majk/calendar', serviceName: '@majk/calendar:all', functionName: 'scheduleEvent' },
539
+ { pluginId: '@majk/notifications', serviceName: '@majk/notifications:all', functionName: 'notify' }
540
+ ]
541
+ }
542
+ ])
543
+ ```
544
+
545
+ ## Best Practices
546
+
547
+ 1. **Clear Role Definition**: Each teammate should have a clear, focused purpose
548
+ 2. **Appropriate Function Access**: Only grant access to functions needed for the role
549
+ 3. **Detailed System Prompts**: Provide clear instructions about capabilities and behavior
550
+ 4. **Consistent Naming**: Use descriptive names that indicate the teammate's role
551
+ 5. **Test Instructions**: Verify teammates behave as expected through conversation
552
+ 6. **Document Functions**: Ensure function descriptions are clear so teammates understand how to use them
553
+
554
+ ## Troubleshooting
555
+
556
+ ### Teammate Not Appearing
557
+
558
+ **Problem**: Your custom teammate doesn't show up in MAJK.
559
+
560
+ **Solution**:
561
+ - Ensure `id` is unique
562
+ - Verify all required fields are present
563
+ - Check build logs for validation errors
564
+
565
+ ### Functions Not Working
566
+
567
+ **Problem**: Teammate can't call expected functions.
568
+
569
+ **Solution**:
570
+ - Verify function names in `functions` array match actual function definitions
571
+ - Check that functions are defined BEFORE `.teamMember()` call
572
+ - For cross-plugin functions, ensure `pluginId` and `serviceName` are correct
573
+
574
+ ### Auto-Generated Teammate Has Wrong Name
575
+
576
+ **Problem**: Default teammate name doesn't match expectations.
577
+
578
+ **Solution**: The name is `"<Plugin Name> Expert"` based on the `name` parameter in `definePlugin()`. To change it, update the plugin name or use `.noDefaultTeammate()` and create a custom one.
579
+
580
+ ## Related Documentation
581
+
582
+ - [Functions](./FUNCTIONS.md) - Define functions that teammates can call
583
+ - [Services](./SERVICES.md) - Group functions into services
584
+ - [Context API](./CONTEXT.md) - PluginContext available to functions
585
+ - [Testing](./TESTING.md) - Test teammates and function calls
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@majkapp/plugin-kit",
3
- "version": "3.5.3",
3
+ "version": "3.5.5",
4
4
  "description": "Pure plugin definition library for MAJK - outputs plugin definitions, not HTTP servers",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",