@xnetjs/plugins 0.0.2

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,583 @@
1
+ /**
2
+ * Local HTTP API Server
3
+ *
4
+ * Provides a REST API for external integrations (N8N, MCP, etc.) to interact
5
+ * with xNet data. Runs on localhost only (port 31415 by default).
6
+ *
7
+ * This is designed to run in the Electron main process.
8
+ */
9
+ /**
10
+ * Node store interface (minimal subset needed by API)
11
+ */
12
+ interface NodeStoreAPI {
13
+ get(id: string): Promise<NodeData | null>;
14
+ list(options?: {
15
+ schemaId?: string;
16
+ limit?: number;
17
+ offset?: number;
18
+ }): Promise<NodeData[]>;
19
+ create(options: {
20
+ schemaId: string;
21
+ properties: Record<string, unknown>;
22
+ }): Promise<NodeData>;
23
+ update(id: string, options: {
24
+ properties: Record<string, unknown>;
25
+ }): Promise<NodeData>;
26
+ delete(id: string): Promise<void>;
27
+ subscribe(listener: (event: NodeChangeEventData) => void): () => void;
28
+ }
29
+ /**
30
+ * Schema registry interface (minimal subset needed by API)
31
+ */
32
+ interface SchemaRegistryAPI {
33
+ getAllIRIs(): string[];
34
+ get(iri: string): Promise<SchemaData | null>;
35
+ }
36
+ /**
37
+ * Node data returned by API
38
+ */
39
+ interface NodeData {
40
+ id: string;
41
+ schemaId: string;
42
+ properties: Record<string, unknown>;
43
+ deleted: boolean;
44
+ createdAt: number;
45
+ updatedAt: number;
46
+ }
47
+ /**
48
+ * Schema data returned by API
49
+ */
50
+ interface SchemaData {
51
+ iri: string;
52
+ name: string;
53
+ properties: Record<string, unknown>;
54
+ }
55
+ /**
56
+ * Node change event data
57
+ */
58
+ interface NodeChangeEventData {
59
+ change: {
60
+ type: string;
61
+ };
62
+ node: NodeData | null;
63
+ isRemote: boolean;
64
+ }
65
+ /**
66
+ * API configuration
67
+ */
68
+ interface LocalAPIConfig {
69
+ /** Port to listen on (default: 31415) */
70
+ port?: number;
71
+ /** Host to bind to (default: '127.0.0.1') */
72
+ host?: string;
73
+ /** API token for authentication (optional) */
74
+ token?: string;
75
+ /**
76
+ * Allowed CORS origins (default: none).
77
+ * Set to specific origins like ['http://localhost:3000'] for local dev,
78
+ * or ['*'] to allow all origins (not recommended for production).
79
+ * Empty array or undefined disables CORS entirely.
80
+ */
81
+ allowedOrigins?: string[];
82
+ /** NodeStore instance */
83
+ store: NodeStoreAPI;
84
+ /** SchemaRegistry instance */
85
+ schemas: SchemaRegistryAPI;
86
+ }
87
+ /**
88
+ * Local HTTP API server for xNet integrations.
89
+ */
90
+ declare class LocalAPIServer {
91
+ private server;
92
+ private config;
93
+ private eventBuffer;
94
+ private unsubscribe?;
95
+ constructor(config: LocalAPIConfig);
96
+ /**
97
+ * Start the API server
98
+ */
99
+ start(): Promise<void>;
100
+ /**
101
+ * Stop the API server
102
+ */
103
+ stop(): Promise<void>;
104
+ /**
105
+ * Get the server port
106
+ */
107
+ get port(): number;
108
+ /**
109
+ * Check if server is running
110
+ */
111
+ get isRunning(): boolean;
112
+ private handleRequest;
113
+ private handleHealth;
114
+ private handleListNodes;
115
+ private handleGetNode;
116
+ private handleCreateNode;
117
+ private handleUpdateNode;
118
+ private handleDeleteNode;
119
+ private handleQuery;
120
+ private handleGetEvents;
121
+ private handleListSchemas;
122
+ private handleGetSchema;
123
+ private parseBody;
124
+ private sendJSON;
125
+ private sendError;
126
+ private getEventType;
127
+ }
128
+ /**
129
+ * Create a local API server.
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * const api = createLocalAPI({
134
+ * port: 31415,
135
+ * store: nodeStore,
136
+ * schemas: schemaRegistry
137
+ * })
138
+ *
139
+ * await api.start()
140
+ * // Server is now listening on http://127.0.0.1:31415
141
+ *
142
+ * await api.stop()
143
+ * ```
144
+ */
145
+ declare function createLocalAPI(config: LocalAPIConfig): LocalAPIServer;
146
+
147
+ /**
148
+ * MCP Server for xNet
149
+ *
150
+ * Exposes xNet data to AI agents via the Model Context Protocol.
151
+ * Provides tools for querying, creating, and updating nodes.
152
+ *
153
+ * This runs as a stdio-based MCP server, typically spawned by an MCP client.
154
+ */
155
+
156
+ /**
157
+ * MCP Tool definition
158
+ */
159
+ interface MCPTool {
160
+ name: string;
161
+ description: string;
162
+ inputSchema: {
163
+ type: 'object';
164
+ properties: Record<string, MCPPropertySchema>;
165
+ required?: string[];
166
+ };
167
+ }
168
+ /**
169
+ * MCP property schema
170
+ */
171
+ interface MCPPropertySchema {
172
+ type: 'string' | 'number' | 'boolean' | 'object' | 'array';
173
+ description?: string;
174
+ items?: MCPPropertySchema;
175
+ }
176
+ /**
177
+ * MCP Resource definition
178
+ */
179
+ interface MCPResource {
180
+ uri: string;
181
+ name: string;
182
+ description?: string;
183
+ mimeType?: string;
184
+ }
185
+ /**
186
+ * MCP Request from client
187
+ */
188
+ interface MCPRequest {
189
+ jsonrpc: '2.0';
190
+ id: number | string;
191
+ method: string;
192
+ params?: Record<string, unknown>;
193
+ }
194
+ /**
195
+ * MCP Response to client
196
+ */
197
+ interface MCPResponse {
198
+ jsonrpc: '2.0';
199
+ id: number | string;
200
+ result?: unknown;
201
+ error?: {
202
+ code: number;
203
+ message: string;
204
+ data?: unknown;
205
+ };
206
+ }
207
+ /**
208
+ * MCP Server configuration
209
+ */
210
+ interface MCPServerConfig {
211
+ store: NodeStoreAPI;
212
+ schemas: SchemaRegistryAPI;
213
+ /** Server name (default: 'xnet') */
214
+ name?: string;
215
+ /** Server version (default: '1.0.0') */
216
+ version?: string;
217
+ }
218
+ /**
219
+ * MCP Server for xNet.
220
+ *
221
+ * Provides tools for AI agents to interact with xNet data:
222
+ * - xnet_query: Query nodes by schema and filter
223
+ * - xnet_create: Create a new node
224
+ * - xnet_update: Update an existing node
225
+ * - xnet_delete: Delete a node
226
+ * - xnet_search: Full-text search across nodes
227
+ * - xnet_schemas: List available schemas
228
+ *
229
+ * @example
230
+ * ```typescript
231
+ * const server = new MCPServer({
232
+ * store: nodeStore,
233
+ * schemas: schemaRegistry
234
+ * })
235
+ *
236
+ * // Start stdio server (for MCP client connections)
237
+ * await server.startStdio()
238
+ * ```
239
+ */
240
+ declare class MCPServer {
241
+ private config;
242
+ private tools;
243
+ private running;
244
+ constructor(config: MCPServerConfig);
245
+ /**
246
+ * Get server info for MCP initialize response
247
+ */
248
+ getServerInfo(): {
249
+ name: string;
250
+ version: string;
251
+ };
252
+ /**
253
+ * Get server capabilities
254
+ */
255
+ getCapabilities(): {
256
+ tools: Record<string, never>;
257
+ resources: Record<string, never>;
258
+ };
259
+ /**
260
+ * Get all registered tools
261
+ */
262
+ getTools(): MCPTool[];
263
+ /**
264
+ * Get available resources
265
+ */
266
+ getResources(): MCPResource[];
267
+ /**
268
+ * Handle an MCP request
269
+ */
270
+ handleRequest(request: MCPRequest): Promise<MCPResponse>;
271
+ /**
272
+ * Start the MCP server in stdio mode.
273
+ * Reads JSON-RPC requests from stdin and writes responses to stdout.
274
+ */
275
+ startStdio(): Promise<void>;
276
+ /**
277
+ * Stop the stdio server
278
+ */
279
+ stop(): void;
280
+ private registerTools;
281
+ private handleToolCall;
282
+ private handleResourceRead;
283
+ }
284
+ /**
285
+ * Create an MCP server for xNet.
286
+ *
287
+ * @example
288
+ * ```typescript
289
+ * const server = createMCPServer({
290
+ * store: nodeStore,
291
+ * schemas: schemaRegistry
292
+ * })
293
+ *
294
+ * // Handle individual requests
295
+ * const response = await server.handleRequest(request)
296
+ *
297
+ * // Or start as a stdio server
298
+ * await server.startStdio()
299
+ * ```
300
+ */
301
+ declare function createMCPServer(config: MCPServerConfig): MCPServer;
302
+
303
+ /**
304
+ * Service Plugin Types
305
+ *
306
+ * Defines the types for background service plugins that run as separate processes.
307
+ * These are primarily used in Electron but the types are shared.
308
+ */
309
+ /**
310
+ * Process configuration for a service
311
+ */
312
+ interface ServiceProcessConfig {
313
+ /** Executable command (e.g., 'node', 'python', 'ollama') */
314
+ command: string;
315
+ /** Command arguments */
316
+ args?: string[];
317
+ /** Working directory */
318
+ cwd?: string;
319
+ /** Environment variables */
320
+ env?: Record<string, string>;
321
+ /** Run in shell (for PATH resolution) */
322
+ shell?: boolean;
323
+ }
324
+ /**
325
+ * Health check configuration
326
+ */
327
+ interface ServiceHealthCheck {
328
+ /** Type of health check */
329
+ type: 'http' | 'stdout' | 'tcp';
330
+ /** URL to check for HTTP health checks */
331
+ url?: string;
332
+ /** Port to check for TCP health checks */
333
+ port?: number;
334
+ /** Regex pattern to match in stdout */
335
+ pattern?: string;
336
+ /** Interval between checks in milliseconds (default: 5000) */
337
+ intervalMs?: number;
338
+ /** Timeout for each check in milliseconds (default: 5000) */
339
+ timeoutMs?: number;
340
+ }
341
+ /**
342
+ * Lifecycle configuration for a service
343
+ */
344
+ interface ServiceLifecycle {
345
+ /** Restart policy */
346
+ restart: 'always' | 'on-failure' | 'never';
347
+ /** Maximum number of restarts (default: 5) */
348
+ maxRestarts?: number;
349
+ /** Delay between restarts in milliseconds (default: 1000) */
350
+ restartDelayMs?: number;
351
+ /** Timeout for service startup in milliseconds (default: 10000) */
352
+ startTimeoutMs?: number;
353
+ /** Health check configuration */
354
+ healthCheck?: ServiceHealthCheck;
355
+ /** Graceful shutdown timeout in milliseconds (default: 5000) */
356
+ shutdownTimeoutMs?: number;
357
+ }
358
+ /**
359
+ * Communication configuration for a service
360
+ */
361
+ interface ServiceCommunication {
362
+ /** Communication protocol */
363
+ protocol: 'stdio' | 'http' | 'websocket' | 'ipc';
364
+ /** Port for HTTP/WebSocket (0 = auto-assign) */
365
+ port?: number;
366
+ /** Host address (default: '127.0.0.1') */
367
+ host?: string;
368
+ }
369
+ /**
370
+ * Capabilities provided by a service
371
+ */
372
+ interface ServiceProvides {
373
+ /** MCP tool definitions */
374
+ mcp?: {
375
+ tools: string[];
376
+ };
377
+ /** HTTP API routes */
378
+ api?: {
379
+ routes: string[];
380
+ };
381
+ }
382
+ /**
383
+ * Complete service definition
384
+ */
385
+ interface ServiceDefinition {
386
+ /** Unique service identifier */
387
+ id: string;
388
+ /** Human-readable name */
389
+ name: string;
390
+ /** Optional description */
391
+ description?: string;
392
+ /** Process configuration */
393
+ process: ServiceProcessConfig;
394
+ /** Lifecycle configuration */
395
+ lifecycle: ServiceLifecycle;
396
+ /** Communication configuration */
397
+ communication: ServiceCommunication;
398
+ /** Capabilities this service provides */
399
+ provides?: ServiceProvides;
400
+ }
401
+ /**
402
+ * Service state
403
+ */
404
+ type ServiceState = 'starting' | 'running' | 'stopping' | 'stopped' | 'error';
405
+ /**
406
+ * Service status
407
+ */
408
+ interface ServiceStatus {
409
+ /** Service ID */
410
+ id: string;
411
+ /** Current state */
412
+ state: ServiceState;
413
+ /** Process ID (when running) */
414
+ pid?: number;
415
+ /** Port (when running with HTTP/WebSocket) */
416
+ port?: number;
417
+ /** Timestamp when service started */
418
+ startedAt?: number;
419
+ /** Last error message */
420
+ lastError?: string;
421
+ /** Number of restarts since initial start */
422
+ restartCount: number;
423
+ /** Uptime in milliseconds (if running) */
424
+ uptime?: number;
425
+ }
426
+ /**
427
+ * Event emitted when service status changes
428
+ */
429
+ interface ServiceStatusEvent {
430
+ serviceId: string;
431
+ status: ServiceStatus;
432
+ previousState?: ServiceState;
433
+ }
434
+ /**
435
+ * Event emitted when service outputs data
436
+ */
437
+ interface ServiceOutputEvent {
438
+ serviceId: string;
439
+ stream: 'stdout' | 'stderr';
440
+ data: string;
441
+ timestamp: number;
442
+ }
443
+ /**
444
+ * Client interface for interacting with services from the renderer process
445
+ */
446
+ interface ServiceClient {
447
+ /** Start a service */
448
+ start(definition: ServiceDefinition): Promise<ServiceStatus>;
449
+ /** Stop a service */
450
+ stop(serviceId: string): Promise<void>;
451
+ /** Restart a service */
452
+ restart(serviceId: string): Promise<ServiceStatus>;
453
+ /** Get service status */
454
+ status(serviceId: string): Promise<ServiceStatus | undefined>;
455
+ /** Get all service statuses */
456
+ listAll(): Promise<ServiceStatus[]>;
457
+ /** Call a service via HTTP */
458
+ call<T>(serviceId: string, method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', path: string, body?: unknown): Promise<T>;
459
+ /** Subscribe to status changes */
460
+ onStatusChange(serviceId: string, callback: (status: ServiceStatus) => void): () => void;
461
+ /** Subscribe to service output */
462
+ onOutput(serviceId: string, callback: (event: ServiceOutputEvent) => void): () => void;
463
+ }
464
+ /**
465
+ * Events emitted by the ProcessManager
466
+ */
467
+ interface ProcessManagerEvents {
468
+ 'service:status': (event: ServiceStatusEvent) => void;
469
+ 'service:output': (event: ServiceOutputEvent) => void;
470
+ 'service:error': (event: {
471
+ serviceId: string;
472
+ error: Error;
473
+ }) => void;
474
+ }
475
+ /**
476
+ * Interface for the process manager (implemented in Electron main process)
477
+ */
478
+ interface IProcessManager {
479
+ /** Start a service */
480
+ start(definition: ServiceDefinition): Promise<ServiceStatus>;
481
+ /** Stop a service */
482
+ stop(serviceId: string): Promise<void>;
483
+ /** Restart a service */
484
+ restart(serviceId: string): Promise<ServiceStatus>;
485
+ /** Get service status */
486
+ getStatus(serviceId: string): ServiceStatus | undefined;
487
+ /** Get all service statuses */
488
+ getAllStatuses(): ServiceStatus[];
489
+ /** Stop all services */
490
+ stopAll(): Promise<void>;
491
+ /** Subscribe to events */
492
+ on<K extends keyof ProcessManagerEvents>(event: K, listener: ProcessManagerEvents[K]): void;
493
+ /** Unsubscribe from events */
494
+ off<K extends keyof ProcessManagerEvents>(event: K, listener: ProcessManagerEvents[K]): void;
495
+ }
496
+
497
+ /**
498
+ * Process Manager
499
+ *
500
+ * Manages background service processes. This module is designed to run in
501
+ * Electron's main process or Node.js environment.
502
+ *
503
+ * Note: In browser environments, this will not work directly - use the
504
+ * ServiceClient with IPC to communicate with the main process.
505
+ */
506
+
507
+ /**
508
+ * Manages multiple service processes
509
+ *
510
+ * @example
511
+ * ```typescript
512
+ * const manager = new ProcessManager()
513
+ *
514
+ * await manager.start({
515
+ * id: 'ollama',
516
+ * name: 'Ollama',
517
+ * process: { command: 'ollama', args: ['serve'] },
518
+ * lifecycle: { restart: 'on-failure' },
519
+ * communication: { protocol: 'http', port: 11434 }
520
+ * })
521
+ *
522
+ * manager.on('service:status', (event) => {
523
+ * console.log(`${event.serviceId}: ${event.status.state}`)
524
+ * })
525
+ * ```
526
+ */
527
+ declare class ProcessManager implements IProcessManager {
528
+ private processes;
529
+ private listeners;
530
+ /**
531
+ * Start a service
532
+ */
533
+ start(definition: ServiceDefinition): Promise<ServiceStatus>;
534
+ /**
535
+ * Stop a service
536
+ */
537
+ stop(serviceId: string): Promise<void>;
538
+ /**
539
+ * Restart a service
540
+ */
541
+ restart(serviceId: string): Promise<ServiceStatus>;
542
+ /**
543
+ * Get service status
544
+ */
545
+ getStatus(serviceId: string): ServiceStatus | undefined;
546
+ /**
547
+ * Get all service statuses
548
+ */
549
+ getAllStatuses(): ServiceStatus[];
550
+ /**
551
+ * Stop all services
552
+ */
553
+ stopAll(): Promise<void>;
554
+ /**
555
+ * Subscribe to events
556
+ */
557
+ on<K extends keyof ProcessManagerEvents>(event: K, listener: ProcessManagerEvents[K]): void;
558
+ /**
559
+ * Unsubscribe from events
560
+ */
561
+ off<K extends keyof ProcessManagerEvents>(event: K, listener: ProcessManagerEvents[K]): void;
562
+ private emit;
563
+ }
564
+
565
+ /**
566
+ * Service Client
567
+ *
568
+ * Client API for interacting with services from the renderer process.
569
+ * Uses IPC to communicate with the ProcessManager in the main process.
570
+ */
571
+
572
+ declare const SERVICE_IPC_CHANNELS: {
573
+ readonly START: "xnet:service:start";
574
+ readonly STOP: "xnet:service:stop";
575
+ readonly RESTART: "xnet:service:restart";
576
+ readonly STATUS: "xnet:service:status";
577
+ readonly LIST_ALL: "xnet:service:list-all";
578
+ readonly CALL: "xnet:service:call";
579
+ readonly STATUS_UPDATE: "xnet:service:status-update";
580
+ readonly OUTPUT: "xnet:service:output";
581
+ };
582
+
583
+ export { type IProcessManager, type LocalAPIConfig, LocalAPIServer, type MCPPropertySchema, type MCPRequest, type MCPResource, type MCPResponse, MCPServer, type MCPServerConfig, type MCPTool, type NodeChangeEventData, type NodeData, type NodeStoreAPI, ProcessManager, type ProcessManagerEvents, SERVICE_IPC_CHANNELS, type SchemaData, type SchemaRegistryAPI, type ServiceClient, type ServiceCommunication, type ServiceDefinition, type ServiceHealthCheck, type ServiceLifecycle, type ServiceOutputEvent, type ServiceProcessConfig, type ServiceProvides, type ServiceState, type ServiceStatus, type ServiceStatusEvent, createLocalAPI, createMCPServer };