@kadi.build/core 0.0.1-alpha.1 → 0.0.1-alpha.3
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 +1145 -216
- package/examples/example-abilities/echo-js/README.md +131 -0
- package/examples/example-abilities/echo-js/agent.json +63 -0
- package/examples/example-abilities/echo-js/package.json +24 -0
- package/examples/example-abilities/echo-js/service.js +43 -0
- package/examples/example-abilities/hash-go/agent.json +53 -0
- package/examples/example-abilities/hash-go/cmd/hash_ability/main.go +340 -0
- package/examples/example-abilities/hash-go/go.mod +3 -0
- package/examples/example-agent/abilities/echo-js/0.0.1/README.md +131 -0
- package/examples/example-agent/abilities/echo-js/0.0.1/agent.json +63 -0
- package/examples/example-agent/abilities/echo-js/0.0.1/package-lock.json +93 -0
- package/examples/example-agent/abilities/echo-js/0.0.1/package.json +24 -0
- package/examples/example-agent/abilities/echo-js/0.0.1/service.js +41 -0
- package/examples/example-agent/abilities/hash-go/0.0.1/agent.json +53 -0
- package/examples/example-agent/abilities/hash-go/0.0.1/bin/hash_ability +0 -0
- package/examples/example-agent/abilities/hash-go/0.0.1/cmd/hash_ability/main.go +340 -0
- package/examples/example-agent/abilities/hash-go/0.0.1/go.mod +3 -0
- package/examples/example-agent/agent.json +39 -0
- package/examples/example-agent/index.js +102 -0
- package/examples/example-agent/package-lock.json +93 -0
- package/examples/example-agent/package.json +17 -0
- package/package.json +4 -2
- package/src/KadiAbility.js +478 -0
- package/src/index.js +65 -0
- package/src/loadAbility.js +1086 -0
- package/src/servers/BaseRpcServer.js +404 -0
- package/src/servers/BrokerRpcServer.js +776 -0
- package/src/servers/StdioRpcServer.js +360 -0
- package/src/transport/BrokerMessageBuilder.js +377 -0
- package/src/transport/IpcMessageBuilder.js +1229 -0
- package/src/utils/agentUtils.js +137 -0
- package/src/utils/commandUtils.js +64 -0
- package/src/utils/configUtils.js +72 -0
- package/src/utils/logger.js +161 -0
- package/src/utils/pathUtils.js +86 -0
- package/broker.js +0 -214
- package/index.js +0 -370
- package/ipc.js +0 -220
- package/ipcInterfaces/pythonAbilityIPC.py +0 -177
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { StdioRpcServer } from './servers/StdioRpcServer.js';
|
|
3
|
+
import { BrokerRpcServer } from './servers/BrokerRpcServer.js';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { createComponentLogger } from './utils/logger.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Factory for creating RPC servers based on protocol
|
|
10
|
+
*/
|
|
11
|
+
class RpcServerFactory {
|
|
12
|
+
static create(protocol, options = {}) {
|
|
13
|
+
switch (protocol?.toLowerCase()) {
|
|
14
|
+
case 'native':
|
|
15
|
+
return undefined; // Native protocol doesn't need an RPC server
|
|
16
|
+
case 'stdio':
|
|
17
|
+
return new StdioRpcServer(options);
|
|
18
|
+
case 'broker':
|
|
19
|
+
return new BrokerRpcServer(options);
|
|
20
|
+
default:
|
|
21
|
+
// Default to stdio for backward compatibility
|
|
22
|
+
return new StdioRpcServer(options);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* KadiAbility - High-level, user-friendly wrapper around RpcServer
|
|
29
|
+
*
|
|
30
|
+
* This class provides a clean API for creating abilities and handles
|
|
31
|
+
* transport selection automatically based on configuration.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* const ability = new KadiAbility({ name: 'my-ability' });
|
|
35
|
+
* ability
|
|
36
|
+
* .method('doSomething', async (params) => {
|
|
37
|
+
* return { result: 'done' };
|
|
38
|
+
* })
|
|
39
|
+
* .serve();
|
|
40
|
+
*/
|
|
41
|
+
export class KadiAbility extends EventEmitter {
|
|
42
|
+
/**
|
|
43
|
+
* Create a new KadiAbility instance
|
|
44
|
+
*
|
|
45
|
+
* @param {Object} options - Configuration options
|
|
46
|
+
* @param {string} options.name - Ability name
|
|
47
|
+
* @param {string} options.version - Ability version
|
|
48
|
+
* @param {string} options.description - Ability description
|
|
49
|
+
* @param {string} options.scope - Ability scope - Same as the agent's. global if not specified
|
|
50
|
+
* @param {string} options.abilityAgentJSON - Path to the ability agent.json file
|
|
51
|
+
* @param {string} options.protocol - Transport mode: 'stdio' or 'broker'
|
|
52
|
+
*/
|
|
53
|
+
constructor(options = {}) {
|
|
54
|
+
super();
|
|
55
|
+
|
|
56
|
+
// Store basic ability information
|
|
57
|
+
this.name = options.name || 'unnamed-ability';
|
|
58
|
+
this.version = options.version || '1.0.0';
|
|
59
|
+
this.description = options.description || '';
|
|
60
|
+
this.protocol = options.protocol || process.env.KADI_PROTOCOL || 'native';
|
|
61
|
+
this.abilityAgentJSON = options.abilityAgentJSON;
|
|
62
|
+
this.scope = options.scope || 'global';
|
|
63
|
+
|
|
64
|
+
this.logger = createComponentLogger('KadiAbility');
|
|
65
|
+
this.logger.lifecycle(
|
|
66
|
+
'constructor',
|
|
67
|
+
`Creating ability: ${this.name}@${this.version}`
|
|
68
|
+
);
|
|
69
|
+
this.logger.trace('constructor options', {
|
|
70
|
+
name: this.name,
|
|
71
|
+
version: this.version,
|
|
72
|
+
protocol: options.protocol,
|
|
73
|
+
scope: this.scope
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Create RPC server for handling requests for the given protocol
|
|
77
|
+
this.rpcServer = RpcServerFactory.create(this.protocol, {
|
|
78
|
+
maxBufferSize: options.maxBufferSize,
|
|
79
|
+
brokerUrl: options.brokerUrl,
|
|
80
|
+
...options
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
this.methodHandlers = new Map(); // method name -> function
|
|
84
|
+
this.methodMCPSchemas = new Map(); // method name -> schema object
|
|
85
|
+
|
|
86
|
+
// Forward events from RPC server (only if server exists)
|
|
87
|
+
if (this.rpcServer) {
|
|
88
|
+
this.rpcServer.on('start', (data) =>
|
|
89
|
+
this.emit('start', { ...data, protocol: this.protocol })
|
|
90
|
+
);
|
|
91
|
+
this.rpcServer.on('error', (error) => this.emit('error', error));
|
|
92
|
+
this.rpcServer.on('stop', () => this.emit('stop'));
|
|
93
|
+
this.rpcServer.on('request', (data) => this.emit('request', data));
|
|
94
|
+
this.rpcServer.on('response', (data) => this.emit('response', data));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Register a method with the ability
|
|
100
|
+
*
|
|
101
|
+
* @param {string} name - Method name
|
|
102
|
+
* @param {Function} handler - Handler function that processes the request
|
|
103
|
+
* @param {Object} [optionalMCPSchema] - Optional MCP schema for the method
|
|
104
|
+
* @returns {KadiAbility} - For chaining
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* // Simple method
|
|
108
|
+
* ability.method('echo', async ({ message }) => ({ echo: message }));
|
|
109
|
+
*
|
|
110
|
+
* // Method with MCP schema
|
|
111
|
+
* ability.method('format', async ({ text }) => ({ formatted: text.toUpperCase() }), {
|
|
112
|
+
* description: 'Format text to uppercase',
|
|
113
|
+
* inputSchema: {
|
|
114
|
+
* type: 'object',
|
|
115
|
+
* properties: {
|
|
116
|
+
* text: { type: 'string', description: 'Text to format' }
|
|
117
|
+
* },
|
|
118
|
+
* required: ['text']
|
|
119
|
+
* },
|
|
120
|
+
* outputSchema: {
|
|
121
|
+
* type: 'object',
|
|
122
|
+
* properties: {
|
|
123
|
+
* formatted: { type: 'string', description: 'Formatted text' }
|
|
124
|
+
* }
|
|
125
|
+
* }
|
|
126
|
+
* });
|
|
127
|
+
*/
|
|
128
|
+
method(name, handler, optionalMCPSchema) {
|
|
129
|
+
if (typeof name !== 'string') {
|
|
130
|
+
throw new TypeError('Method name must be a string');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (typeof handler !== 'function') {
|
|
134
|
+
throw new TypeError('Method handler must be a function');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
this.logger.methodCall('method', `Registering method: ${name}`);
|
|
138
|
+
if (optionalMCPSchema) {
|
|
139
|
+
this.logger.trace('method schema', { name, schema: optionalMCPSchema });
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
this.methodHandlers.set(name, handler);
|
|
143
|
+
|
|
144
|
+
if (optionalMCPSchema) {
|
|
145
|
+
this.methodMCPSchemas.set(name, optionalMCPSchema);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return this;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Publish an event to the connected agent/parent process
|
|
153
|
+
*
|
|
154
|
+
* Events are fire-and-forget notifications that flow from ability to agent.
|
|
155
|
+
* The transport layer determines how events are delivered:
|
|
156
|
+
* - Native: Direct EventEmitter (in-process)
|
|
157
|
+
* - Stdio: JSON-RPC notification with __kadi_event method
|
|
158
|
+
* - Broker: kadi.event message via WebSocket
|
|
159
|
+
*
|
|
160
|
+
* @param {string} eventName - Name of the event to publish
|
|
161
|
+
* @param {any} data - Event data payload (should be JSON-serializable for remote transports)
|
|
162
|
+
* @returns {void}
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* // Publish a simple event
|
|
166
|
+
* ability.publishEvent('server:started', { port: 3000 });
|
|
167
|
+
*
|
|
168
|
+
* // Publish progress updates
|
|
169
|
+
* ability.publishEvent('download:progress', {
|
|
170
|
+
* file: 'data.zip',
|
|
171
|
+
* progress: 0.75,
|
|
172
|
+
* bytesDownloaded: 75000,
|
|
173
|
+
* totalBytes: 100000
|
|
174
|
+
* });
|
|
175
|
+
*
|
|
176
|
+
* // Publish error events
|
|
177
|
+
* ability.publishEvent('error', {
|
|
178
|
+
* message: 'Connection failed',
|
|
179
|
+
* code: 'ECONNREFUSED'
|
|
180
|
+
* });
|
|
181
|
+
*/
|
|
182
|
+
publishEvent(eventName, data = {}) {
|
|
183
|
+
if (typeof eventName !== 'string' || !eventName) {
|
|
184
|
+
throw new TypeError('Event name must be a non-empty string');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
this.logger.trace('publishEvent', `Publishing event: ${eventName}`);
|
|
188
|
+
this.logger.trace('publishEvent data', { eventName, data });
|
|
189
|
+
|
|
190
|
+
// For native protocol, emit directly on this EventEmitter
|
|
191
|
+
// The agent will have direct access to this instance
|
|
192
|
+
if (this.protocol === 'native') {
|
|
193
|
+
this.logger.trace('publishEvent', 'Using native EventEmitter for event');
|
|
194
|
+
// Emit with a special prefix to distinguish from internal events
|
|
195
|
+
this.emit('ability:event', { eventName, data });
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// For remote protocols, delegate to the RPC server
|
|
200
|
+
if (this.rpcServer && typeof this.rpcServer.publishEvent === 'function') {
|
|
201
|
+
this.logger.trace(
|
|
202
|
+
'publishEvent',
|
|
203
|
+
`Delegating to ${this.protocol} RPC server`
|
|
204
|
+
);
|
|
205
|
+
this.rpcServer.publishEvent(eventName, data);
|
|
206
|
+
} else {
|
|
207
|
+
this.logger.warn(
|
|
208
|
+
'publishEvent',
|
|
209
|
+
`Cannot publish event: RPC server (${this.protocol}) does not support event publishing`
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Get all registered method names (excluding internal methods)
|
|
216
|
+
*/
|
|
217
|
+
getMethodNames() {
|
|
218
|
+
return Array.from(this.methodHandlers.keys()).filter(
|
|
219
|
+
(name) => !name.startsWith('__kadi_')
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Check if a method is registered
|
|
225
|
+
*/
|
|
226
|
+
hasMethod(name) {
|
|
227
|
+
return this.methodHandlers.has(name);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Get method handler
|
|
232
|
+
*/
|
|
233
|
+
getMethodHandler(name) {
|
|
234
|
+
return this.methodHandlers.get(name);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Get method schema (if available)
|
|
239
|
+
*/
|
|
240
|
+
getMethodSchema(name) {
|
|
241
|
+
return this.methodMCPSchemas.get(name);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Extract tool definitions for broker capability registration
|
|
246
|
+
* Combines schemas from agent.json exports and inline schemas
|
|
247
|
+
*
|
|
248
|
+
* @returns {Array<Object>} - Array of tool definitions for broker
|
|
249
|
+
*/
|
|
250
|
+
async extractToolsForBroker() {
|
|
251
|
+
this.logger.methodCall(
|
|
252
|
+
'extractToolsForBroker',
|
|
253
|
+
'Extracting tools for broker registration'
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
const tools = [];
|
|
257
|
+
|
|
258
|
+
// console.error(`Registered handlers: ${Array.from(this.methodHandlers.keys())}`);
|
|
259
|
+
// console.error(`Schema map: ${Array.from(this.methodMCPSchemas.entries())}`);
|
|
260
|
+
|
|
261
|
+
// 1. Try to load agent.json exports
|
|
262
|
+
const agentJsonExports = await this._loadAgentJsonExports();
|
|
263
|
+
|
|
264
|
+
this.logger.trace(
|
|
265
|
+
'extractToolsForBroker',
|
|
266
|
+
`Loaded ${agentJsonExports.length} exports from agent.json`
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
// 2. Build tools array from registered methods
|
|
270
|
+
for (const [methodName, handler] of this.methodHandlers) {
|
|
271
|
+
if (methodName.startsWith('__kadi_')) continue; // Skip internal methods
|
|
272
|
+
|
|
273
|
+
let schema = this.methodMCPSchemas.get(methodName);
|
|
274
|
+
|
|
275
|
+
// Resolve schema source
|
|
276
|
+
if (!schema) {
|
|
277
|
+
// Look in agent.json exports
|
|
278
|
+
schema = agentJsonExports.find((exp) => exp.name === methodName);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (!schema) {
|
|
282
|
+
this.logger.warn(
|
|
283
|
+
'extractToolsForBroker',
|
|
284
|
+
`No schema found for method '${methodName}', skipping broker registration`
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
tools.push({
|
|
291
|
+
name: methodName,
|
|
292
|
+
description: schema.description || `Execute ${methodName}`,
|
|
293
|
+
inputSchema: schema.inputSchema || { type: 'object' },
|
|
294
|
+
outputSchema: schema.outputSchema
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
this.logger.success(
|
|
299
|
+
'extractToolsForBroker',
|
|
300
|
+
`Extracted ${tools.length} tools for broker`
|
|
301
|
+
);
|
|
302
|
+
return tools;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Start serving requests
|
|
307
|
+
*
|
|
308
|
+
* @param {Object} options - Serve options
|
|
309
|
+
* @param {string} options.mode - Override transport mode
|
|
310
|
+
* @returns {Promise<void>}
|
|
311
|
+
*/
|
|
312
|
+
async serve(options = {}) {
|
|
313
|
+
this.logger.lifecycle('serve', `Starting to serve ability: ${this.name}`);
|
|
314
|
+
this.logger.info(
|
|
315
|
+
'serve',
|
|
316
|
+
`Protocol: ${this.protocol}, Methods: ${this.getMethodNames().join(', ')}`
|
|
317
|
+
);
|
|
318
|
+
try {
|
|
319
|
+
// Override protocol if specified in options
|
|
320
|
+
if (options.mode && options.mode !== this.protocol) {
|
|
321
|
+
this.logger.info(
|
|
322
|
+
'serve',
|
|
323
|
+
`Protocol override: ${this.protocol} -> ${options.mode}`
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
this.protocol = options.mode;
|
|
327
|
+
this.rpcServer = RpcServerFactory.create(this.protocol, options);
|
|
328
|
+
|
|
329
|
+
// Re-wire events for new server (only if server exists)
|
|
330
|
+
if (this.rpcServer) {
|
|
331
|
+
this.rpcServer.on('start', (data) =>
|
|
332
|
+
this.emit('start', { ...data, protocol: this.protocol })
|
|
333
|
+
);
|
|
334
|
+
this.rpcServer.on('error', (error) => this.emit('error', error));
|
|
335
|
+
this.rpcServer.on('stop', () => this.emit('stop'));
|
|
336
|
+
this.rpcServer.on('request', (data) => this.emit('request', data));
|
|
337
|
+
this.rpcServer.on('response', (data) => this.emit('response', data));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Start serving this ability using the RPC server (if it exists)
|
|
342
|
+
if (this.rpcServer) {
|
|
343
|
+
await this.rpcServer.serve(this);
|
|
344
|
+
this.logger.success(
|
|
345
|
+
'serve',
|
|
346
|
+
`Successfully started serving ${this.name} via ${this.protocol}`
|
|
347
|
+
);
|
|
348
|
+
} else {
|
|
349
|
+
// For native protocol, just emit start event and keep running
|
|
350
|
+
this.logger.success(
|
|
351
|
+
'serve',
|
|
352
|
+
`Successfully started serving ${this.name} via ${this.protocol} (native mode)`
|
|
353
|
+
);
|
|
354
|
+
this.emit('start', {
|
|
355
|
+
protocol: this.protocol,
|
|
356
|
+
methods: this.getMethodNames()
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
// Keep the process alive for native protocol
|
|
360
|
+
// This allows the ability to be imported and used directly
|
|
361
|
+
return new Promise(() => {
|
|
362
|
+
// Never resolve - keep the process running
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
} catch (error) {
|
|
366
|
+
this.logError('Failed to start serving', { error: error.message });
|
|
367
|
+
this.emit('error', error);
|
|
368
|
+
throw error;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Log a message to stderr (safe for stdio mode since stdout is used for RPC)
|
|
374
|
+
*
|
|
375
|
+
* @param {...any} args - Arguments to log
|
|
376
|
+
*/
|
|
377
|
+
log(...args) {
|
|
378
|
+
this.logger.info('general', args.join(' '));
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Log an error to stderr
|
|
383
|
+
*
|
|
384
|
+
* @param {...any} args - Arguments to log
|
|
385
|
+
*/
|
|
386
|
+
logError(...args) {
|
|
387
|
+
this.logger.error('general', args.join(' '));
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Load exports from agent.json file
|
|
392
|
+
*
|
|
393
|
+
* @returns {Array<Object>} - Array of export definitions
|
|
394
|
+
* @private
|
|
395
|
+
*/
|
|
396
|
+
async _loadAgentJsonExports() {
|
|
397
|
+
this.logger.methodCall(
|
|
398
|
+
'_loadAgentJsonExports',
|
|
399
|
+
'Loading agent.json exports'
|
|
400
|
+
);
|
|
401
|
+
try {
|
|
402
|
+
const agentJsonPath = await this._findAgentJson();
|
|
403
|
+
|
|
404
|
+
this.logger.trace(
|
|
405
|
+
'_loadAgentJsonExports',
|
|
406
|
+
`Found agent.json at: ${agentJsonPath}`
|
|
407
|
+
);
|
|
408
|
+
|
|
409
|
+
const agentJson = JSON.parse(fs.readFileSync(agentJsonPath, 'utf8'));
|
|
410
|
+
|
|
411
|
+
const exportCount = agentJson.exports?.length || 0;
|
|
412
|
+
this.logger.success(
|
|
413
|
+
'_loadAgentJsonExports',
|
|
414
|
+
`Loaded ${exportCount} exports`
|
|
415
|
+
);
|
|
416
|
+
|
|
417
|
+
return agentJson.exports || [];
|
|
418
|
+
} catch (err) {
|
|
419
|
+
this.logger.warn(
|
|
420
|
+
'_loadAgentJsonExports',
|
|
421
|
+
`Could not load agent.json exports: ${err.message}`
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
return [];
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Find agent.json file in current directory or parent directories
|
|
430
|
+
*
|
|
431
|
+
* @returns {string} - Path to agent.json file
|
|
432
|
+
* @private
|
|
433
|
+
*/
|
|
434
|
+
async _findAgentJson() {
|
|
435
|
+
this.logger.methodCall('_findAgentJson', 'Searching for agent.json file');
|
|
436
|
+
this.logger.trace(
|
|
437
|
+
'_findAgentJson',
|
|
438
|
+
`Current working directory: ${process.cwd()}`
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
const possiblePaths = [
|
|
442
|
+
// Use explicit path if provided
|
|
443
|
+
this.abilityAgentJSON,
|
|
444
|
+
// Standard locations
|
|
445
|
+
path.join(process.cwd(), 'agent.json'),
|
|
446
|
+
path.join(path.dirname(process.argv[1]), 'agent.json'), // Same directory as the script
|
|
447
|
+
path.join(process.cwd(), '..', 'agent.json'),
|
|
448
|
+
path.join(process.cwd(), '..', '..', 'agent.json')
|
|
449
|
+
].filter(Boolean); // Remove undefined entries
|
|
450
|
+
|
|
451
|
+
this.logger.trace(
|
|
452
|
+
'_findAgentJson',
|
|
453
|
+
`Checking paths: ${possiblePaths.join(', ')}`
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
for (const agentPath of possiblePaths) {
|
|
457
|
+
this.logger.trace('_findAgentJson', `Checking: ${agentPath}`);
|
|
458
|
+
|
|
459
|
+
if (fs.existsSync(agentPath)) {
|
|
460
|
+
this.logger.success(
|
|
461
|
+
'_findAgentJson',
|
|
462
|
+
`Found agent.json at: ${agentPath}`
|
|
463
|
+
);
|
|
464
|
+
|
|
465
|
+
return agentPath;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
this.logger.error(
|
|
470
|
+
'_findAgentJson',
|
|
471
|
+
'agent.json not found in any checked locations'
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
throw new Error('agent.json not found in any of the checked locations');
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
export default KadiAbility;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Update your existing index.js to export the new classes
|
|
2
|
+
export { KadiAbility } from './KadiAbility.js';
|
|
3
|
+
|
|
4
|
+
// Export logging facilities
|
|
5
|
+
export { createLogger, loggers, isDebugEnabled } from './utils/logger.js';
|
|
6
|
+
|
|
7
|
+
// Export servers for advanced users
|
|
8
|
+
export { BaseRpcServer } from './servers/BaseRpcServer.js';
|
|
9
|
+
export { StdioRpcServer } from './servers/StdioRpcServer.js';
|
|
10
|
+
export { BrokerRpcServer } from './servers/BrokerRpcServer.js';
|
|
11
|
+
|
|
12
|
+
// Re-export transport utilities (maintain backward compatibility)
|
|
13
|
+
export {
|
|
14
|
+
StdioFrameReader,
|
|
15
|
+
StdioFrameWriter,
|
|
16
|
+
IpcServer,
|
|
17
|
+
StdioTransport,
|
|
18
|
+
BrokerTransport
|
|
19
|
+
} from './transport/IpcMessageBuilder.js';
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
Broker,
|
|
23
|
+
IdFactory,
|
|
24
|
+
toBase64Der
|
|
25
|
+
} from './transport/BrokerMessageBuilder.js';
|
|
26
|
+
|
|
27
|
+
// Export loadAbility from its own file
|
|
28
|
+
export { loadAbility } from './loadAbility.js';
|
|
29
|
+
|
|
30
|
+
// Your existing utility functions from utils files
|
|
31
|
+
export {
|
|
32
|
+
getAbilityJSON,
|
|
33
|
+
getAbilityJSONPath,
|
|
34
|
+
getAbilitiesDir,
|
|
35
|
+
getProjectJSON,
|
|
36
|
+
getProjectJSONPath,
|
|
37
|
+
getKadiCoreJSON,
|
|
38
|
+
getKadiCoreJSONPath,
|
|
39
|
+
getKadiJSON,
|
|
40
|
+
getKadiJSONPath,
|
|
41
|
+
getKadiExecPath,
|
|
42
|
+
getKadiInstallPath,
|
|
43
|
+
saveAgentJSON,
|
|
44
|
+
getAbilityVersionFromArray,
|
|
45
|
+
KADI_API_URL,
|
|
46
|
+
SEARCH_API_URL,
|
|
47
|
+
GET_API_URL
|
|
48
|
+
} from './utils/agentUtils.js';
|
|
49
|
+
|
|
50
|
+
export { runExecCommand, runSpawnCommand } from './utils/commandUtils.js';
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
KADI_BROKERS,
|
|
54
|
+
KADI_BROKER_URL,
|
|
55
|
+
getBrokerUrl,
|
|
56
|
+
getBrokerNames,
|
|
57
|
+
getDefaultBrokerName,
|
|
58
|
+
setActiveBroker,
|
|
59
|
+
getActiveBrokerName,
|
|
60
|
+
getActiveBrokerUrl,
|
|
61
|
+
findAbilityVersionByName
|
|
62
|
+
} from './utils/configUtils.js';
|
|
63
|
+
|
|
64
|
+
// Note: pathUtils.js exports are internal and not typically needed by external users
|
|
65
|
+
// but you can add them if needed
|