@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 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;