@llamaindex/ui
Version:
A comprehensive UI component library built with React, TypeScript, and Tailwind CSS for LlamaIndex applications
629 lines (621 loc) • 20.4 kB
JavaScript
;
var chunkQYXTD7XU_js = require('./chunk-QYXTD7XU.js');
var chunkSJGLR4O2_js = require('./chunk-SJGLR4O2.js');
var chunkOLGUSX5G_js = require('./chunk-OLGUSX5G.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');
var createState = () => {
return valtio.proxy({ handlers: {} });
};
function createActions(state, client) {
return {
async sync() {
var _a, _b;
const resp = await workflowsClient.getHandlers({
client
});
const allHandlers = (_b = (_a = resp.data) == null ? void 0 : _a.handlers) != null ? _b : [];
allHandlers.forEach((h) => {
state.handlers[h.handler_id] = {
handler_id: h.handler_id,
workflow_name: h.workflow_name,
status: h.status,
started_at: h.started_at,
updated_at: h.updated_at ? new Date(h.updated_at) : void 0,
completed_at: h.completed_at ? new Date(h.completed_at) : void 0,
error: h.error,
result: h.result ? chunkQYXTD7XU_js.StopEvent.fromRawEvent(
h.result
) : void 0
};
});
},
setHandler(handler) {
state.handlers[handler.handler_id] = handler;
}
};
}
// 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);
}
function createState2() {
return valtio.proxy({ workflows: {} });
}
function createActions2(state, client) {
return {
async sync() {
var _a, _b;
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 };
});
},
setWorkflow(workflow) {
state.workflows[workflow.name] = workflow;
}
};
}
// src/lib/shared-streaming.ts
var SharedStreamingManager = class {
constructor() {
chunk4E3IDRQJ_js.__publicField(this, "activeStreams", /* @__PURE__ */ new Map());
}
/**
* Subscribe to a shared stream identified by key.
* If stream already exists, reuses it and sends historical events.
* If stream doesn't exist, creates a new one using the executor.
*
* @param streamKey - Unique identifier for the stream
* @param subscriber - Event handlers for the stream
* @param executor - Function that performs the actual streaming
* @param externalSignal - Optional abort signal from caller
* @returns Promise that resolves with all events and unsubscribe function
*/
subscribe(streamKey, subscriber, executor, canceler) {
const existingStream = this.activeStreams.get(streamKey);
if (existingStream) {
return this.subscribeToExistingStream(
streamKey,
existingStream,
subscriber
);
}
return this.createNewStream(streamKey, subscriber, executor, canceler);
}
/**
* Get current events for a stream without subscribing
*/
getStreamEvents(streamKey) {
const stream = this.activeStreams.get(streamKey);
return stream ? [...stream.events] : [];
}
/**
* Check if a stream is currently active
*/
isStreamActive(streamKey) {
return this.activeStreams.has(streamKey);
}
/**
* Get number of subscribers for a stream
*/
getSubscriberCount(streamKey) {
const stream = this.activeStreams.get(streamKey);
return stream ? stream.subscribers.size : 0;
}
/**
* Force close a stream and all its subscribers
*/
closeStream(streamKey) {
const stream = this.activeStreams.get(streamKey);
if (stream) {
stream.controller.abort();
this.cleanupStream(streamKey);
}
}
/**
* Close all active streams
*/
closeAllStreams() {
for (const streamKey of this.activeStreams.keys()) {
this.closeStream(streamKey);
}
}
subscribeToExistingStream(streamKey, stream, subscriber) {
var _a, _b, _c, _d, _e;
stream.subscribers.add(subscriber);
try {
(_a = subscriber.onStart) == null ? void 0 : _a.call(subscriber);
for (const event of stream.events) {
(_b = subscriber.onData) == null ? void 0 : _b.call(subscriber, event);
}
if (stream.isCompleted) {
if (stream.error) {
(_c = subscriber.onError) == null ? void 0 : _c.call(subscriber, stream.error);
} else {
(_d = subscriber.onSuccess) == null ? void 0 : _d.call(subscriber, stream.events);
}
(_e = subscriber.onComplete) == null ? void 0 : _e.call(subscriber);
}
} catch (error) {
console.error("Error sending historical events to subscriber:", error);
}
return {
promise: stream.promise,
unsubscribe: () => this.unsubscribe(streamKey, subscriber),
disconnect: () => this.disconnect(streamKey),
cancel: () => this.cancel(streamKey)
};
}
createNewStream(streamKey, subscriber, executor, canceler) {
const controller = new AbortController();
const subscribers = /* @__PURE__ */ new Set([subscriber]);
const events = [];
const streamState = {
controller,
promise: Promise.resolve([]),
// Will be replaced below
subscribers,
events,
isCompleted: false,
error: null,
canceler
};
this.activeStreams.set(streamKey, streamState);
const compositeSubscriber = {
onStart: () => {
streamState.subscribers.forEach((sub) => {
var _a;
try {
(_a = sub.onStart) == null ? void 0 : _a.call(sub);
} catch (error) {
console.error("Error in subscriber onStart:", error);
}
});
},
onData: (event) => {
events.push(event);
streamState.subscribers.forEach((sub) => {
var _a;
try {
(_a = sub.onData) == null ? void 0 : _a.call(sub, event);
} catch (error) {
console.error("Error in subscriber onData:", error);
}
});
},
onError: (error) => {
streamState.error = error;
streamState.isCompleted = true;
streamState.subscribers.forEach((sub) => {
var _a, _b;
try {
(_a = sub.onError) == null ? void 0 : _a.call(sub, error);
(_b = sub.onComplete) == null ? void 0 : _b.call(sub);
} catch (err) {
console.error("Error in subscriber onError:", err);
}
});
this.cleanupStream(streamKey);
},
onSuccess: (allEvents) => {
streamState.isCompleted = true;
streamState.subscribers.forEach((sub) => {
var _a, _b;
try {
(_a = sub.onSuccess) == null ? void 0 : _a.call(sub, allEvents);
(_b = sub.onComplete) == null ? void 0 : _b.call(sub);
} catch (error) {
console.error("Error in subscriber onFinish:", error);
}
});
this.cleanupStream(streamKey);
}
};
const streamPromise = this.executeStream(
executor,
compositeSubscriber,
controller.signal
);
streamState.promise = streamPromise;
return {
promise: streamPromise,
unsubscribe: () => this.unsubscribe(streamKey, subscriber),
cancel: () => this.cancel(streamKey),
disconnect: () => this.disconnect(streamKey)
};
}
async executeStream(executor, subscriber, signal) {
var _a;
try {
return await executor(subscriber, signal);
} catch (error) {
const err = error instanceof Error ? error : new Error(String(error));
(_a = subscriber.onError) == null ? void 0 : _a.call(subscriber, err);
throw err;
}
}
async cancel(streamKey) {
const stream = this.activeStreams.get(streamKey);
this.disconnect(streamKey);
await (stream == null ? void 0 : stream.canceler());
}
disconnect(streamKey) {
const stream = this.activeStreams.get(streamKey);
if (stream) {
for (const subscriber of stream.subscribers) {
this.unsubscribe(streamKey, subscriber);
}
this.cleanupStream(streamKey);
}
}
unsubscribe(streamKey, subscriber) {
const stream = this.activeStreams.get(streamKey);
if (!stream) return;
stream.subscribers.delete(subscriber);
if (stream.subscribers.size === 0) {
try {
stream.controller.abort();
} catch (error) {
chunkOLGUSX5G_js.logger.debug("Error aborting stream in unsubscribe", error);
}
this.cleanupStream(streamKey);
}
}
cleanupStream(streamKey) {
this.activeStreams.delete(streamKey);
}
};
var workflowStreamingManager = new SharedStreamingManager();
var emptyState = {
handler_id: "",
workflow_name: "",
status: "not_started",
started_at: "",
updated_at: void 0,
completed_at: void 0,
error: "",
result: void 0
};
var createState3 = (rawHandler) => {
const state = rawHandler ? {
handler_id: rawHandler.handler_id,
workflow_name: rawHandler.workflow_name,
status: rawHandler.status,
started_at: rawHandler.started_at,
updated_at: rawHandler.updated_at ? new Date(rawHandler.updated_at) : void 0,
completed_at: rawHandler.completed_at ? new Date(rawHandler.completed_at) : void 0,
error: rawHandler.error,
result: rawHandler.result ? chunkQYXTD7XU_js.StopEvent.fromRawEvent(
rawHandler.result
) : void 0
} : emptyState;
return valtio.proxy(state);
};
function createActions3(state, client) {
const actions = {
async sendEvent(event, step) {
const rawEvent = event.toRawEvent();
const data = await workflowsClient.postEventsByHandlerId({
client,
path: { handler_id: state.handler_id },
body: {
event: rawEvent,
step
}
});
return data.data;
},
async sync(handlerId) {
var _a, _b, _c;
const data = await workflowsClient.getHandlersByHandlerId({
client,
path: { handler_id: handlerId != null ? handlerId : state.handler_id }
});
Object.assign(state, data.data, {
updated_at: ((_a = data.data) == null ? void 0 : _a.updated_at) ? new Date(data.data.updated_at) : void 0,
completed_at: ((_b = data.data) == null ? void 0 : _b.completed_at) ? new Date(data.data.completed_at) : void 0,
result: ((_c = data.data) == null ? void 0 : _c.result) ? chunkQYXTD7XU_js.StopEvent.fromRawEvent(
data.data.result
) : void 0
});
},
subscribeToEvents(callbacks, includeInternal = false) {
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 } = 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;
chunkOLGUSX5G_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) => {
chunkOLGUSX5G_js.logger.warn("[streamByEventSource] error", event);
return;
});
eventSource.addEventListener("open", () => {
var _a2;
chunkOLGUSX5G_js.logger.debug("[streamByEventSource] open");
(_a2 = callbacks.onStart) == null ? void 0 : _a2.call(callbacks);
});
eventSource.addEventListener("close", () => {
var _a2;
chunkOLGUSX5G_js.logger.debug("[streamByEventSource] close");
(_a2 = callbacks.onSuccess) == null ? void 0 : _a2.call(callbacks, accumulatedEvents);
resolve(accumulatedEvents);
});
});
}
// src/workflows/store/workflow.ts
function createState4(name) {
return valtio.proxy({
name,
graph: null
});
}
function createActions4(state, client) {
return {
async sync() {
var _a, _b;
const data = await workflowsClient.getWorkflowsByNameRepresentation({
client,
path: { name: state.name }
});
state.graph = (_b = (_a = data.data) == null ? void 0 : _a.graph) != null ? _b : null;
},
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 createState3(data.data);
}
};
}
// src/workflows/hooks/index.ts
function useHandlers() {
const client = chunkSJGLR4O2_js.useWorkflowsClient();
const state = getOrCreate(
"handlers",
() => createState()
);
const actions = react.useMemo(() => createActions(state, client), [state, client]);
return chunk4E3IDRQJ_js.__spreadValues({
state: valtio.useSnapshot(state)
}, actions);
}
function useWorkflows() {
const client = chunkSJGLR4O2_js.useWorkflowsClient();
const state = getOrCreate(
"workflows",
() => createState2()
);
const actions = react.useMemo(
() => createActions2(state, client),
[state, client]
);
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) {
const client = chunkSJGLR4O2_js.useWorkflowsClient();
const state = getOrCreate(
`handler:${handlerId}`,
() => createState3()
);
const actions = react.useMemo(
() => createActions3(state, client),
[state, client]
);
return chunk4E3IDRQJ_js.__spreadValues({
state: valtio.useSnapshot(state)
}, actions);
}
function WorkflowTrigger(_a) {
var _b = _a, {
workflowName,
customWorkflowInput,
onSuccess,
onError,
title = "Trigger Workflow",
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 {
setIsCreating(true);
if (customWorkflowInput) {
const workflowInput2 = customWorkflowInput(data, fieldValues);
const handler2 = await createHandler(workflowInput2);
sonner.toast.success("Workflow task created successfully!");
onSuccess == null ? void 0 : onSuccess(handler2);
return;
}
const workflowInput = chunk4E3IDRQJ_js.__spreadValues({
files: data.map((file) => ({
fileId: file.fileId,
url: file.url,
name: file.file.name,
type: file.file.type
}))
}, fieldValues);
const handler = await createHandler(workflowInput);
sonner.toast.success("Workflow task created successfully!");
onSuccess == null ? void 0 : onSuccess(handler);
setIsCreating(false);
} 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);
setIsCreating(false);
throw error;
}
},
[createHandler, onSuccess, onError, customWorkflowInput]
);
return /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
chunkOLGUSX5G_js.FileUploader,
chunk4E3IDRQJ_js.__spreadValues({
title,
description,
onSuccess: handleFileUpload,
isProcessing: isCreating
}, fileUploaderProps)
) });
}
exports.WorkflowTrigger = WorkflowTrigger;
exports.useHandler = useHandler;
exports.useHandlers = useHandlers;
exports.useWorkflow = useWorkflow;
exports.useWorkflows = useWorkflows;