@personaai/react 0.8.0 → 0.9.0

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
@@ -38,7 +38,11 @@ __export(index_exports, {
38
38
  useMemory: () => useMemory,
39
39
  usePersonaContext: () => usePersonaContext,
40
40
  useThreads: () => useThreads,
41
- useVoice: () => useVoice
41
+ useVoice: () => useVoice,
42
+ useWorkflow: () => useWorkflow,
43
+ useWorkflowRuns: () => useWorkflowRuns,
44
+ useWorkflowStream: () => useWorkflowStream,
45
+ useWorkflows: () => useWorkflows
42
46
  });
43
47
  module.exports = __toCommonJS(index_exports);
44
48
 
@@ -177,7 +181,8 @@ function fetchReader(response, controller) {
177
181
  function xhrStream(opts) {
178
182
  return new Promise((resolveStream, rejectStream) => {
179
183
  const xhr = new XMLHttpRequest();
180
- xhr.open("POST", opts.url);
184
+ const method = opts.method ?? "POST";
185
+ xhr.open(method, opts.url);
181
186
  for (const [key, val] of Object.entries(opts.headers))
182
187
  xhr.setRequestHeader(key, val);
183
188
  let consumed = 0;
@@ -276,7 +281,7 @@ function xhrStream(opts) {
276
281
  });
277
282
  }
278
283
  }
279
- xhr.send(opts.body);
284
+ xhr.send(method === "GET" ? null : opts.body ?? null);
280
285
  });
281
286
  }
282
287
  async function openSSEStream(opts) {
@@ -288,10 +293,11 @@ async function openSSEStream(opts) {
288
293
  if (opts.signal.aborted) controller.abort();
289
294
  else opts.signal.addEventListener("abort", () => controller.abort());
290
295
  }
296
+ const method = opts.method ?? "POST";
291
297
  const response = await fetch(opts.url, {
292
- method: "POST",
298
+ method,
293
299
  headers: opts.headers,
294
- body: opts.body,
300
+ body: method === "GET" ? void 0 : opts.body,
295
301
  signal: controller.signal
296
302
  });
297
303
  if (!response.ok) {
@@ -974,6 +980,12 @@ function useChat(options = {}) {
974
980
  }
975
981
  }
976
982
  }
983
+ } else if (event.type === "title") {
984
+ const title = event.title;
985
+ if (typeof title === "string" && title.trim()) {
986
+ chatLogger.info("auto title", { title });
987
+ options.onTitle?.(title);
988
+ }
977
989
  } else if (event.type === "RUN_ERROR") {
978
990
  chatLogger.warn("run error", { message: event.message, code: event.code });
979
991
  chatLogger.error("stream run error", { code: event.code, message: event.message });
@@ -2097,9 +2109,595 @@ function useMcp(options = {}) {
2097
2109
  };
2098
2110
  }
2099
2111
 
2112
+ // src/hooks/useWorkflows.ts
2113
+ var import_react11 = require("react");
2114
+ function useWorkflows(options) {
2115
+ const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
2116
+ const { autoFetch = true, search, status, page, limit } = opts;
2117
+ const { fetchWithAuth } = usePersonaContext();
2118
+ const [workflows, setWorkflows] = (0, import_react11.useState)([]);
2119
+ const [pagination, setPagination] = (0, import_react11.useState)({
2120
+ page: page ?? 1,
2121
+ limit: limit ?? 20,
2122
+ total: 0,
2123
+ totalPages: 0
2124
+ });
2125
+ const [isLoading, setIsLoading] = (0, import_react11.useState)(false);
2126
+ const [error, setError] = (0, import_react11.useState)(null);
2127
+ const fetchWorkflows = (0, import_react11.useCallback)(async () => {
2128
+ setIsLoading(true);
2129
+ setError(null);
2130
+ try {
2131
+ const params = new URLSearchParams();
2132
+ if (search) params.set("search", search);
2133
+ if (status) params.set("status", status);
2134
+ if (page) params.set("page", String(page));
2135
+ if (limit) params.set("limit", String(limit));
2136
+ const queryStr = params.toString() ? `?${params.toString()}` : "";
2137
+ const res = await fetchWithAuth(`/workflows${queryStr}`);
2138
+ if (!res.ok) {
2139
+ throw new Error(`Failed to list workflows: ${res.statusText}`);
2140
+ }
2141
+ const data = await res.json();
2142
+ const items = Array.isArray(data) ? data : data?.items || data?.workflows || [];
2143
+ setWorkflows(items);
2144
+ if (data?.pagination) {
2145
+ setPagination({
2146
+ page: data.pagination.page ?? 1,
2147
+ limit: data.pagination.limit ?? items.length,
2148
+ total: data.pagination.total ?? items.length,
2149
+ totalPages: data.pagination.totalPages ?? 1
2150
+ });
2151
+ } else {
2152
+ setPagination({
2153
+ page: 1,
2154
+ limit: items.length,
2155
+ total: items.length,
2156
+ totalPages: 1
2157
+ });
2158
+ }
2159
+ return items;
2160
+ } catch (err) {
2161
+ const errorObj = err instanceof Error ? err : new Error(String(err));
2162
+ setError(errorObj);
2163
+ return [];
2164
+ } finally {
2165
+ setIsLoading(false);
2166
+ }
2167
+ }, [fetchWithAuth, search, status, page, limit]);
2168
+ const createWorkflow = (0, import_react11.useCallback)(
2169
+ async (input) => {
2170
+ setError(null);
2171
+ try {
2172
+ const res = await fetchWithAuth("/workflows", {
2173
+ method: "POST",
2174
+ headers: { "Content-Type": "application/json" },
2175
+ body: JSON.stringify(input)
2176
+ });
2177
+ if (!res.ok) {
2178
+ const errText = await res.text().catch(() => res.statusText);
2179
+ throw new Error(`Failed to create workflow (${res.status}): ${errText}`);
2180
+ }
2181
+ const created = await res.json();
2182
+ setWorkflows((prev) => [created, ...prev]);
2183
+ return created;
2184
+ } catch (err) {
2185
+ const errorObj = err instanceof Error ? err : new Error(String(err));
2186
+ setError(errorObj);
2187
+ throw errorObj;
2188
+ }
2189
+ },
2190
+ [fetchWithAuth]
2191
+ );
2192
+ (0, import_react11.useEffect)(() => {
2193
+ if (autoFetch) {
2194
+ void fetchWorkflows();
2195
+ }
2196
+ }, [autoFetch, fetchWorkflows]);
2197
+ return {
2198
+ workflows,
2199
+ pagination,
2200
+ isLoading,
2201
+ error,
2202
+ refetch: fetchWorkflows,
2203
+ createWorkflow
2204
+ };
2205
+ }
2206
+
2207
+ // src/hooks/useWorkflow.ts
2208
+ var import_react12 = require("react");
2209
+ function useWorkflow(workflowId, options) {
2210
+ const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
2211
+ const { autoFetch = true } = opts;
2212
+ const { fetchWithAuth } = usePersonaContext();
2213
+ const [workflow, setWorkflow] = (0, import_react12.useState)(null);
2214
+ const [versions, setVersions] = (0, import_react12.useState)([]);
2215
+ const [mermaid, setMermaid] = (0, import_react12.useState)(null);
2216
+ const [isLoading, setIsLoading] = (0, import_react12.useState)(false);
2217
+ const [error, setError] = (0, import_react12.useState)(null);
2218
+ const fetchWorkflow = (0, import_react12.useCallback)(async () => {
2219
+ if (!workflowId) return null;
2220
+ setIsLoading(true);
2221
+ setError(null);
2222
+ try {
2223
+ const res = await fetchWithAuth(`/workflows/${workflowId}`);
2224
+ if (!res.ok) {
2225
+ throw new Error(`Failed to fetch workflow (${res.status}): ${res.statusText}`);
2226
+ }
2227
+ const data = await res.json();
2228
+ setWorkflow(data);
2229
+ return data;
2230
+ } catch (err) {
2231
+ const errorObj = err instanceof Error ? err : new Error(String(err));
2232
+ setError(errorObj);
2233
+ return null;
2234
+ } finally {
2235
+ setIsLoading(false);
2236
+ }
2237
+ }, [fetchWithAuth, workflowId]);
2238
+ const fetchVersions = (0, import_react12.useCallback)(async () => {
2239
+ if (!workflowId) return [];
2240
+ try {
2241
+ const res = await fetchWithAuth(`/workflows/${workflowId}/versions`);
2242
+ if (!res.ok) return [];
2243
+ const data = await res.json();
2244
+ const items = Array.isArray(data) ? data : data?.items || [];
2245
+ setVersions(items);
2246
+ return items;
2247
+ } catch {
2248
+ return [];
2249
+ }
2250
+ }, [fetchWithAuth, workflowId]);
2251
+ const fetchMermaid = (0, import_react12.useCallback)(async () => {
2252
+ if (!workflowId) return "";
2253
+ try {
2254
+ const res = await fetchWithAuth(`/workflows/${workflowId}/mermaid`);
2255
+ if (!res.ok) return "";
2256
+ const data = await res.json();
2257
+ const code = typeof data?.mermaid === "string" ? data.mermaid : String(data ?? "");
2258
+ setMermaid(code);
2259
+ return code;
2260
+ } catch {
2261
+ return "";
2262
+ }
2263
+ }, [fetchWithAuth, workflowId]);
2264
+ const saveDraft = (0, import_react12.useCallback)(
2265
+ async (draft) => {
2266
+ if (!workflowId) throw new Error("Workflow ID is required");
2267
+ setError(null);
2268
+ const res = await fetchWithAuth(`/workflows/${workflowId}/draft`, {
2269
+ method: "POST",
2270
+ headers: { "Content-Type": "application/json" },
2271
+ body: JSON.stringify({ draft })
2272
+ });
2273
+ if (!res.ok) {
2274
+ const errText = await res.text().catch(() => res.statusText);
2275
+ throw new Error(`Failed to save draft (${res.status}): ${errText}`);
2276
+ }
2277
+ const updated = await res.json();
2278
+ setWorkflow(updated);
2279
+ return updated;
2280
+ },
2281
+ [fetchWithAuth, workflowId]
2282
+ );
2283
+ const publish = (0, import_react12.useCallback)(
2284
+ async (summary) => {
2285
+ if (!workflowId) throw new Error("Workflow ID is required");
2286
+ setError(null);
2287
+ const res = await fetchWithAuth(`/workflows/${workflowId}/publish`, {
2288
+ method: "POST",
2289
+ headers: { "Content-Type": "application/json" },
2290
+ body: JSON.stringify(summary ? { summary } : {})
2291
+ });
2292
+ if (!res.ok) {
2293
+ const errText = await res.text().catch(() => res.statusText);
2294
+ throw new Error(`Failed to publish workflow (${res.status}): ${errText}`);
2295
+ }
2296
+ const versionResult = await res.json();
2297
+ void fetchWorkflow();
2298
+ void fetchVersions();
2299
+ return versionResult;
2300
+ },
2301
+ [fetchWithAuth, workflowId, fetchWorkflow, fetchVersions]
2302
+ );
2303
+ const deleteWorkflow = (0, import_react12.useCallback)(async () => {
2304
+ if (!workflowId) throw new Error("Workflow ID is required");
2305
+ setError(null);
2306
+ const res = await fetchWithAuth(`/workflows/${workflowId}`, {
2307
+ method: "DELETE"
2308
+ });
2309
+ if (!res.ok) {
2310
+ throw new Error(`Failed to delete workflow (${res.status}): ${res.statusText}`);
2311
+ }
2312
+ setWorkflow(null);
2313
+ }, [fetchWithAuth, workflowId]);
2314
+ (0, import_react12.useEffect)(() => {
2315
+ if (autoFetch && workflowId) {
2316
+ void fetchWorkflow();
2317
+ }
2318
+ }, [autoFetch, workflowId, fetchWorkflow]);
2319
+ return {
2320
+ workflow,
2321
+ versions,
2322
+ mermaid,
2323
+ isLoading,
2324
+ error,
2325
+ refetch: fetchWorkflow,
2326
+ fetchVersions,
2327
+ fetchMermaid,
2328
+ saveDraft,
2329
+ publish,
2330
+ deleteWorkflow
2331
+ };
2332
+ }
2333
+
2334
+ // src/hooks/useWorkflowStream.ts
2335
+ var import_react13 = require("react");
2336
+ function useWorkflowStream(workflowId, options) {
2337
+ const { baseUrl, getAuthToken, fetchWithAuth, logger } = usePersonaContext();
2338
+ const [status, setStatus] = (0, import_react13.useState)("idle");
2339
+ const [runId, setRunId] = (0, import_react13.useState)(null);
2340
+ const [activeNodeId, setActiveNodeId] = (0, import_react13.useState)(null);
2341
+ const [nodeRuns, setNodeRuns] = (0, import_react13.useState)(
2342
+ {}
2343
+ );
2344
+ const [text, setText] = (0, import_react13.useState)("");
2345
+ const [output, setOutput] = (0, import_react13.useState)(null);
2346
+ const [error, setError] = (0, import_react13.useState)(null);
2347
+ const [events, setEvents] = (0, import_react13.useState)([]);
2348
+ const abortControllerRef = (0, import_react13.useRef)(null);
2349
+ const currentRunIdRef = (0, import_react13.useRef)(null);
2350
+ currentRunIdRef.current = runId;
2351
+ const optionsRef = (0, import_react13.useRef)(options);
2352
+ optionsRef.current = options;
2353
+ const cancel = (0, import_react13.useCallback)(async () => {
2354
+ if (abortControllerRef.current) {
2355
+ abortControllerRef.current.abort();
2356
+ abortControllerRef.current = null;
2357
+ }
2358
+ const currentRun = currentRunIdRef.current;
2359
+ if (currentRun) {
2360
+ try {
2361
+ await fetchWithAuth(`/workflows/runs/${currentRun}/cancel`, {
2362
+ method: "POST"
2363
+ });
2364
+ } catch (err) {
2365
+ logger.warn("Failed to send cancel request to workflow run", {
2366
+ runId: currentRun,
2367
+ error: String(err)
2368
+ });
2369
+ }
2370
+ }
2371
+ setStatus("cancelled");
2372
+ setActiveNodeId(null);
2373
+ }, [fetchWithAuth, logger]);
2374
+ const reset = (0, import_react13.useCallback)(() => {
2375
+ if (abortControllerRef.current) {
2376
+ abortControllerRef.current.abort();
2377
+ abortControllerRef.current = null;
2378
+ }
2379
+ setStatus("idle");
2380
+ setRunId(null);
2381
+ setActiveNodeId(null);
2382
+ setNodeRuns({});
2383
+ setText("");
2384
+ setOutput(null);
2385
+ setError(null);
2386
+ setEvents([]);
2387
+ }, []);
2388
+ const processStream = (0, import_react13.useCallback)(
2389
+ async (url, method, body, targetRunId) => {
2390
+ if (abortControllerRef.current) {
2391
+ abortControllerRef.current.abort();
2392
+ }
2393
+ const controller = new AbortController();
2394
+ abortControllerRef.current = controller;
2395
+ setStatus("running");
2396
+ setError(null);
2397
+ const token = getAuthToken ? await getAuthToken() : null;
2398
+ const headers = {
2399
+ Accept: "text/event-stream"
2400
+ };
2401
+ if (token) {
2402
+ headers["Authorization"] = `Bearer ${token}`;
2403
+ }
2404
+ if (method === "POST") {
2405
+ headers["Content-Type"] = "application/json";
2406
+ }
2407
+ let assignedRunId = targetRunId ?? null;
2408
+ let accumulatedText = "";
2409
+ let finalOutput = null;
2410
+ try {
2411
+ const stream = await openSSEStream({
2412
+ url,
2413
+ method,
2414
+ headers,
2415
+ body,
2416
+ signal: controller.signal
2417
+ });
2418
+ if (!stream.ok) {
2419
+ throw new Error(
2420
+ stream.errorText || `Stream request failed with status ${stream.status}`
2421
+ );
2422
+ }
2423
+ const runIdHeader = stream.getHeader("x-persona-run-id");
2424
+ if (runIdHeader) {
2425
+ assignedRunId = runIdHeader;
2426
+ setRunId(runIdHeader);
2427
+ }
2428
+ let buffer = "";
2429
+ while (true) {
2430
+ const { done, value } = await stream.reader.read();
2431
+ if (done) break;
2432
+ if (!value) continue;
2433
+ buffer += value;
2434
+ const lines = buffer.split("\n");
2435
+ buffer = lines.pop() ?? "";
2436
+ for (const line of lines) {
2437
+ const trimmed = line.trim();
2438
+ if (!trimmed || trimmed.startsWith(":")) continue;
2439
+ if (trimmed.startsWith("data:")) {
2440
+ const rawData = trimmed.slice(5).trim();
2441
+ if (!rawData || rawData === "[DONE]") continue;
2442
+ try {
2443
+ const event = JSON.parse(rawData);
2444
+ setEvents((prev) => [...prev, event]);
2445
+ optionsRef.current?.onEvent?.(event);
2446
+ if ("runId" in event && typeof event.runId === "string" && !assignedRunId) {
2447
+ assignedRunId = event.runId;
2448
+ setRunId(event.runId);
2449
+ }
2450
+ if (event.type === "TEXT_MESSAGE_CHUNK") {
2451
+ accumulatedText += event.delta;
2452
+ setText((prev) => prev + event.delta);
2453
+ } else if (event.type === "CUSTOM") {
2454
+ if (event.name === "workflow_node_started") {
2455
+ const val = event.value;
2456
+ setActiveNodeId(val.nodeId);
2457
+ setNodeRuns((prev) => ({
2458
+ ...prev,
2459
+ [val.nodeId]: {
2460
+ nodeId: val.nodeId,
2461
+ nodeType: val.nodeType,
2462
+ nodeLabel: val.nodeLabel,
2463
+ status: "running",
2464
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
2465
+ input: val.input
2466
+ }
2467
+ }));
2468
+ optionsRef.current?.onNodeStarted?.(val);
2469
+ } else if (event.name === "workflow_node_completed") {
2470
+ const val = event.value;
2471
+ setNodeRuns((prev) => {
2472
+ const existing = prev[val.nodeId];
2473
+ return {
2474
+ ...prev,
2475
+ [val.nodeId]: {
2476
+ nodeId: val.nodeId,
2477
+ nodeType: existing?.nodeType ?? "unknown",
2478
+ nodeLabel: existing?.nodeLabel ?? val.nodeId,
2479
+ status: "completed",
2480
+ startedAt: existing?.startedAt,
2481
+ finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
2482
+ input: existing?.input,
2483
+ output: val.output
2484
+ }
2485
+ };
2486
+ });
2487
+ setActiveNodeId((curr) => curr === val.nodeId ? null : curr);
2488
+ finalOutput = val.output;
2489
+ setOutput(val.output);
2490
+ optionsRef.current?.onNodeCompleted?.(val);
2491
+ } else if (event.name === "workflow_node_failed") {
2492
+ const val = event.value;
2493
+ setNodeRuns((prev) => {
2494
+ const existing = prev[val.nodeId];
2495
+ return {
2496
+ ...prev,
2497
+ [val.nodeId]: {
2498
+ nodeId: val.nodeId,
2499
+ nodeType: existing?.nodeType ?? "unknown",
2500
+ nodeLabel: existing?.nodeLabel ?? val.nodeId,
2501
+ status: "failed",
2502
+ startedAt: existing?.startedAt,
2503
+ finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
2504
+ input: existing?.input,
2505
+ error: val.error
2506
+ }
2507
+ };
2508
+ });
2509
+ setActiveNodeId((curr) => curr === val.nodeId ? null : curr);
2510
+ optionsRef.current?.onNodeFailed?.(val);
2511
+ }
2512
+ } else if (event.type === "RUN_FINISHED") {
2513
+ setStatus("completed");
2514
+ setActiveNodeId(null);
2515
+ optionsRef.current?.onFinish?.({
2516
+ runId: assignedRunId || "",
2517
+ output: finalOutput,
2518
+ text: accumulatedText
2519
+ });
2520
+ } else if (event.type === "RUN_ERROR") {
2521
+ const runErr = new Error(event.message || event.code || "Workflow run error");
2522
+ setStatus("failed");
2523
+ setError(runErr);
2524
+ setActiveNodeId(null);
2525
+ optionsRef.current?.onError?.(runErr);
2526
+ }
2527
+ } catch {
2528
+ }
2529
+ }
2530
+ }
2531
+ }
2532
+ setStatus((prev) => prev === "running" ? "completed" : prev);
2533
+ return finalOutput;
2534
+ } catch (err) {
2535
+ if (controller.signal.aborted) {
2536
+ setStatus("cancelled");
2537
+ return null;
2538
+ }
2539
+ const errorObj = err instanceof Error ? err : new Error(String(err));
2540
+ setStatus("failed");
2541
+ setError(errorObj);
2542
+ setActiveNodeId(null);
2543
+ optionsRef.current?.onError?.(errorObj);
2544
+ throw errorObj;
2545
+ } finally {
2546
+ if (abortControllerRef.current === controller) {
2547
+ abortControllerRef.current = null;
2548
+ }
2549
+ }
2550
+ },
2551
+ [getAuthToken]
2552
+ );
2553
+ const start = (0, import_react13.useCallback)(
2554
+ async (input, opts) => {
2555
+ const targetWfId = opts?.workflowId || workflowId;
2556
+ if (!targetWfId) {
2557
+ throw new Error("Workflow ID must be provided to start execution");
2558
+ }
2559
+ setNodeRuns({});
2560
+ setText("");
2561
+ setOutput(null);
2562
+ setEvents([]);
2563
+ setActiveNodeId(null);
2564
+ const cleanBase = baseUrl.replace(/\/+$/, "");
2565
+ const url = `${cleanBase}/workflows/${targetWfId}/stream`;
2566
+ const body = JSON.stringify({
2567
+ input: input ?? {},
2568
+ dryRun: opts?.dryRun ?? false
2569
+ });
2570
+ return processStream(url, "POST", body);
2571
+ },
2572
+ [workflowId, baseUrl, processStream]
2573
+ );
2574
+ const resume = (0, import_react13.useCallback)(
2575
+ async (targetRunId, sinceSeq) => {
2576
+ if (!targetRunId) {
2577
+ throw new Error("Run ID is required to resume stream");
2578
+ }
2579
+ setRunId(targetRunId);
2580
+ const cleanBase = baseUrl.replace(/\/+$/, "");
2581
+ const query = sinceSeq !== void 0 ? `?since=${sinceSeq}` : "";
2582
+ const url = `${cleanBase}/workflows/runs/${targetRunId}/resume${query}`;
2583
+ await processStream(url, "GET", void 0, targetRunId);
2584
+ },
2585
+ [baseUrl, processStream]
2586
+ );
2587
+ (0, import_react13.useEffect)(() => {
2588
+ return () => {
2589
+ if (abortControllerRef.current) {
2590
+ abortControllerRef.current.abort();
2591
+ }
2592
+ };
2593
+ }, []);
2594
+ return {
2595
+ runId,
2596
+ status,
2597
+ isRunning: status === "running",
2598
+ activeNodeId,
2599
+ nodeRuns,
2600
+ text,
2601
+ output,
2602
+ error,
2603
+ events,
2604
+ start,
2605
+ cancel,
2606
+ resume,
2607
+ reset
2608
+ };
2609
+ }
2610
+
2611
+ // src/hooks/useWorkflowRuns.ts
2612
+ var import_react14 = require("react");
2613
+ function useWorkflowRuns(workflowId, options) {
2614
+ const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
2615
+ const { autoFetch = true, page = 1, limit = 20 } = opts;
2616
+ const { fetchWithAuth } = usePersonaContext();
2617
+ const [runs, setRuns] = (0, import_react14.useState)([]);
2618
+ const [pagination, setPagination] = (0, import_react14.useState)({
2619
+ page,
2620
+ limit,
2621
+ total: 0,
2622
+ totalPages: 0
2623
+ });
2624
+ const [isLoading, setIsLoading] = (0, import_react14.useState)(false);
2625
+ const [error, setError] = (0, import_react14.useState)(null);
2626
+ const fetchRuns = (0, import_react14.useCallback)(async () => {
2627
+ if (!workflowId) return [];
2628
+ setIsLoading(true);
2629
+ setError(null);
2630
+ try {
2631
+ const query = `?page=${page}&limit=${limit}`;
2632
+ const res = await fetchWithAuth(`/workflows/${workflowId}/runs${query}`);
2633
+ if (!res.ok) {
2634
+ throw new Error(`Failed to list workflow runs: ${res.statusText}`);
2635
+ }
2636
+ const data = await res.json();
2637
+ const items = Array.isArray(data) ? data : data?.items || data?.runs || [];
2638
+ setRuns(items);
2639
+ if (data?.pagination) {
2640
+ setPagination({
2641
+ page: data.pagination.page ?? page,
2642
+ limit: data.pagination.limit ?? limit,
2643
+ total: data.pagination.total ?? items.length,
2644
+ totalPages: data.pagination.totalPages ?? 1
2645
+ });
2646
+ }
2647
+ return items;
2648
+ } catch (err) {
2649
+ const errorObj = err instanceof Error ? err : new Error(String(err));
2650
+ setError(errorObj);
2651
+ return [];
2652
+ } finally {
2653
+ setIsLoading(false);
2654
+ }
2655
+ }, [fetchWithAuth, workflowId, page, limit]);
2656
+ const getRun = (0, import_react14.useCallback)(
2657
+ async (runId) => {
2658
+ if (!runId) throw new Error("Run ID is required");
2659
+ const res = await fetchWithAuth(`/workflows/runs/${runId}`);
2660
+ if (!res.ok) {
2661
+ throw new Error(`Failed to fetch workflow run (${res.status}): ${res.statusText}`);
2662
+ }
2663
+ return await res.json();
2664
+ },
2665
+ [fetchWithAuth]
2666
+ );
2667
+ const cancelRun = (0, import_react14.useCallback)(
2668
+ async (runId) => {
2669
+ if (!runId) throw new Error("Run ID is required");
2670
+ const res = await fetchWithAuth(`/workflows/runs/${runId}/cancel`, {
2671
+ method: "POST"
2672
+ });
2673
+ if (!res.ok) {
2674
+ throw new Error(`Failed to cancel workflow run (${res.status}): ${res.statusText}`);
2675
+ }
2676
+ setRuns(
2677
+ (prev) => prev.map((r) => r._id === runId ? { ...r, status: "cancelled" } : r)
2678
+ );
2679
+ },
2680
+ [fetchWithAuth]
2681
+ );
2682
+ (0, import_react14.useEffect)(() => {
2683
+ if (autoFetch && workflowId) {
2684
+ void fetchRuns();
2685
+ }
2686
+ }, [autoFetch, workflowId, fetchRuns]);
2687
+ return {
2688
+ runs,
2689
+ pagination,
2690
+ isLoading,
2691
+ error,
2692
+ refetch: fetchRuns,
2693
+ getRun,
2694
+ cancelRun
2695
+ };
2696
+ }
2697
+
2100
2698
  // src/index.ts
2101
2699
  var import_logger2 = require("@personaai/logger");
2102
- var VERSION = "0.8.0";
2700
+ var VERSION = "0.9.0";
2103
2701
  // Annotate the CommonJS export names for ESM import in node:
2104
2702
  0 && (module.exports = {
2105
2703
  PersonaProvider,
@@ -2120,6 +2718,10 @@ var VERSION = "0.8.0";
2120
2718
  useMemory,
2121
2719
  usePersonaContext,
2122
2720
  useThreads,
2123
- useVoice
2721
+ useVoice,
2722
+ useWorkflow,
2723
+ useWorkflowRuns,
2724
+ useWorkflowStream,
2725
+ useWorkflows
2124
2726
  });
2125
2727
  //# sourceMappingURL=index.cjs.map