@kadi.build/core 0.0.1-alpha.9 → 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 -470
- package/dist/KadiClient.d.ts.map +0 -1
- package/dist/KadiClient.js +0 -1572
- 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,383 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Broker transport for kadi-core v0.1.0
|
|
3
|
+
*
|
|
4
|
+
* Loads abilities that run on REMOTE agents connected to a broker.
|
|
5
|
+
* Communication happens via WebSocket using JSON-RPC.
|
|
6
|
+
*
|
|
7
|
+
* Protocol flow for invoking a remote tool:
|
|
8
|
+
* 1. Client sends kadi.ability.request → broker returns { status: 'pending', requestId }
|
|
9
|
+
* 2. Broker forwards request to provider agent
|
|
10
|
+
* 3. Provider executes tool and sends result back to broker
|
|
11
|
+
* 4. Broker sends kadi.ability.response notification with the actual result
|
|
12
|
+
*
|
|
13
|
+
* This transport doesn't manage the broker connection itself.
|
|
14
|
+
* It receives a BrokerState from KadiClient and uses it for communication.
|
|
15
|
+
*
|
|
16
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
17
|
+
* WORKAROUND NOTE: Ability Discovery
|
|
18
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
19
|
+
*
|
|
20
|
+
* The current broker is TOOL-CENTRIC (tracks tools, not abilities). There's no
|
|
21
|
+
* direct API to ask "What tools does agent X provide?"
|
|
22
|
+
*
|
|
23
|
+
* CURRENT WORKAROUND:
|
|
24
|
+
* 1. Call kadi.ability.list with includeProviders: true (fetches ALL tools)
|
|
25
|
+
* 2. Filter tools where provider.displayName matches the ability name
|
|
26
|
+
* 3. Use the provider's agentId for routing via _kadi hints
|
|
27
|
+
*
|
|
28
|
+
* FUTURE: When the broker implements kadi.agent.discover (see design doc at
|
|
29
|
+
* kadi-broker/docs/design/ABILITY_CENTRIC_DISCOVERY.md), replace the
|
|
30
|
+
* discoverAbilityWorkaround() function with a direct API call.
|
|
31
|
+
* ═══════════════════════════════════════════════════════════════════════════════
|
|
32
|
+
*/
|
|
33
|
+
import { KadiError } from '../errors.js';
|
|
34
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
35
|
+
// REQUEST HELPERS
|
|
36
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
37
|
+
/**
|
|
38
|
+
* Send a JSON-RPC request over WebSocket and wait for response.
|
|
39
|
+
*
|
|
40
|
+
* This is a low-level helper used by both discovery and invoke.
|
|
41
|
+
* The broker connection's pendingRequests map is used to match responses.
|
|
42
|
+
*/
|
|
43
|
+
async function sendBrokerRequest(broker, method, params, timeoutMs) {
|
|
44
|
+
// Verify connection is active
|
|
45
|
+
if (!broker.ws || broker.status !== 'connected') {
|
|
46
|
+
throw new KadiError(`Broker "${broker.name}" is not connected`, 'BROKER_NOT_CONNECTED', {
|
|
47
|
+
broker: broker.name,
|
|
48
|
+
status: broker.status,
|
|
49
|
+
hint: 'Call client.connect() first',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
// Generate unique request ID
|
|
53
|
+
const id = `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
54
|
+
// Build JSON-RPC request
|
|
55
|
+
const request = {
|
|
56
|
+
jsonrpc: '2.0',
|
|
57
|
+
id,
|
|
58
|
+
method,
|
|
59
|
+
params,
|
|
60
|
+
};
|
|
61
|
+
// Create promise that will be resolved when response arrives
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
// Set up timeout
|
|
64
|
+
const timeout = setTimeout(() => {
|
|
65
|
+
broker.pendingRequests.delete(id);
|
|
66
|
+
reject(new KadiError(`Request "${method}" timed out after ${timeoutMs}ms`, 'BROKER_TIMEOUT', {
|
|
67
|
+
broker: broker.name,
|
|
68
|
+
method,
|
|
69
|
+
timeout: timeoutMs,
|
|
70
|
+
}));
|
|
71
|
+
}, timeoutMs);
|
|
72
|
+
// Store in pending requests map
|
|
73
|
+
// The message handler in client.ts will resolve this when response arrives
|
|
74
|
+
broker.pendingRequests.set(id, {
|
|
75
|
+
resolve: (result) => {
|
|
76
|
+
clearTimeout(timeout);
|
|
77
|
+
resolve(result);
|
|
78
|
+
},
|
|
79
|
+
reject: (error) => {
|
|
80
|
+
clearTimeout(timeout);
|
|
81
|
+
reject(error);
|
|
82
|
+
},
|
|
83
|
+
timeout,
|
|
84
|
+
method,
|
|
85
|
+
sentAt: new Date(),
|
|
86
|
+
});
|
|
87
|
+
// Re-check connection before sending (could have disconnected during setup)
|
|
88
|
+
const ws = broker.ws;
|
|
89
|
+
if (!ws || broker.status !== 'connected') {
|
|
90
|
+
broker.pendingRequests.delete(id);
|
|
91
|
+
clearTimeout(timeout);
|
|
92
|
+
reject(new KadiError(`Broker "${broker.name}" disconnected`, 'BROKER_NOT_CONNECTED', {
|
|
93
|
+
broker: broker.name,
|
|
94
|
+
}));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
// Send the request
|
|
98
|
+
try {
|
|
99
|
+
ws.send(JSON.stringify(request));
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
broker.pendingRequests.delete(id);
|
|
103
|
+
clearTimeout(timeout);
|
|
104
|
+
reject(new KadiError(`Failed to send request to broker "${broker.name}"`, 'BROKER_ERROR', {
|
|
105
|
+
broker: broker.name,
|
|
106
|
+
method,
|
|
107
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
113
|
+
// ABILITY DISCOVERY (WORKAROUND)
|
|
114
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
115
|
+
/**
|
|
116
|
+
* Discover an ability on the broker by name.
|
|
117
|
+
*
|
|
118
|
+
* ┌─────────────────────────────────────────────────────────────────────────────┐
|
|
119
|
+
* │ WORKAROUND: This function uses kadi.ability.list + client-side filtering │
|
|
120
|
+
* │ │
|
|
121
|
+
* │ The broker is currently tool-centric and doesn't support querying by │
|
|
122
|
+
* │ agent/ability name directly. This workaround: │
|
|
123
|
+
* │ │
|
|
124
|
+
* │ 1. Fetches ALL tools with provider information │
|
|
125
|
+
* │ 2. Filters to find tools where provider.displayName matches abilityName │
|
|
126
|
+
* │ 3. Extracts the agentId for consistent routing │
|
|
127
|
+
* │ │
|
|
128
|
+
* │ TODO: Replace with kadi.agent.discover when broker supports it. │
|
|
129
|
+
* │ See: kadi-broker/docs/design/ABILITY_CENTRIC_DISCOVERY.md │
|
|
130
|
+
* └─────────────────────────────────────────────────────────────────────────────┘
|
|
131
|
+
*
|
|
132
|
+
* @param broker - The broker connection to query
|
|
133
|
+
* @param abilityName - Name of the ability/agent to find (matches displayName)
|
|
134
|
+
* @param options - Discovery options (timeout)
|
|
135
|
+
* @returns Information about the discovered ability
|
|
136
|
+
* @throws KadiError if ability not found
|
|
137
|
+
*/
|
|
138
|
+
async function discoverAbilityWorkaround(broker, abilityName, options) {
|
|
139
|
+
// Step 1: Fetch all tools with provider information
|
|
140
|
+
// This is inefficient but necessary until the broker supports agent queries
|
|
141
|
+
const response = (await sendBrokerRequest(broker, 'kadi.ability.list', { includeProviders: true }, options.timeoutMs));
|
|
142
|
+
if (!response?.tools) {
|
|
143
|
+
throw new KadiError(`Failed to list tools from broker "${broker.name}"`, 'BROKER_ERROR', { broker: broker.name });
|
|
144
|
+
}
|
|
145
|
+
// Step 2: Filter tools to find those provided by the named agent
|
|
146
|
+
// We match on provider.displayName (the agent's name from registration)
|
|
147
|
+
const matchingTools = [];
|
|
148
|
+
let targetAgentId;
|
|
149
|
+
let targetDisplayName;
|
|
150
|
+
for (const tool of response.tools) {
|
|
151
|
+
if (!tool.providers)
|
|
152
|
+
continue;
|
|
153
|
+
// Find a provider whose displayName matches our ability name
|
|
154
|
+
const matchingProvider = tool.providers.find((p) => p.displayName === abilityName);
|
|
155
|
+
if (matchingProvider) {
|
|
156
|
+
// Extract the agentId (stable identifier for routing)
|
|
157
|
+
// We use the first matching provider's agentId for all invocations
|
|
158
|
+
if (!targetAgentId && matchingProvider.agentId) {
|
|
159
|
+
targetAgentId = matchingProvider.agentId;
|
|
160
|
+
targetDisplayName = matchingProvider.displayName;
|
|
161
|
+
}
|
|
162
|
+
// Add tool to our list (convert to ToolDefinition format)
|
|
163
|
+
matchingTools.push({
|
|
164
|
+
name: tool.name,
|
|
165
|
+
description: tool.description ?? '',
|
|
166
|
+
inputSchema: tool.inputSchema ?? { type: 'object' },
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Step 3: Validate we found the ability
|
|
171
|
+
if (!targetAgentId || matchingTools.length === 0) {
|
|
172
|
+
// Build list of available agents for helpful error message
|
|
173
|
+
const availableAgents = new Set();
|
|
174
|
+
for (const tool of response.tools) {
|
|
175
|
+
for (const provider of tool.providers ?? []) {
|
|
176
|
+
if (provider.displayName) {
|
|
177
|
+
availableAgents.add(provider.displayName);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
throw new KadiError(`Ability "${abilityName}" not found on broker "${broker.name}"`, 'ABILITY_NOT_FOUND', {
|
|
182
|
+
abilityName,
|
|
183
|
+
broker: broker.name,
|
|
184
|
+
availableAgents: [...availableAgents],
|
|
185
|
+
hint: 'Make sure an agent with this name is connected to the broker',
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
agentId: targetAgentId,
|
|
190
|
+
name: targetDisplayName ?? abilityName,
|
|
191
|
+
tools: matchingTools,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
195
|
+
// REMOTE INVOCATION
|
|
196
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
197
|
+
/**
|
|
198
|
+
* Invoke a tool on a remote agent via the broker.
|
|
199
|
+
*
|
|
200
|
+
* Uses the KADI async invocation pattern:
|
|
201
|
+
* 1. Send kadi.ability.request with toolName and toolInput
|
|
202
|
+
* 2. Broker returns { status: 'pending', requestId }
|
|
203
|
+
* 3. Wait for kadi.ability.response notification with the result
|
|
204
|
+
*
|
|
205
|
+
* For consistent routing to a specific agent, we inject _kadi routing hints
|
|
206
|
+
* into the toolInput. The broker strips these before forwarding to the provider.
|
|
207
|
+
*
|
|
208
|
+
* @param broker - The broker connection to use
|
|
209
|
+
* @param targetAgentId - Agent ID to route to (uses requireAgent hint)
|
|
210
|
+
* @param toolName - Name of the tool to invoke
|
|
211
|
+
* @param params - Parameters for the tool
|
|
212
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
213
|
+
* @returns The tool's result
|
|
214
|
+
*/
|
|
215
|
+
async function invokeViaBroker(broker, targetAgentId, toolName, params, timeoutMs) {
|
|
216
|
+
// Fail fast if broker isn't properly initialized
|
|
217
|
+
if (!broker.pendingInvocations) {
|
|
218
|
+
throw new KadiError(`Broker "${broker.name}" is missing pendingInvocations map`, 'BROKER_ERROR', { broker: broker.name, hint: 'This is a bug in broker initialization' });
|
|
219
|
+
}
|
|
220
|
+
// Inject routing hint to ensure the broker routes to our target agent
|
|
221
|
+
// The _kadi property is stripped by the broker before forwarding to the provider
|
|
222
|
+
const paramsWithRouting = {
|
|
223
|
+
...(typeof params === 'object' && params !== null ? params : {}),
|
|
224
|
+
_kadi: { requireAgent: targetAgentId },
|
|
225
|
+
};
|
|
226
|
+
// Use kadi.ability.request (the standard tool invocation method)
|
|
227
|
+
// The response is { status: 'pending', requestId }
|
|
228
|
+
// The actual result comes via kadi.ability.response notification,
|
|
229
|
+
// which is handled by the KadiClient's message handler
|
|
230
|
+
const pendingResult = (await sendBrokerRequest(broker, 'kadi.ability.request', {
|
|
231
|
+
toolName,
|
|
232
|
+
toolInput: paramsWithRouting,
|
|
233
|
+
}, timeoutMs));
|
|
234
|
+
if (pendingResult.status !== 'pending' || !pendingResult.requestId) {
|
|
235
|
+
throw new KadiError('Unexpected response from broker: expected pending acknowledgment', 'BROKER_ERROR', {
|
|
236
|
+
broker: broker.name,
|
|
237
|
+
toolName,
|
|
238
|
+
response: pendingResult,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
// Store requestId locally - TypeScript now knows it's defined
|
|
242
|
+
const requestId = pendingResult.requestId;
|
|
243
|
+
// Wait for the actual result via kadi.ability.response
|
|
244
|
+
// This is handled by registering with the broker's pending invocations
|
|
245
|
+
return new Promise((resolve, reject) => {
|
|
246
|
+
const timeout = setTimeout(() => {
|
|
247
|
+
broker.pendingInvocations.delete(requestId);
|
|
248
|
+
reject(new KadiError(`Tool "${toolName}" invocation timed out`, 'BROKER_TIMEOUT', {
|
|
249
|
+
broker: broker.name,
|
|
250
|
+
toolName,
|
|
251
|
+
requestId,
|
|
252
|
+
timeout: timeoutMs,
|
|
253
|
+
}));
|
|
254
|
+
}, timeoutMs);
|
|
255
|
+
broker.pendingInvocations.set(requestId, {
|
|
256
|
+
resolve: (result) => {
|
|
257
|
+
clearTimeout(timeout);
|
|
258
|
+
resolve(result);
|
|
259
|
+
},
|
|
260
|
+
reject: (error) => {
|
|
261
|
+
clearTimeout(timeout);
|
|
262
|
+
reject(error);
|
|
263
|
+
},
|
|
264
|
+
timeout,
|
|
265
|
+
toolName,
|
|
266
|
+
sentAt: new Date(),
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
271
|
+
// BROKER TRANSPORT
|
|
272
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
273
|
+
/**
|
|
274
|
+
* Load a remote ability via broker.
|
|
275
|
+
*
|
|
276
|
+
* This discovers an agent providing the ability and returns a LoadedAbility
|
|
277
|
+
* interface that invokes tools via the broker, consistently routing to that
|
|
278
|
+
* specific agent.
|
|
279
|
+
*
|
|
280
|
+
* @param abilityName - Name of the ability to load (matches agent's displayName)
|
|
281
|
+
* @param options - Broker connection and options
|
|
282
|
+
* @returns LoadedAbility that can invoke tools remotely
|
|
283
|
+
*
|
|
284
|
+
* @example
|
|
285
|
+
* ```typescript
|
|
286
|
+
* // The broker state comes from KadiClient
|
|
287
|
+
* const brokerState = client.getBrokerState('production');
|
|
288
|
+
*
|
|
289
|
+
* // Load a remote ability
|
|
290
|
+
* const analyzer = await loadBrokerTransport('text-analyzer', {
|
|
291
|
+
* broker: brokerState,
|
|
292
|
+
* requestTimeout: 60000,
|
|
293
|
+
* });
|
|
294
|
+
*
|
|
295
|
+
* // Invoke tools on the remote agent
|
|
296
|
+
* const result = await analyzer.invoke('analyze', { text: 'hello' });
|
|
297
|
+
*
|
|
298
|
+
* // All invocations go to the same agent (consistent routing)
|
|
299
|
+
* const result2 = await analyzer.invoke('summarize', { text: 'world' });
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
export async function loadBrokerTransport(abilityName, options) {
|
|
303
|
+
const timeoutMs = options.requestTimeout ?? 30000;
|
|
304
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
305
|
+
// Step 1: Discover the ability on the broker
|
|
306
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
307
|
+
// TODO: Replace discoverAbilityWorkaround with kadi.agent.discover when
|
|
308
|
+
// the broker implements it. See: kadi-broker/docs/design/ABILITY_CENTRIC_DISCOVERY.md
|
|
309
|
+
const discovered = await discoverAbilityWorkaround(options.broker, abilityName, {
|
|
310
|
+
timeoutMs,
|
|
311
|
+
});
|
|
312
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
313
|
+
// Step 2: Return LoadedAbility interface
|
|
314
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
315
|
+
// The agentId is used for routing hints, ensuring all invocations go to the
|
|
316
|
+
// same agent. This is stable across reconnects (unlike sessionId).
|
|
317
|
+
return {
|
|
318
|
+
name: discovered.name,
|
|
319
|
+
transport: 'broker',
|
|
320
|
+
/**
|
|
321
|
+
* Invoke a tool on the remote agent.
|
|
322
|
+
*
|
|
323
|
+
* Routes through the broker to the target agent using _kadi.requireAgent
|
|
324
|
+
* routing hint. This ensures all calls go to the same agent that was
|
|
325
|
+
* discovered during loadBrokerTransport().
|
|
326
|
+
*/
|
|
327
|
+
async invoke(toolName, params) {
|
|
328
|
+
try {
|
|
329
|
+
return await invokeViaBroker(options.broker, discovered.agentId, toolName, params, timeoutMs);
|
|
330
|
+
}
|
|
331
|
+
catch (error) {
|
|
332
|
+
// Re-throw KadiErrors as-is
|
|
333
|
+
if (error instanceof KadiError) {
|
|
334
|
+
throw error;
|
|
335
|
+
}
|
|
336
|
+
// Wrap other errors
|
|
337
|
+
throw new KadiError(`Remote tool "${toolName}" invocation failed`, 'TOOL_INVOCATION_FAILED', {
|
|
338
|
+
toolName,
|
|
339
|
+
ability: discovered.name,
|
|
340
|
+
targetAgent: discovered.agentId,
|
|
341
|
+
broker: options.broker.name,
|
|
342
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
/**
|
|
347
|
+
* Get the list of tools this ability provides.
|
|
348
|
+
*
|
|
349
|
+
* Returns tools discovered from the agent during loadBrokerTransport().
|
|
350
|
+
* This is a snapshot from discovery time - if the agent registers new
|
|
351
|
+
* tools, you'd need to reload the ability to see them.
|
|
352
|
+
*/
|
|
353
|
+
getTools() {
|
|
354
|
+
return discovered.tools;
|
|
355
|
+
},
|
|
356
|
+
/**
|
|
357
|
+
* Subscribe to events from this ability.
|
|
358
|
+
* NOT YET IMPLEMENTED for broker transport.
|
|
359
|
+
*/
|
|
360
|
+
on(_event, _handler) {
|
|
361
|
+
throw new KadiError('Events are not yet implemented for broker transport', 'NOT_IMPLEMENTED', { transport: 'broker', hint: 'Use stdio or native transport for events' });
|
|
362
|
+
},
|
|
363
|
+
/**
|
|
364
|
+
* Unsubscribe from events.
|
|
365
|
+
* NOT YET IMPLEMENTED for broker transport.
|
|
366
|
+
*/
|
|
367
|
+
off(_event, _handler) {
|
|
368
|
+
throw new KadiError('Events are not yet implemented for broker transport', 'NOT_IMPLEMENTED', { transport: 'broker', hint: 'Use stdio or native transport for events' });
|
|
369
|
+
},
|
|
370
|
+
/**
|
|
371
|
+
* Disconnect and cleanup.
|
|
372
|
+
*
|
|
373
|
+
* For broker transport, there's nothing to cleanup. The broker connection
|
|
374
|
+
* is managed by KadiClient, not by individual abilities. Calling disconnect()
|
|
375
|
+
* on a broker-loaded ability is a safe no-op.
|
|
376
|
+
*/
|
|
377
|
+
async disconnect() {
|
|
378
|
+
// Broker connection is shared - we don't disconnect it here.
|
|
379
|
+
// The KadiClient manages broker lifecycle.
|
|
380
|
+
},
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
//# sourceMappingURL=broker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broker.js","sourceRoot":"","sources":["../../src/transports/broker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native transport for kadi-core v0.1.0
|
|
3
|
+
*
|
|
4
|
+
* Loads abilities that run in the SAME Node.js process.
|
|
5
|
+
* This is the fastest transport - direct function calls with zero serialization.
|
|
6
|
+
*
|
|
7
|
+
* How it works:
|
|
8
|
+
* 1. Dynamic import the module at the given path
|
|
9
|
+
* 2. Verify it exports a KadiClient as default
|
|
10
|
+
* 3. Return a LoadedAbility that delegates to the client
|
|
11
|
+
*
|
|
12
|
+
* Use case: Abilities written in TypeScript/JavaScript that you want
|
|
13
|
+
* to load without spawning a child process.
|
|
14
|
+
*/
|
|
15
|
+
import type { LoadedAbility } from '../types.js';
|
|
16
|
+
/**
|
|
17
|
+
* Load an in-process ability via dynamic import.
|
|
18
|
+
*
|
|
19
|
+
* The module at the given path must export a KadiClient instance as default.
|
|
20
|
+
* This is the standard pattern for KADI abilities.
|
|
21
|
+
*
|
|
22
|
+
* @param path - Absolute path to the ability module
|
|
23
|
+
* @returns LoadedAbility that can invoke tools
|
|
24
|
+
* @throws KadiError if the module can't be loaded or doesn't export a KadiClient
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* // The ability module (calculator/index.ts):
|
|
29
|
+
* const client = new KadiClient({ name: 'calculator' });
|
|
30
|
+
* client.registerTool(...);
|
|
31
|
+
* export default client;
|
|
32
|
+
*
|
|
33
|
+
* // Loading it:
|
|
34
|
+
* const calc = await loadNativeTransport('/path/to/calculator');
|
|
35
|
+
* const result = await calc.invoke('add', { a: 5, b: 3 });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function loadNativeTransport(path: string): Promise<LoadedAbility>;
|
|
39
|
+
//# sourceMappingURL=native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../src/transports/native.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAgC,MAAM,aAAa,CAAC;AAgE/E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAwJ9E"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native transport for kadi-core v0.1.0
|
|
3
|
+
*
|
|
4
|
+
* Loads abilities that run in the SAME Node.js process.
|
|
5
|
+
* This is the fastest transport - direct function calls with zero serialization.
|
|
6
|
+
*
|
|
7
|
+
* How it works:
|
|
8
|
+
* 1. Dynamic import the module at the given path
|
|
9
|
+
* 2. Verify it exports a KadiClient as default
|
|
10
|
+
* 3. Return a LoadedAbility that delegates to the client
|
|
11
|
+
*
|
|
12
|
+
* Use case: Abilities written in TypeScript/JavaScript that you want
|
|
13
|
+
* to load without spawning a child process.
|
|
14
|
+
*/
|
|
15
|
+
import { KadiError } from '../errors.js';
|
|
16
|
+
/**
|
|
17
|
+
* Check if an object looks like a KadiClient.
|
|
18
|
+
* We check for the methods we need rather than using instanceof,
|
|
19
|
+
* because the loaded module might have a different version of KadiClient.
|
|
20
|
+
*/
|
|
21
|
+
function isKadiClient(obj) {
|
|
22
|
+
if (obj === null || typeof obj !== 'object') {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const candidate = obj;
|
|
26
|
+
// Must have readAgentJson method
|
|
27
|
+
if (typeof candidate.readAgentJson !== 'function') {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
// Must have invoke method
|
|
31
|
+
if (typeof candidate.invoke !== 'function') {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
// Must have setEventHandler method (for events)
|
|
35
|
+
if (typeof candidate.setEventHandler !== 'function') {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
41
|
+
// NATIVE TRANSPORT
|
|
42
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
43
|
+
/**
|
|
44
|
+
* Load an in-process ability via dynamic import.
|
|
45
|
+
*
|
|
46
|
+
* The module at the given path must export a KadiClient instance as default.
|
|
47
|
+
* This is the standard pattern for KADI abilities.
|
|
48
|
+
*
|
|
49
|
+
* @param path - Absolute path to the ability module
|
|
50
|
+
* @returns LoadedAbility that can invoke tools
|
|
51
|
+
* @throws KadiError if the module can't be loaded or doesn't export a KadiClient
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* // The ability module (calculator/index.ts):
|
|
56
|
+
* const client = new KadiClient({ name: 'calculator' });
|
|
57
|
+
* client.registerTool(...);
|
|
58
|
+
* export default client;
|
|
59
|
+
*
|
|
60
|
+
* // Loading it:
|
|
61
|
+
* const calc = await loadNativeTransport('/path/to/calculator');
|
|
62
|
+
* const result = await calc.invoke('add', { a: 5, b: 3 });
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export async function loadNativeTransport(path) {
|
|
66
|
+
// Step 1: Dynamic import the module
|
|
67
|
+
let module;
|
|
68
|
+
try {
|
|
69
|
+
module = await import(path);
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
throw new KadiError(`Failed to import ability at "${path}"`, 'NATIVE_IMPORT_ERROR', {
|
|
73
|
+
path,
|
|
74
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
75
|
+
hint: 'Check that the path is correct and the module has no syntax errors',
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
// Step 2: Get the default export
|
|
79
|
+
const client = module.default;
|
|
80
|
+
if (client === undefined) {
|
|
81
|
+
throw new KadiError(`Module at "${path}" has no default export`, 'ABILITY_LOAD_FAILED', {
|
|
82
|
+
path,
|
|
83
|
+
hint: 'The ability must export a KadiClient instance as default export',
|
|
84
|
+
alternative: 'Example: export default client;',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
// Step 3: Verify it's a KadiClient
|
|
88
|
+
if (!isKadiClient(client)) {
|
|
89
|
+
throw new KadiError(`Module at "${path}" does not export a KadiClient`, 'ABILITY_LOAD_FAILED', {
|
|
90
|
+
path,
|
|
91
|
+
hint: 'The default export must be a KadiClient instance',
|
|
92
|
+
alternative: 'Make sure you\'re exporting the client, not the class',
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// Step 4: Get agent information
|
|
96
|
+
let agentJson;
|
|
97
|
+
try {
|
|
98
|
+
agentJson = client.readAgentJson();
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
throw new KadiError(`Failed to read agent information from "${path}"`, 'ABILITY_LOAD_FAILED', {
|
|
102
|
+
path,
|
|
103
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
104
|
+
hint: 'The ability\'s readAgentJson() method threw an error',
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
// Step 5: Set up event handling
|
|
108
|
+
// Map of event name → array of handlers
|
|
109
|
+
const eventHandlers = new Map();
|
|
110
|
+
// When ability calls emit(), this callback fires
|
|
111
|
+
client.setEventHandler((event, data) => {
|
|
112
|
+
const handlers = eventHandlers.get(event);
|
|
113
|
+
if (handlers) {
|
|
114
|
+
for (const handler of handlers) {
|
|
115
|
+
// Fire handlers asynchronously, don't block
|
|
116
|
+
Promise.resolve(handler(data)).catch((err) => {
|
|
117
|
+
console.error(`[KADI] Event handler error for "${event}":`, err);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
// Step 6: Return LoadedAbility interface
|
|
123
|
+
return {
|
|
124
|
+
name: agentJson.name,
|
|
125
|
+
transport: 'native',
|
|
126
|
+
/**
|
|
127
|
+
* Invoke a tool on this ability.
|
|
128
|
+
* For native transport, this is a direct function call - no serialization.
|
|
129
|
+
*/
|
|
130
|
+
async invoke(toolName, params) {
|
|
131
|
+
try {
|
|
132
|
+
const result = await client.invoke(toolName, params);
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
// Re-throw KadiErrors as-is
|
|
137
|
+
if (error instanceof KadiError) {
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
// Wrap other errors
|
|
141
|
+
throw new KadiError(`Tool "${toolName}" invocation failed`, 'TOOL_INVOCATION_FAILED', {
|
|
142
|
+
toolName,
|
|
143
|
+
ability: agentJson.name,
|
|
144
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
/**
|
|
149
|
+
* Get the list of tools this ability provides.
|
|
150
|
+
*/
|
|
151
|
+
getTools() {
|
|
152
|
+
return agentJson.tools ?? [];
|
|
153
|
+
},
|
|
154
|
+
/**
|
|
155
|
+
* Subscribe to events from this ability.
|
|
156
|
+
*/
|
|
157
|
+
on(event, handler) {
|
|
158
|
+
let handlers = eventHandlers.get(event);
|
|
159
|
+
if (!handlers) {
|
|
160
|
+
handlers = new Set();
|
|
161
|
+
eventHandlers.set(event, handlers);
|
|
162
|
+
}
|
|
163
|
+
handlers.add(handler);
|
|
164
|
+
},
|
|
165
|
+
/**
|
|
166
|
+
* Unsubscribe from events.
|
|
167
|
+
*/
|
|
168
|
+
off(event, handler) {
|
|
169
|
+
const handlers = eventHandlers.get(event);
|
|
170
|
+
if (handlers) {
|
|
171
|
+
handlers.delete(handler);
|
|
172
|
+
if (handlers.size === 0) {
|
|
173
|
+
eventHandlers.delete(event);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
/**
|
|
178
|
+
* Disconnect and cleanup.
|
|
179
|
+
* For native transport, there's nothing to cleanup - we share the process.
|
|
180
|
+
*/
|
|
181
|
+
async disconnect() {
|
|
182
|
+
// Clear all event handlers
|
|
183
|
+
eventHandlers.clear();
|
|
184
|
+
// Native abilities share the process with us.
|
|
185
|
+
// No other cleanup needed.
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native.js","sourceRoot":"","sources":["../../src/transports/native.ts"],"names":[],"mappings":"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"}
|