UNPKG

@llamaindex/ui

Version:

A comprehensive UI component library built with React, TypeScript, and Tailwind CSS for LlamaIndex applications

665 lines (658 loc) 25.9 kB
'use strict'; var chunkWGWQIMQI_js = require('./chunk-WGWQIMQI.js'); var chunkQYXTD7XU_js = require('./chunk-QYXTD7XU.js'); var chunk7RP7NPSE_js = require('./chunk-7RP7NPSE.js'); var chunkH5EM4XHA_js = require('./chunk-H5EM4XHA.js'); var chunk2YP352J4_js = require('./chunk-2YP352J4.js'); var chunkSJGLR4O2_js = require('./chunk-SJGLR4O2.js'); var chunkMCKPA5BO_js = require('./chunk-MCKPA5BO.js'); var chunkCODV6TUI_js = require('./chunk-CODV6TUI.js'); var chunkU3IWFKKJ_js = require('./chunk-U3IWFKKJ.js'); var chunk4E3IDRQJ_js = require('./chunk-4E3IDRQJ.js'); var react = require('react'); var valtio = require('valtio'); var workflowsClient = require('@llamaindex/workflows-client'); var sonner = require('sonner'); var jsxRuntime = require('react/jsx-runtime'); // src/shared/store.ts var globalStoreCache = /* @__PURE__ */ new Map(); function getOrCreate(key, factory) { if (!globalStoreCache.has(key)) { globalStoreCache.set(key, factory()); } return globalStoreCache.get(key); } // src/workflows/store/handler.ts var emptyState = { handler_id: "", workflow_name: "", status: "not_started", started_at: "", updated_at: void 0, completed_at: void 0, result: void 0, loading: true}; var createState = (rawHandler = {}) => { var _a, _b, _c, _d; const state = { handler_id: (_a = rawHandler.handler_id) != null ? _a : emptyState.handler_id, workflow_name: (_b = rawHandler.workflow_name) != null ? _b : emptyState.workflow_name, status: (_c = rawHandler.status) != null ? _c : emptyState.status, started_at: (_d = rawHandler.started_at) != null ? _d : emptyState.started_at, updated_at: rawHandler.updated_at ? new Date(rawHandler.updated_at) : emptyState.updated_at, completed_at: rawHandler.completed_at ? new Date(rawHandler.completed_at) : emptyState.completed_at, error: rawHandler.error, result: rawHandler.result ? chunkQYXTD7XU_js.StopEvent.fromRawEvent( rawHandler.result ) : emptyState.result, // use "status" field as a canary to indicate that this is a real response loading: rawHandler.status ? false : emptyState.loading, loadingError: void 0 }; return valtio.proxy(state); }; function createActions(state, client) { const actions = { async sendEvent(event, step) { if (!state.handler_id) { throw new Error("Handler ID is not yet initialized"); } const rawEvent = event instanceof chunkQYXTD7XU_js.WorkflowEvent ? event.toRawEvent() : event; const data = await workflowsClient.postEventsByHandlerId({ client, path: { handler_id: state.handler_id }, body: { event: rawEvent, step } }); return data.data; }, async sync() { var _a; state.loading = true; state.loadingError = void 0; const resolvedHandlerId = state.handler_id; if (!resolvedHandlerId) return; try { const data = await workflowsClient.getHandlersByHandlerId({ client, path: { handler_id: resolvedHandlerId } }); const updated = createState((_a = data.data) != null ? _a : {}); Object.assign(state, updated); } catch (error) { state.loadingError = error instanceof Error ? error.message : String(error); } finally { state.loading = false; } }, subscribeToEvents(callbacks, includeInternal = false) { if (!state.handler_id) { throw new Error("Handler ID is not yet initialized"); } const streamKey = `handler:${state.handler_id}`; const subscriber = { onStart: () => { var _a; state.status = "running"; (_a = callbacks == null ? void 0 : callbacks.onStart) == null ? void 0 : _a.call(callbacks); }, onData: (event) => { var _a; state.updated_at = /* @__PURE__ */ new Date(); (_a = callbacks == null ? void 0 : callbacks.onData) == null ? void 0 : _a.call(callbacks, event); }, onError: (error) => { var _a; state.status = "failed"; state.completed_at = /* @__PURE__ */ new Date(); state.updated_at = /* @__PURE__ */ new Date(); state.error = error.message; (_a = callbacks == null ? void 0 : callbacks.onError) == null ? void 0 : _a.call(callbacks, error); }, onSuccess: (events) => { var _a; state.status = "completed"; state.completed_at = /* @__PURE__ */ new Date(); state.updated_at = /* @__PURE__ */ new Date(); state.result = events[events.length - 1]; (_a = callbacks == null ? void 0 : callbacks.onSuccess) == null ? void 0 : _a.call(callbacks, events); }, onComplete: () => { var _a; state.completed_at = /* @__PURE__ */ new Date(); state.updated_at = /* @__PURE__ */ new Date(); (_a = callbacks == null ? void 0 : callbacks.onComplete) == null ? void 0 : _a.call(callbacks); } }; const canceler = async () => { await workflowsClient.postHandlersByHandlerIdCancel({ client, path: { handler_id: state.handler_id } }); }; const { promise, unsubscribe, disconnect, cancel } = chunk7RP7NPSE_js.workflowStreamingManager.subscribe( streamKey, subscriber, async (subscriber2, signal) => { return streamByEventSource( { client, handlerId: state.handler_id, includeInternal, abortSignal: signal }, subscriber2, actions, state ); }, canceler ); return { promise, unsubscribe, disconnect, cancel }; } }; return actions; } function streamByEventSource(params, callbacks, actions, state) { return new Promise((resolve) => { var _a; const baseUrl = ((_a = params.client.getConfig().baseUrl) != null ? _a : "").replace( /\/$/, "" ); const urlParams = new URLSearchParams(); urlParams.set("sse", "true"); if (params.includeInternal) { urlParams.set("include_internal", "true"); } const accumulatedEvents = []; const eventSource = new EventSource( `${baseUrl}/events/${encodeURIComponent(params.handlerId)}?${urlParams.toString()}`, { withCredentials: true } ); if (params.abortSignal) { params.abortSignal.addEventListener("abort", () => { eventSource.close(); }); } eventSource.addEventListener("message", (event) => { var _a2; chunkCODV6TUI_js.logger.debug("[streamByEventSource] message", JSON.parse(event.data)); const workflowEvent = chunkQYXTD7XU_js.WorkflowEvent.fromRawEvent( JSON.parse(event.data) ); (_a2 = callbacks.onData) == null ? void 0 : _a2.call(callbacks, workflowEvent); accumulatedEvents.push(workflowEvent); if (chunkQYXTD7XU_js.isStopEvent(workflowEvent)) { eventSource.close(); actions.sync().then(() => { var _a3, _b, _c; if (state.status === "completed") { (_a3 = callbacks.onSuccess) == null ? void 0 : _a3.call(callbacks, accumulatedEvents); } else if (state.status === "failed") { (_b = callbacks.onError) == null ? void 0 : _b.call(callbacks, new Error(state.error || "Server Error")); } else if (state.status === "cancelled") { (_c = callbacks.onCancel) == null ? void 0 : _c.call(callbacks); } else { throw new Error( `[This should never happen] Unexpected running status: ${state.status}` ); } resolve(accumulatedEvents); }); } }); eventSource.addEventListener("error", (event) => { chunkCODV6TUI_js.logger.warn("[streamByEventSource] error", event); return; }); eventSource.addEventListener("open", () => { var _a2; chunkCODV6TUI_js.logger.debug("[streamByEventSource] open"); (_a2 = callbacks.onStart) == null ? void 0 : _a2.call(callbacks); }); eventSource.addEventListener("close", () => { var _a2; chunkCODV6TUI_js.logger.debug("[streamByEventSource] close"); (_a2 = callbacks.onSuccess) == null ? void 0 : _a2.call(callbacks, accumulatedEvents); resolve(accumulatedEvents); }); }); } function applyUpdateToHandler(state, update) { const updated = createState(update); Object.assign(state, updated); return state; } // src/workflows/store/handlers.ts var createState2 = ({ query } = {}) => { return valtio.proxy({ query: query != null ? query : {}, loading: true, error: void 0, handlers: {} }); }; function createActions2(state, client) { return { async sync() { var _a, _b; state.loading = true; state.loadingError = void 0; try { const resp = await workflowsClient.getHandlers({ client, query: state.query }); const allHandlers = (_b = (_a = resp.data) == null ? void 0 : _a.handlers) != null ? _b : []; const newIds = new Set(allHandlers.map((h) => h.handler_id)); const oldIds = new Set(Object.keys(state.handlers)); for (const id of oldIds) { if (!newIds.has(id)) { delete state.handlers[id]; } } for (const h of allHandlers) { state.handlers[h.handler_id] = state.handlers[h.handler_id] ? applyUpdateToHandler(state.handlers[h.handler_id], h) : createState(h); } } catch (error) { state.loadingError = error instanceof Error ? error.message : String(error); } finally { state.loading = false; } }, setHandler(handler) { state.handlers[handler.handler_id] = handler; }, actions(handlerId) { return createActions(state.handlers[handlerId], client); } }; } function createState3() { return valtio.proxy({ workflows: {}, loading: true, error: void 0 }); } function createActions3(state, client) { return { async sync() { var _a, _b; state.loading = true; state.loadingError = void 0; try { const resp = await workflowsClient.getWorkflows({ client }); const allWorkflows = (_b = (_a = resp.data) == null ? void 0 : _a.workflows) != null ? _b : []; allWorkflows.forEach((name) => { state.workflows[name] = { name }; }); } catch (error) { state.loadingError = error instanceof Error ? error.message : String(error); } finally { state.loading = false; } }, setWorkflow(workflow) { state.workflows[workflow.name] = workflow; } }; } function createState4(name) { return valtio.proxy({ name, graph: null, loading: true, loadingError: void 0 }); } function createActions4(state, client) { return { async sync() { var _a, _b; state.loading = true; state.loadingError = void 0; try { const data = await workflowsClient.getWorkflowsByNameRepresentation({ client, path: { name: state.name } }); state.graph = (_b = (_a = data.data) == null ? void 0 : _a.graph) != null ? _b : null; } catch (error) { state.loadingError = error instanceof Error ? error.message : String(error); } finally { state.loading = false; } }, async runToCompletion(input) { const data = await workflowsClient.postWorkflowsByNameRun({ client, path: { name: state.name }, body: { start_event: input } }); if (!data.data) { throw new Error(`Workflow run empty, response ${JSON.stringify(data)}`); } return createState(data.data); }, async createHandler(input, handlerId) { const data = await workflowsClient.postWorkflowsByNameRunNowait({ client, path: { name: state.name }, body: { start_event: input, handler_id: handlerId } }); if (!data.data) { throw new Error("Handler creation failed"); } return createState(data.data); } }; } // src/workflows/hooks/index.ts function useHandlers({ query, sync = true } = {}) { const client = chunkSJGLR4O2_js.useWorkflowsClient(); const state = getOrCreate( `handlers:${JSON.stringify(query)}`, () => createState2({ query: query != null ? query : {} }) ); const actions = react.useMemo(() => createActions2(state, client), [state, client]); react.useEffect(() => { if (sync) { actions.sync(); } }, [actions, sync]); return chunk4E3IDRQJ_js.__spreadValues({ state: valtio.useSnapshot(state) }, actions); } function useWorkflows({ sync = true } = {}) { const client = chunkSJGLR4O2_js.useWorkflowsClient(); const state = getOrCreate( "workflows", () => createState3() ); const actions = react.useMemo( () => createActions3(state, client), [state, client] ); react.useEffect(() => { if (sync) { actions.sync(); } }, [actions, sync]); return chunk4E3IDRQJ_js.__spreadValues({ state: valtio.useSnapshot(state) }, actions); } function useWorkflow(name) { const client = chunkSJGLR4O2_js.useWorkflowsClient(); const state = getOrCreate( `workflow:${name}`, () => createState4(name) ); const actions = react.useMemo( () => createActions4(state, client), [state, client] ); return chunk4E3IDRQJ_js.__spreadValues({ state: valtio.useSnapshot(state) }, actions); } function useHandler(handlerId, { sync = true } = {}) { const client = chunkSJGLR4O2_js.useWorkflowsClient(); const state = getOrCreate( `handler:${handlerId}`, () => createState({ handler_id: handlerId != null ? handlerId : void 0 }) ); const actions = react.useMemo( () => createActions(state, client), [state, client] ); react.useEffect(() => { if (sync) { actions.sync(); } }, [actions, sync, handlerId]); return chunk4E3IDRQJ_js.__spreadValues({ state: valtio.useSnapshot(state) }, actions); } function WorkflowTrigger(_a) { var _b = _a, { workflowName, customWorkflowInput, onSuccess, onError, title, description = "Upload files to start workflow processing" } = _b, fileUploaderProps = chunk4E3IDRQJ_js.__objRest(_b, [ "workflowName", "customWorkflowInput", "onSuccess", "onError", "title", "description" ]); const { createHandler } = useWorkflow(workflowName); const [isCreating, setIsCreating] = react.useState(false); const handleFileUpload = react.useCallback( async (data, fieldValues) => { try { const workflowInput = customWorkflowInput ? customWorkflowInput(data, fieldValues) : chunk4E3IDRQJ_js.__spreadValues({ files: data.map((file) => ({ fileId: file.fileId, url: file.url, name: file.file.name, type: file.file.type })) }, fieldValues); setIsCreating(true); const handler = await createHandler(workflowInput); onSuccess == null ? void 0 : onSuccess(handler); } catch (err) { const error = err instanceof Error ? err : new Error(String(err)); sonner.toast.error(`Failed to create workflow task: ${error.message}`); onError == null ? void 0 : onError(error); throw error; } finally { setIsCreating(false); } }, [createHandler, onSuccess, onError, customWorkflowInput] ); return /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx( chunkMCKPA5BO_js.FileUploader, chunk4E3IDRQJ_js.__spreadValues({ title, description, onSuccess: handleFileUpload, isProcessing: isCreating }, fileUploaderProps) ) }); } function HandlerList({ onSelectHandler }) { const { state, sync } = useHandlers(); const handlerList = Object.values(state.handlers); const getStatusColor = (status) => { switch (status) { case "running": return "bg-blue-500"; case "completed": return "bg-green-500"; case "failed": return "bg-red-500"; case "cancelled": return "bg-gray-500"; default: return "bg-gray-400"; } }; return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-semibold", children: "Workflow Handlers" }), /* @__PURE__ */ jsxRuntime.jsx(chunkU3IWFKKJ_js.Button, { onClick: () => sync(), variant: "outline", children: "Refresh" }) ] }), handlerList.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(chunk2YP352J4_js.Card, { children: /* @__PURE__ */ jsxRuntime.jsx(chunk2YP352J4_js.CardContent, { className: "pt-6", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-center text-muted-foreground", children: "No handlers found. Create a workflow to get started." }) }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: handlerList.map((handler) => { var _a; return /* @__PURE__ */ jsxRuntime.jsxs( chunk2YP352J4_js.Card, { className: "cursor-pointer hover:bg-accent transition-colors", onClick: () => onSelectHandler == null ? void 0 : onSelectHandler(handler.handler_id), children: [ /* @__PURE__ */ jsxRuntime.jsx(chunk2YP352J4_js.CardHeader, { className: "pb-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [ /* @__PURE__ */ jsxRuntime.jsx(chunk2YP352J4_js.CardTitle, { className: "text-sm font-medium", children: handler.workflow_name }), /* @__PURE__ */ jsxRuntime.jsx(chunkH5EM4XHA_js.Badge, { className: getStatusColor(handler.status), children: handler.status }) ] }) }), /* @__PURE__ */ jsxRuntime.jsx(chunk2YP352J4_js.CardContent, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-muted-foreground space-y-1", children: [ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "ID:" }), " ", handler.handler_id.slice(0, 8), "..." ] }), /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Started:" }), " ", handler.started_at.toLocaleString() ] }), handler.completed_at && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Completed:" }), " ", (_a = handler.completed_at) == null ? void 0 : _a.toLocaleString() ] }) ] }) }) ] }, handler.handler_id ); }) }) ] }); } function HandlerDetails({ handlerId, onBack }) { const { state, subscribeToEvents } = useHandler(handlerId); const [events, setEvents] = react.useState([]); const [isStreaming, setIsStreaming] = react.useState(false); react.useEffect(() => { if (state.status === "running") { setIsStreaming(true); const { disconnect } = subscribeToEvents( { onData: (event) => { setEvents((prev) => [...prev, event]); }, onSuccess: (allEvents) => { setEvents(allEvents); setIsStreaming(false); }, onError: () => { setIsStreaming(false); }, onComplete: () => { setIsStreaming(false); } }, true ); return () => disconnect(); } }, [state.status, subscribeToEvents]); const getStatusColor = (status) => { switch (status) { case "running": return "bg-blue-500"; case "completed": return "bg-green-500"; case "failed": return "bg-red-500"; case "cancelled": return "bg-gray-500"; default: return "bg-gray-400"; } }; return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-semibold", children: "Handler Details" }), onBack && /* @__PURE__ */ jsxRuntime.jsx(chunkU3IWFKKJ_js.Button, { onClick: onBack, variant: "outline", children: "Back to List" }) ] }), /* @__PURE__ */ jsxRuntime.jsxs(chunk2YP352J4_js.Card, { children: [ /* @__PURE__ */ jsxRuntime.jsx(chunk2YP352J4_js.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [ /* @__PURE__ */ jsxRuntime.jsx(chunk2YP352J4_js.CardTitle, { children: state.workflow_name }), /* @__PURE__ */ jsxRuntime.jsx(chunkH5EM4XHA_js.Badge, { className: getStatusColor(state.status), children: state.status }) ] }) }), /* @__PURE__ */ jsxRuntime.jsxs(chunk2YP352J4_js.CardContent, { className: "space-y-4", children: [ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-4 text-sm", children: [ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-muted-foreground", children: "Handler ID:" }), /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 font-mono text-xs break-all", children: state.handler_id }) ] }), /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-muted-foreground", children: "Started At:" }), /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1", children: state.started_at.toLocaleString() }) ] }), state.updated_at && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-muted-foreground", children: "Updated At:" }), /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1", children: state.updated_at.toLocaleString() }) ] }), state.completed_at && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-muted-foreground", children: "Completed At:" }), /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1", children: state.completed_at.toLocaleString() }) ] }) ] }), state.error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-destructive/10 p-3", children: [ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-destructive", children: "Error:" }), /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-destructive", children: state.error }) ] }), state.result && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-green-50 dark:bg-green-900/10 p-3", children: [ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-green-700 dark:text-green-400", children: "Result:" }), /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "mt-1 text-xs overflow-auto", children: JSON.stringify(state.result.data, null, 2) }) ] }) ] }) ] }), /* @__PURE__ */ jsxRuntime.jsxs(chunk2YP352J4_js.Card, { children: [ /* @__PURE__ */ jsxRuntime.jsx(chunk2YP352J4_js.CardHeader, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [ /* @__PURE__ */ jsxRuntime.jsx(chunk2YP352J4_js.CardTitle, { children: "Events" }), isStreaming && /* @__PURE__ */ jsxRuntime.jsx(chunkH5EM4XHA_js.Badge, { variant: "outline", className: "animate-pulse", children: "Streaming..." }) ] }) }), /* @__PURE__ */ jsxRuntime.jsx(chunk2YP352J4_js.CardContent, { children: /* @__PURE__ */ jsxRuntime.jsx(chunkWGWQIMQI_js.ScrollArea, { className: "h-[400px]", children: events.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-center text-muted-foreground py-8", children: "No events yet. Waiting for workflow events..." }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: events.map((event, index) => /* @__PURE__ */ jsxRuntime.jsxs( "div", { className: "rounded-lg border p-3 text-sm space-y-2", children: [ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [ /* @__PURE__ */ jsxRuntime.jsx(chunkH5EM4XHA_js.Badge, { variant: "secondary", children: event.type }), /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: event.timestamp.toLocaleTimeString() }) ] }), event.data && /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-xs overflow-auto bg-muted p-2 rounded", children: JSON.stringify(event.data, null, 2) }) ] }, index )) }) }) }) ] }) ] }); } exports.HandlerDetails = HandlerDetails; exports.HandlerList = HandlerList; exports.WorkflowTrigger = WorkflowTrigger; exports.useHandler = useHandler; exports.useHandlers = useHandlers; exports.useWorkflow = useWorkflow; exports.useWorkflows = useWorkflows;