@personaai/react 0.8.1 → 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.js CHANGED
@@ -133,7 +133,8 @@ function fetchReader(response, controller) {
133
133
  function xhrStream(opts) {
134
134
  return new Promise((resolveStream, rejectStream) => {
135
135
  const xhr = new XMLHttpRequest();
136
- xhr.open("POST", opts.url);
136
+ const method = opts.method ?? "POST";
137
+ xhr.open(method, opts.url);
137
138
  for (const [key, val] of Object.entries(opts.headers))
138
139
  xhr.setRequestHeader(key, val);
139
140
  let consumed = 0;
@@ -232,7 +233,7 @@ function xhrStream(opts) {
232
233
  });
233
234
  }
234
235
  }
235
- xhr.send(opts.body);
236
+ xhr.send(method === "GET" ? null : opts.body ?? null);
236
237
  });
237
238
  }
238
239
  async function openSSEStream(opts) {
@@ -244,10 +245,11 @@ async function openSSEStream(opts) {
244
245
  if (opts.signal.aborted) controller.abort();
245
246
  else opts.signal.addEventListener("abort", () => controller.abort());
246
247
  }
248
+ const method = opts.method ?? "POST";
247
249
  const response = await fetch(opts.url, {
248
- method: "POST",
250
+ method,
249
251
  headers: opts.headers,
250
- body: opts.body,
252
+ body: method === "GET" ? void 0 : opts.body,
251
253
  signal: controller.signal
252
254
  });
253
255
  if (!response.ok) {
@@ -2059,6 +2061,592 @@ function useMcp(options = {}) {
2059
2061
  };
2060
2062
  }
2061
2063
 
2064
+ // src/hooks/useWorkflows.ts
2065
+ import { useCallback as useCallback10, useEffect as useEffect9, useState as useState9 } from "react";
2066
+ function useWorkflows(options) {
2067
+ const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
2068
+ const { autoFetch = true, search, status, page, limit } = opts;
2069
+ const { fetchWithAuth } = usePersonaContext();
2070
+ const [workflows, setWorkflows] = useState9([]);
2071
+ const [pagination, setPagination] = useState9({
2072
+ page: page ?? 1,
2073
+ limit: limit ?? 20,
2074
+ total: 0,
2075
+ totalPages: 0
2076
+ });
2077
+ const [isLoading, setIsLoading] = useState9(false);
2078
+ const [error, setError] = useState9(null);
2079
+ const fetchWorkflows = useCallback10(async () => {
2080
+ setIsLoading(true);
2081
+ setError(null);
2082
+ try {
2083
+ const params = new URLSearchParams();
2084
+ if (search) params.set("search", search);
2085
+ if (status) params.set("status", status);
2086
+ if (page) params.set("page", String(page));
2087
+ if (limit) params.set("limit", String(limit));
2088
+ const queryStr = params.toString() ? `?${params.toString()}` : "";
2089
+ const res = await fetchWithAuth(`/workflows${queryStr}`);
2090
+ if (!res.ok) {
2091
+ throw new Error(`Failed to list workflows: ${res.statusText}`);
2092
+ }
2093
+ const data = await res.json();
2094
+ const items = Array.isArray(data) ? data : data?.items || data?.workflows || [];
2095
+ setWorkflows(items);
2096
+ if (data?.pagination) {
2097
+ setPagination({
2098
+ page: data.pagination.page ?? 1,
2099
+ limit: data.pagination.limit ?? items.length,
2100
+ total: data.pagination.total ?? items.length,
2101
+ totalPages: data.pagination.totalPages ?? 1
2102
+ });
2103
+ } else {
2104
+ setPagination({
2105
+ page: 1,
2106
+ limit: items.length,
2107
+ total: items.length,
2108
+ totalPages: 1
2109
+ });
2110
+ }
2111
+ return items;
2112
+ } catch (err) {
2113
+ const errorObj = err instanceof Error ? err : new Error(String(err));
2114
+ setError(errorObj);
2115
+ return [];
2116
+ } finally {
2117
+ setIsLoading(false);
2118
+ }
2119
+ }, [fetchWithAuth, search, status, page, limit]);
2120
+ const createWorkflow = useCallback10(
2121
+ async (input) => {
2122
+ setError(null);
2123
+ try {
2124
+ const res = await fetchWithAuth("/workflows", {
2125
+ method: "POST",
2126
+ headers: { "Content-Type": "application/json" },
2127
+ body: JSON.stringify(input)
2128
+ });
2129
+ if (!res.ok) {
2130
+ const errText = await res.text().catch(() => res.statusText);
2131
+ throw new Error(`Failed to create workflow (${res.status}): ${errText}`);
2132
+ }
2133
+ const created = await res.json();
2134
+ setWorkflows((prev) => [created, ...prev]);
2135
+ return created;
2136
+ } catch (err) {
2137
+ const errorObj = err instanceof Error ? err : new Error(String(err));
2138
+ setError(errorObj);
2139
+ throw errorObj;
2140
+ }
2141
+ },
2142
+ [fetchWithAuth]
2143
+ );
2144
+ useEffect9(() => {
2145
+ if (autoFetch) {
2146
+ void fetchWorkflows();
2147
+ }
2148
+ }, [autoFetch, fetchWorkflows]);
2149
+ return {
2150
+ workflows,
2151
+ pagination,
2152
+ isLoading,
2153
+ error,
2154
+ refetch: fetchWorkflows,
2155
+ createWorkflow
2156
+ };
2157
+ }
2158
+
2159
+ // src/hooks/useWorkflow.ts
2160
+ import { useCallback as useCallback11, useEffect as useEffect10, useState as useState10 } from "react";
2161
+ function useWorkflow(workflowId, options) {
2162
+ const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
2163
+ const { autoFetch = true } = opts;
2164
+ const { fetchWithAuth } = usePersonaContext();
2165
+ const [workflow, setWorkflow] = useState10(null);
2166
+ const [versions, setVersions] = useState10([]);
2167
+ const [mermaid, setMermaid] = useState10(null);
2168
+ const [isLoading, setIsLoading] = useState10(false);
2169
+ const [error, setError] = useState10(null);
2170
+ const fetchWorkflow = useCallback11(async () => {
2171
+ if (!workflowId) return null;
2172
+ setIsLoading(true);
2173
+ setError(null);
2174
+ try {
2175
+ const res = await fetchWithAuth(`/workflows/${workflowId}`);
2176
+ if (!res.ok) {
2177
+ throw new Error(`Failed to fetch workflow (${res.status}): ${res.statusText}`);
2178
+ }
2179
+ const data = await res.json();
2180
+ setWorkflow(data);
2181
+ return data;
2182
+ } catch (err) {
2183
+ const errorObj = err instanceof Error ? err : new Error(String(err));
2184
+ setError(errorObj);
2185
+ return null;
2186
+ } finally {
2187
+ setIsLoading(false);
2188
+ }
2189
+ }, [fetchWithAuth, workflowId]);
2190
+ const fetchVersions = useCallback11(async () => {
2191
+ if (!workflowId) return [];
2192
+ try {
2193
+ const res = await fetchWithAuth(`/workflows/${workflowId}/versions`);
2194
+ if (!res.ok) return [];
2195
+ const data = await res.json();
2196
+ const items = Array.isArray(data) ? data : data?.items || [];
2197
+ setVersions(items);
2198
+ return items;
2199
+ } catch {
2200
+ return [];
2201
+ }
2202
+ }, [fetchWithAuth, workflowId]);
2203
+ const fetchMermaid = useCallback11(async () => {
2204
+ if (!workflowId) return "";
2205
+ try {
2206
+ const res = await fetchWithAuth(`/workflows/${workflowId}/mermaid`);
2207
+ if (!res.ok) return "";
2208
+ const data = await res.json();
2209
+ const code = typeof data?.mermaid === "string" ? data.mermaid : String(data ?? "");
2210
+ setMermaid(code);
2211
+ return code;
2212
+ } catch {
2213
+ return "";
2214
+ }
2215
+ }, [fetchWithAuth, workflowId]);
2216
+ const saveDraft = useCallback11(
2217
+ async (draft) => {
2218
+ if (!workflowId) throw new Error("Workflow ID is required");
2219
+ setError(null);
2220
+ const res = await fetchWithAuth(`/workflows/${workflowId}/draft`, {
2221
+ method: "POST",
2222
+ headers: { "Content-Type": "application/json" },
2223
+ body: JSON.stringify({ draft })
2224
+ });
2225
+ if (!res.ok) {
2226
+ const errText = await res.text().catch(() => res.statusText);
2227
+ throw new Error(`Failed to save draft (${res.status}): ${errText}`);
2228
+ }
2229
+ const updated = await res.json();
2230
+ setWorkflow(updated);
2231
+ return updated;
2232
+ },
2233
+ [fetchWithAuth, workflowId]
2234
+ );
2235
+ const publish = useCallback11(
2236
+ async (summary) => {
2237
+ if (!workflowId) throw new Error("Workflow ID is required");
2238
+ setError(null);
2239
+ const res = await fetchWithAuth(`/workflows/${workflowId}/publish`, {
2240
+ method: "POST",
2241
+ headers: { "Content-Type": "application/json" },
2242
+ body: JSON.stringify(summary ? { summary } : {})
2243
+ });
2244
+ if (!res.ok) {
2245
+ const errText = await res.text().catch(() => res.statusText);
2246
+ throw new Error(`Failed to publish workflow (${res.status}): ${errText}`);
2247
+ }
2248
+ const versionResult = await res.json();
2249
+ void fetchWorkflow();
2250
+ void fetchVersions();
2251
+ return versionResult;
2252
+ },
2253
+ [fetchWithAuth, workflowId, fetchWorkflow, fetchVersions]
2254
+ );
2255
+ const deleteWorkflow = useCallback11(async () => {
2256
+ if (!workflowId) throw new Error("Workflow ID is required");
2257
+ setError(null);
2258
+ const res = await fetchWithAuth(`/workflows/${workflowId}`, {
2259
+ method: "DELETE"
2260
+ });
2261
+ if (!res.ok) {
2262
+ throw new Error(`Failed to delete workflow (${res.status}): ${res.statusText}`);
2263
+ }
2264
+ setWorkflow(null);
2265
+ }, [fetchWithAuth, workflowId]);
2266
+ useEffect10(() => {
2267
+ if (autoFetch && workflowId) {
2268
+ void fetchWorkflow();
2269
+ }
2270
+ }, [autoFetch, workflowId, fetchWorkflow]);
2271
+ return {
2272
+ workflow,
2273
+ versions,
2274
+ mermaid,
2275
+ isLoading,
2276
+ error,
2277
+ refetch: fetchWorkflow,
2278
+ fetchVersions,
2279
+ fetchMermaid,
2280
+ saveDraft,
2281
+ publish,
2282
+ deleteWorkflow
2283
+ };
2284
+ }
2285
+
2286
+ // src/hooks/useWorkflowStream.ts
2287
+ import { useCallback as useCallback12, useEffect as useEffect11, useRef as useRef3, useState as useState11 } from "react";
2288
+ function useWorkflowStream(workflowId, options) {
2289
+ const { baseUrl, getAuthToken, fetchWithAuth, logger } = usePersonaContext();
2290
+ const [status, setStatus] = useState11("idle");
2291
+ const [runId, setRunId] = useState11(null);
2292
+ const [activeNodeId, setActiveNodeId] = useState11(null);
2293
+ const [nodeRuns, setNodeRuns] = useState11(
2294
+ {}
2295
+ );
2296
+ const [text, setText] = useState11("");
2297
+ const [output, setOutput] = useState11(null);
2298
+ const [error, setError] = useState11(null);
2299
+ const [events, setEvents] = useState11([]);
2300
+ const abortControllerRef = useRef3(null);
2301
+ const currentRunIdRef = useRef3(null);
2302
+ currentRunIdRef.current = runId;
2303
+ const optionsRef = useRef3(options);
2304
+ optionsRef.current = options;
2305
+ const cancel = useCallback12(async () => {
2306
+ if (abortControllerRef.current) {
2307
+ abortControllerRef.current.abort();
2308
+ abortControllerRef.current = null;
2309
+ }
2310
+ const currentRun = currentRunIdRef.current;
2311
+ if (currentRun) {
2312
+ try {
2313
+ await fetchWithAuth(`/workflows/runs/${currentRun}/cancel`, {
2314
+ method: "POST"
2315
+ });
2316
+ } catch (err) {
2317
+ logger.warn("Failed to send cancel request to workflow run", {
2318
+ runId: currentRun,
2319
+ error: String(err)
2320
+ });
2321
+ }
2322
+ }
2323
+ setStatus("cancelled");
2324
+ setActiveNodeId(null);
2325
+ }, [fetchWithAuth, logger]);
2326
+ const reset = useCallback12(() => {
2327
+ if (abortControllerRef.current) {
2328
+ abortControllerRef.current.abort();
2329
+ abortControllerRef.current = null;
2330
+ }
2331
+ setStatus("idle");
2332
+ setRunId(null);
2333
+ setActiveNodeId(null);
2334
+ setNodeRuns({});
2335
+ setText("");
2336
+ setOutput(null);
2337
+ setError(null);
2338
+ setEvents([]);
2339
+ }, []);
2340
+ const processStream = useCallback12(
2341
+ async (url, method, body, targetRunId) => {
2342
+ if (abortControllerRef.current) {
2343
+ abortControllerRef.current.abort();
2344
+ }
2345
+ const controller = new AbortController();
2346
+ abortControllerRef.current = controller;
2347
+ setStatus("running");
2348
+ setError(null);
2349
+ const token = getAuthToken ? await getAuthToken() : null;
2350
+ const headers = {
2351
+ Accept: "text/event-stream"
2352
+ };
2353
+ if (token) {
2354
+ headers["Authorization"] = `Bearer ${token}`;
2355
+ }
2356
+ if (method === "POST") {
2357
+ headers["Content-Type"] = "application/json";
2358
+ }
2359
+ let assignedRunId = targetRunId ?? null;
2360
+ let accumulatedText = "";
2361
+ let finalOutput = null;
2362
+ try {
2363
+ const stream = await openSSEStream({
2364
+ url,
2365
+ method,
2366
+ headers,
2367
+ body,
2368
+ signal: controller.signal
2369
+ });
2370
+ if (!stream.ok) {
2371
+ throw new Error(
2372
+ stream.errorText || `Stream request failed with status ${stream.status}`
2373
+ );
2374
+ }
2375
+ const runIdHeader = stream.getHeader("x-persona-run-id");
2376
+ if (runIdHeader) {
2377
+ assignedRunId = runIdHeader;
2378
+ setRunId(runIdHeader);
2379
+ }
2380
+ let buffer = "";
2381
+ while (true) {
2382
+ const { done, value } = await stream.reader.read();
2383
+ if (done) break;
2384
+ if (!value) continue;
2385
+ buffer += value;
2386
+ const lines = buffer.split("\n");
2387
+ buffer = lines.pop() ?? "";
2388
+ for (const line of lines) {
2389
+ const trimmed = line.trim();
2390
+ if (!trimmed || trimmed.startsWith(":")) continue;
2391
+ if (trimmed.startsWith("data:")) {
2392
+ const rawData = trimmed.slice(5).trim();
2393
+ if (!rawData || rawData === "[DONE]") continue;
2394
+ try {
2395
+ const event = JSON.parse(rawData);
2396
+ setEvents((prev) => [...prev, event]);
2397
+ optionsRef.current?.onEvent?.(event);
2398
+ if ("runId" in event && typeof event.runId === "string" && !assignedRunId) {
2399
+ assignedRunId = event.runId;
2400
+ setRunId(event.runId);
2401
+ }
2402
+ if (event.type === "TEXT_MESSAGE_CHUNK") {
2403
+ accumulatedText += event.delta;
2404
+ setText((prev) => prev + event.delta);
2405
+ } else if (event.type === "CUSTOM") {
2406
+ if (event.name === "workflow_node_started") {
2407
+ const val = event.value;
2408
+ setActiveNodeId(val.nodeId);
2409
+ setNodeRuns((prev) => ({
2410
+ ...prev,
2411
+ [val.nodeId]: {
2412
+ nodeId: val.nodeId,
2413
+ nodeType: val.nodeType,
2414
+ nodeLabel: val.nodeLabel,
2415
+ status: "running",
2416
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
2417
+ input: val.input
2418
+ }
2419
+ }));
2420
+ optionsRef.current?.onNodeStarted?.(val);
2421
+ } else if (event.name === "workflow_node_completed") {
2422
+ const val = event.value;
2423
+ setNodeRuns((prev) => {
2424
+ const existing = prev[val.nodeId];
2425
+ return {
2426
+ ...prev,
2427
+ [val.nodeId]: {
2428
+ nodeId: val.nodeId,
2429
+ nodeType: existing?.nodeType ?? "unknown",
2430
+ nodeLabel: existing?.nodeLabel ?? val.nodeId,
2431
+ status: "completed",
2432
+ startedAt: existing?.startedAt,
2433
+ finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
2434
+ input: existing?.input,
2435
+ output: val.output
2436
+ }
2437
+ };
2438
+ });
2439
+ setActiveNodeId((curr) => curr === val.nodeId ? null : curr);
2440
+ finalOutput = val.output;
2441
+ setOutput(val.output);
2442
+ optionsRef.current?.onNodeCompleted?.(val);
2443
+ } else if (event.name === "workflow_node_failed") {
2444
+ const val = event.value;
2445
+ setNodeRuns((prev) => {
2446
+ const existing = prev[val.nodeId];
2447
+ return {
2448
+ ...prev,
2449
+ [val.nodeId]: {
2450
+ nodeId: val.nodeId,
2451
+ nodeType: existing?.nodeType ?? "unknown",
2452
+ nodeLabel: existing?.nodeLabel ?? val.nodeId,
2453
+ status: "failed",
2454
+ startedAt: existing?.startedAt,
2455
+ finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
2456
+ input: existing?.input,
2457
+ error: val.error
2458
+ }
2459
+ };
2460
+ });
2461
+ setActiveNodeId((curr) => curr === val.nodeId ? null : curr);
2462
+ optionsRef.current?.onNodeFailed?.(val);
2463
+ }
2464
+ } else if (event.type === "RUN_FINISHED") {
2465
+ setStatus("completed");
2466
+ setActiveNodeId(null);
2467
+ optionsRef.current?.onFinish?.({
2468
+ runId: assignedRunId || "",
2469
+ output: finalOutput,
2470
+ text: accumulatedText
2471
+ });
2472
+ } else if (event.type === "RUN_ERROR") {
2473
+ const runErr = new Error(event.message || event.code || "Workflow run error");
2474
+ setStatus("failed");
2475
+ setError(runErr);
2476
+ setActiveNodeId(null);
2477
+ optionsRef.current?.onError?.(runErr);
2478
+ }
2479
+ } catch {
2480
+ }
2481
+ }
2482
+ }
2483
+ }
2484
+ setStatus((prev) => prev === "running" ? "completed" : prev);
2485
+ return finalOutput;
2486
+ } catch (err) {
2487
+ if (controller.signal.aborted) {
2488
+ setStatus("cancelled");
2489
+ return null;
2490
+ }
2491
+ const errorObj = err instanceof Error ? err : new Error(String(err));
2492
+ setStatus("failed");
2493
+ setError(errorObj);
2494
+ setActiveNodeId(null);
2495
+ optionsRef.current?.onError?.(errorObj);
2496
+ throw errorObj;
2497
+ } finally {
2498
+ if (abortControllerRef.current === controller) {
2499
+ abortControllerRef.current = null;
2500
+ }
2501
+ }
2502
+ },
2503
+ [getAuthToken]
2504
+ );
2505
+ const start = useCallback12(
2506
+ async (input, opts) => {
2507
+ const targetWfId = opts?.workflowId || workflowId;
2508
+ if (!targetWfId) {
2509
+ throw new Error("Workflow ID must be provided to start execution");
2510
+ }
2511
+ setNodeRuns({});
2512
+ setText("");
2513
+ setOutput(null);
2514
+ setEvents([]);
2515
+ setActiveNodeId(null);
2516
+ const cleanBase = baseUrl.replace(/\/+$/, "");
2517
+ const url = `${cleanBase}/workflows/${targetWfId}/stream`;
2518
+ const body = JSON.stringify({
2519
+ input: input ?? {},
2520
+ dryRun: opts?.dryRun ?? false
2521
+ });
2522
+ return processStream(url, "POST", body);
2523
+ },
2524
+ [workflowId, baseUrl, processStream]
2525
+ );
2526
+ const resume = useCallback12(
2527
+ async (targetRunId, sinceSeq) => {
2528
+ if (!targetRunId) {
2529
+ throw new Error("Run ID is required to resume stream");
2530
+ }
2531
+ setRunId(targetRunId);
2532
+ const cleanBase = baseUrl.replace(/\/+$/, "");
2533
+ const query = sinceSeq !== void 0 ? `?since=${sinceSeq}` : "";
2534
+ const url = `${cleanBase}/workflows/runs/${targetRunId}/resume${query}`;
2535
+ await processStream(url, "GET", void 0, targetRunId);
2536
+ },
2537
+ [baseUrl, processStream]
2538
+ );
2539
+ useEffect11(() => {
2540
+ return () => {
2541
+ if (abortControllerRef.current) {
2542
+ abortControllerRef.current.abort();
2543
+ }
2544
+ };
2545
+ }, []);
2546
+ return {
2547
+ runId,
2548
+ status,
2549
+ isRunning: status === "running",
2550
+ activeNodeId,
2551
+ nodeRuns,
2552
+ text,
2553
+ output,
2554
+ error,
2555
+ events,
2556
+ start,
2557
+ cancel,
2558
+ resume,
2559
+ reset
2560
+ };
2561
+ }
2562
+
2563
+ // src/hooks/useWorkflowRuns.ts
2564
+ import { useCallback as useCallback13, useEffect as useEffect12, useState as useState12 } from "react";
2565
+ function useWorkflowRuns(workflowId, options) {
2566
+ const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
2567
+ const { autoFetch = true, page = 1, limit = 20 } = opts;
2568
+ const { fetchWithAuth } = usePersonaContext();
2569
+ const [runs, setRuns] = useState12([]);
2570
+ const [pagination, setPagination] = useState12({
2571
+ page,
2572
+ limit,
2573
+ total: 0,
2574
+ totalPages: 0
2575
+ });
2576
+ const [isLoading, setIsLoading] = useState12(false);
2577
+ const [error, setError] = useState12(null);
2578
+ const fetchRuns = useCallback13(async () => {
2579
+ if (!workflowId) return [];
2580
+ setIsLoading(true);
2581
+ setError(null);
2582
+ try {
2583
+ const query = `?page=${page}&limit=${limit}`;
2584
+ const res = await fetchWithAuth(`/workflows/${workflowId}/runs${query}`);
2585
+ if (!res.ok) {
2586
+ throw new Error(`Failed to list workflow runs: ${res.statusText}`);
2587
+ }
2588
+ const data = await res.json();
2589
+ const items = Array.isArray(data) ? data : data?.items || data?.runs || [];
2590
+ setRuns(items);
2591
+ if (data?.pagination) {
2592
+ setPagination({
2593
+ page: data.pagination.page ?? page,
2594
+ limit: data.pagination.limit ?? limit,
2595
+ total: data.pagination.total ?? items.length,
2596
+ totalPages: data.pagination.totalPages ?? 1
2597
+ });
2598
+ }
2599
+ return items;
2600
+ } catch (err) {
2601
+ const errorObj = err instanceof Error ? err : new Error(String(err));
2602
+ setError(errorObj);
2603
+ return [];
2604
+ } finally {
2605
+ setIsLoading(false);
2606
+ }
2607
+ }, [fetchWithAuth, workflowId, page, limit]);
2608
+ const getRun = useCallback13(
2609
+ async (runId) => {
2610
+ if (!runId) throw new Error("Run ID is required");
2611
+ const res = await fetchWithAuth(`/workflows/runs/${runId}`);
2612
+ if (!res.ok) {
2613
+ throw new Error(`Failed to fetch workflow run (${res.status}): ${res.statusText}`);
2614
+ }
2615
+ return await res.json();
2616
+ },
2617
+ [fetchWithAuth]
2618
+ );
2619
+ const cancelRun = useCallback13(
2620
+ async (runId) => {
2621
+ if (!runId) throw new Error("Run ID is required");
2622
+ const res = await fetchWithAuth(`/workflows/runs/${runId}/cancel`, {
2623
+ method: "POST"
2624
+ });
2625
+ if (!res.ok) {
2626
+ throw new Error(`Failed to cancel workflow run (${res.status}): ${res.statusText}`);
2627
+ }
2628
+ setRuns(
2629
+ (prev) => prev.map((r) => r._id === runId ? { ...r, status: "cancelled" } : r)
2630
+ );
2631
+ },
2632
+ [fetchWithAuth]
2633
+ );
2634
+ useEffect12(() => {
2635
+ if (autoFetch && workflowId) {
2636
+ void fetchRuns();
2637
+ }
2638
+ }, [autoFetch, workflowId, fetchRuns]);
2639
+ return {
2640
+ runs,
2641
+ pagination,
2642
+ isLoading,
2643
+ error,
2644
+ refetch: fetchRuns,
2645
+ getRun,
2646
+ cancelRun
2647
+ };
2648
+ }
2649
+
2062
2650
  // src/index.ts
2063
2651
  import {
2064
2652
  createLogger as createLogger2,
@@ -2067,7 +2655,7 @@ import {
2067
2655
  getLogLevel,
2068
2656
  isLevelEnabled
2069
2657
  } from "@personaai/logger";
2070
- var VERSION = "0.8.1";
2658
+ var VERSION = "0.9.0";
2071
2659
  export {
2072
2660
  PersonaProvider,
2073
2661
  VERSION,
@@ -2087,6 +2675,10 @@ export {
2087
2675
  useMemory,
2088
2676
  usePersonaContext,
2089
2677
  useThreads,
2090
- useVoice
2678
+ useVoice,
2679
+ useWorkflow,
2680
+ useWorkflowRuns,
2681
+ useWorkflowStream,
2682
+ useWorkflows
2091
2683
  };
2092
2684
  //# sourceMappingURL=index.js.map