@majkapp/plugin-kit 3.5.5 โ 3.6.1
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 +148 -0
- package/bin/promptable-cli.js +6 -0
- package/dist/generator/cli.js +90 -0
- package/dist/generator/extract-command.d.ts +10 -0
- package/dist/generator/extract-command.d.ts.map +1 -0
- package/dist/generator/extract-command.js +122 -0
- package/dist/index.d.ts +86 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +104 -1
- package/dist/majk-interface-types.d.ts +15 -0
- package/dist/majk-interface-types.d.ts.map +1 -1
- package/dist/plugin-kit.d.ts +58 -0
- package/dist/plugin-kit.d.ts.map +1 -1
- package/dist/plugin-kit.js +50 -4
- package/dist/types.d.ts +54 -0
- package/dist/types.d.ts.map +1 -1
- package/docs/API.md +8 -0
- package/docs/CONTEXT.md +74 -0
- package/docs/RPC_CALLBACKS.md +518 -0
- package/package.json +8 -2
- package/dist/transports.d.ts +0 -59
- package/dist/transports.d.ts.map +0 -1
- package/dist/transports.js +0 -171
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ Build type-safe, production-ready MAJK plugins with excellent developer experien
|
|
|
15
15
|
๐ง **Tool Management** - Declare tools with schema validation
|
|
16
16
|
๐พ **Storage Integration** - Direct access to plugin storage
|
|
17
17
|
๐ก **Event Bus** - Subscribe to system events
|
|
18
|
+
๐ **RPC Callbacks** - Pass callbacks across plugin boundaries with automatic serialization
|
|
18
19
|
๐งน **Auto Cleanup** - Managed lifecycle with automatic resource cleanup
|
|
19
20
|
โค๏ธ **Health Checks** - Built-in health monitoring
|
|
20
21
|
|
|
@@ -446,6 +447,90 @@ if (imageProviders.length > 0) {
|
|
|
446
447
|
- Integrate multiple AI providers
|
|
447
448
|
- Generate content, analyze data, summarize text
|
|
448
449
|
|
|
450
|
+
### Plugin Management API
|
|
451
|
+
|
|
452
|
+
Generate authenticated URLs for opening plugin UIs in external browsers or creating cross-plugin links:
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
// Simple convenience method - get URL for another plugin's screen
|
|
456
|
+
const url = await ctx.majk.plugins.getExternalUrl(
|
|
457
|
+
'@analytics/dashboard', // Plugin ID (package name format)
|
|
458
|
+
'main', // Screen ID (optional)
|
|
459
|
+
'#/overview' // Hash fragment (optional)
|
|
460
|
+
);
|
|
461
|
+
|
|
462
|
+
// Opens: http://localhost:9000/plugins/analytics/dashboard/ui/main?token=abc123#/overview
|
|
463
|
+
await ctx.shell?.openExternal(url);
|
|
464
|
+
|
|
465
|
+
// Advanced: Full control over URL generation
|
|
466
|
+
const customUrl = await ctx.majk.plugins.getPluginScreenUrl('@myorg/plugin', {
|
|
467
|
+
screenId: 'settings', // Specific screen
|
|
468
|
+
theme: 'dark', // Theme preference
|
|
469
|
+
hash: '#/advanced', // Client-side route
|
|
470
|
+
queryParams: { // Custom query parameters
|
|
471
|
+
view: 'compact',
|
|
472
|
+
filter: 'active'
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
// Direct URL with custom path (when you know the exact endpoint)
|
|
477
|
+
const apiUrl = await ctx.majk.plugins.getPluginExternalUrl('plugin-id', {
|
|
478
|
+
path: '/api/export', // Custom path within plugin
|
|
479
|
+
queryParams: { format: 'json' }
|
|
480
|
+
});
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
**API Methods:**
|
|
484
|
+
|
|
485
|
+
- **`getExternalUrl(pluginId, screenId?, hash?)`** - Simple convenience method for getting screen URLs
|
|
486
|
+
- **`getPluginScreenUrl(pluginId, options)`** - Screen-aware URL generation with full options
|
|
487
|
+
- **`getPluginExternalUrl(pluginId, options)`** - Low-level URL generation for custom paths
|
|
488
|
+
|
|
489
|
+
**URL Format:**
|
|
490
|
+
```
|
|
491
|
+
http://localhost:{port}/plugins/{org}/{plugin}/ui/{screen}?token={token}&theme={theme}#{hash}
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
**Security:**
|
|
495
|
+
- URLs include one-time authentication tokens (60s TTL)
|
|
496
|
+
- After expiration, users are redirected to login if required
|
|
497
|
+
- Tokens are automatically validated by the plugin server
|
|
498
|
+
|
|
499
|
+
**Use Cases:**
|
|
500
|
+
- Open plugin screens in external browser windows
|
|
501
|
+
- Create shareable links to plugin functionality
|
|
502
|
+
- Cross-plugin navigation and deep linking
|
|
503
|
+
- Programmatic browser-based testing
|
|
504
|
+
- Integration with external tools and workflows
|
|
505
|
+
|
|
506
|
+
**Example - Cross-Plugin Integration:**
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
.apiRoute({
|
|
510
|
+
method: 'POST',
|
|
511
|
+
path: '/api/generate-report',
|
|
512
|
+
name: 'Generate Report',
|
|
513
|
+
description: 'Generates analytics report. Creates report and returns link to view.',
|
|
514
|
+
handler: async (req, res, { majk }) => {
|
|
515
|
+
// Generate report data
|
|
516
|
+
const reportId = await generateReport(req.body);
|
|
517
|
+
|
|
518
|
+
// Create link to analytics plugin's viewer
|
|
519
|
+
const viewerUrl = await majk.plugins.getExternalUrl(
|
|
520
|
+
'@analytics/viewer',
|
|
521
|
+
'report',
|
|
522
|
+
`#/report/${reportId}`
|
|
523
|
+
);
|
|
524
|
+
|
|
525
|
+
return {
|
|
526
|
+
success: true,
|
|
527
|
+
reportId,
|
|
528
|
+
viewUrl: viewerUrl // User can click to view in analytics plugin
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
})
|
|
532
|
+
```
|
|
533
|
+
|
|
449
534
|
### PluginStorage
|
|
450
535
|
|
|
451
536
|
Simple key-value storage scoped to your plugin:
|
|
@@ -646,6 +731,69 @@ See `example.ts` for a comprehensive example showing:
|
|
|
646
731
|
- Storage usage
|
|
647
732
|
- Health checks
|
|
648
733
|
|
|
734
|
+
## RPC & Callbacks
|
|
735
|
+
|
|
736
|
+
Plugins can communicate with each other using RPC services and pass callbacks across plugin boundaries:
|
|
737
|
+
|
|
738
|
+
### Basic RPC Service
|
|
739
|
+
|
|
740
|
+
```typescript
|
|
741
|
+
// Plugin A: Register a service
|
|
742
|
+
.onLoad(async (ctx) => {
|
|
743
|
+
await ctx.rpc.registerService('fileProcessor', {
|
|
744
|
+
async processFile(path: string, onProgress: (percent: number) => void): Promise<string> {
|
|
745
|
+
await onProgress(0);
|
|
746
|
+
await onProgress(50);
|
|
747
|
+
await onProgress(100);
|
|
748
|
+
return `Processed: ${path}`;
|
|
749
|
+
}
|
|
750
|
+
});
|
|
751
|
+
})
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
### Consuming with Callbacks
|
|
755
|
+
|
|
756
|
+
```typescript
|
|
757
|
+
// Plugin B: Use the service with callbacks
|
|
758
|
+
.onLoad(async (ctx) => {
|
|
759
|
+
const processor = await ctx.rpc.createProxy<{
|
|
760
|
+
processFile(path: string, onProgress: (p: number) => void): Promise<string>
|
|
761
|
+
}>('fileProcessor');
|
|
762
|
+
|
|
763
|
+
// Pass callback - it just works!
|
|
764
|
+
const result = await processor.processFile('/file.txt', (progress) => {
|
|
765
|
+
console.log(`Progress: ${progress}%`);
|
|
766
|
+
});
|
|
767
|
+
})
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
### Explicit Callbacks with Cleanup
|
|
771
|
+
|
|
772
|
+
For long-lived callbacks (subscriptions, event listeners), use `createCallback()`:
|
|
773
|
+
|
|
774
|
+
```typescript
|
|
775
|
+
// Auto-cleanup after 10 calls
|
|
776
|
+
const callback = await ctx.rpc.createCallback!(
|
|
777
|
+
(event) => console.log('Event:', event),
|
|
778
|
+
{ maxCalls: 10 }
|
|
779
|
+
);
|
|
780
|
+
await eventService.subscribe(callback);
|
|
781
|
+
|
|
782
|
+
// Auto-cleanup after 5 seconds
|
|
783
|
+
const callback = await ctx.rpc.createCallback!(
|
|
784
|
+
(data) => console.log('Data:', data),
|
|
785
|
+
{ timeout: 5000 }
|
|
786
|
+
);
|
|
787
|
+
await dataStream.subscribe(callback);
|
|
788
|
+
|
|
789
|
+
// Manual cleanup
|
|
790
|
+
const callback = await ctx.rpc.createCallback!((msg) => console.log(msg));
|
|
791
|
+
// ... later
|
|
792
|
+
ctx.rpc.cleanupCallback!(callback);
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
See [docs/RPC_CALLBACKS.md](docs/RPC_CALLBACKS.md) for comprehensive documentation, patterns, and best practices.
|
|
796
|
+
|
|
649
797
|
## TypeScript
|
|
650
798
|
|
|
651
799
|
Full TypeScript support with:
|
package/bin/promptable-cli.js
CHANGED
|
@@ -58,6 +58,12 @@ cli.addCommand('--services',
|
|
|
58
58
|
{ description: 'Organize functions by service' }
|
|
59
59
|
);
|
|
60
60
|
|
|
61
|
+
// RPC and callbacks
|
|
62
|
+
cli.addCommand('--rpc',
|
|
63
|
+
cli.createFullDocCommand('RPC_CALLBACKS.md'),
|
|
64
|
+
{ description: 'Inter-plugin RPC with callbacks' }
|
|
65
|
+
);
|
|
66
|
+
|
|
61
67
|
// Teammates
|
|
62
68
|
cli.addCommand('--teammates',
|
|
63
69
|
cli.createFullDocCommand('TEAMMATES.md'),
|
package/dist/generator/cli.js
CHANGED
|
@@ -39,6 +39,7 @@ const path = __importStar(require("path"));
|
|
|
39
39
|
const fs = __importStar(require("fs"));
|
|
40
40
|
const child_process_1 = require("child_process");
|
|
41
41
|
const generator_1 = require("./generator");
|
|
42
|
+
const extract_command_1 = require("./extract-command");
|
|
42
43
|
// Check args BEFORE commander parses to intercept for documentation
|
|
43
44
|
const args = process.argv.slice(2);
|
|
44
45
|
// If -h or --help, let commander handle it normally (show generator help)
|
|
@@ -163,6 +164,26 @@ commander_1.program
|
|
|
163
164
|
await generate();
|
|
164
165
|
}
|
|
165
166
|
});
|
|
167
|
+
// Extract capabilities command
|
|
168
|
+
commander_1.program
|
|
169
|
+
.command('extract')
|
|
170
|
+
.description('Extract plugin capabilities to .majk/capabilities.json for market indexing')
|
|
171
|
+
.option('-e, --entry <path>', 'Path to the compiled plugin entry file', './dist/index.js')
|
|
172
|
+
.option('-o, --output <path>', 'Output directory for capabilities.json', '.majk')
|
|
173
|
+
.option('-s, --silent', 'Suppress output messages', false)
|
|
174
|
+
.action(async (options) => {
|
|
175
|
+
try {
|
|
176
|
+
await (0, extract_command_1.extractCapabilities)({
|
|
177
|
+
entry: options.entry,
|
|
178
|
+
output: options.output,
|
|
179
|
+
silent: options.silent
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
console.error(error.message);
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
166
187
|
// Add documentation options to help
|
|
167
188
|
commander_1.program
|
|
168
189
|
.option('--llm', 'Show plugin development documentation (quick start)')
|
|
@@ -198,6 +219,8 @@ async function extractMetadata(entryPath) {
|
|
|
198
219
|
}
|
|
199
220
|
const content = fs.readFileSync(tempFile, 'utf-8');
|
|
200
221
|
const metadata = JSON.parse(content);
|
|
222
|
+
// NEW: Also save capabilities.json for market indexing
|
|
223
|
+
await saveCapabilitiesForMarket(metadata);
|
|
201
224
|
// Clean up temp file
|
|
202
225
|
fs.unlinkSync(tempFile);
|
|
203
226
|
return metadata;
|
|
@@ -210,3 +233,70 @@ async function extractMetadata(entryPath) {
|
|
|
210
233
|
throw new Error(`Failed to extract metadata: ${error.message}`);
|
|
211
234
|
}
|
|
212
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* Save capabilities.json to .majk/ directory and auto-update package.json
|
|
238
|
+
*/
|
|
239
|
+
async function saveCapabilitiesForMarket(metadata) {
|
|
240
|
+
try {
|
|
241
|
+
// Find project root (where package.json is)
|
|
242
|
+
const projectRoot = process.cwd();
|
|
243
|
+
// Check if plugin opted out
|
|
244
|
+
const pkgPath = path.join(projectRoot, 'package.json');
|
|
245
|
+
if (fs.existsSync(pkgPath)) {
|
|
246
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
247
|
+
if (pkg.majk?.skipCapabilitiesExtraction === true) {
|
|
248
|
+
console.log(' โน๏ธ Skipping capabilities extraction (skipCapabilitiesExtraction: true)');
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
// 1. Create .majk directory
|
|
253
|
+
const majkDir = path.join(projectRoot, '.majk');
|
|
254
|
+
fs.mkdirSync(majkDir, { recursive: true });
|
|
255
|
+
// 2. Write capabilities.json
|
|
256
|
+
const capabilitiesPath = path.join(majkDir, 'capabilities.json');
|
|
257
|
+
fs.writeFileSync(capabilitiesPath, JSON.stringify(metadata, null, 2) + '\n');
|
|
258
|
+
console.log(' โ Generated .majk/capabilities.json for market indexing');
|
|
259
|
+
// 3. Check and update package.json files array
|
|
260
|
+
if (fs.existsSync(pkgPath)) {
|
|
261
|
+
const content = fs.readFileSync(pkgPath, 'utf-8');
|
|
262
|
+
const pkg = JSON.parse(content);
|
|
263
|
+
if (pkg.files) {
|
|
264
|
+
if (!pkg.files.includes('.majk')) {
|
|
265
|
+
// Detect original indentation
|
|
266
|
+
const indent = detectIndent(content);
|
|
267
|
+
pkg.files.push('.majk');
|
|
268
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, indent) + '\n');
|
|
269
|
+
console.log(' โ Added .majk to package.json files array (commit this change)');
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
// No files array means all files included by default
|
|
274
|
+
console.log(' โน๏ธ No "files" array in package.json - .majk will be included by default');
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// 4. Check for service implementations
|
|
278
|
+
const capabilities = metadata.capabilities || [];
|
|
279
|
+
const services = capabilities.filter((c) => c.type === 'service');
|
|
280
|
+
const implementations = services.filter((s) => s.implements);
|
|
281
|
+
if (implementations.length > 0) {
|
|
282
|
+
console.log(' ๐ Service interface implementations detected:');
|
|
283
|
+
implementations.forEach((impl) => {
|
|
284
|
+
console.log(` โข ${impl.implements}`);
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
// Non-fatal: log but don't fail the build
|
|
290
|
+
console.warn(` โ ๏ธ Could not save capabilities for market: ${error.message}`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Detect indentation used in a JSON file
|
|
295
|
+
*/
|
|
296
|
+
function detectIndent(jsonString) {
|
|
297
|
+
const match = jsonString.match(/^(\s+)/m);
|
|
298
|
+
if (match) {
|
|
299
|
+
return match[1].length;
|
|
300
|
+
}
|
|
301
|
+
return 2; // Default to 2 spaces
|
|
302
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ExtractOptions {
|
|
2
|
+
entry?: string;
|
|
3
|
+
output?: string;
|
|
4
|
+
silent?: boolean;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Extract plugin capabilities and write to .majk/capabilities.json
|
|
8
|
+
*/
|
|
9
|
+
export declare function extractCapabilities(options?: ExtractOptions): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=extract-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-command.d.ts","sourceRoot":"","sources":["../../src/generator/extract-command.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyFrF"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.extractCapabilities = extractCapabilities;
|
|
37
|
+
/**
|
|
38
|
+
* Extract capabilities command - Creates .majk/capabilities.json for market indexing
|
|
39
|
+
*/
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const child_process_1 = require("child_process");
|
|
43
|
+
/**
|
|
44
|
+
* Extract plugin capabilities and write to .majk/capabilities.json
|
|
45
|
+
*/
|
|
46
|
+
async function extractCapabilities(options = {}) {
|
|
47
|
+
const entryPath = path.resolve(options.entry || './dist/index.js');
|
|
48
|
+
const outputDir = path.resolve(options.output || '.majk');
|
|
49
|
+
const outputFile = path.join(outputDir, 'capabilities.json');
|
|
50
|
+
const silent = options.silent || false;
|
|
51
|
+
if (!silent) {
|
|
52
|
+
console.log('๐ Extracting plugin capabilities...');
|
|
53
|
+
console.log(` Entry: ${entryPath}`);
|
|
54
|
+
console.log(` Output: ${outputFile}`);
|
|
55
|
+
console.log('');
|
|
56
|
+
}
|
|
57
|
+
// Check if entry file exists
|
|
58
|
+
if (!fs.existsSync(entryPath)) {
|
|
59
|
+
throw new Error(`Entry file not found: ${entryPath}\n` +
|
|
60
|
+
`Make sure to run 'npm run build' first to compile your plugin.`);
|
|
61
|
+
}
|
|
62
|
+
// Ensure output directory exists
|
|
63
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
64
|
+
try {
|
|
65
|
+
// Run the plugin in extract mode
|
|
66
|
+
(0, child_process_1.execSync)(`node "${entryPath}"`, {
|
|
67
|
+
env: {
|
|
68
|
+
...process.env,
|
|
69
|
+
PLUGIN_KIT_MODE: 'extract',
|
|
70
|
+
PLUGIN_KIT_OUTPUT: outputFile
|
|
71
|
+
},
|
|
72
|
+
cwd: path.dirname(entryPath),
|
|
73
|
+
stdio: silent ? 'pipe' : 'inherit'
|
|
74
|
+
});
|
|
75
|
+
// Verify the file was created
|
|
76
|
+
if (!fs.existsSync(outputFile)) {
|
|
77
|
+
throw new Error('Capabilities file was not created');
|
|
78
|
+
}
|
|
79
|
+
// Validate it's valid JSON
|
|
80
|
+
const content = fs.readFileSync(outputFile, 'utf-8');
|
|
81
|
+
const capabilities = JSON.parse(content);
|
|
82
|
+
if (!silent) {
|
|
83
|
+
console.log('โ
Successfully extracted capabilities!');
|
|
84
|
+
console.log('');
|
|
85
|
+
console.log('๐ Summary:');
|
|
86
|
+
console.log(` Plugin: ${capabilities.name} v${capabilities.version}`);
|
|
87
|
+
console.log(` Functions: ${capabilities.functions?.length || 0}`);
|
|
88
|
+
console.log(` Services: ${capabilities.capabilities?.filter((c) => c.type === 'service').length || 0}`);
|
|
89
|
+
console.log(` Screens: ${capabilities.screens?.length || 0}`);
|
|
90
|
+
console.log(` Tools: ${capabilities.tools?.length || 0}`);
|
|
91
|
+
console.log('');
|
|
92
|
+
// Check for service implementations
|
|
93
|
+
const services = capabilities.capabilities?.filter((c) => c.type === 'service') || [];
|
|
94
|
+
const implementations = services.filter((s) => s.implements);
|
|
95
|
+
if (implementations.length > 0) {
|
|
96
|
+
console.log('๐ Service Interface Implementations:');
|
|
97
|
+
implementations.forEach((impl) => {
|
|
98
|
+
console.log(` โข ${impl.implements} (${impl.serviceName})`);
|
|
99
|
+
});
|
|
100
|
+
console.log('');
|
|
101
|
+
}
|
|
102
|
+
console.log('๐ Next steps:');
|
|
103
|
+
console.log(' 1. Ensure ".majk" is in your package.json "files" array');
|
|
104
|
+
console.log(' 2. Run this command before publishing (add to prepublishOnly script)');
|
|
105
|
+
console.log(' 3. Publish to npm/CodeArtifact as usual');
|
|
106
|
+
console.log('');
|
|
107
|
+
console.log('๐ก Tip: Add this to package.json scripts:');
|
|
108
|
+
console.log(' "scripts": {');
|
|
109
|
+
console.log(' "extract": "plugin-kit extract",');
|
|
110
|
+
console.log(' "prepublishOnly": "npm run build && npm run extract"');
|
|
111
|
+
console.log(' }');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (!silent) {
|
|
116
|
+
console.error('');
|
|
117
|
+
console.error('โ Failed to extract capabilities');
|
|
118
|
+
console.error('');
|
|
119
|
+
}
|
|
120
|
+
throw new Error(`Failed to extract capabilities: ${error.message}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,90 @@ export { definePlugin, FluentBuilder, ServiceBuilder } from './plugin-kit';
|
|
|
18
18
|
export { FunctionRegistryImpl, FunctionProviderImpl } from './registry';
|
|
19
19
|
export { FilesystemResourceProvider } from './resource-provider';
|
|
20
20
|
export { generateClient } from './generator/generator';
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Service Discovery Utilities
|
|
23
|
+
*
|
|
24
|
+
* Helper functions for discovering services that implement specific interfaces at runtime.
|
|
25
|
+
* Uses ctx.capabilities to query installed plugins and filter by interface implementation.
|
|
26
|
+
*/
|
|
27
|
+
export declare const ServiceDiscovery: {
|
|
28
|
+
/**
|
|
29
|
+
* Find all installed services that implement a specific interface
|
|
30
|
+
*
|
|
31
|
+
* @param ctx - Plugin context with capabilities API
|
|
32
|
+
* @param interfacePackage - Interface package identifier (e.g., "@majk/service-registry/task-service")
|
|
33
|
+
* @returns Array of CapabilityMetadata for services implementing the interface
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* const openaiServices = await ServiceDiscovery.findImplementations(
|
|
37
|
+
* ctx,
|
|
38
|
+
* '@majk/service-registry/openai-services'
|
|
39
|
+
* );
|
|
40
|
+
*
|
|
41
|
+
* if (openaiServices.length > 0) {
|
|
42
|
+
* const service = await ctx.rpc.createProxy(openaiServices[0].serviceName);
|
|
43
|
+
* const result = await service.prompt({ message: 'Hello!' });
|
|
44
|
+
* }
|
|
45
|
+
*/
|
|
46
|
+
findImplementations(ctx: any, interfacePackage: string): Promise<any[]>;
|
|
47
|
+
/**
|
|
48
|
+
* Find the first service that implements a specific interface
|
|
49
|
+
*
|
|
50
|
+
* @param ctx - Plugin context with capabilities API
|
|
51
|
+
* @param interfacePackage - Interface package identifier
|
|
52
|
+
* @returns CapabilityMetadata for the first matching service, or undefined if none found
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* const taskService = await ServiceDiscovery.findFirst(
|
|
56
|
+
* ctx,
|
|
57
|
+
* '@majk/service-registry/task-service'
|
|
58
|
+
* );
|
|
59
|
+
*
|
|
60
|
+
* if (taskService) {
|
|
61
|
+
* const service = await ctx.rpc.createProxy(taskService.serviceName);
|
|
62
|
+
* await service.createTask({ title: 'New task' });
|
|
63
|
+
* }
|
|
64
|
+
*/
|
|
65
|
+
findFirst(ctx: any, interfacePackage: string): Promise<any | undefined>;
|
|
66
|
+
/**
|
|
67
|
+
* Create an RPC proxy for the first service implementing an interface
|
|
68
|
+
*
|
|
69
|
+
* @param ctx - Plugin context with capabilities and RPC APIs
|
|
70
|
+
* @param interfacePackage - Interface package identifier
|
|
71
|
+
* @returns RPC proxy to the service, or undefined if no implementation found
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* const openai = await ServiceDiscovery.resolve(
|
|
75
|
+
* ctx,
|
|
76
|
+
* '@majk/service-registry/openai-services'
|
|
77
|
+
* );
|
|
78
|
+
*
|
|
79
|
+
* if (openai) {
|
|
80
|
+
* const result = await openai.prompt({ message: 'Hello!' });
|
|
81
|
+
* } else {
|
|
82
|
+
* throw new Error('No OpenAI service implementation found');
|
|
83
|
+
* }
|
|
84
|
+
*/
|
|
85
|
+
resolve<T = any>(ctx: any, interfacePackage: string): Promise<T | undefined>;
|
|
86
|
+
/**
|
|
87
|
+
* Create an RPC proxy for a service implementing an interface, or throw an error
|
|
88
|
+
*
|
|
89
|
+
* @param ctx - Plugin context with capabilities and RPC APIs
|
|
90
|
+
* @param interfacePackage - Interface package identifier
|
|
91
|
+
* @returns RPC proxy to the service
|
|
92
|
+
* @throws Error if no implementation is found
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* const storage = await ServiceDiscovery.resolveOrThrow(
|
|
96
|
+
* ctx,
|
|
97
|
+
* '@majk/service-registry/storage-service'
|
|
98
|
+
* );
|
|
99
|
+
*
|
|
100
|
+
* // Guaranteed to be defined - will throw if not found
|
|
101
|
+
* await storage.save({ key: 'data', value: '...' });
|
|
102
|
+
*/
|
|
103
|
+
resolveOrThrow<T = any>(ctx: any, interfacePackage: string): Promise<T>;
|
|
104
|
+
};
|
|
105
|
+
export type { PluginContext, PluginLogger, PluginStorage, ScopedTimers, ScopedIpcRegistry, PluginCapabilities, PluginCapability, ToolImplementation, InProcessPlugin, PluginHealthStatus, ToolSpec, ToolHandler, ApiMethod, ApiRouteDef, JsonSchema, RouteHandler, RequestLike, ResponseLike, UiConfig, HistoryMode, ScreenBase, ReactScreen, HtmlScreen, ConfigWizardDef, SettingsDef, Scope, EntityType, CleanupFn, HealthCheckFn, MCPServerEntity, TeamMemberEntity, ServiceFunctionBinding, CallbackHandle, CreateCallbackOptions, CallbackStats, FunctionHandler, SubscriptionHandler, FunctionDefinition, SubscriptionDefinition, FunctionRegistry, ClientGenerationConfig, Plugin, FunctionProvider, ResourceProvider, FunctionInfo, AsyncPluginHealthStatus, ServiceCapability, ServiceMetadata, ServiceFunctionMetadata, ServiceParameterMetadata, ServiceReturnMetadata, FunctionEnrichment, IdentityDefinitionCapability, IdentityProviderInfo, IdentitySetupInstructions, IdentityTestConfig, IdentityRequirement } from './types';
|
|
106
|
+
export type { MajkInterface, EntityId, Unsubscribe, BaseEntity, StandardEventType, PluginEventType, RepositoryEventType, EntityType as MajkEntityType, RepositoryEvent, EventFilter, EventListener, Subscription, QueryBuilder, QueryableEventChannel, EventBusAPI, PluginInfo, PluginHealth, PluginCapabilityInfo, PluginLog, InstallPluginOptions, InstallPluginResult, GetLogsOptions, GetPluginExternalUrlOptions, GetPluginScreenUrlOptions, PluginManagementAPI, SecretScope, SecretInfo, ScopedSecretsAPI, SecretsAPI, StartTaskRequest, TaskFilter, TaskMessage, TaskProgress, TaskResult, TaskError, TaskHandle, TaskEventHandler, TaskEvent, TaskAPI, AccountType, AccountMetadata, TimeWindow, CredentialOptions, RefreshOptions, RefreshResult, ValidationResult, TokenInfo, AutoRefreshConfig, AutoRefreshHandle, AwsSdkCredentials, CognitoTokenSet, AzureSdkCredentials, AccountJSON, AwsCognitoCredentials, AzureEntraCredentials, ApiKeyCredentials, SystemDefaultCredentials, Credentials, SystemAccount, OAuthAccount, AwsAccount, AzureAccount, AuthEvent, AuthStateChangeEvent, AuthTokenRefreshedEvent, AuthErrorEvent, AccountChangedEvent, AuthAPI, Message, Conversation, Agent, TeamMember, TeamMemberSkills, TeamMemberPersonality, TeamMemberCodeStats, TeamMemberMetadata, ServiceFunctionBinding as MajkServiceFunctionBinding, Todo, WorkStrategy, Project, MCPServer, ConversationFilter, MessageQueryOptions, ConversationHandle, ConversationAPI, CreateTeammateRequest, TeammateUpdate, TeammateFilter, TeammateHandle, TeammateAPI, CreateTodoRequest, TodoUpdate, TodoFilter, SpawnOptions, TodoHandle, TodoAPI, CreateProjectRequest, ProjectUpdate, ProjectFilter, ProjectHandle, ProjectAPI, CreateMCPServerRequest, MCPServerUpdate, MCPServerFilter, ConnectionTestResult, MCPServerHandle, MCPServerScopedHandle, DiscoveredTool, MCPServerAPI, EverywhereScope, EverywhereScopedHandle, CreateAgentRequest, AgentUpdate, AgentFilter, TestResult, AgentHandle, AgentAPI, AddKnowledgeInput, KnowledgeNode, KnowledgeTree, KnowledgeSearchOptions, KnowledgeAPI, AIAPI, AIProvider, AIProviderCapabilities, AIProviderError, LLMInterface, ModelInfo, AIMessage, ContentBlock, PromptParams, PromptResult, PromptChunk, AIFunctionDefinition, AIJsonSchema, FunctionCallParams, FunctionCallResult, ImageGenerationParams, ImageResult, TranscriptionParams, TranscriptionResult, ProviderStatus } from './majk-interface-types';
|
|
23
107
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* - Lifecycle hooks with cleanup management
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.generateClient = exports.FilesystemResourceProvider = exports.FunctionProviderImpl = exports.FunctionRegistryImpl = exports.definePlugin = void 0;
|
|
19
|
+
exports.ServiceDiscovery = exports.generateClient = exports.FilesystemResourceProvider = exports.FunctionProviderImpl = exports.FunctionRegistryImpl = exports.definePlugin = void 0;
|
|
20
20
|
var plugin_kit_1 = require("./plugin-kit");
|
|
21
21
|
Object.defineProperty(exports, "definePlugin", { enumerable: true, get: function () { return plugin_kit_1.definePlugin; } });
|
|
22
22
|
var registry_1 = require("./registry");
|
|
@@ -26,3 +26,106 @@ var resource_provider_1 = require("./resource-provider");
|
|
|
26
26
|
Object.defineProperty(exports, "FilesystemResourceProvider", { enumerable: true, get: function () { return resource_provider_1.FilesystemResourceProvider; } });
|
|
27
27
|
var generator_1 = require("./generator/generator");
|
|
28
28
|
Object.defineProperty(exports, "generateClient", { enumerable: true, get: function () { return generator_1.generateClient; } });
|
|
29
|
+
/**
|
|
30
|
+
* Service Discovery Utilities
|
|
31
|
+
*
|
|
32
|
+
* Helper functions for discovering services that implement specific interfaces at runtime.
|
|
33
|
+
* Uses ctx.capabilities to query installed plugins and filter by interface implementation.
|
|
34
|
+
*/
|
|
35
|
+
exports.ServiceDiscovery = {
|
|
36
|
+
/**
|
|
37
|
+
* Find all installed services that implement a specific interface
|
|
38
|
+
*
|
|
39
|
+
* @param ctx - Plugin context with capabilities API
|
|
40
|
+
* @param interfacePackage - Interface package identifier (e.g., "@majk/service-registry/task-service")
|
|
41
|
+
* @returns Array of CapabilityMetadata for services implementing the interface
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* const openaiServices = await ServiceDiscovery.findImplementations(
|
|
45
|
+
* ctx,
|
|
46
|
+
* '@majk/service-registry/openai-services'
|
|
47
|
+
* );
|
|
48
|
+
*
|
|
49
|
+
* if (openaiServices.length > 0) {
|
|
50
|
+
* const service = await ctx.rpc.createProxy(openaiServices[0].serviceName);
|
|
51
|
+
* const result = await service.prompt({ message: 'Hello!' });
|
|
52
|
+
* }
|
|
53
|
+
*/
|
|
54
|
+
async findImplementations(ctx, interfacePackage) {
|
|
55
|
+
const allServices = await ctx.capabilities.getProviders('service');
|
|
56
|
+
return allServices.filter((s) => s.metadata?.implements === interfacePackage);
|
|
57
|
+
},
|
|
58
|
+
/**
|
|
59
|
+
* Find the first service that implements a specific interface
|
|
60
|
+
*
|
|
61
|
+
* @param ctx - Plugin context with capabilities API
|
|
62
|
+
* @param interfacePackage - Interface package identifier
|
|
63
|
+
* @returns CapabilityMetadata for the first matching service, or undefined if none found
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* const taskService = await ServiceDiscovery.findFirst(
|
|
67
|
+
* ctx,
|
|
68
|
+
* '@majk/service-registry/task-service'
|
|
69
|
+
* );
|
|
70
|
+
*
|
|
71
|
+
* if (taskService) {
|
|
72
|
+
* const service = await ctx.rpc.createProxy(taskService.serviceName);
|
|
73
|
+
* await service.createTask({ title: 'New task' });
|
|
74
|
+
* }
|
|
75
|
+
*/
|
|
76
|
+
async findFirst(ctx, interfacePackage) {
|
|
77
|
+
const implementations = await this.findImplementations(ctx, interfacePackage);
|
|
78
|
+
return implementations[0];
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* Create an RPC proxy for the first service implementing an interface
|
|
82
|
+
*
|
|
83
|
+
* @param ctx - Plugin context with capabilities and RPC APIs
|
|
84
|
+
* @param interfacePackage - Interface package identifier
|
|
85
|
+
* @returns RPC proxy to the service, or undefined if no implementation found
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* const openai = await ServiceDiscovery.resolve(
|
|
89
|
+
* ctx,
|
|
90
|
+
* '@majk/service-registry/openai-services'
|
|
91
|
+
* );
|
|
92
|
+
*
|
|
93
|
+
* if (openai) {
|
|
94
|
+
* const result = await openai.prompt({ message: 'Hello!' });
|
|
95
|
+
* } else {
|
|
96
|
+
* throw new Error('No OpenAI service implementation found');
|
|
97
|
+
* }
|
|
98
|
+
*/
|
|
99
|
+
async resolve(ctx, interfacePackage) {
|
|
100
|
+
const service = await this.findFirst(ctx, interfacePackage);
|
|
101
|
+
if (!service) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
return (await ctx.rpc.createProxy(service.serviceName));
|
|
105
|
+
},
|
|
106
|
+
/**
|
|
107
|
+
* Create an RPC proxy for a service implementing an interface, or throw an error
|
|
108
|
+
*
|
|
109
|
+
* @param ctx - Plugin context with capabilities and RPC APIs
|
|
110
|
+
* @param interfacePackage - Interface package identifier
|
|
111
|
+
* @returns RPC proxy to the service
|
|
112
|
+
* @throws Error if no implementation is found
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* const storage = await ServiceDiscovery.resolveOrThrow(
|
|
116
|
+
* ctx,
|
|
117
|
+
* '@majk/service-registry/storage-service'
|
|
118
|
+
* );
|
|
119
|
+
*
|
|
120
|
+
* // Guaranteed to be defined - will throw if not found
|
|
121
|
+
* await storage.save({ key: 'data', value: '...' });
|
|
122
|
+
*/
|
|
123
|
+
async resolveOrThrow(ctx, interfacePackage) {
|
|
124
|
+
const service = await this.resolve(ctx, interfacePackage);
|
|
125
|
+
if (!service) {
|
|
126
|
+
throw new Error(`No service found implementing interface: ${interfacePackage}. ` +
|
|
127
|
+
`Make sure the required plugin is installed and enabled.`);
|
|
128
|
+
}
|
|
129
|
+
return service;
|
|
130
|
+
}
|
|
131
|
+
};
|