@lantos1618/better-ui 0.2.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +271 -354
- package/dist/ThemeProvider-BYeqWMsn.d.mts +187 -0
- package/dist/ThemeProvider-BaVZaDBO.d.ts +187 -0
- package/dist/auth/index.d.mts +56 -0
- package/dist/auth/index.d.ts +56 -0
- package/dist/auth/index.js +104 -0
- package/dist/auth/index.mjs +67 -0
- package/dist/chunk-Y6FXYEAI.mjs +10 -0
- package/dist/components/index.d.mts +258 -0
- package/dist/components/index.d.ts +258 -0
- package/dist/components/index.js +1977 -0
- package/dist/components/index.mjs +1922 -0
- package/dist/index.d.mts +75 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.js +587 -0
- package/dist/index.mjs +557 -0
- package/dist/persistence/index.d.mts +11 -0
- package/dist/persistence/index.d.ts +11 -0
- package/dist/persistence/index.js +66 -0
- package/dist/persistence/index.mjs +41 -0
- package/dist/react/index.d.mts +91 -0
- package/dist/react/index.d.ts +91 -0
- package/dist/react/index.js +284 -0
- package/dist/react/index.mjs +257 -0
- package/dist/tool-Ca2x-VNK.d.mts +361 -0
- package/dist/tool-Ca2x-VNK.d.ts +361 -0
- package/dist/types-CAOfGUPH.d.mts +31 -0
- package/dist/types-CAOfGUPH.d.ts +31 -0
- package/package.json +85 -30
- package/src/theme.css +101 -0
- package/lib/aui/README.md +0 -136
- package/lib/aui/__tests__/aui-complete.test.ts +0 -251
- package/lib/aui/__tests__/aui-comprehensive.test.ts +0 -376
- package/lib/aui/__tests__/aui-concise.test.ts +0 -278
- package/lib/aui/__tests__/aui-integration.test.ts +0 -309
- package/lib/aui/__tests__/aui-simple.test.ts +0 -116
- package/lib/aui/__tests__/aui.test.ts +0 -269
- package/lib/aui/__tests__/concise-api.test.ts +0 -165
- package/lib/aui/__tests__/core.test.ts +0 -265
- package/lib/aui/__tests__/simple-api.test.ts +0 -200
- package/lib/aui/ai-assistant.ts +0 -408
- package/lib/aui/ai-control.ts +0 -353
- package/lib/aui/client/use-aui.ts +0 -55
- package/lib/aui/client-control.ts +0 -551
- package/lib/aui/client-executor.ts +0 -417
- package/lib/aui/components/ToolRenderer.tsx +0 -22
- package/lib/aui/core.ts +0 -137
- package/lib/aui/demo.tsx +0 -89
- package/lib/aui/examples/ai-complete-demo.tsx +0 -359
- package/lib/aui/examples/ai-control-demo.tsx +0 -356
- package/lib/aui/examples/ai-control-tools.ts +0 -308
- package/lib/aui/examples/concise-api.tsx +0 -153
- package/lib/aui/examples/index.tsx +0 -163
- package/lib/aui/examples/quick-demo.tsx +0 -91
- package/lib/aui/examples/simple-demo.tsx +0 -71
- package/lib/aui/examples/simple-tools.tsx +0 -160
- package/lib/aui/examples/user-api.tsx +0 -208
- package/lib/aui/examples/user-requested.tsx +0 -174
- package/lib/aui/examples/weather-search-tools.tsx +0 -119
- package/lib/aui/examples.tsx +0 -367
- package/lib/aui/hooks/useAUITool.ts +0 -142
- package/lib/aui/hooks/useAUIToolEnhanced.ts +0 -343
- package/lib/aui/hooks/useAUITools.ts +0 -195
- package/lib/aui/index.ts +0 -156
- package/lib/aui/provider.tsx +0 -45
- package/lib/aui/server-control.ts +0 -386
- package/lib/aui/server-executor.ts +0 -165
- package/lib/aui/server.ts +0 -167
- package/lib/aui/tool-registry.ts +0 -380
- package/lib/aui/tools/advanced-examples.tsx +0 -86
- package/lib/aui/tools/ai-complete.ts +0 -375
- package/lib/aui/tools/api-tools.tsx +0 -230
- package/lib/aui/tools/data-tools.tsx +0 -232
- package/lib/aui/tools/dom-tools.tsx +0 -202
- package/lib/aui/tools/examples.ts +0 -43
- package/lib/aui/tools/file-tools.tsx +0 -202
- package/lib/aui/tools/form-tools.tsx +0 -233
- package/lib/aui/tools/index.ts +0 -8
- package/lib/aui/tools/navigation-tools.tsx +0 -172
- package/lib/aui/tools/notification-tools.ts +0 -213
- package/lib/aui/tools/state-tools.tsx +0 -209
- package/lib/aui/types.ts +0 -47
- package/lib/aui/vercel-ai.ts +0 -100
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { T as Tool, c as ToolContext } from '../tool-Ca2x-VNK.mjs';
|
|
2
|
+
import 'zod';
|
|
3
|
+
import 'react';
|
|
4
|
+
|
|
5
|
+
interface UseToolOptions {
|
|
6
|
+
/** Auto-execute on mount or when input changes */
|
|
7
|
+
auto?: boolean;
|
|
8
|
+
/** Custom context overrides */
|
|
9
|
+
context?: Partial<ToolContext>;
|
|
10
|
+
/** Callback on success */
|
|
11
|
+
onSuccess?: (data: unknown) => void;
|
|
12
|
+
/** Callback on error */
|
|
13
|
+
onError?: (error: Error) => void;
|
|
14
|
+
}
|
|
15
|
+
interface UseToolResult<TInput, TOutput> {
|
|
16
|
+
/** The result data */
|
|
17
|
+
data: TOutput | null;
|
|
18
|
+
/** Loading state */
|
|
19
|
+
loading: boolean;
|
|
20
|
+
/** Error if any */
|
|
21
|
+
error: Error | null;
|
|
22
|
+
/** Execute the tool manually */
|
|
23
|
+
execute: (input?: TInput) => Promise<TOutput | null>;
|
|
24
|
+
/** Reset state */
|
|
25
|
+
reset: () => void;
|
|
26
|
+
/** Whether the tool has been executed at least once */
|
|
27
|
+
executed: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* React hook for executing tools
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // Manual execution
|
|
34
|
+
* const { data, loading, execute } = useTool(weather);
|
|
35
|
+
* <button onClick={() => execute({ city: 'London' })}>Get Weather</button>
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* // Auto execution when input changes
|
|
39
|
+
* const { data, loading } = useTool(weather, { city }, { auto: true });
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // With callbacks
|
|
43
|
+
* const { execute } = useTool(weather, undefined, {
|
|
44
|
+
* onSuccess: (data) => console.log('Got weather:', data),
|
|
45
|
+
* onError: (error) => console.error('Failed:', error),
|
|
46
|
+
* });
|
|
47
|
+
*/
|
|
48
|
+
declare function useTool<TInput, TOutput>(tool: Tool<TInput, TOutput>, initialInput?: TInput, options?: UseToolOptions): UseToolResult<TInput, TOutput>;
|
|
49
|
+
/**
|
|
50
|
+
* React hook for executing multiple tools
|
|
51
|
+
*
|
|
52
|
+
* This hook properly manages state for multiple tools using a single useState,
|
|
53
|
+
* avoiding the hooks-in-loop anti-pattern.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* // Define tools outside component or memoize with useMemo
|
|
57
|
+
* const myTools = { weather, search };
|
|
58
|
+
*
|
|
59
|
+
* function MyComponent() {
|
|
60
|
+
* const tools = useTools(myTools);
|
|
61
|
+
* await tools.weather.execute({ city: 'London' });
|
|
62
|
+
* await tools.search.execute({ query: 'restaurants' });
|
|
63
|
+
* }
|
|
64
|
+
*/
|
|
65
|
+
declare function useTools<T extends Record<string, Tool>>(tools: T, options?: UseToolOptions): {
|
|
66
|
+
[K in keyof T]: UseToolResult<T[K] extends Tool<infer I, any> ? I : never, T[K] extends Tool<any, infer O> ? O : never>;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
interface UseToolStreamResult<TInput, TOutput> {
|
|
70
|
+
/** Progressive partial data (shallow-merged from stream callbacks) */
|
|
71
|
+
data: Partial<TOutput> | null;
|
|
72
|
+
/** Complete validated data when streaming finishes */
|
|
73
|
+
finalData: TOutput | null;
|
|
74
|
+
/** True while receiving partial streaming updates */
|
|
75
|
+
streaming: boolean;
|
|
76
|
+
/** True before first stream chunk arrives */
|
|
77
|
+
loading: boolean;
|
|
78
|
+
/** Error if any */
|
|
79
|
+
error: Error | null;
|
|
80
|
+
/** Execute the tool with streaming */
|
|
81
|
+
execute: (input: TInput) => Promise<TOutput | null>;
|
|
82
|
+
/** Reset all state */
|
|
83
|
+
reset: () => void;
|
|
84
|
+
}
|
|
85
|
+
declare function useToolStream<TInput, TOutput>(tool: Tool<TInput, TOutput>, options?: {
|
|
86
|
+
context?: Partial<ToolContext>;
|
|
87
|
+
onSuccess?: (data: TOutput) => void;
|
|
88
|
+
onError?: (error: Error) => void;
|
|
89
|
+
}): UseToolStreamResult<TInput, TOutput>;
|
|
90
|
+
|
|
91
|
+
export { type UseToolOptions, type UseToolResult, type UseToolStreamResult, useTool, useToolStream, useTools };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { T as Tool, c as ToolContext } from '../tool-Ca2x-VNK.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
import 'react';
|
|
4
|
+
|
|
5
|
+
interface UseToolOptions {
|
|
6
|
+
/** Auto-execute on mount or when input changes */
|
|
7
|
+
auto?: boolean;
|
|
8
|
+
/** Custom context overrides */
|
|
9
|
+
context?: Partial<ToolContext>;
|
|
10
|
+
/** Callback on success */
|
|
11
|
+
onSuccess?: (data: unknown) => void;
|
|
12
|
+
/** Callback on error */
|
|
13
|
+
onError?: (error: Error) => void;
|
|
14
|
+
}
|
|
15
|
+
interface UseToolResult<TInput, TOutput> {
|
|
16
|
+
/** The result data */
|
|
17
|
+
data: TOutput | null;
|
|
18
|
+
/** Loading state */
|
|
19
|
+
loading: boolean;
|
|
20
|
+
/** Error if any */
|
|
21
|
+
error: Error | null;
|
|
22
|
+
/** Execute the tool manually */
|
|
23
|
+
execute: (input?: TInput) => Promise<TOutput | null>;
|
|
24
|
+
/** Reset state */
|
|
25
|
+
reset: () => void;
|
|
26
|
+
/** Whether the tool has been executed at least once */
|
|
27
|
+
executed: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* React hook for executing tools
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // Manual execution
|
|
34
|
+
* const { data, loading, execute } = useTool(weather);
|
|
35
|
+
* <button onClick={() => execute({ city: 'London' })}>Get Weather</button>
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* // Auto execution when input changes
|
|
39
|
+
* const { data, loading } = useTool(weather, { city }, { auto: true });
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // With callbacks
|
|
43
|
+
* const { execute } = useTool(weather, undefined, {
|
|
44
|
+
* onSuccess: (data) => console.log('Got weather:', data),
|
|
45
|
+
* onError: (error) => console.error('Failed:', error),
|
|
46
|
+
* });
|
|
47
|
+
*/
|
|
48
|
+
declare function useTool<TInput, TOutput>(tool: Tool<TInput, TOutput>, initialInput?: TInput, options?: UseToolOptions): UseToolResult<TInput, TOutput>;
|
|
49
|
+
/**
|
|
50
|
+
* React hook for executing multiple tools
|
|
51
|
+
*
|
|
52
|
+
* This hook properly manages state for multiple tools using a single useState,
|
|
53
|
+
* avoiding the hooks-in-loop anti-pattern.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* // Define tools outside component or memoize with useMemo
|
|
57
|
+
* const myTools = { weather, search };
|
|
58
|
+
*
|
|
59
|
+
* function MyComponent() {
|
|
60
|
+
* const tools = useTools(myTools);
|
|
61
|
+
* await tools.weather.execute({ city: 'London' });
|
|
62
|
+
* await tools.search.execute({ query: 'restaurants' });
|
|
63
|
+
* }
|
|
64
|
+
*/
|
|
65
|
+
declare function useTools<T extends Record<string, Tool>>(tools: T, options?: UseToolOptions): {
|
|
66
|
+
[K in keyof T]: UseToolResult<T[K] extends Tool<infer I, any> ? I : never, T[K] extends Tool<any, infer O> ? O : never>;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
interface UseToolStreamResult<TInput, TOutput> {
|
|
70
|
+
/** Progressive partial data (shallow-merged from stream callbacks) */
|
|
71
|
+
data: Partial<TOutput> | null;
|
|
72
|
+
/** Complete validated data when streaming finishes */
|
|
73
|
+
finalData: TOutput | null;
|
|
74
|
+
/** True while receiving partial streaming updates */
|
|
75
|
+
streaming: boolean;
|
|
76
|
+
/** True before first stream chunk arrives */
|
|
77
|
+
loading: boolean;
|
|
78
|
+
/** Error if any */
|
|
79
|
+
error: Error | null;
|
|
80
|
+
/** Execute the tool with streaming */
|
|
81
|
+
execute: (input: TInput) => Promise<TOutput | null>;
|
|
82
|
+
/** Reset all state */
|
|
83
|
+
reset: () => void;
|
|
84
|
+
}
|
|
85
|
+
declare function useToolStream<TInput, TOutput>(tool: Tool<TInput, TOutput>, options?: {
|
|
86
|
+
context?: Partial<ToolContext>;
|
|
87
|
+
onSuccess?: (data: TOutput) => void;
|
|
88
|
+
onError?: (error: Error) => void;
|
|
89
|
+
}): UseToolStreamResult<TInput, TOutput>;
|
|
90
|
+
|
|
91
|
+
export { type UseToolOptions, type UseToolResult, type UseToolStreamResult, useTool, useToolStream, useTools };
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/react/index.ts
|
|
22
|
+
var react_exports = {};
|
|
23
|
+
__export(react_exports, {
|
|
24
|
+
useTool: () => useTool,
|
|
25
|
+
useToolStream: () => useToolStream,
|
|
26
|
+
useTools: () => useTools
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(react_exports);
|
|
29
|
+
|
|
30
|
+
// src/react/useTool.ts
|
|
31
|
+
var import_react = require("react");
|
|
32
|
+
function useTool(tool, initialInput, options = {}) {
|
|
33
|
+
const [data, setData] = (0, import_react.useState)(null);
|
|
34
|
+
const [loading, setLoading] = (0, import_react.useState)(false);
|
|
35
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
36
|
+
const [executed, setExecuted] = (0, import_react.useState)(false);
|
|
37
|
+
const inputRef = (0, import_react.useRef)(initialInput);
|
|
38
|
+
const optionsRef = (0, import_react.useRef)(options);
|
|
39
|
+
optionsRef.current = options;
|
|
40
|
+
const executionIdRef = (0, import_react.useRef)(0);
|
|
41
|
+
const pendingCountRef = (0, import_react.useRef)(0);
|
|
42
|
+
const execute = (0, import_react.useCallback)(
|
|
43
|
+
async (input) => {
|
|
44
|
+
const finalInput = input ?? inputRef.current;
|
|
45
|
+
if (finalInput === void 0) {
|
|
46
|
+
const err = new Error("No input provided to tool");
|
|
47
|
+
setError(err);
|
|
48
|
+
optionsRef.current.onError?.(err);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
const currentExecutionId = ++executionIdRef.current;
|
|
52
|
+
pendingCountRef.current++;
|
|
53
|
+
setLoading(true);
|
|
54
|
+
setError(null);
|
|
55
|
+
try {
|
|
56
|
+
const context = {
|
|
57
|
+
cache: /* @__PURE__ */ new Map(),
|
|
58
|
+
fetch: globalThis.fetch?.bind(globalThis),
|
|
59
|
+
isServer: false,
|
|
60
|
+
...optionsRef.current.context
|
|
61
|
+
};
|
|
62
|
+
const result = await tool.run(finalInput, context);
|
|
63
|
+
if (currentExecutionId === executionIdRef.current) {
|
|
64
|
+
setData(result);
|
|
65
|
+
setExecuted(true);
|
|
66
|
+
optionsRef.current.onSuccess?.(result);
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
} catch (err) {
|
|
70
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
71
|
+
if (currentExecutionId === executionIdRef.current) {
|
|
72
|
+
setError(error2);
|
|
73
|
+
optionsRef.current.onError?.(error2);
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
} finally {
|
|
77
|
+
pendingCountRef.current--;
|
|
78
|
+
if (pendingCountRef.current === 0) {
|
|
79
|
+
setLoading(false);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
[tool]
|
|
84
|
+
);
|
|
85
|
+
const reset = (0, import_react.useCallback)(() => {
|
|
86
|
+
setData(null);
|
|
87
|
+
setError(null);
|
|
88
|
+
setLoading(false);
|
|
89
|
+
setExecuted(false);
|
|
90
|
+
}, []);
|
|
91
|
+
(0, import_react.useEffect)(() => {
|
|
92
|
+
if (options.auto && initialInput !== void 0) {
|
|
93
|
+
inputRef.current = initialInput;
|
|
94
|
+
execute(initialInput);
|
|
95
|
+
}
|
|
96
|
+
}, [options.auto, initialInput, execute]);
|
|
97
|
+
return {
|
|
98
|
+
data,
|
|
99
|
+
loading,
|
|
100
|
+
error,
|
|
101
|
+
execute,
|
|
102
|
+
reset,
|
|
103
|
+
executed
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function useTools(tools, options = {}) {
|
|
107
|
+
const toolsRef = (0, import_react.useRef)(tools);
|
|
108
|
+
const optionsRef = (0, import_react.useRef)(options);
|
|
109
|
+
optionsRef.current = options;
|
|
110
|
+
if (process.env.NODE_ENV !== "production") {
|
|
111
|
+
const prevKeys = Object.keys(toolsRef.current);
|
|
112
|
+
const currKeys = Object.keys(tools);
|
|
113
|
+
if (prevKeys.length !== currKeys.length || !currKeys.every((k) => prevKeys.includes(k))) {
|
|
114
|
+
console.warn(
|
|
115
|
+
"useTools: The tools object keys changed between renders. This may cause unexpected behavior. Define tools outside the component or memoize with useMemo."
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
toolsRef.current = tools;
|
|
119
|
+
}
|
|
120
|
+
const [state, setState] = (0, import_react.useState)(() => {
|
|
121
|
+
const initial = {};
|
|
122
|
+
for (const name of Object.keys(tools)) {
|
|
123
|
+
initial[name] = {
|
|
124
|
+
data: null,
|
|
125
|
+
loading: false,
|
|
126
|
+
error: null,
|
|
127
|
+
executed: false
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return initial;
|
|
131
|
+
});
|
|
132
|
+
const createExecute = (0, import_react.useCallback)(
|
|
133
|
+
(toolName, tool) => {
|
|
134
|
+
return async (input) => {
|
|
135
|
+
if (input === void 0) {
|
|
136
|
+
const err = new Error("No input provided to tool");
|
|
137
|
+
setState((prev) => ({
|
|
138
|
+
...prev,
|
|
139
|
+
[toolName]: { ...prev[toolName], error: err }
|
|
140
|
+
}));
|
|
141
|
+
optionsRef.current.onError?.(err);
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
setState((prev) => ({
|
|
145
|
+
...prev,
|
|
146
|
+
[toolName]: { ...prev[toolName], loading: true, error: null }
|
|
147
|
+
}));
|
|
148
|
+
try {
|
|
149
|
+
const context = {
|
|
150
|
+
cache: /* @__PURE__ */ new Map(),
|
|
151
|
+
fetch: globalThis.fetch?.bind(globalThis),
|
|
152
|
+
isServer: false,
|
|
153
|
+
...optionsRef.current.context
|
|
154
|
+
};
|
|
155
|
+
const result = await tool.run(input, context);
|
|
156
|
+
setState((prev) => ({
|
|
157
|
+
...prev,
|
|
158
|
+
[toolName]: {
|
|
159
|
+
data: result,
|
|
160
|
+
loading: false,
|
|
161
|
+
error: null,
|
|
162
|
+
executed: true
|
|
163
|
+
}
|
|
164
|
+
}));
|
|
165
|
+
optionsRef.current.onSuccess?.(result);
|
|
166
|
+
return result;
|
|
167
|
+
} catch (err) {
|
|
168
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
169
|
+
setState((prev) => ({
|
|
170
|
+
...prev,
|
|
171
|
+
[toolName]: { ...prev[toolName], loading: false, error }
|
|
172
|
+
}));
|
|
173
|
+
optionsRef.current.onError?.(error);
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
},
|
|
178
|
+
[]
|
|
179
|
+
);
|
|
180
|
+
const createReset = (0, import_react.useCallback)((toolName) => {
|
|
181
|
+
return () => {
|
|
182
|
+
setState((prev) => ({
|
|
183
|
+
...prev,
|
|
184
|
+
[toolName]: {
|
|
185
|
+
data: null,
|
|
186
|
+
loading: false,
|
|
187
|
+
error: null,
|
|
188
|
+
executed: false
|
|
189
|
+
}
|
|
190
|
+
}));
|
|
191
|
+
};
|
|
192
|
+
}, []);
|
|
193
|
+
const results = {};
|
|
194
|
+
for (const [name, tool] of Object.entries(tools)) {
|
|
195
|
+
const toolName = name;
|
|
196
|
+
const toolState = state[toolName];
|
|
197
|
+
results[toolName] = {
|
|
198
|
+
data: toolState?.data ?? null,
|
|
199
|
+
loading: toolState?.loading ?? false,
|
|
200
|
+
error: toolState?.error ?? null,
|
|
201
|
+
executed: toolState?.executed ?? false,
|
|
202
|
+
execute: createExecute(toolName, tool),
|
|
203
|
+
reset: createReset(toolName)
|
|
204
|
+
// Per-key type safety is enforced by the function's return type annotation.
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
return results;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/react/useToolStream.ts
|
|
211
|
+
var import_react2 = require("react");
|
|
212
|
+
function useToolStream(tool, options = {}) {
|
|
213
|
+
const [data, setData] = (0, import_react2.useState)(null);
|
|
214
|
+
const [finalData, setFinalData] = (0, import_react2.useState)(null);
|
|
215
|
+
const [streaming, setStreaming] = (0, import_react2.useState)(false);
|
|
216
|
+
const [loading, setLoading] = (0, import_react2.useState)(false);
|
|
217
|
+
const [error, setError] = (0, import_react2.useState)(null);
|
|
218
|
+
const executionIdRef = (0, import_react2.useRef)(0);
|
|
219
|
+
const optionsRef = (0, import_react2.useRef)(options);
|
|
220
|
+
optionsRef.current = options;
|
|
221
|
+
const execute = (0, import_react2.useCallback)(
|
|
222
|
+
async (input) => {
|
|
223
|
+
const currentId = ++executionIdRef.current;
|
|
224
|
+
setLoading(true);
|
|
225
|
+
setStreaming(false);
|
|
226
|
+
setError(null);
|
|
227
|
+
setData(null);
|
|
228
|
+
setFinalData(null);
|
|
229
|
+
try {
|
|
230
|
+
let accumulated = {};
|
|
231
|
+
let result = null;
|
|
232
|
+
let firstChunkReceived = false;
|
|
233
|
+
for await (const chunk of tool.runStream(input, {
|
|
234
|
+
isServer: false,
|
|
235
|
+
...optionsRef.current.context
|
|
236
|
+
})) {
|
|
237
|
+
if (currentId !== executionIdRef.current) return null;
|
|
238
|
+
if (chunk.done) {
|
|
239
|
+
result = chunk.partial;
|
|
240
|
+
setFinalData(result);
|
|
241
|
+
setData(result);
|
|
242
|
+
setStreaming(false);
|
|
243
|
+
setLoading(false);
|
|
244
|
+
optionsRef.current.onSuccess?.(result);
|
|
245
|
+
} else {
|
|
246
|
+
if (!firstChunkReceived) {
|
|
247
|
+
firstChunkReceived = true;
|
|
248
|
+
setStreaming(true);
|
|
249
|
+
setLoading(false);
|
|
250
|
+
}
|
|
251
|
+
accumulated = { ...accumulated, ...chunk.partial };
|
|
252
|
+
setData({ ...accumulated });
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
setLoading(false);
|
|
256
|
+
setStreaming(false);
|
|
257
|
+
return result;
|
|
258
|
+
} catch (err) {
|
|
259
|
+
if (currentId !== executionIdRef.current) return null;
|
|
260
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
261
|
+
setError(e);
|
|
262
|
+
setLoading(false);
|
|
263
|
+
setStreaming(false);
|
|
264
|
+
optionsRef.current.onError?.(e);
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
[tool]
|
|
269
|
+
);
|
|
270
|
+
const reset = (0, import_react2.useCallback)(() => {
|
|
271
|
+
setData(null);
|
|
272
|
+
setFinalData(null);
|
|
273
|
+
setStreaming(false);
|
|
274
|
+
setLoading(false);
|
|
275
|
+
setError(null);
|
|
276
|
+
}, []);
|
|
277
|
+
return { data, finalData, streaming, loading, error, execute, reset };
|
|
278
|
+
}
|
|
279
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
280
|
+
0 && (module.exports = {
|
|
281
|
+
useTool,
|
|
282
|
+
useToolStream,
|
|
283
|
+
useTools
|
|
284
|
+
});
|