@distri/react 0.2.1 → 0.2.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/dist/index.cjs +102 -1100
- package/dist/index.d.cts +79 -501
- package/dist/index.d.ts +79 -501
- package/dist/index.js +102 -1036
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,957 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
2
|
|
|
6
3
|
// src/DistriProvider.tsx
|
|
7
4
|
import { createContext as createContext2, useContext as useContext2, useEffect as useEffect2, useState as useState2 } from "react";
|
|
8
|
-
|
|
9
|
-
// ../../node_modules/.pnpm/@a2a-js+sdk@https+++codeload.github.com+v3g42+a2a-js+tar.gz+51444c9/node_modules/@a2a-js/sdk/dist/chunk-CUGIRVQB.js
|
|
10
|
-
var A2AClient = class {
|
|
11
|
-
/**
|
|
12
|
-
* Constructs an A2AClient instance.
|
|
13
|
-
* It initiates fetching the agent card from the provided agent baseUrl.
|
|
14
|
-
* The Agent Card is expected at `${agentBaseUrl}/.well-known/agent.json`.
|
|
15
|
-
* The `url` field from the Agent Card will be used as the RPC service endpoint.
|
|
16
|
-
* @param agentBaseUrl The base URL of the A2A agent (e.g., https://agent.example.com).
|
|
17
|
-
*/
|
|
18
|
-
constructor(agentBaseUrl, fetchFn) {
|
|
19
|
-
__publicField(this, "agentBaseUrl");
|
|
20
|
-
__publicField(this, "agentCardPromise");
|
|
21
|
-
__publicField(this, "requestIdCounter", 1);
|
|
22
|
-
__publicField(this, "serviceEndpointUrl");
|
|
23
|
-
// To be populated from AgentCard after fetching
|
|
24
|
-
__publicField(this, "fetchFn");
|
|
25
|
-
this.agentBaseUrl = agentBaseUrl.replace(/\/$/, "");
|
|
26
|
-
this.fetchFn = fetchFn || globalThis.fetch;
|
|
27
|
-
this.agentCardPromise = this._fetchAndCacheAgentCard();
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Fetches the Agent Card from the agent's well-known URI and caches its service endpoint URL.
|
|
31
|
-
* This method is called by the constructor.
|
|
32
|
-
* @returns A Promise that resolves to the AgentCard.
|
|
33
|
-
*/
|
|
34
|
-
async _fetchAndCacheAgentCard() {
|
|
35
|
-
const agentCardUrl = `${this.agentBaseUrl}/.well-known/agent.json`;
|
|
36
|
-
try {
|
|
37
|
-
const response = await this.fetchFn(agentCardUrl, {
|
|
38
|
-
headers: { "Accept": "application/json" }
|
|
39
|
-
});
|
|
40
|
-
if (!response.ok) {
|
|
41
|
-
throw new Error(`Failed to fetch Agent Card from ${agentCardUrl}: ${response.status} ${response.statusText}`);
|
|
42
|
-
}
|
|
43
|
-
const agentCard = await response.json();
|
|
44
|
-
if (!agentCard.url) {
|
|
45
|
-
throw new Error("Fetched Agent Card does not contain a valid 'url' for the service endpoint.");
|
|
46
|
-
}
|
|
47
|
-
this.serviceEndpointUrl = agentCard.url;
|
|
48
|
-
return agentCard;
|
|
49
|
-
} catch (error) {
|
|
50
|
-
console.error("Error fetching or parsing Agent Card:");
|
|
51
|
-
throw error;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Retrieves the Agent Card.
|
|
56
|
-
* If an `agentBaseUrl` is provided, it fetches the card from that specific URL.
|
|
57
|
-
* Otherwise, it returns the card fetched and cached during client construction.
|
|
58
|
-
* @param agentBaseUrl Optional. The base URL of the agent to fetch the card from.
|
|
59
|
-
* If provided, this will fetch a new card, not use the cached one from the constructor's URL.
|
|
60
|
-
* @returns A Promise that resolves to the AgentCard.
|
|
61
|
-
*/
|
|
62
|
-
async getAgentCard(agentBaseUrl) {
|
|
63
|
-
if (agentBaseUrl) {
|
|
64
|
-
const specificAgentBaseUrl = agentBaseUrl.replace(/\/$/, "");
|
|
65
|
-
const agentCardUrl = `${specificAgentBaseUrl}/.well-known/agent.json`;
|
|
66
|
-
const response = await this.fetchFn(agentCardUrl, {
|
|
67
|
-
headers: { "Accept": "application/json" }
|
|
68
|
-
});
|
|
69
|
-
if (!response.ok) {
|
|
70
|
-
throw new Error(`Failed to fetch Agent Card from ${agentCardUrl}: ${response.status} ${response.statusText}`);
|
|
71
|
-
}
|
|
72
|
-
return await response.json();
|
|
73
|
-
}
|
|
74
|
-
return this.agentCardPromise;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Gets the RPC service endpoint URL. Ensures the agent card has been fetched first.
|
|
78
|
-
* @returns A Promise that resolves to the service endpoint URL string.
|
|
79
|
-
*/
|
|
80
|
-
async _getServiceEndpoint() {
|
|
81
|
-
if (this.serviceEndpointUrl) {
|
|
82
|
-
return this.serviceEndpointUrl;
|
|
83
|
-
}
|
|
84
|
-
await this.agentCardPromise;
|
|
85
|
-
if (!this.serviceEndpointUrl) {
|
|
86
|
-
throw new Error("Agent Card URL for RPC endpoint is not available. Fetching might have failed.");
|
|
87
|
-
}
|
|
88
|
-
return this.serviceEndpointUrl;
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Helper method to make a generic JSON-RPC POST request.
|
|
92
|
-
* @param method The RPC method name.
|
|
93
|
-
* @param params The parameters for the RPC method.
|
|
94
|
-
* @returns A Promise that resolves to the RPC response.
|
|
95
|
-
*/
|
|
96
|
-
async _postRpcRequest(method, params) {
|
|
97
|
-
const endpoint = await this._getServiceEndpoint();
|
|
98
|
-
const requestId = this.requestIdCounter++;
|
|
99
|
-
const rpcRequest = {
|
|
100
|
-
jsonrpc: "2.0",
|
|
101
|
-
method,
|
|
102
|
-
params,
|
|
103
|
-
// Cast because TParams structure varies per method
|
|
104
|
-
id: requestId
|
|
105
|
-
};
|
|
106
|
-
const httpResponse = await this.fetchFn(endpoint, {
|
|
107
|
-
method: "POST",
|
|
108
|
-
headers: {
|
|
109
|
-
"Content-Type": "application/json",
|
|
110
|
-
"Accept": "application/json"
|
|
111
|
-
// Expect JSON response for non-streaming requests
|
|
112
|
-
},
|
|
113
|
-
body: JSON.stringify(rpcRequest)
|
|
114
|
-
});
|
|
115
|
-
if (!httpResponse.ok) {
|
|
116
|
-
let errorBodyText = "(empty or non-JSON response)";
|
|
117
|
-
try {
|
|
118
|
-
errorBodyText = await httpResponse.text();
|
|
119
|
-
const errorJson = JSON.parse(errorBodyText);
|
|
120
|
-
if (!errorJson.jsonrpc && errorJson.error) {
|
|
121
|
-
throw new Error(`RPC error for ${method}: ${errorJson.error.message} (Code: ${errorJson.error.code}, HTTP Status: ${httpResponse.status}) Data: ${JSON.stringify(errorJson.error.data)}`);
|
|
122
|
-
} else if (!errorJson.jsonrpc) {
|
|
123
|
-
throw new Error(`HTTP error for ${method}! Status: ${httpResponse.status} ${httpResponse.statusText}. Response: ${errorBodyText}`);
|
|
124
|
-
}
|
|
125
|
-
} catch (e) {
|
|
126
|
-
if (e.message.startsWith("RPC error for") || e.message.startsWith("HTTP error for")) throw e;
|
|
127
|
-
throw new Error(`HTTP error for ${method}! Status: ${httpResponse.status} ${httpResponse.statusText}. Response: ${errorBodyText}`);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
const rpcResponse = await httpResponse.json();
|
|
131
|
-
if (rpcResponse.id !== requestId) {
|
|
132
|
-
console.error(`CRITICAL: RPC response ID mismatch for method ${method}. Expected ${requestId}, got ${rpcResponse.id}. This may lead to incorrect response handling.`);
|
|
133
|
-
}
|
|
134
|
-
return rpcResponse;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Sends a message to the agent.
|
|
138
|
-
* The behavior (blocking/non-blocking) and push notification configuration
|
|
139
|
-
* are specified within the `params.configuration` object.
|
|
140
|
-
* Optionally, `params.message.contextId` or `params.message.taskId` can be provided.
|
|
141
|
-
* @param params The parameters for sending the message, including the message content and configuration.
|
|
142
|
-
* @returns A Promise resolving to SendMessageResponse, which can be a Message, Task, or an error.
|
|
143
|
-
*/
|
|
144
|
-
async sendMessage(params) {
|
|
145
|
-
return this._postRpcRequest("message/send", params);
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Sends a message to the agent and streams back responses using Server-Sent Events (SSE).
|
|
149
|
-
* Push notification configuration can be specified in `params.configuration`.
|
|
150
|
-
* Optionally, `params.message.contextId` or `params.message.taskId` can be provided.
|
|
151
|
-
* Requires the agent to support streaming (`capabilities.streaming: true` in AgentCard).
|
|
152
|
-
* @param params The parameters for sending the message.
|
|
153
|
-
* @returns An AsyncGenerator yielding A2AStreamEventData (Message, Task, TaskStatusUpdateEvent, or TaskArtifactUpdateEvent).
|
|
154
|
-
* The generator throws an error if streaming is not supported or if an HTTP/SSE error occurs.
|
|
155
|
-
*/
|
|
156
|
-
async *sendMessageStream(params) {
|
|
157
|
-
const agentCard = await this.agentCardPromise;
|
|
158
|
-
if (!agentCard.capabilities?.streaming) {
|
|
159
|
-
throw new Error("Agent does not support streaming (AgentCard.capabilities.streaming is not true).");
|
|
160
|
-
}
|
|
161
|
-
const endpoint = await this._getServiceEndpoint();
|
|
162
|
-
const clientRequestId = this.requestIdCounter++;
|
|
163
|
-
const rpcRequest = {
|
|
164
|
-
// This is the initial JSON-RPC request to establish the stream
|
|
165
|
-
jsonrpc: "2.0",
|
|
166
|
-
method: "message/stream",
|
|
167
|
-
params,
|
|
168
|
-
id: clientRequestId
|
|
169
|
-
};
|
|
170
|
-
const response = await this.fetchFn(endpoint, {
|
|
171
|
-
method: "POST",
|
|
172
|
-
headers: {
|
|
173
|
-
"Content-Type": "application/json",
|
|
174
|
-
"Accept": "text/event-stream"
|
|
175
|
-
// Crucial for SSE
|
|
176
|
-
},
|
|
177
|
-
body: JSON.stringify(rpcRequest)
|
|
178
|
-
});
|
|
179
|
-
if (!response.ok) {
|
|
180
|
-
let errorBody = "";
|
|
181
|
-
try {
|
|
182
|
-
errorBody = await response.text();
|
|
183
|
-
const errorJson = JSON.parse(errorBody);
|
|
184
|
-
if (errorJson.error) {
|
|
185
|
-
throw new Error(`HTTP error establishing stream for message/stream: ${response.status} ${response.statusText}. RPC Error: ${errorJson.error.message} (Code: ${errorJson.error.code})`);
|
|
186
|
-
}
|
|
187
|
-
} catch (e) {
|
|
188
|
-
if (e.message.startsWith("HTTP error establishing stream")) throw e;
|
|
189
|
-
throw new Error(`HTTP error establishing stream for message/stream: ${response.status} ${response.statusText}. Response: ${errorBody || "(empty)"}`);
|
|
190
|
-
}
|
|
191
|
-
throw new Error(`HTTP error establishing stream for message/stream: ${response.status} ${response.statusText}`);
|
|
192
|
-
}
|
|
193
|
-
if (!response.headers.get("Content-Type")?.startsWith("text/event-stream")) {
|
|
194
|
-
throw new Error("Invalid response Content-Type for SSE stream. Expected 'text/event-stream'.");
|
|
195
|
-
}
|
|
196
|
-
yield* this._parseA2ASseStream(response, clientRequestId);
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Sets or updates the push notification configuration for a given task.
|
|
200
|
-
* Requires the agent to support push notifications (`capabilities.pushNotifications: true` in AgentCard).
|
|
201
|
-
* @param params Parameters containing the taskId and the TaskPushNotificationConfig.
|
|
202
|
-
* @returns A Promise resolving to SetTaskPushNotificationConfigResponse.
|
|
203
|
-
*/
|
|
204
|
-
async setTaskPushNotificationConfig(params) {
|
|
205
|
-
const agentCard = await this.agentCardPromise;
|
|
206
|
-
if (!agentCard.capabilities?.pushNotifications) {
|
|
207
|
-
throw new Error("Agent does not support push notifications (AgentCard.capabilities.pushNotifications is not true).");
|
|
208
|
-
}
|
|
209
|
-
return this._postRpcRequest(
|
|
210
|
-
"tasks/pushNotificationConfig/set",
|
|
211
|
-
params
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Gets the push notification configuration for a given task.
|
|
216
|
-
* @param params Parameters containing the taskId.
|
|
217
|
-
* @returns A Promise resolving to GetTaskPushNotificationConfigResponse.
|
|
218
|
-
*/
|
|
219
|
-
async getTaskPushNotificationConfig(params) {
|
|
220
|
-
return this._postRpcRequest(
|
|
221
|
-
"tasks/pushNotificationConfig/get",
|
|
222
|
-
params
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* Retrieves a task by its ID.
|
|
227
|
-
* @param params Parameters containing the taskId and optional historyLength.
|
|
228
|
-
* @returns A Promise resolving to GetTaskResponse, which contains the Task object or an error.
|
|
229
|
-
*/
|
|
230
|
-
async getTask(params) {
|
|
231
|
-
return this._postRpcRequest("tasks/get", params);
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* Cancels a task by its ID.
|
|
235
|
-
* @param params Parameters containing the taskId.
|
|
236
|
-
* @returns A Promise resolving to CancelTaskResponse, which contains the updated Task object or an error.
|
|
237
|
-
*/
|
|
238
|
-
async cancelTask(params) {
|
|
239
|
-
return this._postRpcRequest("tasks/cancel", params);
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* Resubscribes to a task's event stream using Server-Sent Events (SSE).
|
|
243
|
-
* This is used if a previous SSE connection for an active task was broken.
|
|
244
|
-
* Requires the agent to support streaming (`capabilities.streaming: true` in AgentCard).
|
|
245
|
-
* @param params Parameters containing the taskId.
|
|
246
|
-
* @returns An AsyncGenerator yielding A2AStreamEventData (Message, Task, TaskStatusUpdateEvent, or TaskArtifactUpdateEvent).
|
|
247
|
-
*/
|
|
248
|
-
async *resubscribeTask(params) {
|
|
249
|
-
const agentCard = await this.agentCardPromise;
|
|
250
|
-
if (!agentCard.capabilities?.streaming) {
|
|
251
|
-
throw new Error("Agent does not support streaming (required for tasks/resubscribe).");
|
|
252
|
-
}
|
|
253
|
-
const endpoint = await this._getServiceEndpoint();
|
|
254
|
-
const clientRequestId = this.requestIdCounter++;
|
|
255
|
-
const rpcRequest = {
|
|
256
|
-
// Initial JSON-RPC request to establish the stream
|
|
257
|
-
jsonrpc: "2.0",
|
|
258
|
-
method: "tasks/resubscribe",
|
|
259
|
-
params,
|
|
260
|
-
id: clientRequestId
|
|
261
|
-
};
|
|
262
|
-
const response = await this.fetchFn(endpoint, {
|
|
263
|
-
method: "POST",
|
|
264
|
-
headers: {
|
|
265
|
-
"Content-Type": "application/json",
|
|
266
|
-
"Accept": "text/event-stream"
|
|
267
|
-
},
|
|
268
|
-
body: JSON.stringify(rpcRequest)
|
|
269
|
-
});
|
|
270
|
-
if (!response.ok) {
|
|
271
|
-
let errorBody = "";
|
|
272
|
-
try {
|
|
273
|
-
errorBody = await response.text();
|
|
274
|
-
const errorJson = JSON.parse(errorBody);
|
|
275
|
-
if (errorJson.error) {
|
|
276
|
-
throw new Error(`HTTP error establishing stream for tasks/resubscribe: ${response.status} ${response.statusText}. RPC Error: ${errorJson.error.message} (Code: ${errorJson.error.code})`);
|
|
277
|
-
}
|
|
278
|
-
} catch (e) {
|
|
279
|
-
if (e.message.startsWith("HTTP error establishing stream")) throw e;
|
|
280
|
-
throw new Error(`HTTP error establishing stream for tasks/resubscribe: ${response.status} ${response.statusText}. Response: ${errorBody || "(empty)"}`);
|
|
281
|
-
}
|
|
282
|
-
throw new Error(`HTTP error establishing stream for tasks/resubscribe: ${response.status} ${response.statusText}`);
|
|
283
|
-
}
|
|
284
|
-
if (!response.headers.get("Content-Type")?.startsWith("text/event-stream")) {
|
|
285
|
-
throw new Error("Invalid response Content-Type for SSE stream on resubscribe. Expected 'text/event-stream'.");
|
|
286
|
-
}
|
|
287
|
-
yield* this._parseA2ASseStream(response, clientRequestId);
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Parses an HTTP response body as an A2A Server-Sent Event stream.
|
|
291
|
-
* Each 'data' field of an SSE event is expected to be a JSON-RPC 2.0 Response object,
|
|
292
|
-
* specifically a SendStreamingMessageResponse (or similar structure for resubscribe).
|
|
293
|
-
* @param response The HTTP Response object whose body is the SSE stream.
|
|
294
|
-
* @param originalRequestId The ID of the client's JSON-RPC request that initiated this stream.
|
|
295
|
-
* Used to validate the `id` in the streamed JSON-RPC responses.
|
|
296
|
-
* @returns An AsyncGenerator yielding the `result` field of each valid JSON-RPC success response from the stream.
|
|
297
|
-
*/
|
|
298
|
-
async *_parseA2ASseStream(response, originalRequestId) {
|
|
299
|
-
if (!response.body) {
|
|
300
|
-
throw new Error("SSE response body is undefined. Cannot read stream.");
|
|
301
|
-
}
|
|
302
|
-
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
303
|
-
let buffer = "";
|
|
304
|
-
let eventDataBuffer = "";
|
|
305
|
-
try {
|
|
306
|
-
while (true) {
|
|
307
|
-
const { done, value } = await reader.read();
|
|
308
|
-
if (done) {
|
|
309
|
-
if (eventDataBuffer.trim()) {
|
|
310
|
-
const result = this._processSseEventData(eventDataBuffer, originalRequestId);
|
|
311
|
-
yield result;
|
|
312
|
-
}
|
|
313
|
-
break;
|
|
314
|
-
}
|
|
315
|
-
buffer += value;
|
|
316
|
-
let lineEndIndex;
|
|
317
|
-
while ((lineEndIndex = buffer.indexOf("\n")) >= 0) {
|
|
318
|
-
const line = buffer.substring(0, lineEndIndex).trim();
|
|
319
|
-
buffer = buffer.substring(lineEndIndex + 1);
|
|
320
|
-
if (line === "") {
|
|
321
|
-
if (eventDataBuffer) {
|
|
322
|
-
const result = this._processSseEventData(eventDataBuffer, originalRequestId);
|
|
323
|
-
yield result;
|
|
324
|
-
eventDataBuffer = "";
|
|
325
|
-
}
|
|
326
|
-
} else if (line.startsWith("data:")) {
|
|
327
|
-
eventDataBuffer += line.substring(5).trimStart() + "\n";
|
|
328
|
-
} else if (line.startsWith(":")) {
|
|
329
|
-
} else if (line.includes(":")) {
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
} catch (error) {
|
|
334
|
-
console.error("Error reading or parsing SSE stream:", error.message);
|
|
335
|
-
throw error;
|
|
336
|
-
} finally {
|
|
337
|
-
reader.releaseLock();
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
/**
|
|
341
|
-
* Processes a single SSE event's data string, expecting it to be a JSON-RPC response.
|
|
342
|
-
* @param jsonData The string content from one or more 'data:' lines of an SSE event.
|
|
343
|
-
* @param originalRequestId The ID of the client's request that initiated the stream.
|
|
344
|
-
* @returns The `result` field of the parsed JSON-RPC success response.
|
|
345
|
-
* @throws Error if data is not valid JSON, not a valid JSON-RPC response, an error response, or ID mismatch.
|
|
346
|
-
*/
|
|
347
|
-
_processSseEventData(jsonData, originalRequestId) {
|
|
348
|
-
if (!jsonData.trim()) {
|
|
349
|
-
throw new Error("Attempted to process empty SSE event data.");
|
|
350
|
-
}
|
|
351
|
-
try {
|
|
352
|
-
const sseJsonRpcResponse = JSON.parse(jsonData.replace(/\n$/, ""));
|
|
353
|
-
const a2aStreamResponse = sseJsonRpcResponse;
|
|
354
|
-
if (a2aStreamResponse.id !== originalRequestId) {
|
|
355
|
-
console.warn(`SSE Event's JSON-RPC response ID mismatch. Client request ID: ${originalRequestId}, event response ID: ${a2aStreamResponse.id}.`);
|
|
356
|
-
}
|
|
357
|
-
if (this.isErrorResponse(a2aStreamResponse)) {
|
|
358
|
-
const err = a2aStreamResponse.error;
|
|
359
|
-
throw new Error(`SSE event contained an error: ${err.message} (Code: ${err.code}) Data: ${JSON.stringify(err.data)}`);
|
|
360
|
-
}
|
|
361
|
-
if (!("result" in a2aStreamResponse) || typeof a2aStreamResponse.result === "undefined") {
|
|
362
|
-
throw new Error(`SSE event JSON-RPC response is missing 'result' field. Data: ${jsonData}`);
|
|
363
|
-
}
|
|
364
|
-
const successResponse = a2aStreamResponse;
|
|
365
|
-
return successResponse.result;
|
|
366
|
-
} catch (e) {
|
|
367
|
-
if (e.message.startsWith("SSE event contained an error") || e.message.startsWith("SSE event JSON-RPC response is missing 'result' field")) {
|
|
368
|
-
throw e;
|
|
369
|
-
}
|
|
370
|
-
console.error("Failed to parse SSE event data string or unexpected JSON-RPC structure:", jsonData, e);
|
|
371
|
-
throw new Error(`Failed to parse SSE event data: "${jsonData.substring(0, 100)}...". Original error: ${e.message}`);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
isErrorResponse(response) {
|
|
375
|
-
return "error" in response;
|
|
376
|
-
}
|
|
377
|
-
};
|
|
378
|
-
|
|
379
|
-
// ../core/src/types.ts
|
|
380
|
-
var DistriError = class extends Error {
|
|
381
|
-
constructor(message, code, details) {
|
|
382
|
-
super(message);
|
|
383
|
-
this.code = code;
|
|
384
|
-
this.details = details;
|
|
385
|
-
this.name = "DistriError";
|
|
386
|
-
}
|
|
387
|
-
};
|
|
388
|
-
var A2AProtocolError = class extends DistriError {
|
|
389
|
-
constructor(message, details) {
|
|
390
|
-
super(message, "A2A_PROTOCOL_ERROR", details);
|
|
391
|
-
this.name = "A2AProtocolError";
|
|
392
|
-
}
|
|
393
|
-
};
|
|
394
|
-
var ApiError = class extends DistriError {
|
|
395
|
-
constructor(message, statusCode, details) {
|
|
396
|
-
super(message, "API_ERROR", details);
|
|
397
|
-
this.statusCode = statusCode;
|
|
398
|
-
this.name = "ApiError";
|
|
399
|
-
}
|
|
400
|
-
};
|
|
401
|
-
function isDistriMessage(event) {
|
|
402
|
-
return "id" in event && "role" in event && "parts" in event;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// ../core/src/encoder.ts
|
|
406
|
-
function convertA2AMessageToDistri(a2aMessage) {
|
|
407
|
-
const role = a2aMessage.role === "agent" ? "assistant" : "user";
|
|
408
|
-
return {
|
|
409
|
-
id: a2aMessage.messageId,
|
|
410
|
-
role,
|
|
411
|
-
parts: a2aMessage.parts.map(convertA2APartToDistri),
|
|
412
|
-
created_at: a2aMessage.createdAt
|
|
413
|
-
};
|
|
414
|
-
}
|
|
415
|
-
function decodeA2AStreamEvent(event) {
|
|
416
|
-
if (event.kind === "message") {
|
|
417
|
-
return convertA2AMessageToDistri(event);
|
|
418
|
-
} else if (event.kind === "status-update") {
|
|
419
|
-
return event;
|
|
420
|
-
} else if (event.kind === "artifact-update") {
|
|
421
|
-
return event;
|
|
422
|
-
}
|
|
423
|
-
return event;
|
|
424
|
-
}
|
|
425
|
-
function convertA2APartToDistri(a2aPart) {
|
|
426
|
-
switch (a2aPart.kind) {
|
|
427
|
-
case "text":
|
|
428
|
-
return { type: "text", text: a2aPart.text };
|
|
429
|
-
case "file":
|
|
430
|
-
if ("uri" in a2aPart.file) {
|
|
431
|
-
return { type: "image_url", image: { mime_type: a2aPart.file.mimeType, url: a2aPart.file.uri } };
|
|
432
|
-
} else {
|
|
433
|
-
return { type: "image_bytes", image: { mime_type: a2aPart.file.mimeType, data: a2aPart.file.bytes } };
|
|
434
|
-
}
|
|
435
|
-
case "data":
|
|
436
|
-
switch (a2aPart.data.part_type) {
|
|
437
|
-
case "tool_call":
|
|
438
|
-
return { type: "tool_call", tool_call: a2aPart.data };
|
|
439
|
-
case "tool_result":
|
|
440
|
-
return { type: "tool_result", tool_result: a2aPart.data };
|
|
441
|
-
case "code_observation":
|
|
442
|
-
return { type: "code_observation", thought: a2aPart.data.thought, code: a2aPart.data.code };
|
|
443
|
-
case "plan":
|
|
444
|
-
return { type: "plan", plan: a2aPart.data.plan };
|
|
445
|
-
default:
|
|
446
|
-
return { type: "data", data: a2aPart.data };
|
|
447
|
-
}
|
|
448
|
-
default:
|
|
449
|
-
return { type: "text", text: JSON.stringify(a2aPart) };
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
function convertDistriMessageToA2A(distriMessage, context) {
|
|
453
|
-
let role;
|
|
454
|
-
switch (distriMessage.role) {
|
|
455
|
-
case "assistant":
|
|
456
|
-
role = "agent";
|
|
457
|
-
break;
|
|
458
|
-
case "user":
|
|
459
|
-
role = "user";
|
|
460
|
-
break;
|
|
461
|
-
case "system":
|
|
462
|
-
case "tool":
|
|
463
|
-
role = "user";
|
|
464
|
-
break;
|
|
465
|
-
default:
|
|
466
|
-
role = "user";
|
|
467
|
-
}
|
|
468
|
-
return {
|
|
469
|
-
messageId: distriMessage.id,
|
|
470
|
-
role,
|
|
471
|
-
parts: distriMessage.parts.map(convertDistriPartToA2A),
|
|
472
|
-
kind: "message",
|
|
473
|
-
contextId: context.thread_id,
|
|
474
|
-
taskId: context.run_id
|
|
475
|
-
};
|
|
476
|
-
}
|
|
477
|
-
function convertDistriPartToA2A(distriPart) {
|
|
478
|
-
switch (distriPart.type) {
|
|
479
|
-
case "text":
|
|
480
|
-
return { kind: "text", text: distriPart.text };
|
|
481
|
-
case "image_url":
|
|
482
|
-
return { kind: "file", file: { mimeType: distriPart.image.mime_type, uri: distriPart.image.url } };
|
|
483
|
-
case "image_bytes":
|
|
484
|
-
return { kind: "file", file: { mimeType: distriPart.image.mime_type, bytes: distriPart.image.data } };
|
|
485
|
-
case "tool_call":
|
|
486
|
-
return { kind: "data", data: { part_type: "tool_call", tool_call: distriPart.tool_call } };
|
|
487
|
-
case "tool_result":
|
|
488
|
-
let val = {
|
|
489
|
-
kind: "data",
|
|
490
|
-
data: {
|
|
491
|
-
tool_call_id: distriPart.tool_result.tool_call_id,
|
|
492
|
-
result: distriPart.tool_result.result,
|
|
493
|
-
part_type: "tool_result"
|
|
494
|
-
}
|
|
495
|
-
};
|
|
496
|
-
console.log("<> val", val);
|
|
497
|
-
return val;
|
|
498
|
-
case "code_observation":
|
|
499
|
-
return { kind: "data", data: { ...distriPart, part_type: "code_observation" } };
|
|
500
|
-
case "plan":
|
|
501
|
-
return { kind: "data", data: { ...distriPart, part_type: "plan" } };
|
|
502
|
-
case "data":
|
|
503
|
-
return { kind: "data", ...distriPart.data };
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
// ../core/src/distri-client.ts
|
|
508
|
-
var DistriClient = class {
|
|
509
|
-
constructor(config) {
|
|
510
|
-
this.agentClients = /* @__PURE__ */ new Map();
|
|
511
|
-
this.config = {
|
|
512
|
-
baseUrl: config.baseUrl.replace(/\/$/, ""),
|
|
513
|
-
apiVersion: config.apiVersion || "v1",
|
|
514
|
-
timeout: config.timeout || 3e4,
|
|
515
|
-
retryAttempts: config.retryAttempts || 3,
|
|
516
|
-
retryDelay: config.retryDelay || 1e3,
|
|
517
|
-
debug: config.debug || false,
|
|
518
|
-
headers: config.headers || {},
|
|
519
|
-
interceptor: config.interceptor || ((init) => Promise.resolve(init))
|
|
520
|
-
};
|
|
521
|
-
this.debug("DistriClient initialized with config:", this.config);
|
|
522
|
-
}
|
|
523
|
-
/**
|
|
524
|
-
* Get all available agents from the Distri server
|
|
525
|
-
*/
|
|
526
|
-
async getAgents() {
|
|
527
|
-
try {
|
|
528
|
-
const response = await this.fetch(`/agents`, {
|
|
529
|
-
headers: {
|
|
530
|
-
...this.config.headers
|
|
531
|
-
}
|
|
532
|
-
});
|
|
533
|
-
if (!response.ok) {
|
|
534
|
-
throw new ApiError(`Failed to fetch agents: ${response.statusText}`, response.status);
|
|
535
|
-
}
|
|
536
|
-
const agents = await response.json();
|
|
537
|
-
agents.forEach((agent) => {
|
|
538
|
-
if (!agent.id) {
|
|
539
|
-
agent.id = agent.name;
|
|
540
|
-
}
|
|
541
|
-
});
|
|
542
|
-
return agents;
|
|
543
|
-
} catch (error) {
|
|
544
|
-
if (error instanceof ApiError) throw error;
|
|
545
|
-
throw new DistriError("Failed to fetch agents", "FETCH_ERROR", error);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
/**
|
|
549
|
-
* Get specific agent by ID
|
|
550
|
-
*/
|
|
551
|
-
async getAgent(agentId) {
|
|
552
|
-
try {
|
|
553
|
-
const response = await this.fetch(`/agents/${agentId}`, {
|
|
554
|
-
headers: {
|
|
555
|
-
...this.config.headers
|
|
556
|
-
}
|
|
557
|
-
});
|
|
558
|
-
if (!response.ok) {
|
|
559
|
-
if (response.status === 404) {
|
|
560
|
-
throw new ApiError(`Agent not found: ${agentId}`, 404);
|
|
561
|
-
}
|
|
562
|
-
throw new ApiError(`Failed to fetch agent: ${response.statusText}`, response.status);
|
|
563
|
-
}
|
|
564
|
-
const agent = await response.json();
|
|
565
|
-
if (!agent.id) {
|
|
566
|
-
agent.id = agentId;
|
|
567
|
-
}
|
|
568
|
-
return agent;
|
|
569
|
-
} catch (error) {
|
|
570
|
-
if (error instanceof ApiError) throw error;
|
|
571
|
-
throw new DistriError(`Failed to fetch agent ${agentId}`, "FETCH_ERROR", error);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
/**
|
|
575
|
-
* Get or create A2AClient for an agent
|
|
576
|
-
*/
|
|
577
|
-
getA2AClient(agentId) {
|
|
578
|
-
if (!this.agentClients.has(agentId)) {
|
|
579
|
-
const fetchFn = this.fetchAbsolute.bind(this);
|
|
580
|
-
const agentUrl = `${this.config.baseUrl}/agents/${agentId}`;
|
|
581
|
-
const client = new A2AClient(agentUrl, fetchFn);
|
|
582
|
-
this.agentClients.set(agentId, client);
|
|
583
|
-
this.debug(`Created A2AClient for agent ${agentId} at ${agentUrl}`);
|
|
584
|
-
}
|
|
585
|
-
return this.agentClients.get(agentId);
|
|
586
|
-
}
|
|
587
|
-
/**
|
|
588
|
-
* Send a message to an agent
|
|
589
|
-
*/
|
|
590
|
-
async sendMessage(agentId, params) {
|
|
591
|
-
try {
|
|
592
|
-
const client = this.getA2AClient(agentId);
|
|
593
|
-
const response = await client.sendMessage(params);
|
|
594
|
-
if ("error" in response && response.error) {
|
|
595
|
-
throw new A2AProtocolError(response.error.message, response.error);
|
|
596
|
-
}
|
|
597
|
-
if ("result" in response) {
|
|
598
|
-
const result = response.result;
|
|
599
|
-
this.debug(`Message sent to ${agentId}, got ${result.kind}:`, result);
|
|
600
|
-
return result;
|
|
601
|
-
}
|
|
602
|
-
throw new DistriError("Invalid response format", "INVALID_RESPONSE");
|
|
603
|
-
} catch (error) {
|
|
604
|
-
if (error instanceof A2AProtocolError || error instanceof DistriError) throw error;
|
|
605
|
-
throw new DistriError(`Failed to send message to agent ${agentId}`, "SEND_MESSAGE_ERROR", error);
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
/**
|
|
609
|
-
* Send a streaming message to an agent
|
|
610
|
-
*/
|
|
611
|
-
async *sendMessageStream(agentId, params) {
|
|
612
|
-
try {
|
|
613
|
-
const client = this.getA2AClient(agentId);
|
|
614
|
-
yield* await client.sendMessageStream(params);
|
|
615
|
-
} catch (error) {
|
|
616
|
-
throw new DistriError(`Failed to stream message to agent ${agentId}`, "STREAM_MESSAGE_ERROR", error);
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
/**
|
|
620
|
-
* Get task details
|
|
621
|
-
*/
|
|
622
|
-
async getTask(agentId, taskId) {
|
|
623
|
-
try {
|
|
624
|
-
const client = this.getA2AClient(agentId);
|
|
625
|
-
const response = await client.getTask({ id: taskId });
|
|
626
|
-
if ("error" in response && response.error) {
|
|
627
|
-
throw new A2AProtocolError(response.error.message, response.error);
|
|
628
|
-
}
|
|
629
|
-
if ("result" in response) {
|
|
630
|
-
const result = response.result;
|
|
631
|
-
this.debug(`Got task ${taskId} from ${agentId}:`, result);
|
|
632
|
-
return result;
|
|
633
|
-
}
|
|
634
|
-
throw new DistriError("Invalid response format", "INVALID_RESPONSE");
|
|
635
|
-
} catch (error) {
|
|
636
|
-
if (error instanceof A2AProtocolError || error instanceof DistriError) throw error;
|
|
637
|
-
throw new DistriError(`Failed to get task ${taskId} from agent ${agentId}`, "GET_TASK_ERROR", error);
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
/**
|
|
641
|
-
* Cancel a task
|
|
642
|
-
*/
|
|
643
|
-
async cancelTask(agentId, taskId) {
|
|
644
|
-
try {
|
|
645
|
-
const client = this.getA2AClient(agentId);
|
|
646
|
-
await client.cancelTask({ id: taskId });
|
|
647
|
-
this.debug(`Cancelled task ${taskId} on agent ${agentId}`);
|
|
648
|
-
} catch (error) {
|
|
649
|
-
throw new DistriError(`Failed to cancel task ${taskId} on agent ${agentId}`, "CANCEL_TASK_ERROR", error);
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
/**
|
|
653
|
-
* Get threads from Distri server
|
|
654
|
-
*/
|
|
655
|
-
async getThreads() {
|
|
656
|
-
try {
|
|
657
|
-
const response = await this.fetch(`/threads`);
|
|
658
|
-
if (!response.ok) {
|
|
659
|
-
throw new ApiError(`Failed to fetch threads: ${response.statusText}`, response.status);
|
|
660
|
-
}
|
|
661
|
-
return await response.json();
|
|
662
|
-
} catch (error) {
|
|
663
|
-
if (error instanceof ApiError) throw error;
|
|
664
|
-
throw new DistriError("Failed to fetch threads", "FETCH_ERROR", error);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
async getThread(threadId) {
|
|
668
|
-
try {
|
|
669
|
-
const response = await this.fetch(`/threads/${threadId}`);
|
|
670
|
-
if (!response.ok) {
|
|
671
|
-
throw new ApiError(`Failed to fetch thread: ${response.statusText}`, response.status);
|
|
672
|
-
}
|
|
673
|
-
return await response.json();
|
|
674
|
-
} catch (error) {
|
|
675
|
-
if (error instanceof ApiError) throw error;
|
|
676
|
-
throw new DistriError(`Failed to fetch thread ${threadId}`, "FETCH_ERROR", error);
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
/**
|
|
680
|
-
* Get thread messages
|
|
681
|
-
*/
|
|
682
|
-
async getThreadMessages(threadId) {
|
|
683
|
-
try {
|
|
684
|
-
const response = await this.fetch(`/threads/${threadId}/messages`);
|
|
685
|
-
if (!response.ok) {
|
|
686
|
-
if (response.status === 404) {
|
|
687
|
-
return [];
|
|
688
|
-
}
|
|
689
|
-
throw new ApiError(`Failed to fetch thread messages: ${response.statusText}`, response.status);
|
|
690
|
-
}
|
|
691
|
-
return await response.json();
|
|
692
|
-
} catch (error) {
|
|
693
|
-
if (error instanceof ApiError) throw error;
|
|
694
|
-
throw new DistriError(`Failed to fetch messages for thread ${threadId}`, "FETCH_ERROR", error);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
/**
|
|
698
|
-
* Get messages from a thread as DistriMessage format
|
|
699
|
-
*/
|
|
700
|
-
async getThreadMessagesAsDistri(threadId) {
|
|
701
|
-
const messages = await this.getThreadMessages(threadId);
|
|
702
|
-
return messages.map(convertA2AMessageToDistri);
|
|
703
|
-
}
|
|
704
|
-
/**
|
|
705
|
-
* Send a DistriMessage to a thread
|
|
706
|
-
*/
|
|
707
|
-
async sendDistriMessage(threadId, message, context) {
|
|
708
|
-
const a2aMessage = convertDistriMessageToA2A(message, context);
|
|
709
|
-
const params = {
|
|
710
|
-
message: a2aMessage,
|
|
711
|
-
metadata: context.metadata
|
|
712
|
-
};
|
|
713
|
-
await this.sendMessage(threadId, params);
|
|
714
|
-
}
|
|
715
|
-
/**
|
|
716
|
-
* Get the base URL for making direct requests
|
|
717
|
-
*/
|
|
718
|
-
get baseUrl() {
|
|
719
|
-
return this.config.baseUrl;
|
|
720
|
-
}
|
|
721
|
-
/**
|
|
722
|
-
* Enhanced fetch with retry logic
|
|
723
|
-
*/
|
|
724
|
-
async fetchAbsolute(url, initialInit) {
|
|
725
|
-
const init = await this.config.interceptor(initialInit);
|
|
726
|
-
let lastError;
|
|
727
|
-
for (let attempt = 0; attempt <= this.config.retryAttempts; attempt++) {
|
|
728
|
-
try {
|
|
729
|
-
const controller = new AbortController();
|
|
730
|
-
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
731
|
-
const response = await fetch(url, {
|
|
732
|
-
...init,
|
|
733
|
-
signal: controller.signal,
|
|
734
|
-
headers: {
|
|
735
|
-
...this.config.headers,
|
|
736
|
-
...init?.headers
|
|
737
|
-
}
|
|
738
|
-
});
|
|
739
|
-
clearTimeout(timeoutId);
|
|
740
|
-
return response;
|
|
741
|
-
} catch (error) {
|
|
742
|
-
lastError = error instanceof Error ? error : new Error(String(error));
|
|
743
|
-
if (attempt < this.config.retryAttempts) {
|
|
744
|
-
this.debug(`Request failed (attempt ${attempt + 1}), retrying in ${this.config.retryDelay}ms...`);
|
|
745
|
-
await this.delay(this.config.retryDelay);
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
throw lastError;
|
|
750
|
-
}
|
|
751
|
-
/**
|
|
752
|
-
* Enhanced fetch with retry logic
|
|
753
|
-
*/
|
|
754
|
-
async fetch(input, initialInit) {
|
|
755
|
-
const url = `${this.config.baseUrl}${input}`;
|
|
756
|
-
return this.fetchAbsolute(url, initialInit);
|
|
757
|
-
}
|
|
758
|
-
/**
|
|
759
|
-
* Delay utility
|
|
760
|
-
*/
|
|
761
|
-
delay(ms) {
|
|
762
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
763
|
-
}
|
|
764
|
-
/**
|
|
765
|
-
* Debug logging
|
|
766
|
-
*/
|
|
767
|
-
debug(...args) {
|
|
768
|
-
if (this.config.debug) {
|
|
769
|
-
console.log("[DistriClient]", ...args);
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
/**
|
|
773
|
-
* Helper method to create A2A messages
|
|
774
|
-
*/
|
|
775
|
-
static initMessage(parts, role = "user", message) {
|
|
776
|
-
return {
|
|
777
|
-
messageId: message.messageId || uuidv4(),
|
|
778
|
-
taskId: message.taskId || uuidv4(),
|
|
779
|
-
contextId: message.contextId,
|
|
780
|
-
role,
|
|
781
|
-
parts: Array.isArray(parts) ? parts : [{ kind: "text", text: parts.trim() }],
|
|
782
|
-
...message,
|
|
783
|
-
kind: "message"
|
|
784
|
-
};
|
|
785
|
-
}
|
|
786
|
-
/**
|
|
787
|
-
* Create a DistriMessage instance
|
|
788
|
-
*/
|
|
789
|
-
static initDistriMessage(role, parts, id, created_at) {
|
|
790
|
-
return {
|
|
791
|
-
id: id || uuidv4(),
|
|
792
|
-
role,
|
|
793
|
-
parts,
|
|
794
|
-
created_at
|
|
795
|
-
};
|
|
796
|
-
}
|
|
797
|
-
/**
|
|
798
|
-
* Helper method to create message send parameters
|
|
799
|
-
*/
|
|
800
|
-
static initMessageParams(message, configuration, metadata) {
|
|
801
|
-
return {
|
|
802
|
-
message,
|
|
803
|
-
configuration: {
|
|
804
|
-
acceptedOutputModes: ["text/plain"],
|
|
805
|
-
blocking: false,
|
|
806
|
-
// Default to non-blocking for streaming
|
|
807
|
-
...configuration
|
|
808
|
-
},
|
|
809
|
-
metadata
|
|
810
|
-
};
|
|
811
|
-
}
|
|
812
|
-
/**
|
|
813
|
-
* Create MessageSendParams from a DistriMessage using InvokeContext
|
|
814
|
-
*/
|
|
815
|
-
static initDistriMessageParams(message, context) {
|
|
816
|
-
const a2aMessage = convertDistriMessageToA2A(message, context);
|
|
817
|
-
return {
|
|
818
|
-
message: a2aMessage,
|
|
819
|
-
metadata: context.metadata
|
|
820
|
-
};
|
|
821
|
-
}
|
|
822
|
-
};
|
|
823
|
-
function uuidv4() {
|
|
824
|
-
if (typeof crypto?.randomUUID === "function") {
|
|
825
|
-
return crypto.randomUUID();
|
|
826
|
-
}
|
|
827
|
-
const array = new Uint8Array(16);
|
|
828
|
-
crypto.getRandomValues(array);
|
|
829
|
-
array[6] = array[6] & 15 | 64;
|
|
830
|
-
array[8] = array[8] & 63 | 128;
|
|
831
|
-
return [...array].map(
|
|
832
|
-
(b, i) => ([4, 6, 8, 10].includes(i) ? "-" : "") + b.toString(16).padStart(2, "0")
|
|
833
|
-
).join("");
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
// ../core/src/agent.ts
|
|
837
|
-
var Agent = class _Agent {
|
|
838
|
-
constructor(agentDefinition, client) {
|
|
839
|
-
this.tools = /* @__PURE__ */ new Map();
|
|
840
|
-
this.agentDefinition = agentDefinition;
|
|
841
|
-
this.client = client;
|
|
842
|
-
}
|
|
843
|
-
/**
|
|
844
|
-
* Add a tool to the agent (AG-UI style)
|
|
845
|
-
*/
|
|
846
|
-
registerTool(tool) {
|
|
847
|
-
this.tools.set(tool.name, tool);
|
|
848
|
-
}
|
|
849
|
-
/**
|
|
850
|
-
* Add multiple tools at once
|
|
851
|
-
*/
|
|
852
|
-
registerTools(tools) {
|
|
853
|
-
tools.forEach((tool) => this.registerTool(tool));
|
|
854
|
-
}
|
|
855
|
-
/**
|
|
856
|
-
* Remove a tool
|
|
857
|
-
*/
|
|
858
|
-
unregisterTool(toolName) {
|
|
859
|
-
this.tools.delete(toolName);
|
|
860
|
-
}
|
|
861
|
-
/**
|
|
862
|
-
* Get all registered tools
|
|
863
|
-
*/
|
|
864
|
-
getTools() {
|
|
865
|
-
return Array.from(this.tools.values());
|
|
866
|
-
}
|
|
867
|
-
/**
|
|
868
|
-
* Check if a tool is registered
|
|
869
|
-
*/
|
|
870
|
-
hasTool(toolName) {
|
|
871
|
-
return this.tools.has(toolName);
|
|
872
|
-
}
|
|
873
|
-
/**
|
|
874
|
-
* Get agent information
|
|
875
|
-
*/
|
|
876
|
-
get id() {
|
|
877
|
-
return this.agentDefinition.id;
|
|
878
|
-
}
|
|
879
|
-
get name() {
|
|
880
|
-
return this.agentDefinition.name;
|
|
881
|
-
}
|
|
882
|
-
get description() {
|
|
883
|
-
return this.agentDefinition.description;
|
|
884
|
-
}
|
|
885
|
-
get iconUrl() {
|
|
886
|
-
return this.agentDefinition.icon_url;
|
|
887
|
-
}
|
|
888
|
-
/**
|
|
889
|
-
* Fetch messages for a thread (public method for useChat)
|
|
890
|
-
*/
|
|
891
|
-
async getThreadMessages(threadId) {
|
|
892
|
-
return this.client.getThreadMessages(threadId);
|
|
893
|
-
}
|
|
894
|
-
/**
|
|
895
|
-
* Direct (non-streaming) invoke
|
|
896
|
-
*/
|
|
897
|
-
async invoke(params) {
|
|
898
|
-
const enhancedParams = this.enhanceParamsWithTools(params);
|
|
899
|
-
console.log("enhancedParams", enhancedParams);
|
|
900
|
-
return await this.client.sendMessage(this.agentDefinition.id, enhancedParams);
|
|
901
|
-
}
|
|
902
|
-
/**
|
|
903
|
-
* Streaming invoke
|
|
904
|
-
*/
|
|
905
|
-
async invokeStream(params) {
|
|
906
|
-
const enhancedParams = this.enhanceParamsWithTools(params);
|
|
907
|
-
console.log("enhancedParams", enhancedParams);
|
|
908
|
-
const a2aStream = this.client.sendMessageStream(this.agentDefinition.id, enhancedParams);
|
|
909
|
-
return async function* () {
|
|
910
|
-
for await (const event of a2aStream) {
|
|
911
|
-
if (event.kind === "message") {
|
|
912
|
-
yield convertA2AMessageToDistri(event);
|
|
913
|
-
} else if (event.kind === "status-update") {
|
|
914
|
-
yield event;
|
|
915
|
-
} else if (event.kind === "artifact-update") {
|
|
916
|
-
yield event;
|
|
917
|
-
} else {
|
|
918
|
-
yield event;
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
}();
|
|
922
|
-
}
|
|
923
|
-
/**
|
|
924
|
-
* Enhance message params with tool definitions
|
|
925
|
-
*/
|
|
926
|
-
enhanceParamsWithTools(params) {
|
|
927
|
-
const tools = this.getTools();
|
|
928
|
-
return {
|
|
929
|
-
...params,
|
|
930
|
-
metadata: {
|
|
931
|
-
...params.metadata,
|
|
932
|
-
tools: tools.map((tool) => ({
|
|
933
|
-
name: tool.name,
|
|
934
|
-
description: tool.description,
|
|
935
|
-
input_schema: tool.input_schema
|
|
936
|
-
}))
|
|
937
|
-
}
|
|
938
|
-
};
|
|
939
|
-
}
|
|
940
|
-
/**
|
|
941
|
-
* Create an agent instance from an agent ID
|
|
942
|
-
*/
|
|
943
|
-
static async create(agentId, client) {
|
|
944
|
-
const agentDefinition = await client.getAgent(agentId);
|
|
945
|
-
return new _Agent(agentDefinition, client);
|
|
946
|
-
}
|
|
947
|
-
/**
|
|
948
|
-
* List all available agents
|
|
949
|
-
*/
|
|
950
|
-
static async list(client) {
|
|
951
|
-
const agentDefinitions = await client.getAgents();
|
|
952
|
-
return agentDefinitions.map((def) => new _Agent(def, client));
|
|
953
|
-
}
|
|
954
|
-
};
|
|
5
|
+
import { DistriClient } from "@distri/core";
|
|
955
6
|
|
|
956
7
|
// src/components/ThemeProvider.tsx
|
|
957
8
|
import { createContext, useContext, useEffect, useState } from "react";
|
|
@@ -1059,6 +110,9 @@ function useDistri() {
|
|
|
1059
110
|
|
|
1060
111
|
// src/useAgent.ts
|
|
1061
112
|
import React2, { useState as useState3, useCallback, useRef } from "react";
|
|
113
|
+
import {
|
|
114
|
+
Agent
|
|
115
|
+
} from "@distri/core";
|
|
1062
116
|
function useAgent({
|
|
1063
117
|
agentId,
|
|
1064
118
|
autoCreateAgent = true
|
|
@@ -1178,6 +232,63 @@ function useAgents() {
|
|
|
1178
232
|
|
|
1179
233
|
// src/useChat.ts
|
|
1180
234
|
import { useState as useState7, useCallback as useCallback4, useEffect as useEffect6, useRef as useRef3 } from "react";
|
|
235
|
+
import { DistriClient as DistriClient2 } from "@distri/core";
|
|
236
|
+
import {
|
|
237
|
+
convertDistriMessageToA2A
|
|
238
|
+
} from "@distri/core";
|
|
239
|
+
|
|
240
|
+
// ../core/src/encoder.ts
|
|
241
|
+
function convertA2AMessageToDistri(a2aMessage) {
|
|
242
|
+
const role = a2aMessage.role === "agent" ? "assistant" : "user";
|
|
243
|
+
return {
|
|
244
|
+
id: a2aMessage.messageId,
|
|
245
|
+
role,
|
|
246
|
+
parts: a2aMessage.parts.map(convertA2APartToDistri),
|
|
247
|
+
created_at: a2aMessage.createdAt
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function decodeA2AStreamEvent(event) {
|
|
251
|
+
if (event.kind === "message") {
|
|
252
|
+
return convertA2AMessageToDistri(event);
|
|
253
|
+
} else if (event.kind === "status-update") {
|
|
254
|
+
return event;
|
|
255
|
+
} else if (event.kind === "artifact-update") {
|
|
256
|
+
return event;
|
|
257
|
+
}
|
|
258
|
+
return event;
|
|
259
|
+
}
|
|
260
|
+
function convertA2APartToDistri(a2aPart) {
|
|
261
|
+
switch (a2aPart.kind) {
|
|
262
|
+
case "text":
|
|
263
|
+
return { type: "text", text: a2aPart.text };
|
|
264
|
+
case "file":
|
|
265
|
+
if ("uri" in a2aPart.file) {
|
|
266
|
+
return { type: "image_url", image: { mime_type: a2aPart.file.mimeType, url: a2aPart.file.uri } };
|
|
267
|
+
} else {
|
|
268
|
+
return { type: "image_bytes", image: { mime_type: a2aPart.file.mimeType, data: a2aPart.file.bytes } };
|
|
269
|
+
}
|
|
270
|
+
case "data":
|
|
271
|
+
switch (a2aPart.data.part_type) {
|
|
272
|
+
case "tool_call":
|
|
273
|
+
return { type: "tool_call", tool_call: a2aPart.data };
|
|
274
|
+
case "tool_result":
|
|
275
|
+
return { type: "tool_result", tool_result: a2aPart.data };
|
|
276
|
+
case "code_observation":
|
|
277
|
+
return { type: "code_observation", thought: a2aPart.data.thought, code: a2aPart.data.code };
|
|
278
|
+
case "plan":
|
|
279
|
+
return { type: "plan", plan: a2aPart.data.plan };
|
|
280
|
+
default:
|
|
281
|
+
return { type: "data", data: a2aPart.data };
|
|
282
|
+
}
|
|
283
|
+
default:
|
|
284
|
+
return { type: "text", text: JSON.stringify(a2aPart) };
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// ../core/src/types.ts
|
|
289
|
+
function isDistriMessage(event) {
|
|
290
|
+
return "id" in event && "role" in event && "parts" in event;
|
|
291
|
+
}
|
|
1181
292
|
|
|
1182
293
|
// src/hooks/registerTools.tsx
|
|
1183
294
|
import { useEffect as useEffect5, useRef as useRef2 } from "react";
|
|
@@ -1528,7 +639,7 @@ function useChat({
|
|
|
1528
639
|
threadId,
|
|
1529
640
|
onMessage,
|
|
1530
641
|
onError,
|
|
1531
|
-
|
|
642
|
+
getMetadata,
|
|
1532
643
|
onMessagesUpdate,
|
|
1533
644
|
agent,
|
|
1534
645
|
tools
|
|
@@ -1541,8 +652,8 @@ function useChat({
|
|
|
1541
652
|
const createInvokeContext = useCallback4(() => ({
|
|
1542
653
|
thread_id: threadId,
|
|
1543
654
|
run_id: void 0,
|
|
1544
|
-
|
|
1545
|
-
}), [threadId,
|
|
655
|
+
getMetadata
|
|
656
|
+
}), [threadId, getMetadata]);
|
|
1546
657
|
registerTools({ agent, tools });
|
|
1547
658
|
const toolStateHandler = useToolCallState({
|
|
1548
659
|
agent,
|
|
@@ -1647,13 +758,14 @@ function useChat({
|
|
|
1647
758
|
abortControllerRef.current = new AbortController();
|
|
1648
759
|
try {
|
|
1649
760
|
const parts = typeof content === "string" ? [{ type: "text", text: content }] : content;
|
|
1650
|
-
const distriMessage =
|
|
761
|
+
const distriMessage = DistriClient2.initDistriMessage("user", parts);
|
|
1651
762
|
const context = createInvokeContext();
|
|
1652
763
|
const a2aMessage = convertDistriMessageToA2A(distriMessage, context);
|
|
1653
764
|
setMessages((prev) => [...prev, distriMessage]);
|
|
765
|
+
const contextMetadata = await getMetadata?.() || {};
|
|
1654
766
|
const stream = await agent.invokeStream({
|
|
1655
767
|
message: a2aMessage,
|
|
1656
|
-
metadata:
|
|
768
|
+
metadata: contextMetadata
|
|
1657
769
|
});
|
|
1658
770
|
for await (const event of stream) {
|
|
1659
771
|
if (abortControllerRef.current?.signal.aborted) {
|
|
@@ -1685,13 +797,14 @@ function useChat({
|
|
|
1685
797
|
abortControllerRef.current = new AbortController();
|
|
1686
798
|
try {
|
|
1687
799
|
const parts = typeof content === "string" ? [{ type: "text", text: content }] : content;
|
|
1688
|
-
const distriMessage =
|
|
800
|
+
const distriMessage = DistriClient2.initDistriMessage(role, parts);
|
|
1689
801
|
const context = createInvokeContext();
|
|
1690
802
|
const a2aMessage = convertDistriMessageToA2A(distriMessage, context);
|
|
1691
803
|
setMessages((prev) => [...prev, distriMessage]);
|
|
804
|
+
const contextMetadata = await getMetadata?.() || {};
|
|
1692
805
|
const stream = await agent.invokeStream({
|
|
1693
806
|
message: a2aMessage,
|
|
1694
|
-
metadata:
|
|
807
|
+
metadata: { ...contextMetadata }
|
|
1695
808
|
});
|
|
1696
809
|
for await (const event of stream) {
|
|
1697
810
|
if (abortControllerRef.current?.signal.aborted) {
|
|
@@ -1757,6 +870,9 @@ function useThreads() {
|
|
|
1757
870
|
const [error, setError] = useState8(null);
|
|
1758
871
|
const fetchThreads = useCallback5(async () => {
|
|
1759
872
|
if (!client) {
|
|
873
|
+
console.error("[useThreads] Client not available");
|
|
874
|
+
setError(new Error("Client not available"));
|
|
875
|
+
setLoading(false);
|
|
1760
876
|
return;
|
|
1761
877
|
}
|
|
1762
878
|
try {
|
|
@@ -1788,7 +904,7 @@ function useThreads() {
|
|
|
1788
904
|
throw new Error("Client not available");
|
|
1789
905
|
}
|
|
1790
906
|
try {
|
|
1791
|
-
const response = await fetch(`${client.baseUrl}/
|
|
907
|
+
const response = await fetch(`${client.baseUrl}/threads/${threadId}`, {
|
|
1792
908
|
method: "DELETE"
|
|
1793
909
|
});
|
|
1794
910
|
if (!response.ok) {
|
|
@@ -1805,7 +921,7 @@ function useThreads() {
|
|
|
1805
921
|
return;
|
|
1806
922
|
}
|
|
1807
923
|
try {
|
|
1808
|
-
const response = await fetch(`${client.baseUrl}/
|
|
924
|
+
const response = await fetch(`${client.baseUrl}/threads/${threadId}`);
|
|
1809
925
|
if (response.ok) {
|
|
1810
926
|
const updatedThread = await response.json();
|
|
1811
927
|
setThreads((prev) => {
|
|
@@ -1864,6 +980,7 @@ import { useState as useState13, useCallback as useCallback8, useEffect as useEf
|
|
|
1864
980
|
// src/components/EmbeddableChat.tsx
|
|
1865
981
|
import { useState as useState10, useRef as useRef5, useEffect as useEffect9, useMemo as useMemo2 } from "react";
|
|
1866
982
|
import { MessageSquare } from "lucide-react";
|
|
983
|
+
import { isDistriMessage as isDistriMessage4 } from "@distri/core";
|
|
1867
984
|
|
|
1868
985
|
// src/components/Components.tsx
|
|
1869
986
|
import React8, { useState as useState9 } from "react";
|
|
@@ -1901,6 +1018,7 @@ var useChatConfig = () => {
|
|
|
1901
1018
|
};
|
|
1902
1019
|
|
|
1903
1020
|
// src/components/MessageRenderer.tsx
|
|
1021
|
+
import { isDistriMessage as isDistriMessage2 } from "@distri/core";
|
|
1904
1022
|
import { jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1905
1023
|
var CodeBlock = ({ language, children, inline = false }) => {
|
|
1906
1024
|
const [copied, setCopied] = React7.useState(false);
|
|
@@ -2119,7 +1237,7 @@ var MessageRenderer = ({
|
|
|
2119
1237
|
theme: "chatgpt"
|
|
2120
1238
|
};
|
|
2121
1239
|
}
|
|
2122
|
-
if (message &&
|
|
1240
|
+
if (message && isDistriMessage2(message)) {
|
|
2123
1241
|
const hasToolCalls = message.parts.some((part) => part.type === "tool_call");
|
|
2124
1242
|
const filteredParts = hasToolCalls ? message.parts.filter((part) => part.type !== "tool_result") : message.parts;
|
|
2125
1243
|
const groupedParts = [];
|
|
@@ -2528,8 +1646,9 @@ var DebugMessage = ({
|
|
|
2528
1646
|
};
|
|
2529
1647
|
|
|
2530
1648
|
// src/utils/messageUtils.ts
|
|
1649
|
+
import { isDistriMessage as isDistriMessage3 } from "@distri/core";
|
|
2531
1650
|
var extractTextFromMessage = (message) => {
|
|
2532
|
-
if (
|
|
1651
|
+
if (isDistriMessage3(message)) {
|
|
2533
1652
|
if (!message?.parts || !Array.isArray(message.parts)) {
|
|
2534
1653
|
return "";
|
|
2535
1654
|
}
|
|
@@ -2541,7 +1660,7 @@ var extractTextFromMessage = (message) => {
|
|
|
2541
1660
|
};
|
|
2542
1661
|
var shouldDisplayMessage = (message, showDebugMessages = false) => {
|
|
2543
1662
|
if (!message) return false;
|
|
2544
|
-
if (
|
|
1663
|
+
if (isDistriMessage3(message)) {
|
|
2545
1664
|
if (message.role === "user") {
|
|
2546
1665
|
const textContent2 = extractTextFromMessage(message);
|
|
2547
1666
|
return textContent2.trim().length > 0;
|
|
@@ -2561,7 +1680,6 @@ import * as SelectPrimitive from "@radix-ui/react-select";
|
|
|
2561
1680
|
import { Check as Check2, ChevronDown as ChevronDown2, ChevronUp } from "lucide-react";
|
|
2562
1681
|
import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2563
1682
|
var Select = SelectPrimitive.Root;
|
|
2564
|
-
var SelectGroup = SelectPrimitive.Group;
|
|
2565
1683
|
var SelectValue = SelectPrimitive.Value;
|
|
2566
1684
|
var SelectTrigger = React9.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs4(
|
|
2567
1685
|
SelectPrimitive.Trigger,
|
|
@@ -2785,6 +1903,20 @@ var ChatInput = ({
|
|
|
2785
1903
|
] }) }) });
|
|
2786
1904
|
};
|
|
2787
1905
|
|
|
1906
|
+
// ../core/src/distri-client.ts
|
|
1907
|
+
function uuidv4() {
|
|
1908
|
+
if (typeof crypto?.randomUUID === "function") {
|
|
1909
|
+
return crypto.randomUUID();
|
|
1910
|
+
}
|
|
1911
|
+
const array = new Uint8Array(16);
|
|
1912
|
+
crypto.getRandomValues(array);
|
|
1913
|
+
array[6] = array[6] & 15 | 64;
|
|
1914
|
+
array[8] = array[8] & 63 | 128;
|
|
1915
|
+
return [...array].map(
|
|
1916
|
+
(b, i) => ([4, 6, 8, 10].includes(i) ? "-" : "") + b.toString(16).padStart(2, "0")
|
|
1917
|
+
).join("");
|
|
1918
|
+
}
|
|
1919
|
+
|
|
2788
1920
|
// src/components/EmbeddableChat.tsx
|
|
2789
1921
|
import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2790
1922
|
var EmbeddableChat = ({
|
|
@@ -2792,7 +1924,7 @@ var EmbeddableChat = ({
|
|
|
2792
1924
|
agent,
|
|
2793
1925
|
className = "",
|
|
2794
1926
|
style = {},
|
|
2795
|
-
|
|
1927
|
+
getMetadata,
|
|
2796
1928
|
tools,
|
|
2797
1929
|
availableAgents = [],
|
|
2798
1930
|
UserMessageComponent = UserMessage,
|
|
@@ -2822,7 +1954,7 @@ var EmbeddableChat = ({
|
|
|
2822
1954
|
threadId,
|
|
2823
1955
|
agent: agent || void 0,
|
|
2824
1956
|
tools,
|
|
2825
|
-
|
|
1957
|
+
getMetadata,
|
|
2826
1958
|
onMessagesUpdate
|
|
2827
1959
|
});
|
|
2828
1960
|
useEffect9(() => {
|
|
@@ -2855,7 +1987,7 @@ var EmbeddableChat = ({
|
|
|
2855
1987
|
const messageContent = extractTextFromMessage(message);
|
|
2856
1988
|
const key = `message-${index}`;
|
|
2857
1989
|
const timestamp = message.created_at ? new Date(message.created_at) : void 0;
|
|
2858
|
-
if (
|
|
1990
|
+
if (isDistriMessage4(message)) {
|
|
2859
1991
|
switch (getMessageType(message)) {
|
|
2860
1992
|
case "user":
|
|
2861
1993
|
return /* @__PURE__ */ jsx14(
|
|
@@ -3892,17 +3024,11 @@ var badgeVariants = cva3(
|
|
|
3892
3024
|
}
|
|
3893
3025
|
}
|
|
3894
3026
|
);
|
|
3895
|
-
function Badge({ className, variant, ...props }) {
|
|
3896
|
-
return /* @__PURE__ */ jsx24("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
3897
|
-
}
|
|
3898
3027
|
|
|
3899
3028
|
// src/components/ui/dialog.tsx
|
|
3900
3029
|
import * as React19 from "react";
|
|
3901
3030
|
import { jsx as jsx25, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3902
3031
|
var Dialog = React19.createContext({});
|
|
3903
|
-
var DialogRoot = ({ open, onOpenChange, children }) => {
|
|
3904
|
-
return /* @__PURE__ */ jsx25(Dialog.Provider, { value: { open, onOpenChange }, children });
|
|
3905
|
-
};
|
|
3906
3032
|
var DialogTrigger = React19.forwardRef(({ className, children, ...props }, ref) => {
|
|
3907
3033
|
const context = React19.useContext(Dialog);
|
|
3908
3034
|
return /* @__PURE__ */ jsx25(
|
|
@@ -4342,7 +3468,7 @@ function AppSidebar({
|
|
|
4342
3468
|
import { jsx as jsx29, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4343
3469
|
var FullChat = ({
|
|
4344
3470
|
agentId: initialAgentId,
|
|
4345
|
-
|
|
3471
|
+
getMetadata,
|
|
4346
3472
|
className = "",
|
|
4347
3473
|
UserMessageComponent,
|
|
4348
3474
|
AssistantMessageComponent,
|
|
@@ -4366,7 +3492,8 @@ var FullChat = ({
|
|
|
4366
3492
|
const currentThread = threads.find((t) => t.id === selectedThreadId);
|
|
4367
3493
|
const { messages } = useChat({
|
|
4368
3494
|
threadId: selectedThreadId,
|
|
4369
|
-
agent: agent || void 0
|
|
3495
|
+
agent: agent || void 0,
|
|
3496
|
+
getMetadata
|
|
4370
3497
|
});
|
|
4371
3498
|
const threadHasStarted = messages.length > 0;
|
|
4372
3499
|
useEffect11(() => {
|
|
@@ -4433,7 +3560,7 @@ var FullChat = ({
|
|
|
4433
3560
|
threadId: selectedThreadId,
|
|
4434
3561
|
showAgentSelector: false,
|
|
4435
3562
|
agent,
|
|
4436
|
-
|
|
3563
|
+
getMetadata,
|
|
4437
3564
|
height: "calc(100vh - 4rem)",
|
|
4438
3565
|
availableAgents,
|
|
4439
3566
|
UserMessageComponent,
|
|
@@ -4521,76 +3648,16 @@ export {
|
|
|
4521
3648
|
ApprovalToolCall,
|
|
4522
3649
|
AssistantMessage,
|
|
4523
3650
|
AssistantWithToolCalls,
|
|
4524
|
-
Badge,
|
|
4525
|
-
Button,
|
|
4526
|
-
Card,
|
|
4527
|
-
CardContent,
|
|
4528
|
-
CardDescription,
|
|
4529
|
-
CardFooter,
|
|
4530
|
-
CardHeader,
|
|
4531
|
-
CardTitle,
|
|
4532
3651
|
ChatInput,
|
|
4533
3652
|
DebugMessage,
|
|
4534
|
-
DialogRoot as Dialog,
|
|
4535
|
-
DialogContent,
|
|
4536
|
-
DialogHeader,
|
|
4537
|
-
DialogTitle,
|
|
4538
|
-
DialogTrigger,
|
|
4539
3653
|
DistriProvider,
|
|
4540
3654
|
EmbeddableChat,
|
|
4541
3655
|
FullChat_default as FullChat,
|
|
4542
|
-
Input,
|
|
4543
3656
|
PlanMessage,
|
|
4544
|
-
Select,
|
|
4545
|
-
SelectContent,
|
|
4546
|
-
SelectGroup,
|
|
4547
|
-
SelectItem,
|
|
4548
|
-
SelectLabel,
|
|
4549
|
-
SelectScrollDownButton,
|
|
4550
|
-
SelectScrollUpButton,
|
|
4551
|
-
SelectSeparator,
|
|
4552
|
-
SelectTrigger,
|
|
4553
|
-
SelectValue,
|
|
4554
|
-
Separator2 as Separator,
|
|
4555
|
-
Sheet,
|
|
4556
|
-
SheetContent,
|
|
4557
|
-
SheetDescription,
|
|
4558
|
-
SheetFooter,
|
|
4559
|
-
SheetHeader,
|
|
4560
|
-
SheetTitle,
|
|
4561
|
-
Sidebar,
|
|
4562
|
-
SidebarContent,
|
|
4563
|
-
SidebarFooter,
|
|
4564
|
-
SidebarGroup,
|
|
4565
|
-
SidebarGroupAction,
|
|
4566
|
-
SidebarGroupContent,
|
|
4567
|
-
SidebarGroupLabel,
|
|
4568
|
-
SidebarHeader,
|
|
4569
|
-
SidebarInset,
|
|
4570
|
-
SidebarMenu,
|
|
4571
|
-
SidebarMenuAction,
|
|
4572
|
-
SidebarMenuBadge,
|
|
4573
|
-
SidebarMenuButton,
|
|
4574
|
-
SidebarMenuItem,
|
|
4575
|
-
SidebarMenuSkeleton,
|
|
4576
|
-
SidebarMenuSub,
|
|
4577
|
-
SidebarMenuSubButton,
|
|
4578
|
-
SidebarMenuSubItem,
|
|
4579
|
-
SidebarProvider,
|
|
4580
|
-
SidebarRail,
|
|
4581
|
-
SidebarSeparator,
|
|
4582
|
-
SidebarTrigger,
|
|
4583
|
-
Skeleton,
|
|
4584
|
-
Textarea,
|
|
4585
3657
|
ThemeProvider,
|
|
4586
3658
|
ThemeToggle,
|
|
4587
3659
|
ToastToolCall,
|
|
4588
|
-
Tooltip,
|
|
4589
|
-
TooltipContent,
|
|
4590
|
-
TooltipProvider,
|
|
4591
|
-
TooltipTrigger,
|
|
4592
3660
|
UserMessage,
|
|
4593
|
-
cn,
|
|
4594
3661
|
extractTextFromMessage,
|
|
4595
3662
|
registerTools,
|
|
4596
3663
|
shouldDisplayMessage,
|
|
@@ -4598,7 +3665,6 @@ export {
|
|
|
4598
3665
|
useAgents,
|
|
4599
3666
|
useChat,
|
|
4600
3667
|
useDistri,
|
|
4601
|
-
useSidebar,
|
|
4602
3668
|
useTheme,
|
|
4603
3669
|
useThreads,
|
|
4604
3670
|
useToolCallState
|