@ash-cloud/ash-ui 0.0.5 → 0.0.6
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 +207 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +163 -1
- package/dist/index.d.ts +163 -1
- package/dist/index.js +207 -1
- package/dist/index.js.map +1 -1
- package/dist/styles-full.css +1 -0
- package/dist/styles.css +1 -1
- package/package.json +6 -3
package/dist/index.cjs
CHANGED
|
@@ -2973,6 +2973,212 @@ function useFileUpload({
|
|
|
2973
2973
|
openFilePicker
|
|
2974
2974
|
};
|
|
2975
2975
|
}
|
|
2976
|
+
function useAgentChat(options) {
|
|
2977
|
+
const {
|
|
2978
|
+
createStream,
|
|
2979
|
+
initialSessionId,
|
|
2980
|
+
initialEntries = [],
|
|
2981
|
+
onSessionStart,
|
|
2982
|
+
onSessionEnd,
|
|
2983
|
+
onError,
|
|
2984
|
+
onSandboxLog
|
|
2985
|
+
} = options;
|
|
2986
|
+
const [historyEntries, setHistoryEntries] = react.useState(initialEntries);
|
|
2987
|
+
const [streamingEntries, setStreamingEntries] = react.useState([]);
|
|
2988
|
+
const [isStreaming, setIsStreaming] = react.useState(false);
|
|
2989
|
+
const [error, setError] = react.useState(null);
|
|
2990
|
+
const [sessionId, setSessionId] = react.useState(initialSessionId || null);
|
|
2991
|
+
const abortControllerRef = react.useRef(null);
|
|
2992
|
+
const currentTextRef = react.useRef("");
|
|
2993
|
+
const currentTextIdRef = react.useRef(null);
|
|
2994
|
+
const pendingToolCallsRef = react.useRef(/* @__PURE__ */ new Map());
|
|
2995
|
+
const hadToolCallSinceTextRef = react.useRef(false);
|
|
2996
|
+
const entries = [...historyEntries, ...streamingEntries];
|
|
2997
|
+
const emitStreamingEntries = react.useCallback((newEntries) => {
|
|
2998
|
+
setStreamingEntries([...newEntries]);
|
|
2999
|
+
}, []);
|
|
3000
|
+
const createTextEntry = react.useCallback((id, content) => ({
|
|
3001
|
+
id,
|
|
3002
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3003
|
+
entryType: { type: "assistant_message" },
|
|
3004
|
+
content
|
|
3005
|
+
}), []);
|
|
3006
|
+
const resetStreamingState = react.useCallback(() => {
|
|
3007
|
+
currentTextRef.current = "";
|
|
3008
|
+
currentTextIdRef.current = null;
|
|
3009
|
+
pendingToolCallsRef.current.clear();
|
|
3010
|
+
hadToolCallSinceTextRef.current = false;
|
|
3011
|
+
setStreamingEntries([]);
|
|
3012
|
+
}, []);
|
|
3013
|
+
const processEvent = react.useCallback((event, streamEntries) => {
|
|
3014
|
+
const newEntries = [...streamEntries];
|
|
3015
|
+
switch (event.type) {
|
|
3016
|
+
case "session_start":
|
|
3017
|
+
if (event.sessionId) {
|
|
3018
|
+
setSessionId(event.sessionId);
|
|
3019
|
+
onSessionStart?.(event.sessionId);
|
|
3020
|
+
}
|
|
3021
|
+
break;
|
|
3022
|
+
case "text_delta":
|
|
3023
|
+
if (event.delta) {
|
|
3024
|
+
if (hadToolCallSinceTextRef.current && currentTextIdRef.current) {
|
|
3025
|
+
currentTextRef.current = "";
|
|
3026
|
+
currentTextIdRef.current = null;
|
|
3027
|
+
hadToolCallSinceTextRef.current = false;
|
|
3028
|
+
}
|
|
3029
|
+
currentTextRef.current += event.delta;
|
|
3030
|
+
if (!currentTextIdRef.current) {
|
|
3031
|
+
currentTextIdRef.current = `text-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
3032
|
+
newEntries.push(createTextEntry(currentTextIdRef.current, currentTextRef.current));
|
|
3033
|
+
} else {
|
|
3034
|
+
const entryIndex = newEntries.findIndex((e) => e.id === currentTextIdRef.current);
|
|
3035
|
+
if (entryIndex !== -1) {
|
|
3036
|
+
newEntries[entryIndex] = createTextEntry(currentTextIdRef.current, currentTextRef.current);
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
break;
|
|
3041
|
+
case "tool_use":
|
|
3042
|
+
if (event.toolId && event.toolName) {
|
|
3043
|
+
currentTextRef.current = "";
|
|
3044
|
+
currentTextIdRef.current = null;
|
|
3045
|
+
hadToolCallSinceTextRef.current = true;
|
|
3046
|
+
const toolCall = createToolCall({
|
|
3047
|
+
id: event.toolId,
|
|
3048
|
+
name: event.toolName,
|
|
3049
|
+
input: event.input
|
|
3050
|
+
});
|
|
3051
|
+
const entry = {
|
|
3052
|
+
id: event.toolId,
|
|
3053
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3054
|
+
entryType: { type: "tool_call", toolCall },
|
|
3055
|
+
content: toolCall.summary
|
|
3056
|
+
};
|
|
3057
|
+
const entryIndex = newEntries.length;
|
|
3058
|
+
newEntries.push(entry);
|
|
3059
|
+
pendingToolCallsRef.current.set(event.toolId, { entryIndex, toolCall });
|
|
3060
|
+
}
|
|
3061
|
+
break;
|
|
3062
|
+
case "tool_result":
|
|
3063
|
+
if (event.toolId) {
|
|
3064
|
+
const pending = pendingToolCallsRef.current.get(event.toolId);
|
|
3065
|
+
if (pending) {
|
|
3066
|
+
const updatedToolCall = updateToolCallWithResult(
|
|
3067
|
+
pending.toolCall,
|
|
3068
|
+
event.toolResult,
|
|
3069
|
+
event.isError
|
|
3070
|
+
);
|
|
3071
|
+
const existingEntry = newEntries[pending.entryIndex];
|
|
3072
|
+
if (existingEntry && existingEntry.entryType.type === "tool_call") {
|
|
3073
|
+
newEntries[pending.entryIndex] = {
|
|
3074
|
+
...existingEntry,
|
|
3075
|
+
entryType: { type: "tool_call", toolCall: updatedToolCall }
|
|
3076
|
+
};
|
|
3077
|
+
}
|
|
3078
|
+
pendingToolCallsRef.current.delete(event.toolId);
|
|
3079
|
+
}
|
|
3080
|
+
}
|
|
3081
|
+
break;
|
|
3082
|
+
case "sandbox_log":
|
|
3083
|
+
if (event.entry) {
|
|
3084
|
+
onSandboxLog?.(event.entry);
|
|
3085
|
+
}
|
|
3086
|
+
break;
|
|
3087
|
+
case "error":
|
|
3088
|
+
if (event.error) {
|
|
3089
|
+
setError(event.error);
|
|
3090
|
+
onError?.(event.error);
|
|
3091
|
+
newEntries.push({
|
|
3092
|
+
id: `error-${Date.now()}`,
|
|
3093
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3094
|
+
entryType: { type: "error", message: event.error, code: event.code },
|
|
3095
|
+
content: event.error
|
|
3096
|
+
});
|
|
3097
|
+
}
|
|
3098
|
+
break;
|
|
3099
|
+
case "session_end":
|
|
3100
|
+
onSessionEnd?.(event.sessionId || sessionId || "", event.status || "completed");
|
|
3101
|
+
break;
|
|
3102
|
+
case "complete":
|
|
3103
|
+
if (newEntries.length > 0) {
|
|
3104
|
+
setHistoryEntries((prev) => [...prev, ...newEntries]);
|
|
3105
|
+
}
|
|
3106
|
+
resetStreamingState();
|
|
3107
|
+
return [];
|
|
3108
|
+
}
|
|
3109
|
+
return newEntries;
|
|
3110
|
+
}, [sessionId, onSessionStart, onSessionEnd, onError, onSandboxLog, createTextEntry, resetStreamingState]);
|
|
3111
|
+
const send = react.useCallback(async (prompt) => {
|
|
3112
|
+
if (isStreaming) return;
|
|
3113
|
+
setIsStreaming(true);
|
|
3114
|
+
setError(null);
|
|
3115
|
+
const userEntry = {
|
|
3116
|
+
id: `user-${Date.now()}`,
|
|
3117
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3118
|
+
entryType: { type: "user_message" },
|
|
3119
|
+
content: prompt
|
|
3120
|
+
};
|
|
3121
|
+
setHistoryEntries((prev) => [...prev, userEntry]);
|
|
3122
|
+
resetStreamingState();
|
|
3123
|
+
const controller = new AbortController();
|
|
3124
|
+
abortControllerRef.current = controller;
|
|
3125
|
+
let localStreamingEntries = [];
|
|
3126
|
+
try {
|
|
3127
|
+
const stream = createStream(prompt, sessionId || void 0);
|
|
3128
|
+
for await (const event of stream) {
|
|
3129
|
+
if (controller.signal.aborted) break;
|
|
3130
|
+
localStreamingEntries = processEvent(event, localStreamingEntries);
|
|
3131
|
+
emitStreamingEntries(localStreamingEntries);
|
|
3132
|
+
}
|
|
3133
|
+
if (localStreamingEntries.length > 0) {
|
|
3134
|
+
setHistoryEntries((prev) => [...prev, ...localStreamingEntries]);
|
|
3135
|
+
setStreamingEntries([]);
|
|
3136
|
+
}
|
|
3137
|
+
} catch (err) {
|
|
3138
|
+
if (err.name !== "AbortError") {
|
|
3139
|
+
const errorMessage = err instanceof Error ? err.message : "Unknown error";
|
|
3140
|
+
setError(errorMessage);
|
|
3141
|
+
onError?.(errorMessage);
|
|
3142
|
+
}
|
|
3143
|
+
} finally {
|
|
3144
|
+
setIsStreaming(false);
|
|
3145
|
+
abortControllerRef.current = null;
|
|
3146
|
+
resetStreamingState();
|
|
3147
|
+
}
|
|
3148
|
+
}, [isStreaming, sessionId, createStream, processEvent, emitStreamingEntries, resetStreamingState, onError]);
|
|
3149
|
+
const stop = react.useCallback(() => {
|
|
3150
|
+
if (abortControllerRef.current) {
|
|
3151
|
+
abortControllerRef.current.abort();
|
|
3152
|
+
}
|
|
3153
|
+
}, []);
|
|
3154
|
+
const clear = react.useCallback(() => {
|
|
3155
|
+
setHistoryEntries([]);
|
|
3156
|
+
resetStreamingState();
|
|
3157
|
+
setSessionId(initialSessionId || null);
|
|
3158
|
+
setError(null);
|
|
3159
|
+
}, [initialSessionId, resetStreamingState]);
|
|
3160
|
+
const setEntries = react.useCallback((newEntries) => {
|
|
3161
|
+
resetStreamingState();
|
|
3162
|
+
setHistoryEntries(newEntries);
|
|
3163
|
+
}, [resetStreamingState]);
|
|
3164
|
+
react.useEffect(() => {
|
|
3165
|
+
return () => {
|
|
3166
|
+
if (abortControllerRef.current) {
|
|
3167
|
+
abortControllerRef.current.abort();
|
|
3168
|
+
}
|
|
3169
|
+
};
|
|
3170
|
+
}, []);
|
|
3171
|
+
return {
|
|
3172
|
+
entries,
|
|
3173
|
+
isStreaming,
|
|
3174
|
+
error,
|
|
3175
|
+
sessionId,
|
|
3176
|
+
send,
|
|
3177
|
+
stop,
|
|
3178
|
+
clear,
|
|
3179
|
+
setEntries
|
|
3180
|
+
};
|
|
3181
|
+
}
|
|
2976
3182
|
|
|
2977
3183
|
exports.ActionIcon = ActionIcon;
|
|
2978
3184
|
exports.AlertCircleIcon = AlertCircleIcon;
|
|
@@ -3082,6 +3288,7 @@ exports.transitions = transitions;
|
|
|
3082
3288
|
exports.truncate = truncate;
|
|
3083
3289
|
exports.typography = typography;
|
|
3084
3290
|
exports.updateToolCallWithResult = updateToolCallWithResult;
|
|
3291
|
+
exports.useAgentChat = useAgentChat;
|
|
3085
3292
|
exports.useDisplayConfig = useDisplayConfig;
|
|
3086
3293
|
exports.useDisplayMode = useDisplayMode;
|
|
3087
3294
|
exports.useFileUpload = useFileUpload;
|