@antipopp/agno-react 0.1.0 → 0.3.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/dist/index.mjs CHANGED
@@ -20,35 +20,687 @@ function useAgnoClient() {
20
20
  return client;
21
21
  }
22
22
 
23
+ // src/context/ToolHandlerContext.tsx
24
+ import { createContext as createContext2, useContext as useContext2, useState, useCallback } from "react";
25
+ import { jsx as jsx2 } from "react/jsx-runtime";
26
+ var ToolHandlerContext = createContext2(null);
27
+ function ToolHandlerProvider({ handlers: initialHandlers = {}, children }) {
28
+ const [handlers, setHandlers] = useState(initialHandlers);
29
+ const registerHandler = useCallback((name, handler) => {
30
+ setHandlers((prev) => ({ ...prev, [name]: handler }));
31
+ }, []);
32
+ const unregisterHandler = useCallback((name) => {
33
+ setHandlers((prev) => {
34
+ const { [name]: _, ...rest } = prev;
35
+ return rest;
36
+ });
37
+ }, []);
38
+ const value = {
39
+ handlers,
40
+ registerHandler,
41
+ unregisterHandler
42
+ };
43
+ return /* @__PURE__ */ jsx2(ToolHandlerContext.Provider, { value, children });
44
+ }
45
+ function useToolHandlers() {
46
+ return useContext2(ToolHandlerContext);
47
+ }
48
+
49
+ // src/components/GenerativeUIRenderer.tsx
50
+ import React3 from "react";
51
+
52
+ // src/utils/component-registry.ts
53
+ var ComponentRegistry = class _ComponentRegistry {
54
+ constructor() {
55
+ this.components = /* @__PURE__ */ new Map();
56
+ }
57
+ /**
58
+ * Get the singleton instance
59
+ */
60
+ static getInstance() {
61
+ if (!_ComponentRegistry.instance) {
62
+ _ComponentRegistry.instance = new _ComponentRegistry();
63
+ }
64
+ return _ComponentRegistry.instance;
65
+ }
66
+ /**
67
+ * Register a component renderer
68
+ */
69
+ register(type, renderer) {
70
+ this.components.set(type, renderer);
71
+ }
72
+ /**
73
+ * Register multiple components at once
74
+ */
75
+ registerBatch(components) {
76
+ Object.entries(components).forEach(([type, renderer]) => {
77
+ this.register(type, renderer);
78
+ });
79
+ }
80
+ /**
81
+ * Get a registered component renderer
82
+ */
83
+ get(type) {
84
+ return this.components.get(type);
85
+ }
86
+ /**
87
+ * Check if a component is registered
88
+ */
89
+ has(type) {
90
+ return this.components.has(type);
91
+ }
92
+ /**
93
+ * Unregister a component
94
+ */
95
+ unregister(type) {
96
+ this.components.delete(type);
97
+ }
98
+ /**
99
+ * Get all registered component types
100
+ */
101
+ getRegisteredTypes() {
102
+ return Array.from(this.components.keys());
103
+ }
104
+ /**
105
+ * Clear all registered components
106
+ */
107
+ clear() {
108
+ this.components.clear();
109
+ }
110
+ };
111
+ function getComponentRegistry() {
112
+ return ComponentRegistry.getInstance();
113
+ }
114
+ function registerChartComponent(name, renderer) {
115
+ getComponentRegistry().register(`chart:${name}`, renderer);
116
+ }
117
+ function getChartComponent(name) {
118
+ return getComponentRegistry().get(`chart:${name}`);
119
+ }
120
+
121
+ // src/hooks/useAgnoToolExecution.ts
122
+ import { useState as useState2, useEffect as useEffect2, useCallback as useCallback2, useMemo as useMemo2 } from "react";
123
+ var customRenderRegistry = /* @__PURE__ */ new Map();
124
+ function registerCustomRender(renderFn) {
125
+ const key = `custom-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
126
+ customRenderRegistry.set(key, renderFn);
127
+ return key;
128
+ }
129
+ function getCustomRender(key) {
130
+ return customRenderRegistry.get(key);
131
+ }
132
+ function isToolHandlerResult(value) {
133
+ return value && typeof value === "object" && ("data" in value || "ui" in value);
134
+ }
135
+ function isUIComponentSpec(value) {
136
+ return value && typeof value === "object" && "type" in value;
137
+ }
138
+ function processToolResult(result, _tool) {
139
+ if (isToolHandlerResult(result)) {
140
+ const { data, ui } = result;
141
+ let uiComponent = void 0;
142
+ if (ui) {
143
+ if (ui.type === "custom" && typeof ui.render === "function") {
144
+ const renderKey = registerCustomRender(ui.render);
145
+ uiComponent = {
146
+ ...ui,
147
+ renderKey,
148
+ render: void 0
149
+ // Don't store the function itself
150
+ };
151
+ } else {
152
+ uiComponent = ui;
153
+ }
154
+ }
155
+ return {
156
+ resultData: typeof data === "string" ? data : JSON.stringify(data),
157
+ uiComponent
158
+ };
159
+ }
160
+ if (isUIComponentSpec(result)) {
161
+ let uiComponent;
162
+ if (result.type === "custom" && typeof result.render === "function") {
163
+ const renderKey = registerCustomRender(result.render);
164
+ uiComponent = {
165
+ ...result,
166
+ renderKey,
167
+ render: void 0
168
+ };
169
+ } else {
170
+ uiComponent = result;
171
+ }
172
+ return {
173
+ resultData: JSON.stringify(result),
174
+ uiComponent
175
+ };
176
+ }
177
+ return {
178
+ resultData: typeof result === "string" ? result : JSON.stringify(result),
179
+ uiComponent: void 0
180
+ };
181
+ }
182
+ function useAgnoToolExecution(handlers = {}, autoExecute = true) {
183
+ const client = useAgnoClient();
184
+ const toolHandlerContext = useToolHandlers();
185
+ const mergedHandlers = useMemo2(() => {
186
+ const globalHandlers = toolHandlerContext?.handlers || {};
187
+ return { ...globalHandlers, ...handlers };
188
+ }, [toolHandlerContext?.handlers, handlers]);
189
+ const [pendingTools, setPendingTools] = useState2([]);
190
+ const [isPaused, setIsPaused] = useState2(false);
191
+ const [isExecuting, setIsExecuting] = useState2(false);
192
+ const [executionError, setExecutionError] = useState2();
193
+ useEffect2(() => {
194
+ const handleRunPaused = (event) => {
195
+ setIsPaused(true);
196
+ setPendingTools(event.tools);
197
+ setExecutionError(void 0);
198
+ };
199
+ const handleRunContinued = () => {
200
+ setIsPaused(false);
201
+ setPendingTools([]);
202
+ setIsExecuting(false);
203
+ setExecutionError(void 0);
204
+ };
205
+ client.on("run:paused", handleRunPaused);
206
+ client.on("run:continued", handleRunContinued);
207
+ return () => {
208
+ client.off("run:paused", handleRunPaused);
209
+ client.off("run:continued", handleRunContinued);
210
+ };
211
+ }, [client]);
212
+ const executeAndContinue = useCallback2(async () => {
213
+ if (!isPaused || pendingTools.length === 0) {
214
+ console.warn("[useAgnoToolExecution] Cannot execute: no pending tools");
215
+ return;
216
+ }
217
+ setIsExecuting(true);
218
+ setExecutionError(void 0);
219
+ try {
220
+ const updatedTools = await Promise.all(
221
+ pendingTools.map(async (tool) => {
222
+ const handler = mergedHandlers[tool.tool_name];
223
+ if (!handler) {
224
+ return {
225
+ ...tool,
226
+ result: JSON.stringify({
227
+ error: `No handler registered for ${tool.tool_name}`
228
+ })
229
+ };
230
+ }
231
+ try {
232
+ const result = await handler(tool.tool_args);
233
+ const { resultData, uiComponent } = processToolResult(result, tool);
234
+ return {
235
+ ...tool,
236
+ result: resultData,
237
+ ui_component: uiComponent
238
+ };
239
+ } catch (error) {
240
+ return {
241
+ ...tool,
242
+ result: JSON.stringify({
243
+ error: error instanceof Error ? error.message : String(error)
244
+ })
245
+ };
246
+ }
247
+ })
248
+ );
249
+ const toolsWithUI = updatedTools.filter((t) => t.ui_component);
250
+ if (toolsWithUI.length > 0) {
251
+ client.emit("ui:render", {
252
+ tools: updatedTools,
253
+ runId: client.getState().pausedRunId
254
+ });
255
+ }
256
+ client.addToolCallsToLastMessage(updatedTools);
257
+ await client.continueRun(updatedTools);
258
+ } catch (error) {
259
+ const errorMessage = error instanceof Error ? error.message : String(error);
260
+ setExecutionError(errorMessage);
261
+ setIsExecuting(false);
262
+ throw error;
263
+ }
264
+ }, [client, mergedHandlers, isPaused, pendingTools]);
265
+ useEffect2(() => {
266
+ const handleSessionLoaded = async (_sessionId) => {
267
+ const messages = client.getMessages();
268
+ for (const message of messages) {
269
+ if (!message.tool_calls)
270
+ continue;
271
+ for (const tool of message.tool_calls) {
272
+ if (tool.ui_component)
273
+ continue;
274
+ const handler = mergedHandlers[tool.tool_name];
275
+ if (!handler)
276
+ continue;
277
+ try {
278
+ const result = await handler(tool.tool_args);
279
+ const { uiComponent } = processToolResult(result, tool);
280
+ if (uiComponent) {
281
+ client.hydrateToolCallUI(tool.tool_call_id, uiComponent);
282
+ }
283
+ } catch (err) {
284
+ console.error(`Failed to hydrate UI for ${tool.tool_name}:`, err);
285
+ }
286
+ }
287
+ }
288
+ };
289
+ client.on("session:loaded", handleSessionLoaded);
290
+ return () => {
291
+ client.off("session:loaded", handleSessionLoaded);
292
+ };
293
+ }, [client, mergedHandlers]);
294
+ const executeTools = useCallback2(
295
+ async (tools) => {
296
+ return Promise.all(
297
+ tools.map(async (tool) => {
298
+ const handler = mergedHandlers[tool.tool_name];
299
+ if (!handler)
300
+ return tool;
301
+ try {
302
+ const result = await handler(tool.tool_args);
303
+ const { resultData, uiComponent } = processToolResult(result, tool);
304
+ return {
305
+ ...tool,
306
+ result: resultData,
307
+ ui_component: uiComponent
308
+ };
309
+ } catch (error) {
310
+ return {
311
+ ...tool,
312
+ result: JSON.stringify({
313
+ error: error instanceof Error ? error.message : String(error)
314
+ })
315
+ };
316
+ }
317
+ })
318
+ );
319
+ },
320
+ [mergedHandlers]
321
+ );
322
+ const continueWithResults = useCallback2(
323
+ async (tools) => {
324
+ if (!isPaused) {
325
+ throw new Error("No paused run to continue");
326
+ }
327
+ setIsExecuting(true);
328
+ try {
329
+ await client.continueRun(tools);
330
+ } catch (error) {
331
+ setIsExecuting(false);
332
+ throw error;
333
+ }
334
+ },
335
+ [client, isPaused]
336
+ );
337
+ useEffect2(() => {
338
+ if (autoExecute && isPaused && !isExecuting && pendingTools.length > 0) {
339
+ executeAndContinue();
340
+ }
341
+ }, [autoExecute, isPaused, isExecuting, pendingTools.length, executeAndContinue]);
342
+ return {
343
+ /** Whether the run is currently paused awaiting tool execution */
344
+ isPaused,
345
+ /** Whether tools are currently being executed */
346
+ isExecuting,
347
+ /** Tools awaiting execution */
348
+ pendingTools,
349
+ /** Execute all pending tools and continue the run */
350
+ executeAndContinue,
351
+ /** Execute specific tools and return results without continuing */
352
+ executeTools,
353
+ /** Continue the run with manually provided tool results */
354
+ continueWithResults,
355
+ /** Error from tool execution, if any */
356
+ executionError
357
+ };
358
+ }
359
+
360
+ // src/components/GenerativeUIRenderer.tsx
361
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
362
+ var UIErrorBoundary = class extends React3.Component {
363
+ constructor(props) {
364
+ super(props);
365
+ this.state = { hasError: false };
366
+ }
367
+ static getDerivedStateFromError(error) {
368
+ return { hasError: true, error };
369
+ }
370
+ componentDidCatch(error, errorInfo) {
371
+ console.error("[GenerativeUIRenderer] Error rendering component:", error, errorInfo);
372
+ this.props.onError?.(error);
373
+ }
374
+ render() {
375
+ if (this.state.hasError) {
376
+ return this.props.fallback || /* @__PURE__ */ jsxs("div", { className: "p-4 border border-red-300 rounded-md bg-red-50 text-red-800", children: [
377
+ /* @__PURE__ */ jsx3("p", { className: "font-semibold", children: "Failed to render UI component" }),
378
+ /* @__PURE__ */ jsx3("p", { className: "text-sm mt-1", children: this.state.error?.message || "Unknown error" })
379
+ ] });
380
+ }
381
+ return this.props.children;
382
+ }
383
+ };
384
+ function GenerativeUIRenderer({
385
+ spec,
386
+ className,
387
+ onError
388
+ }) {
389
+ const registry = getComponentRegistry();
390
+ if (spec.type === "custom") {
391
+ const customSpec = spec;
392
+ if (customSpec.renderKey) {
393
+ const renderFn = getCustomRender(customSpec.renderKey);
394
+ if (renderFn) {
395
+ return /* @__PURE__ */ jsx3(UIErrorBoundary, { onError, children: /* @__PURE__ */ jsx3("div", { className, children: renderFn(customSpec.props || {}) }) });
396
+ }
397
+ }
398
+ return /* @__PURE__ */ jsxs("div", { className: `p-4 border border-yellow-300 rounded-md bg-yellow-50 text-yellow-800 ${className || ""}`, children: [
399
+ /* @__PURE__ */ jsx3("p", { className: "font-semibold", children: "Custom component not available" }),
400
+ /* @__PURE__ */ jsx3("p", { className: "text-sm mt-1", children: "The custom render function for this component is not available." })
401
+ ] });
402
+ }
403
+ if (spec.type === "chart") {
404
+ const chartSpec = spec;
405
+ const chartType = `chart:${chartSpec.component}`;
406
+ if (registry.has(chartType)) {
407
+ const ChartRenderer = registry.get(chartType);
408
+ return /* @__PURE__ */ jsx3(UIErrorBoundary, { onError, children: /* @__PURE__ */ jsxs("div", { className, children: [
409
+ chartSpec.title && /* @__PURE__ */ jsx3("h3", { className: "font-semibold mb-2", children: chartSpec.title }),
410
+ chartSpec.description && /* @__PURE__ */ jsx3("p", { className: "text-sm text-gray-600 mb-4", children: chartSpec.description }),
411
+ /* @__PURE__ */ jsx3(ChartRenderer, { ...chartSpec.props })
412
+ ] }) });
413
+ }
414
+ return /* @__PURE__ */ jsxs("div", { className: `p-4 border border-gray-300 rounded-md ${className || ""}`, children: [
415
+ /* @__PURE__ */ jsx3("p", { className: "font-semibold mb-2", children: chartSpec.title || "Chart Data" }),
416
+ chartSpec.description && /* @__PURE__ */ jsx3("p", { className: "text-sm text-gray-600 mb-2", children: chartSpec.description }),
417
+ /* @__PURE__ */ jsx3("pre", { className: "text-xs bg-gray-100 p-2 rounded overflow-auto", children: JSON.stringify(chartSpec.props.data, null, 2) })
418
+ ] });
419
+ }
420
+ if (spec.type === "card-grid") {
421
+ const cardGridSpec = spec;
422
+ if (registry.has("card-grid")) {
423
+ const CardGridRenderer = registry.get("card-grid");
424
+ return /* @__PURE__ */ jsx3(UIErrorBoundary, { onError, children: /* @__PURE__ */ jsxs("div", { className, children: [
425
+ cardGridSpec.title && /* @__PURE__ */ jsx3("h3", { className: "font-semibold mb-2", children: cardGridSpec.title }),
426
+ cardGridSpec.description && /* @__PURE__ */ jsx3("p", { className: "text-sm text-gray-600 mb-4", children: cardGridSpec.description }),
427
+ /* @__PURE__ */ jsx3(CardGridRenderer, { ...cardGridSpec.props })
428
+ ] }) });
429
+ }
430
+ }
431
+ if (spec.type === "table") {
432
+ const tableSpec = spec;
433
+ if (registry.has("table")) {
434
+ const TableRenderer = registry.get("table");
435
+ return /* @__PURE__ */ jsx3(UIErrorBoundary, { onError, children: /* @__PURE__ */ jsxs("div", { className, children: [
436
+ tableSpec.title && /* @__PURE__ */ jsx3("h3", { className: "font-semibold mb-2", children: tableSpec.title }),
437
+ tableSpec.description && /* @__PURE__ */ jsx3("p", { className: "text-sm text-gray-600 mb-4", children: tableSpec.description }),
438
+ /* @__PURE__ */ jsx3(TableRenderer, { ...tableSpec.props })
439
+ ] }) });
440
+ }
441
+ }
442
+ if (spec.type === "markdown") {
443
+ const markdownSpec = spec;
444
+ if (registry.has("markdown")) {
445
+ const MarkdownRenderer = registry.get("markdown");
446
+ return /* @__PURE__ */ jsx3(UIErrorBoundary, { onError, children: /* @__PURE__ */ jsx3("div", { className, children: /* @__PURE__ */ jsx3(MarkdownRenderer, { ...markdownSpec.props }) }) });
447
+ }
448
+ return /* @__PURE__ */ jsx3("div", { className, children: markdownSpec.props.content });
449
+ }
450
+ if (spec.type === "artifact") {
451
+ const artifactSpec = spec;
452
+ return /* @__PURE__ */ jsx3(UIErrorBoundary, { onError, children: /* @__PURE__ */ jsxs("div", { className: `p-4 border rounded-md ${className || ""}`, children: [
453
+ artifactSpec.title && /* @__PURE__ */ jsx3("h3", { className: "font-semibold mb-4", children: artifactSpec.title }),
454
+ artifactSpec.description && /* @__PURE__ */ jsx3("p", { className: "text-sm text-gray-600 mb-4", children: artifactSpec.description }),
455
+ /* @__PURE__ */ jsx3("div", { className: "space-y-4", children: artifactSpec.props.content?.map((childSpec, index) => /* @__PURE__ */ jsx3(GenerativeUIRenderer, { spec: childSpec, onError }, index)) })
456
+ ] }) });
457
+ }
458
+ return /* @__PURE__ */ jsxs("div", { className: `p-4 border border-gray-300 rounded-md ${className || ""}`, children: [
459
+ /* @__PURE__ */ jsx3("p", { className: "font-semibold", children: "Unsupported UI component" }),
460
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-600 mt-1", children: [
461
+ "Component type: ",
462
+ spec.type
463
+ ] })
464
+ ] });
465
+ }
466
+
467
+ // src/utils/ui-helpers.ts
468
+ function createBarChart(data, xKey, bars, options) {
469
+ return {
470
+ type: "chart",
471
+ component: "BarChart",
472
+ layout: options?.layout,
473
+ title: options?.title,
474
+ description: options?.description,
475
+ props: {
476
+ data,
477
+ xKey,
478
+ bars: bars.map((bar) => ({
479
+ key: bar.key,
480
+ label: bar.label || bar.key,
481
+ color: bar.color
482
+ })),
483
+ showLegend: options?.showLegend ?? true,
484
+ showGrid: options?.showGrid ?? true,
485
+ height: options?.height,
486
+ width: options?.width
487
+ }
488
+ };
489
+ }
490
+ function createLineChart(data, xKey, lines, options) {
491
+ return {
492
+ type: "chart",
493
+ component: "LineChart",
494
+ layout: options?.layout,
495
+ title: options?.title,
496
+ description: options?.description,
497
+ props: {
498
+ data,
499
+ xKey,
500
+ lines: lines.map((line) => ({
501
+ key: line.key,
502
+ label: line.label || line.key,
503
+ color: line.color
504
+ })),
505
+ showLegend: options?.showLegend ?? true,
506
+ showGrid: options?.showGrid ?? true,
507
+ height: options?.height,
508
+ width: options?.width
509
+ }
510
+ };
511
+ }
512
+ function createPieChart(data, dataKey, nameKey, options) {
513
+ return {
514
+ type: "chart",
515
+ component: "PieChart",
516
+ layout: options?.layout,
517
+ title: options?.title,
518
+ description: options?.description,
519
+ props: {
520
+ data,
521
+ pie: {
522
+ dataKey,
523
+ nameKey,
524
+ label: options?.showLabel ?? true
525
+ },
526
+ showLegend: options?.showLegend ?? true,
527
+ height: options?.height || 400,
528
+ width: options?.width
529
+ }
530
+ };
531
+ }
532
+ function createAreaChart(data, xKey, areas, options) {
533
+ return {
534
+ type: "chart",
535
+ component: "AreaChart",
536
+ layout: options?.layout,
537
+ title: options?.title,
538
+ description: options?.description,
539
+ props: {
540
+ data,
541
+ xKey,
542
+ areas: areas.map((area) => ({
543
+ key: area.key,
544
+ label: area.label || area.key,
545
+ color: area.color
546
+ })),
547
+ showLegend: options?.showLegend ?? true,
548
+ showGrid: options?.showGrid ?? true,
549
+ height: options?.height,
550
+ width: options?.width
551
+ }
552
+ };
553
+ }
554
+ function createCardGrid(cards, options) {
555
+ return {
556
+ type: "card-grid",
557
+ layout: options?.layout,
558
+ title: options?.title,
559
+ description: options?.description,
560
+ props: {
561
+ cards,
562
+ columns: options?.columns || { default: 1, md: 2, lg: 3 },
563
+ variant: options?.variant || "default"
564
+ }
565
+ };
566
+ }
567
+ function createCard(id, title, description, options) {
568
+ return {
569
+ id,
570
+ title,
571
+ description,
572
+ image: options?.image,
573
+ metadata: options?.metadata,
574
+ actions: options?.actions
575
+ };
576
+ }
577
+ function createTable(data, columns, options) {
578
+ return {
579
+ type: "table",
580
+ layout: options?.layout,
581
+ title: options?.title,
582
+ description: options?.description,
583
+ props: {
584
+ data,
585
+ columns,
586
+ sortable: options?.sortable ?? true,
587
+ filterable: options?.filterable,
588
+ pagination: options?.pagination,
589
+ density: options?.density || "comfortable"
590
+ }
591
+ };
592
+ }
593
+ function createColumn(key, header, options) {
594
+ return {
595
+ key,
596
+ header,
597
+ width: options?.width,
598
+ sortable: options?.sortable,
599
+ cellType: options?.cellType || "text",
600
+ format: options?.format
601
+ };
602
+ }
603
+ function createMarkdown(content, options) {
604
+ return {
605
+ type: "markdown",
606
+ layout: options?.layout,
607
+ title: options?.title,
608
+ description: options?.description,
609
+ props: {
610
+ content,
611
+ syntaxHighlight: options?.syntaxHighlight ?? true
612
+ }
613
+ };
614
+ }
615
+ function createArtifact(content, options) {
616
+ return {
617
+ type: "artifact",
618
+ title: options?.title,
619
+ description: options?.description,
620
+ props: {
621
+ content,
622
+ variant: options?.variant || "default"
623
+ }
624
+ };
625
+ }
626
+ function createSmartChart(data, options) {
627
+ if (!data || data.length === 0) {
628
+ return createBarChart([], "", [], options);
629
+ }
630
+ const firstItem = data[0];
631
+ const keys = Object.keys(firstItem);
632
+ const xKey = options?.xKey || keys.find(
633
+ (k) => ["name", "label", "category", "date", "time", "month", "year"].includes(k.toLowerCase())
634
+ ) || keys[0];
635
+ const numericKeys = keys.filter((k) => k !== xKey && typeof firstItem[k] === "number");
636
+ const yKeys = options?.yKeys || numericKeys;
637
+ if ((options?.preferredType === "pie" || yKeys.length === 1) && typeof firstItem[xKey] === "string") {
638
+ return createPieChart(data, yKeys[0], xKey, options);
639
+ }
640
+ if (options?.preferredType === "line" || xKey.toLowerCase().includes("date") || xKey.toLowerCase().includes("time") || xKey.toLowerCase().includes("month") || xKey.toLowerCase().includes("year")) {
641
+ return createLineChart(
642
+ data,
643
+ xKey,
644
+ yKeys.map((key) => ({ key })),
645
+ options
646
+ );
647
+ }
648
+ return createBarChart(
649
+ data,
650
+ xKey,
651
+ yKeys.map((key) => ({ key })),
652
+ options
653
+ );
654
+ }
655
+ function createToolResult(data, ui) {
656
+ return { data, ui };
657
+ }
658
+ function resultWithBarChart(data, xKey, bars, options) {
659
+ return createToolResult(data, createBarChart(data, xKey, bars, options));
660
+ }
661
+ function resultWithSmartChart(data, options) {
662
+ return createToolResult(data, createSmartChart(data, options));
663
+ }
664
+ function resultWithCardGrid(cards, options) {
665
+ return createToolResult(cards, createCardGrid(cards, options));
666
+ }
667
+ function resultWithTable(data, columns, options) {
668
+ return createToolResult(data, createTable(data, columns, options));
669
+ }
670
+
23
671
  // src/hooks/useAgnoChat.ts
24
- import { useState, useEffect as useEffect2, useCallback } from "react";
672
+ import { useState as useState3, useEffect as useEffect3, useCallback as useCallback3 } from "react";
25
673
  function useAgnoChat() {
26
674
  const client = useAgnoClient();
27
- const [messages, setMessages] = useState(client.getMessages());
28
- const [state, setState] = useState(client.getState());
29
- const [error, setError] = useState();
30
- useEffect2(() => {
675
+ const [messages, setMessages] = useState3(client.getMessages());
676
+ const [state, setState] = useState3(client.getState());
677
+ const [error, setError] = useState3();
678
+ useEffect3(() => {
31
679
  const handleMessageUpdate = (updatedMessages) => {
32
- console.log("[useAgnoChat] message:update event received, messages:", updatedMessages.length);
33
680
  setMessages(updatedMessages);
34
681
  };
35
682
  const handleMessageComplete = (updatedMessages) => {
36
- console.log("[useAgnoChat] message:complete event received, messages:", updatedMessages.length);
37
683
  setMessages(updatedMessages);
38
684
  };
39
685
  const handleMessageError = (errorMessage) => {
40
- console.log("[useAgnoChat] message:error event received:", errorMessage);
41
686
  setError(errorMessage);
42
687
  };
43
688
  const handleStateChange = (newState) => {
44
- console.log("[useAgnoChat] state:change event received");
45
689
  setState(newState);
46
690
  };
691
+ const handleUIRender = (event) => {
692
+ const { tools } = event;
693
+ for (const tool of tools) {
694
+ if (tool.ui_component) {
695
+ client.hydrateToolCallUI(tool.tool_call_id, tool.ui_component);
696
+ }
697
+ }
698
+ };
47
699
  client.on("message:update", handleMessageUpdate);
48
700
  client.on("message:complete", handleMessageComplete);
49
701
  client.on("message:error", handleMessageError);
50
702
  client.on("state:change", handleStateChange);
51
- console.log("[useAgnoChat] Initializing with messages:", client.getMessages().length);
703
+ client.on("ui:render", handleUIRender);
52
704
  setMessages(client.getMessages());
53
705
  setState(client.getState());
54
706
  return () => {
@@ -56,9 +708,10 @@ function useAgnoChat() {
56
708
  client.off("message:complete", handleMessageComplete);
57
709
  client.off("message:error", handleMessageError);
58
710
  client.off("state:change", handleStateChange);
711
+ client.off("ui:render", handleUIRender);
59
712
  };
60
713
  }, [client]);
61
- const sendMessage = useCallback(
714
+ const sendMessage = useCallback3(
62
715
  async (message, options) => {
63
716
  setError(void 0);
64
717
  try {
@@ -71,7 +724,7 @@ function useAgnoChat() {
71
724
  },
72
725
  [client]
73
726
  );
74
- const clearMessages = useCallback(() => {
727
+ const clearMessages = useCallback3(() => {
75
728
  client.clearMessages();
76
729
  setMessages([]);
77
730
  setError(void 0);
@@ -88,16 +741,16 @@ function useAgnoChat() {
88
741
  }
89
742
 
90
743
  // src/hooks/useAgnoSession.ts
91
- import { useState as useState2, useEffect as useEffect3, useCallback as useCallback2 } from "react";
744
+ import { useState as useState4, useEffect as useEffect4, useCallback as useCallback4 } from "react";
92
745
  function useAgnoSession() {
93
746
  const client = useAgnoClient();
94
- const [sessions, setSessions] = useState2([]);
95
- const [currentSessionId, setCurrentSessionId] = useState2(
747
+ const [sessions, setSessions] = useState4([]);
748
+ const [currentSessionId, setCurrentSessionId] = useState4(
96
749
  client.getConfig().sessionId
97
750
  );
98
- const [isLoading, setIsLoading] = useState2(false);
99
- const [error, setError] = useState2();
100
- useEffect3(() => {
751
+ const [isLoading, setIsLoading] = useState4(false);
752
+ const [error, setError] = useState4();
753
+ useEffect4(() => {
101
754
  const handleSessionLoaded = (sessionId) => {
102
755
  setCurrentSessionId(sessionId);
103
756
  };
@@ -121,7 +774,7 @@ function useAgnoSession() {
121
774
  client.off("state:change", handleStateChange);
122
775
  };
123
776
  }, [client]);
124
- const loadSession = useCallback2(
777
+ const loadSession = useCallback4(
125
778
  async (sessionId) => {
126
779
  setIsLoading(true);
127
780
  setError(void 0);
@@ -139,7 +792,7 @@ function useAgnoSession() {
139
792
  },
140
793
  [client]
141
794
  );
142
- const fetchSessions = useCallback2(async () => {
795
+ const fetchSessions = useCallback4(async () => {
143
796
  setIsLoading(true);
144
797
  setError(void 0);
145
798
  try {
@@ -165,12 +818,12 @@ function useAgnoSession() {
165
818
  }
166
819
 
167
820
  // src/hooks/useAgnoActions.ts
168
- import { useState as useState3, useCallback as useCallback3 } from "react";
821
+ import { useState as useState5, useCallback as useCallback5 } from "react";
169
822
  function useAgnoActions() {
170
823
  const client = useAgnoClient();
171
- const [isInitializing, setIsInitializing] = useState3(false);
172
- const [error, setError] = useState3();
173
- const initialize = useCallback3(async () => {
824
+ const [isInitializing, setIsInitializing] = useState5(false);
825
+ const [error, setError] = useState5();
826
+ const initialize = useCallback5(async () => {
174
827
  setIsInitializing(true);
175
828
  setError(void 0);
176
829
  try {
@@ -184,7 +837,7 @@ function useAgnoActions() {
184
837
  setIsInitializing(false);
185
838
  }
186
839
  }, [client]);
187
- const checkStatus = useCallback3(async () => {
840
+ const checkStatus = useCallback5(async () => {
188
841
  setError(void 0);
189
842
  try {
190
843
  return await client.checkStatus();
@@ -194,7 +847,7 @@ function useAgnoActions() {
194
847
  return false;
195
848
  }
196
849
  }, [client]);
197
- const fetchAgents = useCallback3(async () => {
850
+ const fetchAgents = useCallback5(async () => {
198
851
  setError(void 0);
199
852
  try {
200
853
  return await client.fetchAgents();
@@ -204,7 +857,7 @@ function useAgnoActions() {
204
857
  throw err;
205
858
  }
206
859
  }, [client]);
207
- const fetchTeams = useCallback3(async () => {
860
+ const fetchTeams = useCallback5(async () => {
208
861
  setError(void 0);
209
862
  try {
210
863
  return await client.fetchTeams();
@@ -214,7 +867,7 @@ function useAgnoActions() {
214
867
  throw err;
215
868
  }
216
869
  }, [client]);
217
- const updateConfig = useCallback3(
870
+ const updateConfig = useCallback5(
218
871
  (updates) => {
219
872
  client.updateConfig(updates);
220
873
  },
@@ -230,155 +883,35 @@ function useAgnoActions() {
230
883
  error
231
884
  };
232
885
  }
233
-
234
- // src/hooks/useAgnoToolExecution.ts
235
- import { useState as useState4, useEffect as useEffect4, useCallback as useCallback4 } from "react";
236
- function useAgnoToolExecution(handlers, autoExecute = true) {
237
- const client = useAgnoClient();
238
- const [pendingTools, setPendingTools] = useState4([]);
239
- const [isPaused, setIsPaused] = useState4(false);
240
- const [isExecuting, setIsExecuting] = useState4(false);
241
- const [executionError, setExecutionError] = useState4();
242
- useEffect4(() => {
243
- const handleRunPaused = (event) => {
244
- console.log("[useAgnoToolExecution] Run paused, tools:", event.tools);
245
- setIsPaused(true);
246
- setPendingTools(event.tools);
247
- setExecutionError(void 0);
248
- };
249
- const handleRunContinued = () => {
250
- console.log("[useAgnoToolExecution] Run continued");
251
- setIsPaused(false);
252
- setPendingTools([]);
253
- setIsExecuting(false);
254
- setExecutionError(void 0);
255
- };
256
- client.on("run:paused", handleRunPaused);
257
- client.on("run:continued", handleRunContinued);
258
- return () => {
259
- client.off("run:paused", handleRunPaused);
260
- client.off("run:continued", handleRunContinued);
261
- };
262
- }, [client]);
263
- const executeAndContinue = useCallback4(async () => {
264
- if (!isPaused || pendingTools.length === 0) {
265
- console.warn("[useAgnoToolExecution] Cannot execute: no pending tools");
266
- return;
267
- }
268
- setIsExecuting(true);
269
- setExecutionError(void 0);
270
- try {
271
- console.log("[useAgnoToolExecution] Executing", pendingTools.length, "tools");
272
- const updatedTools = await Promise.all(
273
- pendingTools.map(async (tool) => {
274
- const handler = handlers[tool.tool_name];
275
- if (!handler) {
276
- console.warn(`[useAgnoToolExecution] No handler for tool: ${tool.tool_name}`);
277
- return {
278
- ...tool,
279
- result: JSON.stringify({
280
- error: `No handler registered for ${tool.tool_name}`
281
- })
282
- };
283
- }
284
- try {
285
- console.log(`[useAgnoToolExecution] Executing tool: ${tool.tool_name}`, tool.tool_args);
286
- const result = await handler(tool.tool_args);
287
- console.log(`[useAgnoToolExecution] Tool result:`, result);
288
- return {
289
- ...tool,
290
- result: typeof result === "string" ? result : JSON.stringify(result)
291
- };
292
- } catch (error) {
293
- console.error(`[useAgnoToolExecution] Tool execution error:`, error);
294
- return {
295
- ...tool,
296
- result: JSON.stringify({
297
- error: error instanceof Error ? error.message : String(error)
298
- })
299
- };
300
- }
301
- })
302
- );
303
- console.log("[useAgnoToolExecution] Continuing run with results");
304
- await client.continueRun(updatedTools);
305
- } catch (error) {
306
- const errorMessage = error instanceof Error ? error.message : String(error);
307
- console.error("[useAgnoToolExecution] Failed to continue run:", errorMessage);
308
- setExecutionError(errorMessage);
309
- setIsExecuting(false);
310
- throw error;
311
- }
312
- }, [client, handlers, isPaused, pendingTools]);
313
- const executeTools = useCallback4(
314
- async (tools) => {
315
- return Promise.all(
316
- tools.map(async (tool) => {
317
- const handler = handlers[tool.tool_name];
318
- if (!handler)
319
- return tool;
320
- try {
321
- const result = await handler(tool.tool_args);
322
- return {
323
- ...tool,
324
- result: typeof result === "string" ? result : JSON.stringify(result)
325
- };
326
- } catch (error) {
327
- return {
328
- ...tool,
329
- result: JSON.stringify({
330
- error: error instanceof Error ? error.message : String(error)
331
- })
332
- };
333
- }
334
- })
335
- );
336
- },
337
- [handlers]
338
- );
339
- const continueWithResults = useCallback4(
340
- async (tools) => {
341
- if (!isPaused) {
342
- throw new Error("No paused run to continue");
343
- }
344
- setIsExecuting(true);
345
- try {
346
- await client.continueRun(tools);
347
- } catch (error) {
348
- setIsExecuting(false);
349
- throw error;
350
- }
351
- },
352
- [client, isPaused]
353
- );
354
- useEffect4(() => {
355
- if (autoExecute && isPaused && !isExecuting && pendingTools.length > 0) {
356
- console.log("[useAgnoToolExecution] Auto-executing tools");
357
- executeAndContinue();
358
- }
359
- }, [autoExecute, isPaused, isExecuting, pendingTools.length, executeAndContinue]);
360
- return {
361
- /** Whether the run is currently paused awaiting tool execution */
362
- isPaused,
363
- /** Whether tools are currently being executed */
364
- isExecuting,
365
- /** Tools awaiting execution */
366
- pendingTools,
367
- /** Execute all pending tools and continue the run */
368
- executeAndContinue,
369
- /** Execute specific tools and return results without continuing */
370
- executeTools,
371
- /** Continue the run with manually provided tool results */
372
- continueWithResults,
373
- /** Error from tool execution, if any */
374
- executionError
375
- };
376
- }
377
886
  export {
378
887
  AgnoProvider,
888
+ ComponentRegistry,
889
+ GenerativeUIRenderer,
890
+ ToolHandlerProvider,
891
+ createAreaChart,
892
+ createArtifact,
893
+ createBarChart,
894
+ createCard,
895
+ createCardGrid,
896
+ createColumn,
897
+ createLineChart,
898
+ createMarkdown,
899
+ createPieChart,
900
+ createSmartChart,
901
+ createTable,
902
+ createToolResult,
903
+ getChartComponent,
904
+ getComponentRegistry,
905
+ getCustomRender,
906
+ registerChartComponent,
907
+ resultWithBarChart,
908
+ resultWithCardGrid,
909
+ resultWithSmartChart,
910
+ resultWithTable,
379
911
  useAgnoActions,
380
912
  useAgnoChat,
381
913
  useAgnoClient,
382
914
  useAgnoSession,
383
- useAgnoToolExecution
915
+ useAgnoToolExecution,
916
+ useToolHandlers
384
917
  };