@personaai/react 0.5.4 → 0.7.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/README.md CHANGED
@@ -13,7 +13,7 @@ npm install @personaai/react
13
13
  ## Quickstart
14
14
 
15
15
  ```tsx
16
- import { PersonaProvider, useChat } from '@personaai/react';
16
+ import { PersonaProvider, useChat } from "@personaai/react";
17
17
 
18
18
  function App() {
19
19
  return (
@@ -46,14 +46,39 @@ function Chat() {
46
46
 
47
47
  ## Hooks
48
48
 
49
- | Hook | Purpose |
50
- | --- | --- |
51
- | `useChat` | Streaming chat — messages, send, stop, reload, interrupts, workspace files |
52
- | `useThreads` | Thread CRUD — list, create, delete, rename, archive |
53
- | `useFiles` | Upload management — list, upload, delete |
54
- | `useMemory` | Persistent memory — read, write, delete |
55
- | `useAgents` | Agent discovery — list available agents |
56
- | `useConnection` | Health check — backend connectivity status |
49
+ | Hook | Purpose |
50
+ | --------------- | -------------------------------------------------------------------------- |
51
+ | `useChat` | Streaming chat — messages, send, stop, reload, interrupts, workspace files |
52
+ | `useThreads` | Thread CRUD — list, create, delete, rename, reset, archive |
53
+ | `useFiles` | Upload management — list, upload, delete |
54
+ | `useMemory` | Persistent memory — read, write, delete |
55
+ | `useAgents` | Agent discovery — list available agents |
56
+ | `useConnection` | Health check — backend connectivity status |
57
+
58
+ ## Devtools
59
+
60
+ Floating panel for local debugging — inspect hooks, messages and threads with zero runtime changes. Dev-only, not bundled to production unless imported.
61
+
62
+ ```bash
63
+ npm install -D @personaai/devtools
64
+ ```
65
+
66
+ ```tsx
67
+ import { PersonaDevtools } from "@personaai/devtools/react";
68
+ import { useChat, useThreads } from "@personaai/react";
69
+
70
+ function Devtools() {
71
+ const { threads } = useThreads();
72
+ const { messages, files, todos } = useChat();
73
+ return <PersonaDevtools clientState={{ threads, messages, files, todos }} />;
74
+ }
75
+
76
+ {
77
+ process.env.NODE_ENV === "development" && <Devtools />;
78
+ }
79
+ ```
80
+
81
+ See `@personaai/devtools` `sdk/devtools/README.md` for `core`/`react`/`nextjs` subpaths and `baseUrl` polling option.
57
82
 
58
83
  ## Full documentation
59
84
 
package/dist/index.cjs CHANGED
@@ -36,7 +36,8 @@ __export(index_exports, {
36
36
  useMcpConnections: () => useMcpConnections,
37
37
  useMemory: () => useMemory,
38
38
  usePersonaContext: () => usePersonaContext,
39
- useThreads: () => useThreads
39
+ useThreads: () => useThreads,
40
+ useVoice: () => useVoice
40
41
  });
41
42
  module.exports = __toCommonJS(index_exports);
42
43
 
@@ -1207,6 +1208,21 @@ function useThreads(autoFetch = true) {
1207
1208
  (threadId, title) => updateThread(threadId, { title }),
1208
1209
  [updateThread]
1209
1210
  );
1211
+ const resetThread = (0, import_react4.useCallback)(
1212
+ async (threadId) => {
1213
+ const res = await fetchWithAuth(`/threads/${threadId}/reset`, {
1214
+ method: "POST"
1215
+ });
1216
+ if (!res.ok) throw new Error(`Failed to reset thread: ${res.statusText}`);
1217
+ const data = await res.json();
1218
+ const reset = data?.data ?? data;
1219
+ setThreads(
1220
+ (prev) => prev.map((t) => t._id === threadId ? { ...t, ...reset } : t)
1221
+ );
1222
+ return reset;
1223
+ },
1224
+ [fetchWithAuth]
1225
+ );
1210
1226
  const getThread = (0, import_react4.useCallback)(
1211
1227
  async (threadId) => {
1212
1228
  const res = await fetchWithAuth(`/threads/${threadId}`);
@@ -1232,19 +1248,443 @@ function useThreads(autoFetch = true) {
1232
1248
  deleteAllThreads,
1233
1249
  updateThread,
1234
1250
  renameThread,
1251
+ resetThread,
1235
1252
  getThread
1236
1253
  };
1237
1254
  }
1238
1255
 
1239
- // src/hooks/useFiles.ts
1256
+ // src/hooks/useVoice.ts
1240
1257
  var import_react5 = require("react");
1258
+
1259
+ // src/hooks/voiceWorklets.ts
1260
+ var RECORDER_WORKLET_SOURCE = `
1261
+ class PCMRecorderProcessor extends AudioWorkletProcessor {
1262
+ constructor() {
1263
+ super();
1264
+ this._buffer = [];
1265
+ this._chunkSamples = 320; // 20ms @ 16kHz
1266
+ }
1267
+
1268
+ process(inputs) {
1269
+ const input = inputs[0];
1270
+ const channel = input && input[0];
1271
+ if (channel) {
1272
+ for (let i = 0; i < channel.length; i++) {
1273
+ this._buffer.push(channel[i]);
1274
+ }
1275
+ while (this._buffer.length >= this._chunkSamples) {
1276
+ const chunk = this._buffer.splice(0, this._chunkSamples);
1277
+ const int16 = new Int16Array(chunk.length);
1278
+ for (let i = 0; i < chunk.length; i++) {
1279
+ const s = Math.max(-1, Math.min(1, chunk[i]));
1280
+ int16[i] = s < 0 ? s * 0x8000 : s * 0x7fff;
1281
+ }
1282
+ this.port.postMessage(int16.buffer, [int16.buffer]);
1283
+ }
1284
+ }
1285
+ return true;
1286
+ }
1287
+ }
1288
+
1289
+ registerProcessor('pcm-recorder-processor', PCMRecorderProcessor);
1290
+ `;
1291
+ var PLAYER_WORKLET_SOURCE = `
1292
+ class PCMPlayerProcessor extends AudioWorkletProcessor {
1293
+ constructor() {
1294
+ super();
1295
+ this._queue = [];
1296
+ this._readOffset = 0;
1297
+ this.port.onmessage = (event) => {
1298
+ const msg = event.data;
1299
+ if (msg && msg.type === 'flush') {
1300
+ this._queue = [];
1301
+ this._readOffset = 0;
1302
+ return;
1303
+ }
1304
+ const int16 = new Int16Array(msg);
1305
+ const float32 = new Float32Array(int16.length);
1306
+ for (let i = 0; i < int16.length; i++) {
1307
+ float32[i] = int16[i] / 0x8000;
1308
+ }
1309
+ this._queue.push(float32);
1310
+ };
1311
+ }
1312
+
1313
+ process(_inputs, outputs) {
1314
+ const output = outputs[0][0];
1315
+ let outIdx = 0;
1316
+ while (outIdx < output.length) {
1317
+ if (this._queue.length === 0) {
1318
+ output[outIdx++] = 0;
1319
+ continue;
1320
+ }
1321
+ const current = this._queue[0];
1322
+ const remaining = current.length - this._readOffset;
1323
+ const toCopy = Math.min(remaining, output.length - outIdx);
1324
+ output.set(current.subarray(this._readOffset, this._readOffset + toCopy), outIdx);
1325
+ outIdx += toCopy;
1326
+ this._readOffset += toCopy;
1327
+ if (this._readOffset >= current.length) {
1328
+ this._queue.shift();
1329
+ this._readOffset = 0;
1330
+ }
1331
+ }
1332
+ return true;
1333
+ }
1334
+ }
1335
+
1336
+ registerProcessor('pcm-player-processor', PCMPlayerProcessor);
1337
+ `;
1338
+ function toModuleUrl(source) {
1339
+ const blob = new Blob([source], { type: "application/javascript" });
1340
+ return URL.createObjectURL(blob);
1341
+ }
1342
+ function recorderWorkletUrl() {
1343
+ return toModuleUrl(RECORDER_WORKLET_SOURCE);
1344
+ }
1345
+ function playerWorkletUrl() {
1346
+ return toModuleUrl(PLAYER_WORKLET_SOURCE);
1347
+ }
1348
+
1349
+ // src/hooks/useVoice.ts
1350
+ function useVoice(options = {}) {
1351
+ const { defaultAgentId, fetchWithAuth, logger } = usePersonaContext();
1352
+ const voiceLogger = (0, import_react5.useMemo)(() => logger.child("voice"), [logger]);
1353
+ const agentId = options.agentId || defaultAgentId;
1354
+ const [state, setState] = (0, import_react5.useState)("idle");
1355
+ const [isMuted, setIsMuted] = (0, import_react5.useState)(false);
1356
+ const [transcript, setTranscript] = (0, import_react5.useState)(
1357
+ []
1358
+ );
1359
+ const [partial, setPartial] = (0, import_react5.useState)(
1360
+ null
1361
+ );
1362
+ const [toolCalls, setToolCalls] = (0, import_react5.useState)([]);
1363
+ const [error, setError] = (0, import_react5.useState)(null);
1364
+ const [endReason, setEndReason] = (0, import_react5.useState)(
1365
+ null
1366
+ );
1367
+ const wsRef = (0, import_react5.useRef)(null);
1368
+ const streamRef = (0, import_react5.useRef)(null);
1369
+ const inputCtxRef = (0, import_react5.useRef)(null);
1370
+ const outputCtxRef = (0, import_react5.useRef)(null);
1371
+ const recorderNodeRef = (0, import_react5.useRef)(null);
1372
+ const playerNodeRef = (0, import_react5.useRef)(null);
1373
+ const acceptedTurnSeqRef = (0, import_react5.useRef)(0);
1374
+ const mountedRef = (0, import_react5.useRef)(true);
1375
+ (0, import_react5.useEffect)(() => {
1376
+ mountedRef.current = true;
1377
+ return () => {
1378
+ mountedRef.current = false;
1379
+ };
1380
+ }, []);
1381
+ const teardownAudio = (0, import_react5.useCallback)(() => {
1382
+ try {
1383
+ streamRef.current?.getTracks().forEach((track) => track.stop());
1384
+ } catch {
1385
+ }
1386
+ streamRef.current = null;
1387
+ try {
1388
+ recorderNodeRef.current?.disconnect();
1389
+ } catch {
1390
+ }
1391
+ recorderNodeRef.current = null;
1392
+ try {
1393
+ playerNodeRef.current?.disconnect();
1394
+ } catch {
1395
+ }
1396
+ playerNodeRef.current = null;
1397
+ try {
1398
+ void inputCtxRef.current?.close();
1399
+ } catch {
1400
+ }
1401
+ inputCtxRef.current = null;
1402
+ try {
1403
+ void outputCtxRef.current?.close();
1404
+ } catch {
1405
+ }
1406
+ outputCtxRef.current = null;
1407
+ }, []);
1408
+ const stop = (0, import_react5.useCallback)(() => {
1409
+ voiceLogger.debug("stop() called");
1410
+ try {
1411
+ wsRef.current?.close(1e3, "client_stop");
1412
+ } catch {
1413
+ }
1414
+ wsRef.current = null;
1415
+ teardownAudio();
1416
+ if (mountedRef.current) setState("idle");
1417
+ }, [teardownAudio, voiceLogger]);
1418
+ (0, import_react5.useEffect)(() => stop, [stop]);
1419
+ const startCapture = (0, import_react5.useCallback)(async (inputSampleRate) => {
1420
+ const stream = await navigator.mediaDevices.getUserMedia({
1421
+ audio: {
1422
+ echoCancellation: true,
1423
+ noiseSuppression: true,
1424
+ autoGainControl: true,
1425
+ channelCount: 1
1426
+ }
1427
+ });
1428
+ streamRef.current = stream;
1429
+ const inputCtx = new AudioContext({ sampleRate: inputSampleRate });
1430
+ inputCtxRef.current = inputCtx;
1431
+ await inputCtx.audioWorklet.addModule(recorderWorkletUrl());
1432
+ const source = inputCtx.createMediaStreamSource(stream);
1433
+ const recorderNode = new AudioWorkletNode(
1434
+ inputCtx,
1435
+ "pcm-recorder-processor"
1436
+ );
1437
+ recorderNode.port.onmessage = (event) => {
1438
+ if (wsRef.current?.readyState === WebSocket.OPEN) {
1439
+ wsRef.current.send(event.data);
1440
+ }
1441
+ };
1442
+ recorderNodeRef.current = recorderNode;
1443
+ source.connect(recorderNode);
1444
+ }, []);
1445
+ const setupPlayback = (0, import_react5.useCallback)(async (outputSampleRate) => {
1446
+ const outputCtx = new AudioContext({ sampleRate: outputSampleRate });
1447
+ outputCtxRef.current = outputCtx;
1448
+ await outputCtx.audioWorklet.addModule(playerWorkletUrl());
1449
+ const playerNode = new AudioWorkletNode(outputCtx, "pcm-player-processor");
1450
+ playerNode.connect(outputCtx.destination);
1451
+ playerNodeRef.current = playerNode;
1452
+ }, []);
1453
+ const upsertToolCall = (0, import_react5.useCallback)(
1454
+ (id, patch) => {
1455
+ setToolCalls((prev) => {
1456
+ const idx = prev.findIndex((t) => t.id === id);
1457
+ if (idx === -1)
1458
+ return [...prev, { id, status: "running", ...patch }];
1459
+ const next = [...prev];
1460
+ next[idx] = { ...next[idx], ...patch };
1461
+ return next;
1462
+ });
1463
+ },
1464
+ []
1465
+ );
1466
+ const handleTranscript = (0, import_react5.useCallback)(
1467
+ (value) => {
1468
+ const { speaker, text, isFinal } = value;
1469
+ if (isFinal) {
1470
+ setPartial((prev) => prev?.speaker === speaker ? null : prev);
1471
+ setTranscript((prev) => [
1472
+ ...prev,
1473
+ { id: `${speaker}-${prev.length}`, speaker, text }
1474
+ ]);
1475
+ } else {
1476
+ setPartial({ id: "partial", speaker, text });
1477
+ }
1478
+ },
1479
+ []
1480
+ );
1481
+ const handleCustomEvent = (0, import_react5.useCallback)(
1482
+ (name, value) => {
1483
+ switch (name) {
1484
+ case "voice_session_ready":
1485
+ voiceLogger.debug("voice_session_ready", value);
1486
+ Promise.all([
1487
+ setupPlayback(value.outputSampleRate),
1488
+ startCapture(value.inputSampleRate)
1489
+ ]).then(() => {
1490
+ if (mountedRef.current) setState("listening");
1491
+ }).catch((err) => {
1492
+ voiceLogger.error("audio graph setup failed", {
1493
+ error: err instanceof Error ? err.message : String(err)
1494
+ });
1495
+ if (mountedRef.current) {
1496
+ setError(err instanceof Error ? err : new Error(String(err)));
1497
+ setState("error");
1498
+ }
1499
+ });
1500
+ break;
1501
+ case "voice_activity":
1502
+ if (value.speaker === "user" && value.state === "start") {
1503
+ setState("listening");
1504
+ } else if (value.speaker === "user" && value.state === "end") {
1505
+ setState("thinking");
1506
+ } else if (value.speaker === "agent" && value.state === "start") {
1507
+ setState("speaking");
1508
+ } else if (value.speaker === "agent" && value.state === "end") {
1509
+ setState("listening");
1510
+ }
1511
+ break;
1512
+ case "voice_transcript":
1513
+ handleTranscript(
1514
+ value
1515
+ );
1516
+ break;
1517
+ case "voice_interrupted":
1518
+ acceptedTurnSeqRef.current = value.turnSeq;
1519
+ playerNodeRef.current?.port.postMessage({ type: "flush" });
1520
+ break;
1521
+ case "voice_session_resumed":
1522
+ voiceLogger.info("session transparently resumed");
1523
+ break;
1524
+ case "voice_session_ended":
1525
+ voiceLogger.info("session ended", { reason: value.reason });
1526
+ setState("ended");
1527
+ setEndReason(value.reason ?? null);
1528
+ teardownAudio();
1529
+ try {
1530
+ wsRef.current?.close();
1531
+ } catch {
1532
+ }
1533
+ wsRef.current = null;
1534
+ break;
1535
+ default:
1536
+ break;
1537
+ }
1538
+ },
1539
+ [handleTranscript, setupPlayback, startCapture, teardownAudio, voiceLogger]
1540
+ );
1541
+ const handleMessage = (0, import_react5.useCallback)(
1542
+ (event) => {
1543
+ if (typeof event.data !== "string") {
1544
+ const buf = event.data;
1545
+ const view = new DataView(buf);
1546
+ const turnSeq = view.getUint32(0, true);
1547
+ if (turnSeq >= acceptedTurnSeqRef.current) {
1548
+ acceptedTurnSeqRef.current = turnSeq;
1549
+ const pcmBytes = buf.slice(4);
1550
+ playerNodeRef.current?.port.postMessage(pcmBytes, [pcmBytes]);
1551
+ }
1552
+ return;
1553
+ }
1554
+ let msg;
1555
+ try {
1556
+ msg = JSON.parse(event.data);
1557
+ } catch {
1558
+ return;
1559
+ }
1560
+ switch (msg.type) {
1561
+ case "CUSTOM":
1562
+ handleCustomEvent(
1563
+ msg.name,
1564
+ msg.value
1565
+ );
1566
+ break;
1567
+ case "TOOL_CALL_CHUNK":
1568
+ upsertToolCall(msg.toolCallId, {
1569
+ name: msg.toolCallName,
1570
+ status: "running"
1571
+ });
1572
+ break;
1573
+ case "TOOL_CALL_RESULT": {
1574
+ let parsed = null;
1575
+ try {
1576
+ parsed = JSON.parse(msg.content);
1577
+ } catch {
1578
+ parsed = { output: msg.content };
1579
+ }
1580
+ upsertToolCall(msg.toolCallId, {
1581
+ status: parsed?.error ? "error" : "done",
1582
+ summary: parsed?.error || (typeof parsed?.output === "string" ? parsed.output : JSON.stringify(parsed?.output ?? ""))
1583
+ });
1584
+ break;
1585
+ }
1586
+ case "RUN_ERROR":
1587
+ voiceLogger.warn("RUN_ERROR", { message: msg.message });
1588
+ setError(new Error(msg.message || "The agent run failed."));
1589
+ setState("error");
1590
+ break;
1591
+ default:
1592
+ break;
1593
+ }
1594
+ },
1595
+ [handleCustomEvent, upsertToolCall, voiceLogger]
1596
+ );
1597
+ const start = (0, import_react5.useCallback)(async () => {
1598
+ if (!agentId) {
1599
+ const err = new Error(
1600
+ "useVoice: no agentId provided and no defaultAgentId set on PersonaProvider"
1601
+ );
1602
+ setError(err);
1603
+ setState("error");
1604
+ return;
1605
+ }
1606
+ setError(null);
1607
+ setEndReason(null);
1608
+ setTranscript([]);
1609
+ setPartial(null);
1610
+ setToolCalls([]);
1611
+ acceptedTurnSeqRef.current = 0;
1612
+ setState("connecting");
1613
+ voiceLogger.debug("start() called", { agentId });
1614
+ try {
1615
+ const res = await fetchWithAuth("/voice/sessions", {
1616
+ method: "POST",
1617
+ headers: { "Content-Type": "application/json" },
1618
+ body: JSON.stringify({ agentId })
1619
+ });
1620
+ if (!res.ok) {
1621
+ throw new Error(`Failed to start voice session: ${res.statusText}`);
1622
+ }
1623
+ const data = await res.json();
1624
+ const ticket = data?.data ?? data;
1625
+ if (!ticket?.wsUrl) {
1626
+ throw new Error("Server did not return a voice session URL.");
1627
+ }
1628
+ const ws = new WebSocket(ticket.wsUrl);
1629
+ ws.binaryType = "arraybuffer";
1630
+ wsRef.current = ws;
1631
+ ws.onmessage = handleMessage;
1632
+ ws.onerror = () => {
1633
+ voiceLogger.warn("WebSocket error");
1634
+ if (mountedRef.current) {
1635
+ setError(new Error("Voice connection error."));
1636
+ setState("error");
1637
+ }
1638
+ };
1639
+ ws.onclose = () => {
1640
+ if (mountedRef.current && wsRef.current === ws) {
1641
+ setState((prev) => prev === "error" ? prev : "idle");
1642
+ }
1643
+ };
1644
+ } catch (err) {
1645
+ const errorObj = err instanceof Error ? err : new Error(String(err));
1646
+ voiceLogger.error("start() failed", { error: errorObj.message });
1647
+ if (mountedRef.current) {
1648
+ setError(errorObj);
1649
+ setState("error");
1650
+ }
1651
+ teardownAudio();
1652
+ }
1653
+ }, [agentId, fetchWithAuth, handleMessage, teardownAudio, voiceLogger]);
1654
+ const mute = (0, import_react5.useCallback)((muted) => {
1655
+ setIsMuted(muted);
1656
+ streamRef.current?.getAudioTracks().forEach((track) => {
1657
+ track.enabled = !muted;
1658
+ });
1659
+ }, []);
1660
+ const sendText = (0, import_react5.useCallback)((text) => {
1661
+ if (!text?.trim() || wsRef.current?.readyState !== WebSocket.OPEN) return;
1662
+ wsRef.current.send(JSON.stringify({ type: "voice.text", text }));
1663
+ }, []);
1664
+ return {
1665
+ state,
1666
+ isMuted,
1667
+ transcript,
1668
+ partial,
1669
+ toolCalls,
1670
+ error,
1671
+ endReason,
1672
+ start,
1673
+ stop,
1674
+ mute,
1675
+ sendText
1676
+ };
1677
+ }
1678
+
1679
+ // src/hooks/useFiles.ts
1680
+ var import_react6 = require("react");
1241
1681
  function useFiles(autoFetch = true) {
1242
1682
  const { fetchWithAuth } = usePersonaContext();
1243
- const [files, setFiles] = (0, import_react5.useState)([]);
1244
- const [isLoading, setIsLoading] = (0, import_react5.useState)(false);
1245
- const [isUploading, setIsUploading] = (0, import_react5.useState)(false);
1246
- const [error, setError] = (0, import_react5.useState)(null);
1247
- const fetchFiles = (0, import_react5.useCallback)(async () => {
1683
+ const [files, setFiles] = (0, import_react6.useState)([]);
1684
+ const [isLoading, setIsLoading] = (0, import_react6.useState)(false);
1685
+ const [isUploading, setIsUploading] = (0, import_react6.useState)(false);
1686
+ const [error, setError] = (0, import_react6.useState)(null);
1687
+ const fetchFiles = (0, import_react6.useCallback)(async () => {
1248
1688
  setIsLoading(true);
1249
1689
  setError(null);
1250
1690
  try {
@@ -1262,7 +1702,7 @@ function useFiles(autoFetch = true) {
1262
1702
  setIsLoading(false);
1263
1703
  }
1264
1704
  }, [fetchWithAuth]);
1265
- const uploadFile = (0, import_react5.useCallback)(
1705
+ const uploadFile = (0, import_react6.useCallback)(
1266
1706
  async (fileOrFormData) => {
1267
1707
  setIsUploading(true);
1268
1708
  setError(null);
@@ -1295,7 +1735,7 @@ function useFiles(autoFetch = true) {
1295
1735
  },
1296
1736
  [fetchWithAuth, fetchFiles]
1297
1737
  );
1298
- const deleteFile = (0, import_react5.useCallback)(
1738
+ const deleteFile = (0, import_react6.useCallback)(
1299
1739
  async (fileId) => {
1300
1740
  const res = await fetchWithAuth(`/files/${fileId}`, { method: "DELETE" });
1301
1741
  if (!res.ok) throw new Error(`Failed to delete file: ${res.statusText}`);
@@ -1303,7 +1743,7 @@ function useFiles(autoFetch = true) {
1303
1743
  },
1304
1744
  [fetchWithAuth]
1305
1745
  );
1306
- const bulkDeleteFiles = (0, import_react5.useCallback)(
1746
+ const bulkDeleteFiles = (0, import_react6.useCallback)(
1307
1747
  async (fileIds) => {
1308
1748
  const res = await fetchWithAuth("/files/bulk-delete", {
1309
1749
  method: "POST",
@@ -1318,10 +1758,10 @@ function useFiles(autoFetch = true) {
1318
1758
  },
1319
1759
  [fetchWithAuth]
1320
1760
  );
1321
- const getDownloadUrl = (0, import_react5.useCallback)((fileId) => {
1761
+ const getDownloadUrl = (0, import_react6.useCallback)((fileId) => {
1322
1762
  return `/files/${fileId}`;
1323
1763
  }, []);
1324
- (0, import_react5.useEffect)(() => {
1764
+ (0, import_react6.useEffect)(() => {
1325
1765
  if (autoFetch) {
1326
1766
  void fetchFiles();
1327
1767
  }
@@ -1340,13 +1780,13 @@ function useFiles(autoFetch = true) {
1340
1780
  }
1341
1781
 
1342
1782
  // src/hooks/useAgents.ts
1343
- var import_react6 = require("react");
1783
+ var import_react7 = require("react");
1344
1784
  function useAgents(autoFetch = true) {
1345
1785
  const { fetchWithAuth } = usePersonaContext();
1346
- const [agents, setAgents] = (0, import_react6.useState)([]);
1347
- const [isLoading, setIsLoading] = (0, import_react6.useState)(false);
1348
- const [error, setError] = (0, import_react6.useState)(null);
1349
- const fetchAgents = (0, import_react6.useCallback)(async () => {
1786
+ const [agents, setAgents] = (0, import_react7.useState)([]);
1787
+ const [isLoading, setIsLoading] = (0, import_react7.useState)(false);
1788
+ const [error, setError] = (0, import_react7.useState)(null);
1789
+ const fetchAgents = (0, import_react7.useCallback)(async () => {
1350
1790
  setIsLoading(true);
1351
1791
  setError(null);
1352
1792
  try {
@@ -1364,7 +1804,7 @@ function useAgents(autoFetch = true) {
1364
1804
  setIsLoading(false);
1365
1805
  }
1366
1806
  }, [fetchWithAuth]);
1367
- (0, import_react6.useEffect)(() => {
1807
+ (0, import_react7.useEffect)(() => {
1368
1808
  if (autoFetch) {
1369
1809
  void fetchAgents();
1370
1810
  }
@@ -1378,13 +1818,13 @@ function useAgents(autoFetch = true) {
1378
1818
  }
1379
1819
 
1380
1820
  // src/hooks/useConnection.ts
1381
- var import_react7 = require("react");
1821
+ var import_react8 = require("react");
1382
1822
  function useConnection(autoCheck = true) {
1383
1823
  const { fetchWithAuth } = usePersonaContext();
1384
- const [health, setHealth] = (0, import_react7.useState)(null);
1385
- const [isConnected, setIsConnected] = (0, import_react7.useState)(false);
1386
- const [isLoading, setIsLoading] = (0, import_react7.useState)(false);
1387
- const checkHealth = (0, import_react7.useCallback)(async () => {
1824
+ const [health, setHealth] = (0, import_react8.useState)(null);
1825
+ const [isConnected, setIsConnected] = (0, import_react8.useState)(false);
1826
+ const [isLoading, setIsLoading] = (0, import_react8.useState)(false);
1827
+ const checkHealth = (0, import_react8.useCallback)(async () => {
1388
1828
  setIsLoading(true);
1389
1829
  try {
1390
1830
  const res = await fetchWithAuth("/health");
@@ -1403,7 +1843,7 @@ function useConnection(autoCheck = true) {
1403
1843
  setIsLoading(false);
1404
1844
  }
1405
1845
  }, [fetchWithAuth]);
1406
- (0, import_react7.useEffect)(() => {
1846
+ (0, import_react8.useEffect)(() => {
1407
1847
  if (autoCheck) {
1408
1848
  void checkHealth();
1409
1849
  }
@@ -1417,15 +1857,15 @@ function useConnection(autoCheck = true) {
1417
1857
  }
1418
1858
 
1419
1859
  // src/hooks/useMcpConnections.ts
1420
- var import_react8 = require("react");
1860
+ var import_react9 = require("react");
1421
1861
  function useMcpConnections(options = {}) {
1422
1862
  const { defaultAgentId, fetchWithAuth } = usePersonaContext();
1423
1863
  const agentId = options.agentId ?? defaultAgentId;
1424
1864
  const autoFetch = options.autoFetch ?? true;
1425
- const [connections, setConnections] = (0, import_react8.useState)([]);
1426
- const [isLoading, setIsLoading] = (0, import_react8.useState)(false);
1427
- const [error, setError] = (0, import_react8.useState)(null);
1428
- const fetchConnections = (0, import_react8.useCallback)(async () => {
1865
+ const [connections, setConnections] = (0, import_react9.useState)([]);
1866
+ const [isLoading, setIsLoading] = (0, import_react9.useState)(false);
1867
+ const [error, setError] = (0, import_react9.useState)(null);
1868
+ const fetchConnections = (0, import_react9.useCallback)(async () => {
1429
1869
  if (!agentId) return [];
1430
1870
  setIsLoading(true);
1431
1871
  setError(null);
@@ -1449,7 +1889,7 @@ function useMcpConnections(options = {}) {
1449
1889
  setIsLoading(false);
1450
1890
  }
1451
1891
  }, [agentId, fetchWithAuth, options.returnTo]);
1452
- (0, import_react8.useEffect)(() => {
1892
+ (0, import_react9.useEffect)(() => {
1453
1893
  if (autoFetch) void fetchConnections();
1454
1894
  }, [autoFetch, fetchConnections]);
1455
1895
  return {
@@ -1464,7 +1904,7 @@ function useMcpConnections(options = {}) {
1464
1904
 
1465
1905
  // src/index.ts
1466
1906
  var import_logger2 = require("@personaai/logger");
1467
- var VERSION = "0.5.4";
1907
+ var VERSION = "0.7.0";
1468
1908
  // Annotate the CommonJS export names for ESM import in node:
1469
1909
  0 && (module.exports = {
1470
1910
  PersonaProvider,
@@ -1483,6 +1923,7 @@ var VERSION = "0.5.4";
1483
1923
  useMcpConnections,
1484
1924
  useMemory,
1485
1925
  usePersonaContext,
1486
- useThreads
1926
+ useThreads,
1927
+ useVoice
1487
1928
  });
1488
1929
  //# sourceMappingURL=index.cjs.map