@ash-cloud/ash-ui 0.0.4 → 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.js CHANGED
@@ -1736,6 +1736,9 @@ function isToolCallEntry(entry) {
1736
1736
  function isErrorEntry(entry) {
1737
1737
  return entry.type === "error";
1738
1738
  }
1739
+ function isWidgetEntry(entry) {
1740
+ return entry.type === "widget";
1741
+ }
1739
1742
  var DEFAULT_DISPLAY_CONFIG = {
1740
1743
  mode: "inline",
1741
1744
  breakEveryNToolCalls: 0,
@@ -1791,10 +1794,25 @@ function MessageList({
1791
1794
  streamingContent,
1792
1795
  displayConfig: displayConfigProp,
1793
1796
  onOptionSelect,
1797
+ renderWidget,
1798
+ onWidgetAction,
1794
1799
  className
1795
1800
  }) {
1796
1801
  const contextConfig = useDisplayConfig();
1797
1802
  const config = displayConfigProp || contextConfig;
1803
+ const createWidgetActionHandler = useCallback(
1804
+ (entryId, widgetType) => {
1805
+ if (!onWidgetAction) return void 0;
1806
+ return (action) => {
1807
+ onWidgetAction({
1808
+ ...action,
1809
+ entryId,
1810
+ widgetType
1811
+ });
1812
+ };
1813
+ },
1814
+ [onWidgetAction]
1815
+ );
1798
1816
  const groupedEntries = useMemo(() => {
1799
1817
  if (config.mode === "inline") {
1800
1818
  return entries.map((entry) => ({
@@ -1808,7 +1826,20 @@ function MessageList({
1808
1826
  return /* @__PURE__ */ jsxs("div", { className: cn("flex-1 overflow-y-auto p-4 space-y-4 ash-scrollbar", className), children: [
1809
1827
  groupedEntries.map((groupedEntry) => {
1810
1828
  if (groupedEntry.type === "single") {
1811
- return /* @__PURE__ */ jsx(MessageEntry, { entry: groupedEntry.entry, onOptionSelect }, groupedEntry.entry.id);
1829
+ const entry = groupedEntry.entry;
1830
+ if (entry.entryType.type === "widget" && renderWidget) {
1831
+ const widgetEntry = entry.entryType;
1832
+ const widgetContent = renderWidget({
1833
+ entry,
1834
+ widgetType: widgetEntry.widgetType,
1835
+ widgetData: widgetEntry.widgetData,
1836
+ onAction: createWidgetActionHandler(entry.id, widgetEntry.widgetType)
1837
+ });
1838
+ if (widgetContent !== null) {
1839
+ return /* @__PURE__ */ jsx("div", { className: "ash-animate-fade-in", children: widgetContent }, entry.id);
1840
+ }
1841
+ }
1842
+ return /* @__PURE__ */ jsx(MessageEntry, { entry, onOptionSelect }, entry.id);
1812
1843
  }
1813
1844
  const toolCalls = extractToolCallsFromGroup(groupedEntry.entries);
1814
1845
  return /* @__PURE__ */ jsxs("div", { className: "flex gap-3 ash-animate-fade-in", children: [
@@ -2936,7 +2967,213 @@ function useFileUpload({
2936
2967
  openFilePicker
2937
2968
  };
2938
2969
  }
2970
+ function useAgentChat(options) {
2971
+ const {
2972
+ createStream,
2973
+ initialSessionId,
2974
+ initialEntries = [],
2975
+ onSessionStart,
2976
+ onSessionEnd,
2977
+ onError,
2978
+ onSandboxLog
2979
+ } = options;
2980
+ const [historyEntries, setHistoryEntries] = useState(initialEntries);
2981
+ const [streamingEntries, setStreamingEntries] = useState([]);
2982
+ const [isStreaming, setIsStreaming] = useState(false);
2983
+ const [error, setError] = useState(null);
2984
+ const [sessionId, setSessionId] = useState(initialSessionId || null);
2985
+ const abortControllerRef = useRef(null);
2986
+ const currentTextRef = useRef("");
2987
+ const currentTextIdRef = useRef(null);
2988
+ const pendingToolCallsRef = useRef(/* @__PURE__ */ new Map());
2989
+ const hadToolCallSinceTextRef = useRef(false);
2990
+ const entries = [...historyEntries, ...streamingEntries];
2991
+ const emitStreamingEntries = useCallback((newEntries) => {
2992
+ setStreamingEntries([...newEntries]);
2993
+ }, []);
2994
+ const createTextEntry = useCallback((id, content) => ({
2995
+ id,
2996
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2997
+ entryType: { type: "assistant_message" },
2998
+ content
2999
+ }), []);
3000
+ const resetStreamingState = useCallback(() => {
3001
+ currentTextRef.current = "";
3002
+ currentTextIdRef.current = null;
3003
+ pendingToolCallsRef.current.clear();
3004
+ hadToolCallSinceTextRef.current = false;
3005
+ setStreamingEntries([]);
3006
+ }, []);
3007
+ const processEvent = useCallback((event, streamEntries) => {
3008
+ const newEntries = [...streamEntries];
3009
+ switch (event.type) {
3010
+ case "session_start":
3011
+ if (event.sessionId) {
3012
+ setSessionId(event.sessionId);
3013
+ onSessionStart?.(event.sessionId);
3014
+ }
3015
+ break;
3016
+ case "text_delta":
3017
+ if (event.delta) {
3018
+ if (hadToolCallSinceTextRef.current && currentTextIdRef.current) {
3019
+ currentTextRef.current = "";
3020
+ currentTextIdRef.current = null;
3021
+ hadToolCallSinceTextRef.current = false;
3022
+ }
3023
+ currentTextRef.current += event.delta;
3024
+ if (!currentTextIdRef.current) {
3025
+ currentTextIdRef.current = `text-${Date.now()}-${Math.random().toString(36).slice(2)}`;
3026
+ newEntries.push(createTextEntry(currentTextIdRef.current, currentTextRef.current));
3027
+ } else {
3028
+ const entryIndex = newEntries.findIndex((e) => e.id === currentTextIdRef.current);
3029
+ if (entryIndex !== -1) {
3030
+ newEntries[entryIndex] = createTextEntry(currentTextIdRef.current, currentTextRef.current);
3031
+ }
3032
+ }
3033
+ }
3034
+ break;
3035
+ case "tool_use":
3036
+ if (event.toolId && event.toolName) {
3037
+ currentTextRef.current = "";
3038
+ currentTextIdRef.current = null;
3039
+ hadToolCallSinceTextRef.current = true;
3040
+ const toolCall = createToolCall({
3041
+ id: event.toolId,
3042
+ name: event.toolName,
3043
+ input: event.input
3044
+ });
3045
+ const entry = {
3046
+ id: event.toolId,
3047
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3048
+ entryType: { type: "tool_call", toolCall },
3049
+ content: toolCall.summary
3050
+ };
3051
+ const entryIndex = newEntries.length;
3052
+ newEntries.push(entry);
3053
+ pendingToolCallsRef.current.set(event.toolId, { entryIndex, toolCall });
3054
+ }
3055
+ break;
3056
+ case "tool_result":
3057
+ if (event.toolId) {
3058
+ const pending = pendingToolCallsRef.current.get(event.toolId);
3059
+ if (pending) {
3060
+ const updatedToolCall = updateToolCallWithResult(
3061
+ pending.toolCall,
3062
+ event.toolResult,
3063
+ event.isError
3064
+ );
3065
+ const existingEntry = newEntries[pending.entryIndex];
3066
+ if (existingEntry && existingEntry.entryType.type === "tool_call") {
3067
+ newEntries[pending.entryIndex] = {
3068
+ ...existingEntry,
3069
+ entryType: { type: "tool_call", toolCall: updatedToolCall }
3070
+ };
3071
+ }
3072
+ pendingToolCallsRef.current.delete(event.toolId);
3073
+ }
3074
+ }
3075
+ break;
3076
+ case "sandbox_log":
3077
+ if (event.entry) {
3078
+ onSandboxLog?.(event.entry);
3079
+ }
3080
+ break;
3081
+ case "error":
3082
+ if (event.error) {
3083
+ setError(event.error);
3084
+ onError?.(event.error);
3085
+ newEntries.push({
3086
+ id: `error-${Date.now()}`,
3087
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3088
+ entryType: { type: "error", message: event.error, code: event.code },
3089
+ content: event.error
3090
+ });
3091
+ }
3092
+ break;
3093
+ case "session_end":
3094
+ onSessionEnd?.(event.sessionId || sessionId || "", event.status || "completed");
3095
+ break;
3096
+ case "complete":
3097
+ if (newEntries.length > 0) {
3098
+ setHistoryEntries((prev) => [...prev, ...newEntries]);
3099
+ }
3100
+ resetStreamingState();
3101
+ return [];
3102
+ }
3103
+ return newEntries;
3104
+ }, [sessionId, onSessionStart, onSessionEnd, onError, onSandboxLog, createTextEntry, resetStreamingState]);
3105
+ const send = useCallback(async (prompt) => {
3106
+ if (isStreaming) return;
3107
+ setIsStreaming(true);
3108
+ setError(null);
3109
+ const userEntry = {
3110
+ id: `user-${Date.now()}`,
3111
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3112
+ entryType: { type: "user_message" },
3113
+ content: prompt
3114
+ };
3115
+ setHistoryEntries((prev) => [...prev, userEntry]);
3116
+ resetStreamingState();
3117
+ const controller = new AbortController();
3118
+ abortControllerRef.current = controller;
3119
+ let localStreamingEntries = [];
3120
+ try {
3121
+ const stream = createStream(prompt, sessionId || void 0);
3122
+ for await (const event of stream) {
3123
+ if (controller.signal.aborted) break;
3124
+ localStreamingEntries = processEvent(event, localStreamingEntries);
3125
+ emitStreamingEntries(localStreamingEntries);
3126
+ }
3127
+ if (localStreamingEntries.length > 0) {
3128
+ setHistoryEntries((prev) => [...prev, ...localStreamingEntries]);
3129
+ setStreamingEntries([]);
3130
+ }
3131
+ } catch (err) {
3132
+ if (err.name !== "AbortError") {
3133
+ const errorMessage = err instanceof Error ? err.message : "Unknown error";
3134
+ setError(errorMessage);
3135
+ onError?.(errorMessage);
3136
+ }
3137
+ } finally {
3138
+ setIsStreaming(false);
3139
+ abortControllerRef.current = null;
3140
+ resetStreamingState();
3141
+ }
3142
+ }, [isStreaming, sessionId, createStream, processEvent, emitStreamingEntries, resetStreamingState, onError]);
3143
+ const stop = useCallback(() => {
3144
+ if (abortControllerRef.current) {
3145
+ abortControllerRef.current.abort();
3146
+ }
3147
+ }, []);
3148
+ const clear = useCallback(() => {
3149
+ setHistoryEntries([]);
3150
+ resetStreamingState();
3151
+ setSessionId(initialSessionId || null);
3152
+ setError(null);
3153
+ }, [initialSessionId, resetStreamingState]);
3154
+ const setEntries = useCallback((newEntries) => {
3155
+ resetStreamingState();
3156
+ setHistoryEntries(newEntries);
3157
+ }, [resetStreamingState]);
3158
+ useEffect(() => {
3159
+ return () => {
3160
+ if (abortControllerRef.current) {
3161
+ abortControllerRef.current.abort();
3162
+ }
3163
+ };
3164
+ }, []);
3165
+ return {
3166
+ entries,
3167
+ isStreaming,
3168
+ error,
3169
+ sessionId,
3170
+ send,
3171
+ stop,
3172
+ clear,
3173
+ setEntries
3174
+ };
3175
+ }
2939
3176
 
2940
- export { ActionIcon, AlertCircleIcon, AlertTriangleIcon, AssistantMessage, BotIcon, BrainIcon, BugIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CircleIcon, ClipboardListIcon, CodeBlock, CodeIcon, CompactToolStatusLine, CopyIcon, DEFAULT_DISPLAY_CONFIG, DisplayModeProvider, DisplayModeToggle, EditIcon, EnvVarsPanel, ErrorIcon, ErrorMessage, FileIcon, FilePlusIcon, FolderSearchIcon, GlobeIcon, InfoIcon, JsonDisplay, ListChecksIcon, LoaderIcon, LoadingIndicator, LogsPanel, MessageEntry, MessageList, MessageSquareIcon, MoonIcon, OptionCards, PaperclipIcon, PlugIcon, SearchIcon, SendIcon, SparklesIcon, SpinnerIcon, StatusIndicator, StepAccordion, StopCircleIcon, StreamingText, SunIcon, TerminalIcon, ThemeProvider, ThinkingMessage, TodoPanel, ToolCallCard, ToolCallMessage, ToolExecutionGroup, ToolIcon, TypewriterText, UserIcon, UserMessage, XCircleIcon, XIcon, allKeyframesCss, borderRadius, cn, colors, createToolCall, extractTextContent, extractToolCallsFromGroup, formatFileSize, formatTimestamp, formatToolName, generateToolSummary, getActionIcon, getActionLabel, groupEntriesForCompactMode, inlineStyles, isCommandRunAction, isErrorEntry, isFileEditAction, isFileReadAction, isFileWriteAction, isGenericToolAction, isGlobAction, isMcpToolAction, isSearchAction, isTodoWriteAction, isToolCallEntry, isWebFetchAction, isWebSearchAction, keyframes, keyframesCss, mapToolToActionType, normalizeToolResult, parseCommandResult, parseMcpToolName, parseOptionsFromContent, shadows, spacing, tokensToCssVariables, transitions, truncate, typography, updateToolCallWithResult, useDisplayConfig, useDisplayMode, useFileUpload, useMessageQueue, useStopExecution, useTheme, widget, zIndex };
3177
+ export { ActionIcon, AlertCircleIcon, AlertTriangleIcon, AssistantMessage, BotIcon, BrainIcon, BugIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CircleIcon, ClipboardListIcon, CodeBlock, CodeIcon, CompactToolStatusLine, CopyIcon, DEFAULT_DISPLAY_CONFIG, DisplayModeProvider, DisplayModeToggle, EditIcon, EnvVarsPanel, ErrorIcon, ErrorMessage, FileIcon, FilePlusIcon, FolderSearchIcon, GlobeIcon, InfoIcon, JsonDisplay, ListChecksIcon, LoaderIcon, LoadingIndicator, LogsPanel, MessageEntry, MessageList, MessageSquareIcon, MoonIcon, OptionCards, PaperclipIcon, PlugIcon, SearchIcon, SendIcon, SparklesIcon, SpinnerIcon, StatusIndicator, StepAccordion, StopCircleIcon, StreamingText, SunIcon, TerminalIcon, ThemeProvider, ThinkingMessage, TodoPanel, ToolCallCard, ToolCallMessage, ToolExecutionGroup, ToolIcon, TypewriterText, UserIcon, UserMessage, XCircleIcon, XIcon, allKeyframesCss, borderRadius, cn, colors, createToolCall, extractTextContent, extractToolCallsFromGroup, formatFileSize, formatTimestamp, formatToolName, generateToolSummary, getActionIcon, getActionLabel, groupEntriesForCompactMode, inlineStyles, isCommandRunAction, isErrorEntry, isFileEditAction, isFileReadAction, isFileWriteAction, isGenericToolAction, isGlobAction, isMcpToolAction, isSearchAction, isTodoWriteAction, isToolCallEntry, isWebFetchAction, isWebSearchAction, isWidgetEntry, keyframes, keyframesCss, mapToolToActionType, normalizeToolResult, parseCommandResult, parseMcpToolName, parseOptionsFromContent, shadows, spacing, tokensToCssVariables, transitions, truncate, typography, updateToolCallWithResult, useAgentChat, useDisplayConfig, useDisplayMode, useFileUpload, useMessageQueue, useStopExecution, useTheme, widget, zIndex };
2941
3178
  //# sourceMappingURL=index.js.map
2942
3179
  //# sourceMappingURL=index.js.map