@kadi.build/core 0.0.1-alpha.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +362 -1305
- package/dist/client.d.ts +573 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +1673 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +107 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +147 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +37 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -23
- package/dist/index.js.map +1 -1
- package/dist/lockfile.d.ts +190 -0
- package/dist/lockfile.d.ts.map +1 -0
- package/dist/lockfile.js +373 -0
- package/dist/lockfile.js.map +1 -0
- package/dist/transports/broker.d.ts +75 -0
- package/dist/transports/broker.d.ts.map +1 -0
- package/dist/transports/broker.js +383 -0
- package/dist/transports/broker.js.map +1 -0
- package/dist/transports/native.d.ts +39 -0
- package/dist/transports/native.d.ts.map +1 -0
- package/dist/transports/native.js +189 -0
- package/dist/transports/native.js.map +1 -0
- package/dist/transports/stdio.d.ts +46 -0
- package/dist/transports/stdio.d.ts.map +1 -0
- package/dist/transports/stdio.js +460 -0
- package/dist/transports/stdio.js.map +1 -0
- package/dist/types.d.ts +664 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/dist/zod.d.ts +34 -0
- package/dist/zod.d.ts.map +1 -0
- package/dist/zod.js +60 -0
- package/dist/zod.js.map +1 -0
- package/package.json +13 -28
- package/dist/KadiClient.d.ts +0 -432
- package/dist/KadiClient.d.ts.map +0 -1
- package/dist/KadiClient.js +0 -1506
- package/dist/KadiClient.js.map +0 -1
- package/dist/errors/error-codes.d.ts +0 -985
- package/dist/errors/error-codes.d.ts.map +0 -1
- package/dist/errors/error-codes.js +0 -638
- package/dist/errors/error-codes.js.map +0 -1
- package/dist/loadAbility.d.ts +0 -105
- package/dist/loadAbility.d.ts.map +0 -1
- package/dist/loadAbility.js +0 -370
- package/dist/loadAbility.js.map +0 -1
- package/dist/messages/BrokerMessages.d.ts +0 -84
- package/dist/messages/BrokerMessages.d.ts.map +0 -1
- package/dist/messages/BrokerMessages.js +0 -125
- package/dist/messages/BrokerMessages.js.map +0 -1
- package/dist/messages/MessageBuilder.d.ts +0 -83
- package/dist/messages/MessageBuilder.d.ts.map +0 -1
- package/dist/messages/MessageBuilder.js +0 -144
- package/dist/messages/MessageBuilder.js.map +0 -1
- package/dist/schemas/events.schemas.d.ts +0 -177
- package/dist/schemas/events.schemas.d.ts.map +0 -1
- package/dist/schemas/events.schemas.js +0 -265
- package/dist/schemas/events.schemas.js.map +0 -1
- package/dist/schemas/index.d.ts +0 -3
- package/dist/schemas/index.d.ts.map +0 -1
- package/dist/schemas/index.js +0 -4
- package/dist/schemas/index.js.map +0 -1
- package/dist/schemas/kadi.schemas.d.ts +0 -70
- package/dist/schemas/kadi.schemas.d.ts.map +0 -1
- package/dist/schemas/kadi.schemas.js +0 -120
- package/dist/schemas/kadi.schemas.js.map +0 -1
- package/dist/transports/BrokerTransport.d.ts +0 -102
- package/dist/transports/BrokerTransport.d.ts.map +0 -1
- package/dist/transports/BrokerTransport.js +0 -177
- package/dist/transports/BrokerTransport.js.map +0 -1
- package/dist/transports/NativeTransport.d.ts +0 -82
- package/dist/transports/NativeTransport.d.ts.map +0 -1
- package/dist/transports/NativeTransport.js +0 -263
- package/dist/transports/NativeTransport.js.map +0 -1
- package/dist/transports/StdioTransport.d.ts +0 -112
- package/dist/transports/StdioTransport.d.ts.map +0 -1
- package/dist/transports/StdioTransport.js +0 -450
- package/dist/transports/StdioTransport.js.map +0 -1
- package/dist/transports/Transport.d.ts +0 -93
- package/dist/transports/Transport.d.ts.map +0 -1
- package/dist/transports/Transport.js +0 -13
- package/dist/transports/Transport.js.map +0 -1
- package/dist/types/broker.d.ts +0 -31
- package/dist/types/broker.d.ts.map +0 -1
- package/dist/types/broker.js +0 -6
- package/dist/types/broker.js.map +0 -1
- package/dist/types/core.d.ts +0 -139
- package/dist/types/core.d.ts.map +0 -1
- package/dist/types/core.js +0 -26
- package/dist/types/core.js.map +0 -1
- package/dist/types/events.d.ts +0 -186
- package/dist/types/events.d.ts.map +0 -1
- package/dist/types/events.js +0 -16
- package/dist/types/events.js.map +0 -1
- package/dist/types/index.d.ts +0 -9
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -13
- package/dist/types/index.js.map +0 -1
- package/dist/types/protocol.d.ts +0 -160
- package/dist/types/protocol.d.ts.map +0 -1
- package/dist/types/protocol.js +0 -5
- package/dist/types/protocol.js.map +0 -1
- package/dist/utils/agentUtils.d.ts +0 -187
- package/dist/utils/agentUtils.d.ts.map +0 -1
- package/dist/utils/agentUtils.js +0 -185
- package/dist/utils/agentUtils.js.map +0 -1
- package/dist/utils/commandUtils.d.ts +0 -45
- package/dist/utils/commandUtils.d.ts.map +0 -1
- package/dist/utils/commandUtils.js +0 -145
- package/dist/utils/commandUtils.js.map +0 -1
- package/dist/utils/configUtils.d.ts +0 -55
- package/dist/utils/configUtils.d.ts.map +0 -1
- package/dist/utils/configUtils.js +0 -100
- package/dist/utils/configUtils.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -59
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -122
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/pathUtils.d.ts +0 -48
- package/dist/utils/pathUtils.d.ts.map +0 -1
- package/dist/utils/pathUtils.js +0 -128
- package/dist/utils/pathUtils.js.map +0 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stdio transport for kadi-core v0.1.0
|
|
3
|
+
*
|
|
4
|
+
* Loads abilities that run as CHILD PROCESSES.
|
|
5
|
+
* Communication happens via stdin/stdout using JSON-RPC with Content-Length framing.
|
|
6
|
+
*
|
|
7
|
+
* Protocol (same as LSP - Language Server Protocol):
|
|
8
|
+
* - Each message is prefixed with "Content-Length: <bytes>\r\n\r\n"
|
|
9
|
+
* - The content is JSON (JSON-RPC 2.0 format)
|
|
10
|
+
*
|
|
11
|
+
* This transport is language-agnostic - the child process can be Python, Go, etc.
|
|
12
|
+
* as long as it speaks the same protocol.
|
|
13
|
+
*
|
|
14
|
+
* How it works:
|
|
15
|
+
* 1. Spawn the child process
|
|
16
|
+
* 2. Send "readAgentJson" to get tool definitions
|
|
17
|
+
* 3. For each invoke(), send request and wait for response
|
|
18
|
+
* 4. On disconnect, send "shutdown" and kill the process
|
|
19
|
+
*/
|
|
20
|
+
import type { LoadedAbility } from '../types.js';
|
|
21
|
+
/**
|
|
22
|
+
* Load a child process ability via stdio.
|
|
23
|
+
*
|
|
24
|
+
* The child process must speak JSON-RPC over stdin/stdout with Content-Length framing.
|
|
25
|
+
* This is the standard KADI ability protocol.
|
|
26
|
+
*
|
|
27
|
+
* @param command - Command to run (e.g., 'python3', 'node')
|
|
28
|
+
* @param args - Arguments to pass to the command
|
|
29
|
+
* @param options - Additional options
|
|
30
|
+
* @returns LoadedAbility that can invoke tools
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* // Load a Python ability
|
|
35
|
+
* const analyzer = await loadStdioTransport('python3', ['analyzer.py']);
|
|
36
|
+
* const result = await analyzer.invoke('analyze', { text: 'hello' });
|
|
37
|
+
*
|
|
38
|
+
* // Load a Node.js ability
|
|
39
|
+
* const calc = await loadStdioTransport('node', ['dist/index.js']);
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function loadStdioTransport(command: string, args?: string[], options?: {
|
|
43
|
+
timeoutMs?: number;
|
|
44
|
+
cwd?: string;
|
|
45
|
+
}): Promise<LoadedAbility>;
|
|
46
|
+
//# sourceMappingURL=stdio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAiE,MAAM,aAAa,CAAC;AA6OhH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,EAAO,EACnB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,aAAa,CAAC,CAiSxB"}
|
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stdio transport for kadi-core v0.1.0
|
|
3
|
+
*
|
|
4
|
+
* Loads abilities that run as CHILD PROCESSES.
|
|
5
|
+
* Communication happens via stdin/stdout using JSON-RPC with Content-Length framing.
|
|
6
|
+
*
|
|
7
|
+
* Protocol (same as LSP - Language Server Protocol):
|
|
8
|
+
* - Each message is prefixed with "Content-Length: <bytes>\r\n\r\n"
|
|
9
|
+
* - The content is JSON (JSON-RPC 2.0 format)
|
|
10
|
+
*
|
|
11
|
+
* This transport is language-agnostic - the child process can be Python, Go, etc.
|
|
12
|
+
* as long as it speaks the same protocol.
|
|
13
|
+
*
|
|
14
|
+
* How it works:
|
|
15
|
+
* 1. Spawn the child process
|
|
16
|
+
* 2. Send "readAgentJson" to get tool definitions
|
|
17
|
+
* 3. For each invoke(), send request and wait for response
|
|
18
|
+
* 4. On disconnect, send "shutdown" and kill the process
|
|
19
|
+
*/
|
|
20
|
+
import { spawn } from 'child_process';
|
|
21
|
+
import { z } from 'zod';
|
|
22
|
+
import { KadiError } from '../errors.js';
|
|
23
|
+
/** Schema for event notification params */
|
|
24
|
+
const EventNotificationParams = z.object({
|
|
25
|
+
name: z.string(),
|
|
26
|
+
data: z.unknown(),
|
|
27
|
+
});
|
|
28
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
29
|
+
// MESSAGE READER (Content-Length framing)
|
|
30
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
31
|
+
/**
|
|
32
|
+
* Reads JSON-RPC messages from a stream using Content-Length framing.
|
|
33
|
+
*
|
|
34
|
+
* Uses Buffer (not string) for binary safety. Handles partial messages
|
|
35
|
+
* across chunks and recovers from malformed headers.
|
|
36
|
+
*
|
|
37
|
+
* Message format:
|
|
38
|
+
* ```
|
|
39
|
+
* Content-Length: 42\r\n
|
|
40
|
+
* \r\n
|
|
41
|
+
* {"jsonrpc":"2.0","id":1,"result":{...}}
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
class StdioReader {
|
|
45
|
+
timeoutMs;
|
|
46
|
+
buffer = Buffer.alloc(0);
|
|
47
|
+
static HEADER_END = '\r\n\r\n';
|
|
48
|
+
static HEADER_END_LENGTH = 4; // \r\n\r\n
|
|
49
|
+
static CONTENT_LENGTH_MARKER = Buffer.from('Content-Length:');
|
|
50
|
+
static CONTENT_LENGTH_PATTERN = /Content-Length:\s*(\d+)/;
|
|
51
|
+
waiters = [];
|
|
52
|
+
/** Handler for event notifications */
|
|
53
|
+
notificationHandler = null;
|
|
54
|
+
constructor(stream, timeoutMs = 30000) {
|
|
55
|
+
this.timeoutMs = timeoutMs;
|
|
56
|
+
stream.on('data', (chunk) => this.onData(chunk));
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Set handler for notifications (messages without id).
|
|
60
|
+
*/
|
|
61
|
+
setNotificationHandler(handler) {
|
|
62
|
+
this.notificationHandler = handler;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Handle incoming data from the stream.
|
|
66
|
+
*/
|
|
67
|
+
onData(chunk) {
|
|
68
|
+
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
69
|
+
this.processBuffer();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Process the buffer, extracting complete messages.
|
|
73
|
+
*/
|
|
74
|
+
processBuffer() {
|
|
75
|
+
let message;
|
|
76
|
+
while ((message = this.tryReadSingleMessage()) !== null) {
|
|
77
|
+
this.dispatchMessage(message);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Try to read a single complete message from the buffer.
|
|
82
|
+
* @returns Parsed message, or null if no complete message available
|
|
83
|
+
*/
|
|
84
|
+
tryReadSingleMessage() {
|
|
85
|
+
// Look for header end marker
|
|
86
|
+
const headerEndIndex = this.buffer.indexOf(StdioReader.HEADER_END);
|
|
87
|
+
if (headerEndIndex === -1) {
|
|
88
|
+
return null; // No complete header yet
|
|
89
|
+
}
|
|
90
|
+
// Parse Content-Length from header
|
|
91
|
+
const header = this.buffer.slice(0, headerEndIndex).toString('utf8');
|
|
92
|
+
const match = header.match(StdioReader.CONTENT_LENGTH_PATTERN);
|
|
93
|
+
if (!match?.[1]) {
|
|
94
|
+
// Invalid header - skip to next potential header
|
|
95
|
+
this.skipToNextHeader();
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const contentLength = parseInt(match[1], 10);
|
|
99
|
+
const contentStart = headerEndIndex + StdioReader.HEADER_END_LENGTH;
|
|
100
|
+
const contentEnd = contentStart + contentLength;
|
|
101
|
+
// Check if we have the complete message
|
|
102
|
+
if (this.buffer.length < contentEnd) {
|
|
103
|
+
return null; // Need more data
|
|
104
|
+
}
|
|
105
|
+
// Extract and parse JSON
|
|
106
|
+
const content = this.buffer.slice(contentStart, contentEnd).toString('utf8');
|
|
107
|
+
this.buffer = this.buffer.slice(contentEnd); // Remove processed data
|
|
108
|
+
try {
|
|
109
|
+
return JSON.parse(content);
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
// Invalid JSON - log error so developer knows something's wrong
|
|
113
|
+
console.error('[KADI] Failed to parse message from child process:', error);
|
|
114
|
+
console.error('[KADI] Raw content (truncated):', content.slice(0, 200));
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Skip to next potential header (error recovery).
|
|
120
|
+
* Called when we encounter a malformed header.
|
|
121
|
+
*/
|
|
122
|
+
skipToNextHeader() {
|
|
123
|
+
const nextHeaderIndex = this.buffer.indexOf(StdioReader.CONTENT_LENGTH_MARKER, 1);
|
|
124
|
+
if (nextHeaderIndex === -1) {
|
|
125
|
+
this.buffer = Buffer.alloc(0); // No more headers, clear buffer
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
this.buffer = this.buffer.slice(nextHeaderIndex);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Dispatch a parsed message to waiting handlers or notification handler.
|
|
133
|
+
*/
|
|
134
|
+
dispatchMessage(message) {
|
|
135
|
+
// Check if this is a notification (no id field)
|
|
136
|
+
if (!('id' in message) || message.id === undefined) {
|
|
137
|
+
// It's a notification - route to notification handler
|
|
138
|
+
if (this.notificationHandler) {
|
|
139
|
+
this.notificationHandler(message);
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
// It's a response - find and remove waiter for this message id
|
|
144
|
+
const waiterIndex = this.waiters.findIndex((w) => w.id === message.id);
|
|
145
|
+
if (waiterIndex === -1) {
|
|
146
|
+
return; // No one waiting for this response
|
|
147
|
+
}
|
|
148
|
+
// splice returns removed elements - use destructuring to get the waiter
|
|
149
|
+
const [waiter] = this.waiters.splice(waiterIndex, 1);
|
|
150
|
+
if (!waiter) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
clearTimeout(waiter.timeout);
|
|
154
|
+
waiter.resolve(message);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Wait for a response with a specific id.
|
|
158
|
+
*/
|
|
159
|
+
waitForResponse(id) {
|
|
160
|
+
return new Promise((resolve, reject) => {
|
|
161
|
+
const timeout = setTimeout(() => {
|
|
162
|
+
// Remove from waiters
|
|
163
|
+
const index = this.waiters.findIndex((w) => w.id === id);
|
|
164
|
+
if (index !== -1) {
|
|
165
|
+
this.waiters.splice(index, 1);
|
|
166
|
+
}
|
|
167
|
+
reject(new KadiError(`Timeout waiting for response to request ${id}`, 'TIMEOUT', { requestId: id }));
|
|
168
|
+
}, this.timeoutMs);
|
|
169
|
+
this.waiters.push({ id, resolve, reject, timeout });
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Cancel all pending waiters (for cleanup).
|
|
174
|
+
* @param error - Optional error to reject with (defaults to generic close error)
|
|
175
|
+
*/
|
|
176
|
+
cancelAll(error) {
|
|
177
|
+
const rejectError = error ?? new KadiError('Connection closed', 'STDIO_ERROR');
|
|
178
|
+
for (const waiter of this.waiters) {
|
|
179
|
+
clearTimeout(waiter.timeout);
|
|
180
|
+
waiter.reject(rejectError);
|
|
181
|
+
}
|
|
182
|
+
this.waiters = [];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
186
|
+
// MESSAGE WRITER (Content-Length framing)
|
|
187
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
188
|
+
/**
|
|
189
|
+
* Writes JSON-RPC messages to a stream using Content-Length framing.
|
|
190
|
+
*/
|
|
191
|
+
class StdioWriter {
|
|
192
|
+
stream;
|
|
193
|
+
constructor(stream) {
|
|
194
|
+
this.stream = stream;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Write a message to the stream.
|
|
198
|
+
*/
|
|
199
|
+
write(message) {
|
|
200
|
+
const json = JSON.stringify(message);
|
|
201
|
+
const contentLength = Buffer.byteLength(json, 'utf-8');
|
|
202
|
+
const header = `Content-Length: ${contentLength}\r\n\r\n`;
|
|
203
|
+
this.stream.write(header + json);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Load a child process ability via stdio.
|
|
208
|
+
*
|
|
209
|
+
* The child process must speak JSON-RPC over stdin/stdout with Content-Length framing.
|
|
210
|
+
* This is the standard KADI ability protocol.
|
|
211
|
+
*
|
|
212
|
+
* @param command - Command to run (e.g., 'python3', 'node')
|
|
213
|
+
* @param args - Arguments to pass to the command
|
|
214
|
+
* @param options - Additional options
|
|
215
|
+
* @returns LoadedAbility that can invoke tools
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* ```typescript
|
|
219
|
+
* // Load a Python ability
|
|
220
|
+
* const analyzer = await loadStdioTransport('python3', ['analyzer.py']);
|
|
221
|
+
* const result = await analyzer.invoke('analyze', { text: 'hello' });
|
|
222
|
+
*
|
|
223
|
+
* // Load a Node.js ability
|
|
224
|
+
* const calc = await loadStdioTransport('node', ['dist/index.js']);
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
export async function loadStdioTransport(command, args = [], options = {}) {
|
|
228
|
+
const timeoutMs = options.timeoutMs ?? 30000;
|
|
229
|
+
// Step 1: Spawn the child process
|
|
230
|
+
let proc;
|
|
231
|
+
try {
|
|
232
|
+
proc = spawn(command, args, {
|
|
233
|
+
stdio: ['pipe', 'pipe', 'inherit'], // stdin, stdout, stderr
|
|
234
|
+
cwd: options.cwd, // Working directory for the child process
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
throw new KadiError(`Failed to spawn process: ${command}`, 'STDIO_ERROR', {
|
|
239
|
+
command,
|
|
240
|
+
args,
|
|
241
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
242
|
+
hint: 'Check that the command exists and is executable',
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
// Step 2: Set up reader and writer
|
|
246
|
+
// IMPORTANT: Must do this BEFORE setting up event handlers that reference reader
|
|
247
|
+
if (!proc.stdin || !proc.stdout) {
|
|
248
|
+
proc.kill();
|
|
249
|
+
throw new KadiError('Failed to get stdio streams', 'STDIO_ERROR', { command });
|
|
250
|
+
}
|
|
251
|
+
const reader = new StdioReader(proc.stdout, timeoutMs);
|
|
252
|
+
const writer = new StdioWriter(proc.stdin);
|
|
253
|
+
let idCounter = 1;
|
|
254
|
+
let isShutdown = false;
|
|
255
|
+
// Track whether WE initiated the shutdown (vs process crashing)
|
|
256
|
+
// This distinguishes graceful disconnect() from unexpected crashes
|
|
257
|
+
let shutdownInitiated = false;
|
|
258
|
+
// Track process errors to reject pending requests
|
|
259
|
+
let processError = null;
|
|
260
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
261
|
+
// PROCESS EVENT HANDLERS
|
|
262
|
+
// These are set up AFTER reader exists so we can call reader.cancelAll()
|
|
263
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
264
|
+
// Handle spawn errors (e.g., command not found, permission denied)
|
|
265
|
+
proc.on('error', (error) => {
|
|
266
|
+
processError = new KadiError(`Process error: ${command}`, 'STDIO_ERROR', {
|
|
267
|
+
command,
|
|
268
|
+
reason: error.message,
|
|
269
|
+
hint: 'Check that the command exists and is executable',
|
|
270
|
+
});
|
|
271
|
+
reader.cancelAll(processError);
|
|
272
|
+
});
|
|
273
|
+
// Handle process exit (crash detection)
|
|
274
|
+
// This fires when the child process terminates for ANY reason:
|
|
275
|
+
// - process.exit() called
|
|
276
|
+
// - Uncaught exception
|
|
277
|
+
// - Killed by signal
|
|
278
|
+
// - Normal completion
|
|
279
|
+
proc.on('exit', (code, signal) => {
|
|
280
|
+
// Only treat as error if WE didn't initiate the shutdown
|
|
281
|
+
// If shutdownInitiated is true, this is expected (we called disconnect())
|
|
282
|
+
if (!shutdownInitiated) {
|
|
283
|
+
// Build descriptive error message based on how process exited
|
|
284
|
+
const message = signal
|
|
285
|
+
? `Child process killed by signal ${signal}`
|
|
286
|
+
: `Child process exited with code ${code}`;
|
|
287
|
+
processError = new KadiError(message, 'STDIO_ERROR', {
|
|
288
|
+
command,
|
|
289
|
+
exitCode: code,
|
|
290
|
+
signal,
|
|
291
|
+
hint: 'Check stderr output from the child process for details',
|
|
292
|
+
});
|
|
293
|
+
// Reject all pending requests immediately (no waiting for timeout)
|
|
294
|
+
reader.cancelAll(processError);
|
|
295
|
+
}
|
|
296
|
+
// Mark as shutdown regardless (can't send more requests to dead process)
|
|
297
|
+
isShutdown = true;
|
|
298
|
+
});
|
|
299
|
+
/**
|
|
300
|
+
* Send a request and wait for response.
|
|
301
|
+
*/
|
|
302
|
+
async function sendRequest(method, params) {
|
|
303
|
+
if (isShutdown) {
|
|
304
|
+
throw new KadiError('Connection is closed', 'STDIO_ERROR');
|
|
305
|
+
}
|
|
306
|
+
// Check if process has errored
|
|
307
|
+
if (processError) {
|
|
308
|
+
throw processError;
|
|
309
|
+
}
|
|
310
|
+
const id = idCounter++;
|
|
311
|
+
const request = {
|
|
312
|
+
jsonrpc: '2.0',
|
|
313
|
+
id,
|
|
314
|
+
method,
|
|
315
|
+
params,
|
|
316
|
+
};
|
|
317
|
+
writer.write(request);
|
|
318
|
+
const response = await reader.waitForResponse(id);
|
|
319
|
+
if (response.error) {
|
|
320
|
+
throw new KadiError(response.error.message, 'STDIO_ERROR', { code: response.error.code, data: response.error.data });
|
|
321
|
+
}
|
|
322
|
+
return response.result;
|
|
323
|
+
}
|
|
324
|
+
// Step 3: Get agent information
|
|
325
|
+
let agentJson;
|
|
326
|
+
try {
|
|
327
|
+
agentJson = await sendRequest('readAgentJson', {});
|
|
328
|
+
}
|
|
329
|
+
catch (error) {
|
|
330
|
+
proc.kill();
|
|
331
|
+
throw new KadiError('Failed to get agent information from child process', 'ABILITY_LOAD_FAILED', {
|
|
332
|
+
command,
|
|
333
|
+
args,
|
|
334
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
335
|
+
hint: 'The child process must respond to "readAgentJson" requests',
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
// Step 4: Set up event handling
|
|
339
|
+
const eventHandlers = new Map();
|
|
340
|
+
reader.setNotificationHandler((notification) => {
|
|
341
|
+
// Only handle 'event' notifications
|
|
342
|
+
if (notification.method !== 'event') {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
// Validate params with Zod (consistent with rest of kadi-core)
|
|
346
|
+
const parsed = EventNotificationParams.safeParse(notification.params);
|
|
347
|
+
if (!parsed.success) {
|
|
348
|
+
console.warn('[KADI] Ignoring malformed event notification:', parsed.error.format());
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
const { name: eventName, data: eventData } = parsed.data;
|
|
352
|
+
const handlers = eventHandlers.get(eventName);
|
|
353
|
+
if (handlers) {
|
|
354
|
+
for (const handler of handlers) {
|
|
355
|
+
Promise.resolve(handler(eventData)).catch((err) => {
|
|
356
|
+
console.error(`[KADI] Event handler error for "${eventName}":`, err);
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
// Step 5: Return LoadedAbility interface
|
|
362
|
+
return {
|
|
363
|
+
name: agentJson.name,
|
|
364
|
+
transport: 'stdio',
|
|
365
|
+
/**
|
|
366
|
+
* Invoke a tool on this ability.
|
|
367
|
+
* Sends a JSON-RPC request and waits for the response.
|
|
368
|
+
*/
|
|
369
|
+
async invoke(toolName, params) {
|
|
370
|
+
try {
|
|
371
|
+
const result = await sendRequest('invoke', { toolName, toolInput: params });
|
|
372
|
+
return result;
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
if (error instanceof KadiError) {
|
|
376
|
+
throw error;
|
|
377
|
+
}
|
|
378
|
+
throw new KadiError(`Tool "${toolName}" invocation failed`, 'TOOL_INVOCATION_FAILED', {
|
|
379
|
+
toolName,
|
|
380
|
+
ability: agentJson.name,
|
|
381
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
/**
|
|
386
|
+
* Get the list of tools this ability provides.
|
|
387
|
+
*/
|
|
388
|
+
getTools() {
|
|
389
|
+
return agentJson.tools ?? [];
|
|
390
|
+
},
|
|
391
|
+
/**
|
|
392
|
+
* Subscribe to events from this ability.
|
|
393
|
+
*/
|
|
394
|
+
on(event, handler) {
|
|
395
|
+
let handlers = eventHandlers.get(event);
|
|
396
|
+
if (!handlers) {
|
|
397
|
+
handlers = new Set();
|
|
398
|
+
eventHandlers.set(event, handlers);
|
|
399
|
+
}
|
|
400
|
+
handlers.add(handler);
|
|
401
|
+
},
|
|
402
|
+
/**
|
|
403
|
+
* Unsubscribe from events.
|
|
404
|
+
*/
|
|
405
|
+
off(event, handler) {
|
|
406
|
+
const handlers = eventHandlers.get(event);
|
|
407
|
+
if (handlers) {
|
|
408
|
+
handlers.delete(handler);
|
|
409
|
+
if (handlers.size === 0) {
|
|
410
|
+
eventHandlers.delete(event);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
/**
|
|
415
|
+
* Disconnect and cleanup.
|
|
416
|
+
* Sends a shutdown request and kills the process.
|
|
417
|
+
*/
|
|
418
|
+
async disconnect() {
|
|
419
|
+
if (isShutdown) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
// Clear event handlers
|
|
423
|
+
eventHandlers.clear();
|
|
424
|
+
// Mark that WE initiated shutdown BEFORE sending the request
|
|
425
|
+
// This prevents the 'exit' handler from treating our graceful
|
|
426
|
+
// shutdown as a crash (race condition: process might exit before
|
|
427
|
+
// we set this flag if we waited until after sendRequest)
|
|
428
|
+
shutdownInitiated = true;
|
|
429
|
+
// Try to send shutdown gracefully
|
|
430
|
+
// Note: sendRequest checks isShutdown, not shutdownInitiated,
|
|
431
|
+
// so this will still work
|
|
432
|
+
try {
|
|
433
|
+
await sendRequest('shutdown', {});
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
// Ignore errors during shutdown (process might have already exited)
|
|
437
|
+
}
|
|
438
|
+
isShutdown = true;
|
|
439
|
+
// Cancel any pending requests (there shouldn't be any at this point,
|
|
440
|
+
// but this ensures cleanup if something went wrong)
|
|
441
|
+
reader.cancelAll();
|
|
442
|
+
// Kill the process and wait for it to exit
|
|
443
|
+
proc.kill('SIGTERM');
|
|
444
|
+
// Wait for graceful termination, then force kill
|
|
445
|
+
await new Promise((resolve) => {
|
|
446
|
+
const forceKillTimer = setTimeout(() => {
|
|
447
|
+
if (!proc.killed) {
|
|
448
|
+
proc.kill('SIGKILL');
|
|
449
|
+
}
|
|
450
|
+
resolve();
|
|
451
|
+
}, 1000);
|
|
452
|
+
proc.once('exit', () => {
|
|
453
|
+
clearTimeout(forceKillTimer);
|
|
454
|
+
resolve();
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
},
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
//# sourceMappingURL=stdio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/transports/stdio.ts"],"names":[],"mappings":"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"}
|