@majkapp/plugin-kit 3.5.4 → 3.6.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/docs/API.md CHANGED
@@ -63,6 +63,14 @@ handler: async (input, ctx) => {
63
63
  await ctx.storage.delete(key);
64
64
  await ctx.storage.clear();
65
65
 
66
+ // RPC - Inter-plugin communication
67
+ await ctx.rpc.registerService(serviceName, implementation);
68
+ await ctx.rpc.unregisterService(serviceName);
69
+ const proxy = await ctx.rpc.createProxy<T>(serviceName);
70
+ const callback = await ctx.rpc.createCallback!(fn, options); // Optional
71
+ ctx.rpc.cleanupCallback!(callback); // Optional
72
+ const stats = ctx.rpc.getCallbackStats!(); // Optional
73
+
66
74
  // MAJK APIs
67
75
  await ctx.majk.conversations.list();
68
76
  await ctx.majk.conversations.get(id);
package/docs/CONTEXT.md CHANGED
@@ -351,6 +351,79 @@ Subscribe to MAJK events (conversations, todos, projects, etc.).
351
351
  })
352
352
  ```
353
353
 
354
+ ## ctx.rpc
355
+
356
+ Enable inter-plugin communication with RPC services and callbacks.
357
+
358
+ ### Register Service
359
+
360
+ Make your plugin's functions available to other plugins:
361
+
362
+ ```typescript
363
+ .onLoad(async (ctx) => {
364
+ // Register a service that other plugins can call
365
+ await ctx.rpc.registerService('fileProcessor', {
366
+ async processFile(path: string, onProgress: (percent: number) => void): Promise<string> {
367
+ await onProgress(0);
368
+ // ... process file ...
369
+ await onProgress(50);
370
+ // ... more processing ...
371
+ await onProgress(100);
372
+ return `Processed: ${path}`;
373
+ }
374
+ });
375
+ })
376
+ ```
377
+
378
+ ### Call Service with Inline Callbacks
379
+
380
+ Consume services from other plugins:
381
+
382
+ ```typescript
383
+ handler: async (input, ctx) => {
384
+ // Create proxy to another plugin's service
385
+ const processor = await ctx.rpc.createProxy<{
386
+ processFile(path: string, onProgress: (p: number) => void): Promise<string>
387
+ }>('fileProcessor');
388
+
389
+ // Pass callback - it just works!
390
+ const result = await processor.processFile('/file.txt', (progress) => {
391
+ ctx.logger.info(`Progress: ${progress}%`);
392
+ });
393
+
394
+ return { result };
395
+ }
396
+ ```
397
+
398
+ ### Explicit Callbacks with Cleanup
399
+
400
+ For long-lived callbacks (subscriptions, event listeners), use `createCallback()`:
401
+
402
+ ```typescript
403
+ handler: async (input, ctx) => {
404
+ // Auto-cleanup after 10 calls
405
+ const callback = await ctx.rpc.createCallback!(
406
+ (event) => ctx.logger.info('Event:', event),
407
+ { maxCalls: 10 }
408
+ );
409
+ await eventService.subscribe(callback);
410
+
411
+ // Auto-cleanup after 5 seconds
412
+ const callback2 = await ctx.rpc.createCallback!(
413
+ (data) => ctx.logger.info('Data:', data),
414
+ { timeout: 5000 }
415
+ );
416
+ await dataStream.subscribe(callback2);
417
+
418
+ // Manual cleanup
419
+ const callback3 = await ctx.rpc.createCallback!((msg) => ctx.logger.info(msg));
420
+ // ... later
421
+ ctx.rpc.cleanupCallback!(callback3);
422
+ }
423
+ ```
424
+
425
+ **For comprehensive RPC patterns and best practices:** Run `npx @majkapp/plugin-kit --rpc`
426
+
354
427
  ## Complete Example: Dashboard Data
355
428
 
356
429
  ```typescript
@@ -495,6 +568,7 @@ test('getDashboardData aggregates MAJK data', async () => {
495
568
 
496
569
  ## Next Steps
497
570
 
571
+ Run `npx @majkapp/plugin-kit --rpc` - Inter-plugin communication with callbacks
498
572
  Run `npx @majkapp/plugin-kit --lifecycle` - onReady and event subscriptions
499
573
  Run `npx @majkapp/plugin-kit --services` - Group functions into services
500
574
  Run `npx @majkapp/plugin-kit --testing` - Test functions with mock context
package/docs/FULL.md CHANGED
@@ -10,12 +10,13 @@ Comprehensive reference for @majkapp/plugin-kit covering all features and patter
10
10
  4. [Screens](#screens)
11
11
  5. [Generated Hooks](#generated-hooks)
12
12
  6. [Context API](#context-api)
13
- 7. [Services](#services)
14
- 8. [Teammates](#teammates)
15
- 9. [Lifecycle](#lifecycle)
16
- 10. [Testing](#testing)
17
- 11. [Configuration](#configuration)
18
- 12. [Best Practices](#best-practices)
13
+ 7. [AI API](#ai-api)
14
+ 8. [Services](#services)
15
+ 9. [Teammates](#teammates)
16
+ 10. [Lifecycle](#lifecycle)
17
+ 11. [Testing](#testing)
18
+ 12. [Configuration](#configuration)
19
+ 13. [Best Practices](#best-practices)
19
20
 
20
21
  ## Quick Start
21
22
 
@@ -334,6 +335,147 @@ await ctx.majk.mcpServers.get(id);
334
335
  const subscription = await ctx.majk.eventBus.subscribeAll(handler);
335
336
  ```
336
337
 
338
+ ## AI API
339
+
340
+ Access AI providers and language models with a unified, provider-agnostic interface.
341
+
342
+ ### Basic Usage
343
+
344
+ ```typescript
345
+ // Get default LLM
346
+ const llm = ctx.majk.ai.getDefaultLLM();
347
+
348
+ // Send a prompt
349
+ const result = await llm.prompt({
350
+ messages: [
351
+ { role: 'system', content: 'You are a helpful assistant' },
352
+ { role: 'user', content: 'What is TypeScript?' }
353
+ ],
354
+ temperature: 0.7,
355
+ maxTokens: 500
356
+ });
357
+
358
+ console.log(result.content);
359
+ console.log(`Tokens used: ${result.usage?.totalTokens}`);
360
+ ```
361
+
362
+ ### Provider Management
363
+
364
+ ```typescript
365
+ // List all providers
366
+ const providers = ctx.majk.ai.listProviders();
367
+ for (const provider of providers) {
368
+ console.log(`${provider.name}: ${provider.capabilities}`);
369
+ }
370
+
371
+ // Get specific provider
372
+ const bedrock = ctx.majk.ai.getProvider('bedrock');
373
+ if (bedrock) {
374
+ const claude = bedrock.getLLM('anthropic.claude-3-5-sonnet-20241022-v2:0');
375
+ }
376
+
377
+ // Query by capability
378
+ const imageProviders = ctx.majk.ai.getProvidersWithCapability('imageGeneration');
379
+
380
+ // Check status
381
+ const status = await ctx.majk.ai.getProviderStatus('bedrock');
382
+ console.log(`Available: ${status.available}, Authenticated: ${status.authenticated}`);
383
+ ```
384
+
385
+ ### Streaming Responses
386
+
387
+ ```typescript
388
+ const stream = llm.promptStream({
389
+ messages: [{ role: 'user', content: 'Tell me a story' }]
390
+ });
391
+
392
+ for await (const chunk of stream) {
393
+ if (chunk.type === 'content_delta') {
394
+ process.stdout.write(chunk.content);
395
+ }
396
+ }
397
+ ```
398
+
399
+ ### Structured JSON Output
400
+
401
+ ```typescript
402
+ const result = await llm.promptForJson({
403
+ messages: [
404
+ { role: 'user', content: 'Analyze sentiment: "This is amazing!"' }
405
+ ],
406
+ schema: {
407
+ type: 'object',
408
+ properties: {
409
+ sentiment: { type: 'string', enum: ['positive', 'negative', 'neutral'] },
410
+ confidence: { type: 'number' }
411
+ },
412
+ required: ['sentiment', 'confidence']
413
+ }
414
+ });
415
+
416
+ console.log(result.sentiment); // Type-safe access
417
+ ```
418
+
419
+ ### Advanced Features
420
+
421
+ ```typescript
422
+ // Function calling
423
+ const result = await llm.functionCall({
424
+ messages: [{ role: 'user', content: 'What is the weather?' }],
425
+ functions: [{
426
+ name: 'getWeather',
427
+ description: 'Get weather for a location',
428
+ parameters: {
429
+ type: 'object',
430
+ properties: {
431
+ location: { type: 'string' }
432
+ }
433
+ }
434
+ }]
435
+ });
436
+
437
+ // Image generation (if provider supports it)
438
+ const imageProviders = ctx.majk.ai.getProvidersWithCapability('imageGeneration');
439
+ if (imageProviders.length > 0) {
440
+ const image = await imageProviders[0].generateImage?.({
441
+ prompt: 'A beautiful sunset',
442
+ size: '1024x1024'
443
+ });
444
+ }
445
+
446
+ // Text embeddings (if provider supports it)
447
+ const embedding = await provider.generateEmbedding?.('Some text to embed');
448
+
449
+ // Audio transcription (if provider supports it)
450
+ const transcription = await provider.transcribeAudio?.({
451
+ audio: audioBuffer,
452
+ format: 'mp3'
453
+ });
454
+ ```
455
+
456
+ ### Error Handling
457
+
458
+ ```typescript
459
+ import { AIProviderError } from '@majkapp/plugin-kit';
460
+
461
+ try {
462
+ const result = await llm.prompt({ messages });
463
+ } catch (error) {
464
+ if (error instanceof AIProviderError) {
465
+ console.error(`AI Error [${error.code}]: ${error.message}`);
466
+
467
+ if (error.code === 'RATE_LIMIT_EXCEEDED') {
468
+ // Handle rate limiting
469
+ }
470
+ if (error.code === 'AUTHENTICATION_FAILED') {
471
+ // Handle auth errors
472
+ }
473
+ }
474
+ }
475
+ ```
476
+
477
+ For complete AI documentation, run: `npx @majkapp/plugin-kit --ai`
478
+
337
479
  ## Services
338
480
 
339
481
  Group related functions together.
package/docs/INDEX.md CHANGED
@@ -639,6 +639,7 @@ Run `npx @majkapp/plugin-kit --functions` - Deep dive into function patterns
639
639
  Run `npx @majkapp/plugin-kit --screens` - Screen configuration details
640
640
  Run `npx @majkapp/plugin-kit --hooks` - Generated hooks reference
641
641
  Run `npx @majkapp/plugin-kit --context` - ctx.majk and ctx.logger APIs
642
+ Run `npx @majkapp/plugin-kit --ai` - AI providers and LLMs
642
643
  Run `npx @majkapp/plugin-kit --services` - Service grouping patterns
643
644
  Run `npx @majkapp/plugin-kit --teammates` - AI teammates and agents
644
645
  Run `npx @majkapp/plugin-kit --lifecycle` - onReady and cleanup