@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/dist/index.js CHANGED
@@ -1165,6 +1165,21 @@ function useThreads(autoFetch = true) {
1165
1165
  (threadId, title) => updateThread(threadId, { title }),
1166
1166
  [updateThread]
1167
1167
  );
1168
+ const resetThread = useCallback3(
1169
+ async (threadId) => {
1170
+ const res = await fetchWithAuth(`/threads/${threadId}/reset`, {
1171
+ method: "POST"
1172
+ });
1173
+ if (!res.ok) throw new Error(`Failed to reset thread: ${res.statusText}`);
1174
+ const data = await res.json();
1175
+ const reset = data?.data ?? data;
1176
+ setThreads(
1177
+ (prev) => prev.map((t) => t._id === threadId ? { ...t, ...reset } : t)
1178
+ );
1179
+ return reset;
1180
+ },
1181
+ [fetchWithAuth]
1182
+ );
1168
1183
  const getThread = useCallback3(
1169
1184
  async (threadId) => {
1170
1185
  const res = await fetchWithAuth(`/threads/${threadId}`);
@@ -1190,19 +1205,443 @@ function useThreads(autoFetch = true) {
1190
1205
  deleteAllThreads,
1191
1206
  updateThread,
1192
1207
  renameThread,
1208
+ resetThread,
1193
1209
  getThread
1194
1210
  };
1195
1211
  }
1196
1212
 
1213
+ // src/hooks/useVoice.ts
1214
+ import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo3, useRef as useRef2, useState as useState4 } from "react";
1215
+
1216
+ // src/hooks/voiceWorklets.ts
1217
+ var RECORDER_WORKLET_SOURCE = `
1218
+ class PCMRecorderProcessor extends AudioWorkletProcessor {
1219
+ constructor() {
1220
+ super();
1221
+ this._buffer = [];
1222
+ this._chunkSamples = 320; // 20ms @ 16kHz
1223
+ }
1224
+
1225
+ process(inputs) {
1226
+ const input = inputs[0];
1227
+ const channel = input && input[0];
1228
+ if (channel) {
1229
+ for (let i = 0; i < channel.length; i++) {
1230
+ this._buffer.push(channel[i]);
1231
+ }
1232
+ while (this._buffer.length >= this._chunkSamples) {
1233
+ const chunk = this._buffer.splice(0, this._chunkSamples);
1234
+ const int16 = new Int16Array(chunk.length);
1235
+ for (let i = 0; i < chunk.length; i++) {
1236
+ const s = Math.max(-1, Math.min(1, chunk[i]));
1237
+ int16[i] = s < 0 ? s * 0x8000 : s * 0x7fff;
1238
+ }
1239
+ this.port.postMessage(int16.buffer, [int16.buffer]);
1240
+ }
1241
+ }
1242
+ return true;
1243
+ }
1244
+ }
1245
+
1246
+ registerProcessor('pcm-recorder-processor', PCMRecorderProcessor);
1247
+ `;
1248
+ var PLAYER_WORKLET_SOURCE = `
1249
+ class PCMPlayerProcessor extends AudioWorkletProcessor {
1250
+ constructor() {
1251
+ super();
1252
+ this._queue = [];
1253
+ this._readOffset = 0;
1254
+ this.port.onmessage = (event) => {
1255
+ const msg = event.data;
1256
+ if (msg && msg.type === 'flush') {
1257
+ this._queue = [];
1258
+ this._readOffset = 0;
1259
+ return;
1260
+ }
1261
+ const int16 = new Int16Array(msg);
1262
+ const float32 = new Float32Array(int16.length);
1263
+ for (let i = 0; i < int16.length; i++) {
1264
+ float32[i] = int16[i] / 0x8000;
1265
+ }
1266
+ this._queue.push(float32);
1267
+ };
1268
+ }
1269
+
1270
+ process(_inputs, outputs) {
1271
+ const output = outputs[0][0];
1272
+ let outIdx = 0;
1273
+ while (outIdx < output.length) {
1274
+ if (this._queue.length === 0) {
1275
+ output[outIdx++] = 0;
1276
+ continue;
1277
+ }
1278
+ const current = this._queue[0];
1279
+ const remaining = current.length - this._readOffset;
1280
+ const toCopy = Math.min(remaining, output.length - outIdx);
1281
+ output.set(current.subarray(this._readOffset, this._readOffset + toCopy), outIdx);
1282
+ outIdx += toCopy;
1283
+ this._readOffset += toCopy;
1284
+ if (this._readOffset >= current.length) {
1285
+ this._queue.shift();
1286
+ this._readOffset = 0;
1287
+ }
1288
+ }
1289
+ return true;
1290
+ }
1291
+ }
1292
+
1293
+ registerProcessor('pcm-player-processor', PCMPlayerProcessor);
1294
+ `;
1295
+ function toModuleUrl(source) {
1296
+ const blob = new Blob([source], { type: "application/javascript" });
1297
+ return URL.createObjectURL(blob);
1298
+ }
1299
+ function recorderWorkletUrl() {
1300
+ return toModuleUrl(RECORDER_WORKLET_SOURCE);
1301
+ }
1302
+ function playerWorkletUrl() {
1303
+ return toModuleUrl(PLAYER_WORKLET_SOURCE);
1304
+ }
1305
+
1306
+ // src/hooks/useVoice.ts
1307
+ function useVoice(options = {}) {
1308
+ const { defaultAgentId, fetchWithAuth, logger } = usePersonaContext();
1309
+ const voiceLogger = useMemo3(() => logger.child("voice"), [logger]);
1310
+ const agentId = options.agentId || defaultAgentId;
1311
+ const [state, setState] = useState4("idle");
1312
+ const [isMuted, setIsMuted] = useState4(false);
1313
+ const [transcript, setTranscript] = useState4(
1314
+ []
1315
+ );
1316
+ const [partial, setPartial] = useState4(
1317
+ null
1318
+ );
1319
+ const [toolCalls, setToolCalls] = useState4([]);
1320
+ const [error, setError] = useState4(null);
1321
+ const [endReason, setEndReason] = useState4(
1322
+ null
1323
+ );
1324
+ const wsRef = useRef2(null);
1325
+ const streamRef = useRef2(null);
1326
+ const inputCtxRef = useRef2(null);
1327
+ const outputCtxRef = useRef2(null);
1328
+ const recorderNodeRef = useRef2(null);
1329
+ const playerNodeRef = useRef2(null);
1330
+ const acceptedTurnSeqRef = useRef2(0);
1331
+ const mountedRef = useRef2(true);
1332
+ useEffect4(() => {
1333
+ mountedRef.current = true;
1334
+ return () => {
1335
+ mountedRef.current = false;
1336
+ };
1337
+ }, []);
1338
+ const teardownAudio = useCallback4(() => {
1339
+ try {
1340
+ streamRef.current?.getTracks().forEach((track) => track.stop());
1341
+ } catch {
1342
+ }
1343
+ streamRef.current = null;
1344
+ try {
1345
+ recorderNodeRef.current?.disconnect();
1346
+ } catch {
1347
+ }
1348
+ recorderNodeRef.current = null;
1349
+ try {
1350
+ playerNodeRef.current?.disconnect();
1351
+ } catch {
1352
+ }
1353
+ playerNodeRef.current = null;
1354
+ try {
1355
+ void inputCtxRef.current?.close();
1356
+ } catch {
1357
+ }
1358
+ inputCtxRef.current = null;
1359
+ try {
1360
+ void outputCtxRef.current?.close();
1361
+ } catch {
1362
+ }
1363
+ outputCtxRef.current = null;
1364
+ }, []);
1365
+ const stop = useCallback4(() => {
1366
+ voiceLogger.debug("stop() called");
1367
+ try {
1368
+ wsRef.current?.close(1e3, "client_stop");
1369
+ } catch {
1370
+ }
1371
+ wsRef.current = null;
1372
+ teardownAudio();
1373
+ if (mountedRef.current) setState("idle");
1374
+ }, [teardownAudio, voiceLogger]);
1375
+ useEffect4(() => stop, [stop]);
1376
+ const startCapture = useCallback4(async (inputSampleRate) => {
1377
+ const stream = await navigator.mediaDevices.getUserMedia({
1378
+ audio: {
1379
+ echoCancellation: true,
1380
+ noiseSuppression: true,
1381
+ autoGainControl: true,
1382
+ channelCount: 1
1383
+ }
1384
+ });
1385
+ streamRef.current = stream;
1386
+ const inputCtx = new AudioContext({ sampleRate: inputSampleRate });
1387
+ inputCtxRef.current = inputCtx;
1388
+ await inputCtx.audioWorklet.addModule(recorderWorkletUrl());
1389
+ const source = inputCtx.createMediaStreamSource(stream);
1390
+ const recorderNode = new AudioWorkletNode(
1391
+ inputCtx,
1392
+ "pcm-recorder-processor"
1393
+ );
1394
+ recorderNode.port.onmessage = (event) => {
1395
+ if (wsRef.current?.readyState === WebSocket.OPEN) {
1396
+ wsRef.current.send(event.data);
1397
+ }
1398
+ };
1399
+ recorderNodeRef.current = recorderNode;
1400
+ source.connect(recorderNode);
1401
+ }, []);
1402
+ const setupPlayback = useCallback4(async (outputSampleRate) => {
1403
+ const outputCtx = new AudioContext({ sampleRate: outputSampleRate });
1404
+ outputCtxRef.current = outputCtx;
1405
+ await outputCtx.audioWorklet.addModule(playerWorkletUrl());
1406
+ const playerNode = new AudioWorkletNode(outputCtx, "pcm-player-processor");
1407
+ playerNode.connect(outputCtx.destination);
1408
+ playerNodeRef.current = playerNode;
1409
+ }, []);
1410
+ const upsertToolCall = useCallback4(
1411
+ (id, patch) => {
1412
+ setToolCalls((prev) => {
1413
+ const idx = prev.findIndex((t) => t.id === id);
1414
+ if (idx === -1)
1415
+ return [...prev, { id, status: "running", ...patch }];
1416
+ const next = [...prev];
1417
+ next[idx] = { ...next[idx], ...patch };
1418
+ return next;
1419
+ });
1420
+ },
1421
+ []
1422
+ );
1423
+ const handleTranscript = useCallback4(
1424
+ (value) => {
1425
+ const { speaker, text, isFinal } = value;
1426
+ if (isFinal) {
1427
+ setPartial((prev) => prev?.speaker === speaker ? null : prev);
1428
+ setTranscript((prev) => [
1429
+ ...prev,
1430
+ { id: `${speaker}-${prev.length}`, speaker, text }
1431
+ ]);
1432
+ } else {
1433
+ setPartial({ id: "partial", speaker, text });
1434
+ }
1435
+ },
1436
+ []
1437
+ );
1438
+ const handleCustomEvent = useCallback4(
1439
+ (name, value) => {
1440
+ switch (name) {
1441
+ case "voice_session_ready":
1442
+ voiceLogger.debug("voice_session_ready", value);
1443
+ Promise.all([
1444
+ setupPlayback(value.outputSampleRate),
1445
+ startCapture(value.inputSampleRate)
1446
+ ]).then(() => {
1447
+ if (mountedRef.current) setState("listening");
1448
+ }).catch((err) => {
1449
+ voiceLogger.error("audio graph setup failed", {
1450
+ error: err instanceof Error ? err.message : String(err)
1451
+ });
1452
+ if (mountedRef.current) {
1453
+ setError(err instanceof Error ? err : new Error(String(err)));
1454
+ setState("error");
1455
+ }
1456
+ });
1457
+ break;
1458
+ case "voice_activity":
1459
+ if (value.speaker === "user" && value.state === "start") {
1460
+ setState("listening");
1461
+ } else if (value.speaker === "user" && value.state === "end") {
1462
+ setState("thinking");
1463
+ } else if (value.speaker === "agent" && value.state === "start") {
1464
+ setState("speaking");
1465
+ } else if (value.speaker === "agent" && value.state === "end") {
1466
+ setState("listening");
1467
+ }
1468
+ break;
1469
+ case "voice_transcript":
1470
+ handleTranscript(
1471
+ value
1472
+ );
1473
+ break;
1474
+ case "voice_interrupted":
1475
+ acceptedTurnSeqRef.current = value.turnSeq;
1476
+ playerNodeRef.current?.port.postMessage({ type: "flush" });
1477
+ break;
1478
+ case "voice_session_resumed":
1479
+ voiceLogger.info("session transparently resumed");
1480
+ break;
1481
+ case "voice_session_ended":
1482
+ voiceLogger.info("session ended", { reason: value.reason });
1483
+ setState("ended");
1484
+ setEndReason(value.reason ?? null);
1485
+ teardownAudio();
1486
+ try {
1487
+ wsRef.current?.close();
1488
+ } catch {
1489
+ }
1490
+ wsRef.current = null;
1491
+ break;
1492
+ default:
1493
+ break;
1494
+ }
1495
+ },
1496
+ [handleTranscript, setupPlayback, startCapture, teardownAudio, voiceLogger]
1497
+ );
1498
+ const handleMessage = useCallback4(
1499
+ (event) => {
1500
+ if (typeof event.data !== "string") {
1501
+ const buf = event.data;
1502
+ const view = new DataView(buf);
1503
+ const turnSeq = view.getUint32(0, true);
1504
+ if (turnSeq >= acceptedTurnSeqRef.current) {
1505
+ acceptedTurnSeqRef.current = turnSeq;
1506
+ const pcmBytes = buf.slice(4);
1507
+ playerNodeRef.current?.port.postMessage(pcmBytes, [pcmBytes]);
1508
+ }
1509
+ return;
1510
+ }
1511
+ let msg;
1512
+ try {
1513
+ msg = JSON.parse(event.data);
1514
+ } catch {
1515
+ return;
1516
+ }
1517
+ switch (msg.type) {
1518
+ case "CUSTOM":
1519
+ handleCustomEvent(
1520
+ msg.name,
1521
+ msg.value
1522
+ );
1523
+ break;
1524
+ case "TOOL_CALL_CHUNK":
1525
+ upsertToolCall(msg.toolCallId, {
1526
+ name: msg.toolCallName,
1527
+ status: "running"
1528
+ });
1529
+ break;
1530
+ case "TOOL_CALL_RESULT": {
1531
+ let parsed = null;
1532
+ try {
1533
+ parsed = JSON.parse(msg.content);
1534
+ } catch {
1535
+ parsed = { output: msg.content };
1536
+ }
1537
+ upsertToolCall(msg.toolCallId, {
1538
+ status: parsed?.error ? "error" : "done",
1539
+ summary: parsed?.error || (typeof parsed?.output === "string" ? parsed.output : JSON.stringify(parsed?.output ?? ""))
1540
+ });
1541
+ break;
1542
+ }
1543
+ case "RUN_ERROR":
1544
+ voiceLogger.warn("RUN_ERROR", { message: msg.message });
1545
+ setError(new Error(msg.message || "The agent run failed."));
1546
+ setState("error");
1547
+ break;
1548
+ default:
1549
+ break;
1550
+ }
1551
+ },
1552
+ [handleCustomEvent, upsertToolCall, voiceLogger]
1553
+ );
1554
+ const start = useCallback4(async () => {
1555
+ if (!agentId) {
1556
+ const err = new Error(
1557
+ "useVoice: no agentId provided and no defaultAgentId set on PersonaProvider"
1558
+ );
1559
+ setError(err);
1560
+ setState("error");
1561
+ return;
1562
+ }
1563
+ setError(null);
1564
+ setEndReason(null);
1565
+ setTranscript([]);
1566
+ setPartial(null);
1567
+ setToolCalls([]);
1568
+ acceptedTurnSeqRef.current = 0;
1569
+ setState("connecting");
1570
+ voiceLogger.debug("start() called", { agentId });
1571
+ try {
1572
+ const res = await fetchWithAuth("/voice/sessions", {
1573
+ method: "POST",
1574
+ headers: { "Content-Type": "application/json" },
1575
+ body: JSON.stringify({ agentId })
1576
+ });
1577
+ if (!res.ok) {
1578
+ throw new Error(`Failed to start voice session: ${res.statusText}`);
1579
+ }
1580
+ const data = await res.json();
1581
+ const ticket = data?.data ?? data;
1582
+ if (!ticket?.wsUrl) {
1583
+ throw new Error("Server did not return a voice session URL.");
1584
+ }
1585
+ const ws = new WebSocket(ticket.wsUrl);
1586
+ ws.binaryType = "arraybuffer";
1587
+ wsRef.current = ws;
1588
+ ws.onmessage = handleMessage;
1589
+ ws.onerror = () => {
1590
+ voiceLogger.warn("WebSocket error");
1591
+ if (mountedRef.current) {
1592
+ setError(new Error("Voice connection error."));
1593
+ setState("error");
1594
+ }
1595
+ };
1596
+ ws.onclose = () => {
1597
+ if (mountedRef.current && wsRef.current === ws) {
1598
+ setState((prev) => prev === "error" ? prev : "idle");
1599
+ }
1600
+ };
1601
+ } catch (err) {
1602
+ const errorObj = err instanceof Error ? err : new Error(String(err));
1603
+ voiceLogger.error("start() failed", { error: errorObj.message });
1604
+ if (mountedRef.current) {
1605
+ setError(errorObj);
1606
+ setState("error");
1607
+ }
1608
+ teardownAudio();
1609
+ }
1610
+ }, [agentId, fetchWithAuth, handleMessage, teardownAudio, voiceLogger]);
1611
+ const mute = useCallback4((muted) => {
1612
+ setIsMuted(muted);
1613
+ streamRef.current?.getAudioTracks().forEach((track) => {
1614
+ track.enabled = !muted;
1615
+ });
1616
+ }, []);
1617
+ const sendText = useCallback4((text) => {
1618
+ if (!text?.trim() || wsRef.current?.readyState !== WebSocket.OPEN) return;
1619
+ wsRef.current.send(JSON.stringify({ type: "voice.text", text }));
1620
+ }, []);
1621
+ return {
1622
+ state,
1623
+ isMuted,
1624
+ transcript,
1625
+ partial,
1626
+ toolCalls,
1627
+ error,
1628
+ endReason,
1629
+ start,
1630
+ stop,
1631
+ mute,
1632
+ sendText
1633
+ };
1634
+ }
1635
+
1197
1636
  // src/hooks/useFiles.ts
1198
- import { useCallback as useCallback4, useEffect as useEffect4, useState as useState4 } from "react";
1637
+ import { useCallback as useCallback5, useEffect as useEffect5, useState as useState5 } from "react";
1199
1638
  function useFiles(autoFetch = true) {
1200
1639
  const { fetchWithAuth } = usePersonaContext();
1201
- const [files, setFiles] = useState4([]);
1202
- const [isLoading, setIsLoading] = useState4(false);
1203
- const [isUploading, setIsUploading] = useState4(false);
1204
- const [error, setError] = useState4(null);
1205
- const fetchFiles = useCallback4(async () => {
1640
+ const [files, setFiles] = useState5([]);
1641
+ const [isLoading, setIsLoading] = useState5(false);
1642
+ const [isUploading, setIsUploading] = useState5(false);
1643
+ const [error, setError] = useState5(null);
1644
+ const fetchFiles = useCallback5(async () => {
1206
1645
  setIsLoading(true);
1207
1646
  setError(null);
1208
1647
  try {
@@ -1220,7 +1659,7 @@ function useFiles(autoFetch = true) {
1220
1659
  setIsLoading(false);
1221
1660
  }
1222
1661
  }, [fetchWithAuth]);
1223
- const uploadFile = useCallback4(
1662
+ const uploadFile = useCallback5(
1224
1663
  async (fileOrFormData) => {
1225
1664
  setIsUploading(true);
1226
1665
  setError(null);
@@ -1253,7 +1692,7 @@ function useFiles(autoFetch = true) {
1253
1692
  },
1254
1693
  [fetchWithAuth, fetchFiles]
1255
1694
  );
1256
- const deleteFile = useCallback4(
1695
+ const deleteFile = useCallback5(
1257
1696
  async (fileId) => {
1258
1697
  const res = await fetchWithAuth(`/files/${fileId}`, { method: "DELETE" });
1259
1698
  if (!res.ok) throw new Error(`Failed to delete file: ${res.statusText}`);
@@ -1261,7 +1700,7 @@ function useFiles(autoFetch = true) {
1261
1700
  },
1262
1701
  [fetchWithAuth]
1263
1702
  );
1264
- const bulkDeleteFiles = useCallback4(
1703
+ const bulkDeleteFiles = useCallback5(
1265
1704
  async (fileIds) => {
1266
1705
  const res = await fetchWithAuth("/files/bulk-delete", {
1267
1706
  method: "POST",
@@ -1276,10 +1715,10 @@ function useFiles(autoFetch = true) {
1276
1715
  },
1277
1716
  [fetchWithAuth]
1278
1717
  );
1279
- const getDownloadUrl = useCallback4((fileId) => {
1718
+ const getDownloadUrl = useCallback5((fileId) => {
1280
1719
  return `/files/${fileId}`;
1281
1720
  }, []);
1282
- useEffect4(() => {
1721
+ useEffect5(() => {
1283
1722
  if (autoFetch) {
1284
1723
  void fetchFiles();
1285
1724
  }
@@ -1298,13 +1737,13 @@ function useFiles(autoFetch = true) {
1298
1737
  }
1299
1738
 
1300
1739
  // src/hooks/useAgents.ts
1301
- import { useCallback as useCallback5, useEffect as useEffect5, useState as useState5 } from "react";
1740
+ import { useCallback as useCallback6, useEffect as useEffect6, useState as useState6 } from "react";
1302
1741
  function useAgents(autoFetch = true) {
1303
1742
  const { fetchWithAuth } = usePersonaContext();
1304
- const [agents, setAgents] = useState5([]);
1305
- const [isLoading, setIsLoading] = useState5(false);
1306
- const [error, setError] = useState5(null);
1307
- const fetchAgents = useCallback5(async () => {
1743
+ const [agents, setAgents] = useState6([]);
1744
+ const [isLoading, setIsLoading] = useState6(false);
1745
+ const [error, setError] = useState6(null);
1746
+ const fetchAgents = useCallback6(async () => {
1308
1747
  setIsLoading(true);
1309
1748
  setError(null);
1310
1749
  try {
@@ -1322,7 +1761,7 @@ function useAgents(autoFetch = true) {
1322
1761
  setIsLoading(false);
1323
1762
  }
1324
1763
  }, [fetchWithAuth]);
1325
- useEffect5(() => {
1764
+ useEffect6(() => {
1326
1765
  if (autoFetch) {
1327
1766
  void fetchAgents();
1328
1767
  }
@@ -1336,13 +1775,13 @@ function useAgents(autoFetch = true) {
1336
1775
  }
1337
1776
 
1338
1777
  // src/hooks/useConnection.ts
1339
- import { useCallback as useCallback6, useEffect as useEffect6, useState as useState6 } from "react";
1778
+ import { useCallback as useCallback7, useEffect as useEffect7, useState as useState7 } from "react";
1340
1779
  function useConnection(autoCheck = true) {
1341
1780
  const { fetchWithAuth } = usePersonaContext();
1342
- const [health, setHealth] = useState6(null);
1343
- const [isConnected, setIsConnected] = useState6(false);
1344
- const [isLoading, setIsLoading] = useState6(false);
1345
- const checkHealth = useCallback6(async () => {
1781
+ const [health, setHealth] = useState7(null);
1782
+ const [isConnected, setIsConnected] = useState7(false);
1783
+ const [isLoading, setIsLoading] = useState7(false);
1784
+ const checkHealth = useCallback7(async () => {
1346
1785
  setIsLoading(true);
1347
1786
  try {
1348
1787
  const res = await fetchWithAuth("/health");
@@ -1361,7 +1800,7 @@ function useConnection(autoCheck = true) {
1361
1800
  setIsLoading(false);
1362
1801
  }
1363
1802
  }, [fetchWithAuth]);
1364
- useEffect6(() => {
1803
+ useEffect7(() => {
1365
1804
  if (autoCheck) {
1366
1805
  void checkHealth();
1367
1806
  }
@@ -1375,15 +1814,15 @@ function useConnection(autoCheck = true) {
1375
1814
  }
1376
1815
 
1377
1816
  // src/hooks/useMcpConnections.ts
1378
- import { useCallback as useCallback7, useEffect as useEffect7, useState as useState7 } from "react";
1817
+ import { useCallback as useCallback8, useEffect as useEffect8, useState as useState8 } from "react";
1379
1818
  function useMcpConnections(options = {}) {
1380
1819
  const { defaultAgentId, fetchWithAuth } = usePersonaContext();
1381
1820
  const agentId = options.agentId ?? defaultAgentId;
1382
1821
  const autoFetch = options.autoFetch ?? true;
1383
- const [connections, setConnections] = useState7([]);
1384
- const [isLoading, setIsLoading] = useState7(false);
1385
- const [error, setError] = useState7(null);
1386
- const fetchConnections = useCallback7(async () => {
1822
+ const [connections, setConnections] = useState8([]);
1823
+ const [isLoading, setIsLoading] = useState8(false);
1824
+ const [error, setError] = useState8(null);
1825
+ const fetchConnections = useCallback8(async () => {
1387
1826
  if (!agentId) return [];
1388
1827
  setIsLoading(true);
1389
1828
  setError(null);
@@ -1407,7 +1846,7 @@ function useMcpConnections(options = {}) {
1407
1846
  setIsLoading(false);
1408
1847
  }
1409
1848
  }, [agentId, fetchWithAuth, options.returnTo]);
1410
- useEffect7(() => {
1849
+ useEffect8(() => {
1411
1850
  if (autoFetch) void fetchConnections();
1412
1851
  }, [autoFetch, fetchConnections]);
1413
1852
  return {
@@ -1428,7 +1867,7 @@ import {
1428
1867
  getLogLevel,
1429
1868
  isLevelEnabled
1430
1869
  } from "@personaai/logger";
1431
- var VERSION = "0.5.4";
1870
+ var VERSION = "0.7.0";
1432
1871
  export {
1433
1872
  PersonaProvider,
1434
1873
  VERSION,
@@ -1446,6 +1885,7 @@ export {
1446
1885
  useMcpConnections,
1447
1886
  useMemory,
1448
1887
  usePersonaContext,
1449
- useThreads
1888
+ useThreads,
1889
+ useVoice
1450
1890
  };
1451
1891
  //# sourceMappingURL=index.js.map