@kadi.build/core 0.0.1-alpha.3 → 0.0.1-alpha.4

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.
Files changed (128) hide show
  1. package/README.md +571 -594
  2. package/dist/KadiClient.d.ts +303 -0
  3. package/dist/KadiClient.d.ts.map +1 -0
  4. package/dist/KadiClient.js +1162 -0
  5. package/dist/KadiClient.js.map +1 -0
  6. package/dist/errors/error-codes.d.ts +215 -0
  7. package/dist/errors/error-codes.d.ts.map +1 -0
  8. package/dist/errors/error-codes.js +295 -0
  9. package/dist/errors/error-codes.js.map +1 -0
  10. package/dist/index.d.ts +15 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +24 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/loadAbility.d.ts +65 -0
  15. package/dist/loadAbility.d.ts.map +1 -0
  16. package/dist/loadAbility.js +335 -0
  17. package/dist/loadAbility.js.map +1 -0
  18. package/dist/messages/BrokerMessages.d.ts +84 -0
  19. package/dist/messages/BrokerMessages.d.ts.map +1 -0
  20. package/dist/messages/BrokerMessages.js +127 -0
  21. package/dist/messages/BrokerMessages.js.map +1 -0
  22. package/dist/messages/MessageBuilder.d.ts +83 -0
  23. package/dist/messages/MessageBuilder.d.ts.map +1 -0
  24. package/dist/messages/MessageBuilder.js +144 -0
  25. package/dist/messages/MessageBuilder.js.map +1 -0
  26. package/dist/schemas/events.schemas.d.ts +177 -0
  27. package/dist/schemas/events.schemas.d.ts.map +1 -0
  28. package/dist/schemas/events.schemas.js +265 -0
  29. package/dist/schemas/events.schemas.js.map +1 -0
  30. package/dist/schemas/index.d.ts +3 -0
  31. package/dist/schemas/index.d.ts.map +1 -0
  32. package/dist/schemas/index.js +4 -0
  33. package/dist/schemas/index.js.map +1 -0
  34. package/dist/schemas/kadi.schemas.d.ts +70 -0
  35. package/dist/schemas/kadi.schemas.d.ts.map +1 -0
  36. package/dist/schemas/kadi.schemas.js +120 -0
  37. package/dist/schemas/kadi.schemas.js.map +1 -0
  38. package/dist/transports/BrokerTransport.d.ts +96 -0
  39. package/dist/transports/BrokerTransport.d.ts.map +1 -0
  40. package/dist/transports/BrokerTransport.js +145 -0
  41. package/dist/transports/BrokerTransport.js.map +1 -0
  42. package/dist/transports/NativeTransport.d.ts +92 -0
  43. package/dist/transports/NativeTransport.d.ts.map +1 -0
  44. package/dist/transports/NativeTransport.js +221 -0
  45. package/dist/transports/NativeTransport.js.map +1 -0
  46. package/dist/transports/StdioTransport.d.ts +112 -0
  47. package/dist/transports/StdioTransport.d.ts.map +1 -0
  48. package/dist/transports/StdioTransport.js +440 -0
  49. package/dist/transports/StdioTransport.js.map +1 -0
  50. package/dist/transports/Transport.d.ts +93 -0
  51. package/dist/transports/Transport.d.ts.map +1 -0
  52. package/dist/transports/Transport.js +13 -0
  53. package/dist/transports/Transport.js.map +1 -0
  54. package/dist/types/broker.d.ts +31 -0
  55. package/dist/types/broker.d.ts.map +1 -0
  56. package/dist/types/broker.js +6 -0
  57. package/dist/types/broker.js.map +1 -0
  58. package/dist/types/core.d.ts +138 -0
  59. package/dist/types/core.d.ts.map +1 -0
  60. package/dist/types/core.js +26 -0
  61. package/dist/types/core.js.map +1 -0
  62. package/dist/types/events.d.ts +186 -0
  63. package/dist/types/events.d.ts.map +1 -0
  64. package/dist/types/events.js +16 -0
  65. package/dist/types/events.js.map +1 -0
  66. package/dist/types/index.d.ts +9 -0
  67. package/dist/types/index.d.ts.map +1 -0
  68. package/dist/types/index.js +13 -0
  69. package/dist/types/index.js.map +1 -0
  70. package/dist/types/protocol.d.ts +160 -0
  71. package/dist/types/protocol.d.ts.map +1 -0
  72. package/dist/types/protocol.js +5 -0
  73. package/dist/types/protocol.js.map +1 -0
  74. package/dist/utils/agentUtils.d.ts +102 -0
  75. package/dist/utils/agentUtils.d.ts.map +1 -0
  76. package/dist/utils/agentUtils.js +166 -0
  77. package/dist/utils/agentUtils.js.map +1 -0
  78. package/dist/utils/commandUtils.d.ts +45 -0
  79. package/dist/utils/commandUtils.d.ts.map +1 -0
  80. package/dist/utils/commandUtils.js +145 -0
  81. package/dist/utils/commandUtils.js.map +1 -0
  82. package/dist/utils/configUtils.d.ts +55 -0
  83. package/dist/utils/configUtils.d.ts.map +1 -0
  84. package/dist/utils/configUtils.js +100 -0
  85. package/dist/utils/configUtils.js.map +1 -0
  86. package/dist/utils/logger.d.ts +59 -0
  87. package/dist/utils/logger.d.ts.map +1 -0
  88. package/dist/utils/logger.js +122 -0
  89. package/dist/utils/logger.js.map +1 -0
  90. package/dist/utils/pathUtils.d.ts +48 -0
  91. package/dist/utils/pathUtils.d.ts.map +1 -0
  92. package/dist/utils/pathUtils.js +128 -0
  93. package/dist/utils/pathUtils.js.map +1 -0
  94. package/package.json +56 -5
  95. package/agent.json +0 -18
  96. package/examples/example-abilities/echo-js/README.md +0 -131
  97. package/examples/example-abilities/echo-js/agent.json +0 -63
  98. package/examples/example-abilities/echo-js/package.json +0 -24
  99. package/examples/example-abilities/echo-js/service.js +0 -43
  100. package/examples/example-abilities/hash-go/agent.json +0 -53
  101. package/examples/example-abilities/hash-go/cmd/hash_ability/main.go +0 -340
  102. package/examples/example-abilities/hash-go/go.mod +0 -3
  103. package/examples/example-agent/abilities/echo-js/0.0.1/README.md +0 -131
  104. package/examples/example-agent/abilities/echo-js/0.0.1/agent.json +0 -63
  105. package/examples/example-agent/abilities/echo-js/0.0.1/package-lock.json +0 -93
  106. package/examples/example-agent/abilities/echo-js/0.0.1/package.json +0 -24
  107. package/examples/example-agent/abilities/echo-js/0.0.1/service.js +0 -41
  108. package/examples/example-agent/abilities/hash-go/0.0.1/agent.json +0 -53
  109. package/examples/example-agent/abilities/hash-go/0.0.1/bin/hash_ability +0 -0
  110. package/examples/example-agent/abilities/hash-go/0.0.1/cmd/hash_ability/main.go +0 -340
  111. package/examples/example-agent/abilities/hash-go/0.0.1/go.mod +0 -3
  112. package/examples/example-agent/agent.json +0 -39
  113. package/examples/example-agent/index.js +0 -102
  114. package/examples/example-agent/package-lock.json +0 -93
  115. package/examples/example-agent/package.json +0 -17
  116. package/src/KadiAbility.js +0 -478
  117. package/src/index.js +0 -65
  118. package/src/loadAbility.js +0 -1086
  119. package/src/servers/BaseRpcServer.js +0 -404
  120. package/src/servers/BrokerRpcServer.js +0 -776
  121. package/src/servers/StdioRpcServer.js +0 -360
  122. package/src/transport/BrokerMessageBuilder.js +0 -377
  123. package/src/transport/IpcMessageBuilder.js +0 -1229
  124. package/src/utils/agentUtils.js +0 -137
  125. package/src/utils/commandUtils.js +0 -64
  126. package/src/utils/configUtils.js +0 -72
  127. package/src/utils/logger.js +0 -161
  128. package/src/utils/pathUtils.js +0 -86
@@ -1,360 +0,0 @@
1
- import { BaseRpcServer } from './BaseRpcServer.js';
2
- import {
3
- StdioFrameReader,
4
- StdioFrameWriter
5
- } from '../transport/IpcMessageBuilder.js';
6
- import { createComponentLogger } from '../utils/logger.js';
7
- /**
8
- * RPC Server for stdio transport using LSP-style framing
9
- *
10
- * This server handles JSON-RPC requests over stdio using Language Server Protocol
11
- * style framing (Content-Length headers + JSON body). It's designed for process-to-process
12
- * communication where the parent process spawns this ability as a child process.
13
- */
14
- export class StdioRpcServer extends BaseRpcServer {
15
- /**
16
- * Create a new StdioRpcServer instance
17
- *
18
- * @param {Object} options - Configuration options
19
- * @param {number} options.maxBufferSize - Maximum buffer size for frame reader
20
- * @param {Readable} options.stdin - Input stream (default: process.stdin)
21
- * @param {Writable} options.stdout - Output stream (default: process.stdout)
22
- */
23
- constructor(options = {}) {
24
- super({ ...options, protocol: 'stdio' });
25
-
26
- this.frameReader = new StdioFrameReader(options.stdin || process.stdin, {
27
- maxBufferSize: options.maxBufferSize || 8 * 1024 * 1024
28
- });
29
- this.frameWriter = new StdioFrameWriter(options.stdout || process.stdout);
30
-
31
- this.logger = createComponentLogger('StdioRpcServer');
32
- this.logger.lifecycle('constructor', 'StdioRpcServer initialized');
33
- this.logger.trace(
34
- 'constructor',
35
- `Max buffer size: ${options.maxBufferSize || 8 * 1024 * 1024} bytes`
36
- );
37
-
38
- this.ability = null;
39
- this.resolve = null;
40
- this.reject = null;
41
- }
42
-
43
- /**
44
- * Start serving the ability over stdio
45
- *
46
- * @param {KadiAbility} ability - The ability instance to serve
47
- * @returns {Promise<void>} - Promise that resolves when server stops
48
- */
49
- async serve(ability) {
50
- if (this.isServing) {
51
- this.logger.error('serve', 'StdioRpcServer is already serving');
52
- throw new Error('StdioRpcServer is already serving');
53
- }
54
-
55
- this.ability = ability;
56
- this.isServing = true;
57
-
58
- this.logger.lifecycle(
59
- 'serve',
60
- `Starting ${ability.name || 'unnamed ability'} on stdio`
61
- );
62
- this.logger.info(
63
- 'serve',
64
- `Available methods: ${ability.getMethodNames().join(', ')}`
65
- );
66
- this.logger.trace('serve', 'Setting up frame reader and process handlers');
67
-
68
- // Emit start event
69
- this.emit('start', {
70
- name: ability.name,
71
- version: ability.version,
72
- methods: ability.getMethodNames()
73
- });
74
-
75
- // Set up frame reading with message handling
76
- this.frameReader.onMessage(async (frameResult) => {
77
- if (!frameResult.success) {
78
- this.logger.error('frame', `Frame corruption: ${frameResult.error}`);
79
- this.logger.trace(
80
- 'frame',
81
- `Corruption type: ${frameResult.corruption_type}, message: ${frameResult.message}`
82
- );
83
-
84
- // Emit error event but don't crash - frame corruption can be recovered
85
- this.emit('error', new Error(`Frame corruption: ${frameResult.error}`));
86
- return;
87
- }
88
-
89
- try {
90
- this.logger.trace(
91
- 'request',
92
- `Processing JSON-RPC request: ${frameResult.data?.method}`
93
- );
94
-
95
- // Process the JSON-RPC request
96
- const response = await this.handleRequest(frameResult.data);
97
-
98
- // Write response if it's not a notification
99
- if (response !== null) {
100
- this.logger.trace(
101
- 'response',
102
- `Sending response for request ID: ${frameResult.data?.id}`
103
- );
104
-
105
- await this.frameWriter.write(response);
106
- } else {
107
- this.logger.trace(
108
- 'notification',
109
- `Notification processed: ${frameResult.data?.method}`
110
- );
111
- }
112
- } catch (error) {
113
- this.logger.error(
114
- 'request',
115
- `Fatal error processing request: ${error.message}`
116
- );
117
- this.logger.trace('request', `Error stack: ${error.stack}`);
118
-
119
- this.logError('Fatal error processing request:', error);
120
-
121
- // Try to send an error response if we can extract an ID
122
- const requestId = frameResult.data?.id;
123
- if (requestId !== undefined) {
124
- try {
125
- const errorResponse = this.createInternalErrorResponse(
126
- requestId,
127
- 'Internal error',
128
- { error: error.message }
129
- );
130
- await this.frameWriter.write(errorResponse);
131
- } catch (writeError) {
132
- this.logError('Failed to send error response:', writeError);
133
- }
134
- }
135
-
136
- // Emit error event
137
- this.emit('error', error);
138
- }
139
- });
140
-
141
- // Handle process termination gracefully
142
- const signalHandler = (signal) => {
143
- this.logger.lifecycle(
144
- 'signal',
145
- `Received ${signal}, shutting down gracefully`
146
- );
147
-
148
- this.log(`Received ${signal}, shutting down gracefully`);
149
- this.shutdown(signal);
150
- };
151
-
152
- process.on('SIGINT', signalHandler);
153
- process.on('SIGTERM', signalHandler);
154
-
155
- // Keep the process alive and handle stdio events
156
- return new Promise((resolve, reject) => {
157
- this.resolve = resolve;
158
- this.reject = reject;
159
-
160
- // Handle stdin end - parent process closed the pipe
161
- process.stdin.on('end', () => {
162
- this.logger.lifecycle('stdin', 'stdin closed, shutting down');
163
- this.log('stdin closed, shutting down');
164
- this.shutdown('stdin_end');
165
- });
166
-
167
- // Handle stdin errors
168
- process.stdin.on('error', (error) => {
169
- this.logger.error('stdin', `stdin error: ${error.message}`);
170
- this.logError('stdin error:', error);
171
- this.reject(error);
172
- });
173
-
174
- // Handle stdout errors (broken pipe, etc.)
175
- process.stdout.on('error', (error) => {
176
- this.logger.error('stdout', `stdout error: ${error.message}`);
177
- this.logError('stdout error:', error);
178
- this.reject(error);
179
- });
180
- });
181
- }
182
-
183
- /**
184
- * Handle requests in stdio-native format
185
- *
186
- * This implementation applies stdio-specific validation and error handling.
187
- * Stdio requests come as JSON-RPC over LSP framing and often need more
188
- * human-readable error messages since they might be displayed to developers.
189
- *
190
- * @param {Object} request - The JSON-RPC request object
191
- * @returns {Object|null} - JSON-RPC response or null for notifications
192
- */
193
- async handleRequest(request) {
194
- this.logger.trace('validation', 'Validating JSON-RPC request format');
195
-
196
- // Validate JSON-RPC format
197
- if (!request || typeof request !== 'object') {
198
- this.logger.warn('validation', 'Invalid request: not an object');
199
- return this.createInvalidRequestResponse(null);
200
- }
201
-
202
- // Check for required jsonrpc field
203
- if (request.jsonrpc !== '2.0') {
204
- this.logger.warn(
205
- 'validation',
206
- `Invalid JSON-RPC version: ${request.jsonrpc}`
207
- );
208
- return this.createInvalidRequestResponse(request.id || null);
209
- }
210
-
211
- // Check for required method field
212
- if (typeof request.method !== 'string') {
213
- this.logger.warn('validation', 'Invalid request: method is not a string');
214
- return this.createInvalidRequestResponse(request.id || null);
215
- }
216
-
217
- // Validate params if present
218
- if (
219
- request.params !== undefined &&
220
- typeof request.params !== 'object' &&
221
- !Array.isArray(request.params)
222
- ) {
223
- this.logger.warn(
224
- 'validation',
225
- 'Invalid request: params is not an object or array'
226
- );
227
- return this.createInvalidRequestResponse(request.id || null);
228
- }
229
-
230
- this.logger.trace('validation', 'JSON-RPC request validation passed');
231
-
232
- // Use base class request handling
233
- return await super.handleRequest(request);
234
- }
235
-
236
- /**
237
- * Gracefully shutdown the stdio server
238
- *
239
- * @param {string} reason - Reason for shutdown
240
- */
241
- async shutdown(reason = 'unknown') {
242
- this.logger.lifecycle(
243
- 'shutdown',
244
- `Shutting down stdio server, reason: ${reason}`
245
- );
246
- await super.shutdown(reason);
247
-
248
- // Resolve the serve promise to allow clean exit
249
- if (this.resolve) {
250
- this.logger.trace('shutdown', 'Resolving serve promise for clean exit');
251
- this.resolve();
252
- }
253
- }
254
-
255
- /**
256
- * Send a notification to the parent process
257
- *
258
- * This is useful for sending status updates or logs that don't require a response
259
- *
260
- * @param {string} method - Notification method name
261
- * @param {Object} params - Notification parameters
262
- */
263
- async sendNotification(method, params = {}) {
264
- this.logger.trace('notification', `Sending notification: ${method}`);
265
-
266
- const notification = {
267
- jsonrpc: '2.0',
268
- method,
269
- params
270
- };
271
-
272
- try {
273
- await this.frameWriter.write(notification);
274
- this.logger.trace(
275
- 'notification',
276
- `Notification ${method} sent successfully`
277
- );
278
- } catch (error) {
279
- this.logger.error(
280
- 'notification',
281
- `Failed to send notification ${method}: ${error.message}`
282
- );
283
-
284
- this.logError('Failed to send notification:', error);
285
- }
286
- }
287
-
288
- /**
289
- * Publish an event to the parent process via stdio
290
- *
291
- * Events are sent as JSON-RPC notifications with the special method '__kadi_event'.
292
- * The parent process (agent) will receive these and emit them on the ability's
293
- * events EventEmitter.
294
- *
295
- * @param {string} eventName - Name of the event to publish
296
- * @param {any} data - Event data payload (must be JSON-serializable)
297
- */
298
- async publishEvent(eventName, data = {}) {
299
- this.logger.trace(
300
- 'publishEvent',
301
- `Publishing event via stdio: ${eventName}`
302
- );
303
-
304
- try {
305
- // Send as a JSON-RPC notification with special method name
306
- // No 'id' field means it's fire-and-forget
307
- const eventNotification = {
308
- jsonrpc: '2.0',
309
- method: '__kadi_event',
310
- params: {
311
- eventName,
312
- data,
313
- timestamp: Date.now() // Add timestamp for event ordering
314
- }
315
- };
316
-
317
- await this.frameWriter.write(eventNotification);
318
-
319
- this.logger.trace('publishEvent', `Event ${eventName} sent successfully`);
320
- } catch (error) {
321
- // Events are best-effort - log but don't throw
322
- this.logger.warn(
323
- 'publishEvent',
324
- `Failed to publish event ${eventName}: ${error.message}`
325
- );
326
- }
327
- }
328
-
329
- /**
330
- * Send a status update notification
331
- *
332
- * @param {string} status - Status message
333
- * @param {Object} data - Additional status data
334
- */
335
- async sendStatus(status, data = {}) {
336
- await this.sendNotification('__kadi_status', { status, ...data });
337
- }
338
-
339
- /**
340
- * Send a progress notification
341
- *
342
- * @param {number} current - Current progress value
343
- * @param {number} total - Total progress value
344
- * @param {string} message - Progress message
345
- */
346
- async sendProgress(current, total, message = '') {
347
- this.logger.trace(
348
- 'progress',
349
- `Sending progress: ${current}/${total} - ${message}`
350
- );
351
- await this.sendNotification('__kadi_progress', {
352
- current,
353
- total,
354
- percentage: Math.round((current / total) * 100),
355
- message
356
- });
357
- }
358
- }
359
-
360
- export default StdioRpcServer;