@personaai/react 0.6.0 → 0.7.1

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
@@ -1210,15 +1210,443 @@ function useThreads(autoFetch = true) {
1210
1210
  };
1211
1211
  }
1212
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 threadId = options.threadId;
1312
+ const [state, setState] = useState4("idle");
1313
+ const [isMuted, setIsMuted] = useState4(false);
1314
+ const [transcript, setTranscript] = useState4(
1315
+ []
1316
+ );
1317
+ const [partial, setPartial] = useState4(
1318
+ null
1319
+ );
1320
+ const [toolCalls, setToolCalls] = useState4([]);
1321
+ const [error, setError] = useState4(null);
1322
+ const [endReason, setEndReason] = useState4(
1323
+ null
1324
+ );
1325
+ const wsRef = useRef2(null);
1326
+ const streamRef = useRef2(null);
1327
+ const inputCtxRef = useRef2(null);
1328
+ const outputCtxRef = useRef2(null);
1329
+ const recorderNodeRef = useRef2(null);
1330
+ const playerNodeRef = useRef2(null);
1331
+ const acceptedTurnSeqRef = useRef2(0);
1332
+ const mountedRef = useRef2(true);
1333
+ useEffect4(() => {
1334
+ mountedRef.current = true;
1335
+ return () => {
1336
+ mountedRef.current = false;
1337
+ };
1338
+ }, []);
1339
+ const teardownAudio = useCallback4(() => {
1340
+ try {
1341
+ streamRef.current?.getTracks().forEach((track) => track.stop());
1342
+ } catch {
1343
+ }
1344
+ streamRef.current = null;
1345
+ try {
1346
+ recorderNodeRef.current?.disconnect();
1347
+ } catch {
1348
+ }
1349
+ recorderNodeRef.current = null;
1350
+ try {
1351
+ playerNodeRef.current?.disconnect();
1352
+ } catch {
1353
+ }
1354
+ playerNodeRef.current = null;
1355
+ try {
1356
+ void inputCtxRef.current?.close();
1357
+ } catch {
1358
+ }
1359
+ inputCtxRef.current = null;
1360
+ try {
1361
+ void outputCtxRef.current?.close();
1362
+ } catch {
1363
+ }
1364
+ outputCtxRef.current = null;
1365
+ }, []);
1366
+ const stop = useCallback4(() => {
1367
+ voiceLogger.debug("stop() called");
1368
+ try {
1369
+ wsRef.current?.close(1e3, "client_stop");
1370
+ } catch {
1371
+ }
1372
+ wsRef.current = null;
1373
+ teardownAudio();
1374
+ if (mountedRef.current) setState("idle");
1375
+ }, [teardownAudio, voiceLogger]);
1376
+ useEffect4(() => stop, [stop]);
1377
+ const startCapture = useCallback4(async (inputSampleRate) => {
1378
+ const stream = await navigator.mediaDevices.getUserMedia({
1379
+ audio: {
1380
+ echoCancellation: true,
1381
+ noiseSuppression: true,
1382
+ autoGainControl: true,
1383
+ channelCount: 1
1384
+ }
1385
+ });
1386
+ streamRef.current = stream;
1387
+ const inputCtx = new AudioContext({ sampleRate: inputSampleRate });
1388
+ inputCtxRef.current = inputCtx;
1389
+ await inputCtx.audioWorklet.addModule(recorderWorkletUrl());
1390
+ const source = inputCtx.createMediaStreamSource(stream);
1391
+ const recorderNode = new AudioWorkletNode(
1392
+ inputCtx,
1393
+ "pcm-recorder-processor"
1394
+ );
1395
+ recorderNode.port.onmessage = (event) => {
1396
+ if (wsRef.current?.readyState === WebSocket.OPEN) {
1397
+ wsRef.current.send(event.data);
1398
+ }
1399
+ };
1400
+ recorderNodeRef.current = recorderNode;
1401
+ source.connect(recorderNode);
1402
+ }, []);
1403
+ const setupPlayback = useCallback4(async (outputSampleRate) => {
1404
+ const outputCtx = new AudioContext({ sampleRate: outputSampleRate });
1405
+ outputCtxRef.current = outputCtx;
1406
+ await outputCtx.audioWorklet.addModule(playerWorkletUrl());
1407
+ const playerNode = new AudioWorkletNode(outputCtx, "pcm-player-processor");
1408
+ playerNode.connect(outputCtx.destination);
1409
+ playerNodeRef.current = playerNode;
1410
+ }, []);
1411
+ const upsertToolCall = useCallback4(
1412
+ (id, patch) => {
1413
+ setToolCalls((prev) => {
1414
+ const idx = prev.findIndex((t) => t.id === id);
1415
+ if (idx === -1) 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(
1546
+ new Error(msg.message || "The agent run failed.")
1547
+ );
1548
+ setState("error");
1549
+ break;
1550
+ default:
1551
+ break;
1552
+ }
1553
+ },
1554
+ [handleCustomEvent, upsertToolCall, voiceLogger]
1555
+ );
1556
+ const start = useCallback4(async () => {
1557
+ if (!agentId) {
1558
+ const err = new Error(
1559
+ "useVoice: no agentId provided and no defaultAgentId set on PersonaProvider"
1560
+ );
1561
+ setError(err);
1562
+ setState("error");
1563
+ return;
1564
+ }
1565
+ setError(null);
1566
+ setEndReason(null);
1567
+ setTranscript([]);
1568
+ setPartial(null);
1569
+ setToolCalls([]);
1570
+ acceptedTurnSeqRef.current = 0;
1571
+ setState("connecting");
1572
+ voiceLogger.debug("start() called", { agentId, threadId });
1573
+ try {
1574
+ const res = await fetchWithAuth("/voice/sessions", {
1575
+ method: "POST",
1576
+ headers: { "Content-Type": "application/json" },
1577
+ body: JSON.stringify({
1578
+ agentId,
1579
+ ...threadId ? { threadId } : {}
1580
+ })
1581
+ });
1582
+ if (!res.ok) {
1583
+ throw new Error(`Failed to start voice session: ${res.statusText}`);
1584
+ }
1585
+ const data = await res.json();
1586
+ const ticket = data?.data ?? data;
1587
+ if (!ticket?.wsUrl) {
1588
+ throw new Error("Server did not return a voice session URL.");
1589
+ }
1590
+ const ws = new WebSocket(ticket.wsUrl);
1591
+ ws.binaryType = "arraybuffer";
1592
+ wsRef.current = ws;
1593
+ ws.onmessage = handleMessage;
1594
+ ws.onerror = () => {
1595
+ voiceLogger.warn("WebSocket error");
1596
+ if (mountedRef.current) {
1597
+ setError(new Error("Voice connection error."));
1598
+ setState("error");
1599
+ }
1600
+ };
1601
+ ws.onclose = () => {
1602
+ if (mountedRef.current && wsRef.current === ws) {
1603
+ setState((prev) => prev === "error" ? prev : "idle");
1604
+ }
1605
+ };
1606
+ } catch (err) {
1607
+ const errorObj = err instanceof Error ? err : new Error(String(err));
1608
+ voiceLogger.error("start() failed", { error: errorObj.message });
1609
+ if (mountedRef.current) {
1610
+ setError(errorObj);
1611
+ setState("error");
1612
+ }
1613
+ teardownAudio();
1614
+ }
1615
+ }, [agentId, threadId, fetchWithAuth, handleMessage, teardownAudio, voiceLogger]);
1616
+ const mute = useCallback4((muted) => {
1617
+ setIsMuted(muted);
1618
+ streamRef.current?.getAudioTracks().forEach((track) => {
1619
+ track.enabled = !muted;
1620
+ });
1621
+ }, []);
1622
+ const sendText = useCallback4((text) => {
1623
+ if (!text?.trim() || wsRef.current?.readyState !== WebSocket.OPEN) return;
1624
+ wsRef.current.send(JSON.stringify({ type: "voice.text", text }));
1625
+ }, []);
1626
+ return {
1627
+ state,
1628
+ isMuted,
1629
+ transcript,
1630
+ partial,
1631
+ toolCalls,
1632
+ error,
1633
+ endReason,
1634
+ start,
1635
+ stop,
1636
+ mute,
1637
+ sendText
1638
+ };
1639
+ }
1640
+
1213
1641
  // src/hooks/useFiles.ts
1214
- import { useCallback as useCallback4, useEffect as useEffect4, useState as useState4 } from "react";
1642
+ import { useCallback as useCallback5, useEffect as useEffect5, useState as useState5 } from "react";
1215
1643
  function useFiles(autoFetch = true) {
1216
1644
  const { fetchWithAuth } = usePersonaContext();
1217
- const [files, setFiles] = useState4([]);
1218
- const [isLoading, setIsLoading] = useState4(false);
1219
- const [isUploading, setIsUploading] = useState4(false);
1220
- const [error, setError] = useState4(null);
1221
- const fetchFiles = useCallback4(async () => {
1645
+ const [files, setFiles] = useState5([]);
1646
+ const [isLoading, setIsLoading] = useState5(false);
1647
+ const [isUploading, setIsUploading] = useState5(false);
1648
+ const [error, setError] = useState5(null);
1649
+ const fetchFiles = useCallback5(async () => {
1222
1650
  setIsLoading(true);
1223
1651
  setError(null);
1224
1652
  try {
@@ -1236,7 +1664,7 @@ function useFiles(autoFetch = true) {
1236
1664
  setIsLoading(false);
1237
1665
  }
1238
1666
  }, [fetchWithAuth]);
1239
- const uploadFile = useCallback4(
1667
+ const uploadFile = useCallback5(
1240
1668
  async (fileOrFormData) => {
1241
1669
  setIsUploading(true);
1242
1670
  setError(null);
@@ -1269,7 +1697,7 @@ function useFiles(autoFetch = true) {
1269
1697
  },
1270
1698
  [fetchWithAuth, fetchFiles]
1271
1699
  );
1272
- const deleteFile = useCallback4(
1700
+ const deleteFile = useCallback5(
1273
1701
  async (fileId) => {
1274
1702
  const res = await fetchWithAuth(`/files/${fileId}`, { method: "DELETE" });
1275
1703
  if (!res.ok) throw new Error(`Failed to delete file: ${res.statusText}`);
@@ -1277,7 +1705,7 @@ function useFiles(autoFetch = true) {
1277
1705
  },
1278
1706
  [fetchWithAuth]
1279
1707
  );
1280
- const bulkDeleteFiles = useCallback4(
1708
+ const bulkDeleteFiles = useCallback5(
1281
1709
  async (fileIds) => {
1282
1710
  const res = await fetchWithAuth("/files/bulk-delete", {
1283
1711
  method: "POST",
@@ -1292,10 +1720,10 @@ function useFiles(autoFetch = true) {
1292
1720
  },
1293
1721
  [fetchWithAuth]
1294
1722
  );
1295
- const getDownloadUrl = useCallback4((fileId) => {
1723
+ const getDownloadUrl = useCallback5((fileId) => {
1296
1724
  return `/files/${fileId}`;
1297
1725
  }, []);
1298
- useEffect4(() => {
1726
+ useEffect5(() => {
1299
1727
  if (autoFetch) {
1300
1728
  void fetchFiles();
1301
1729
  }
@@ -1314,13 +1742,13 @@ function useFiles(autoFetch = true) {
1314
1742
  }
1315
1743
 
1316
1744
  // src/hooks/useAgents.ts
1317
- import { useCallback as useCallback5, useEffect as useEffect5, useState as useState5 } from "react";
1745
+ import { useCallback as useCallback6, useEffect as useEffect6, useState as useState6 } from "react";
1318
1746
  function useAgents(autoFetch = true) {
1319
1747
  const { fetchWithAuth } = usePersonaContext();
1320
- const [agents, setAgents] = useState5([]);
1321
- const [isLoading, setIsLoading] = useState5(false);
1322
- const [error, setError] = useState5(null);
1323
- const fetchAgents = useCallback5(async () => {
1748
+ const [agents, setAgents] = useState6([]);
1749
+ const [isLoading, setIsLoading] = useState6(false);
1750
+ const [error, setError] = useState6(null);
1751
+ const fetchAgents = useCallback6(async () => {
1324
1752
  setIsLoading(true);
1325
1753
  setError(null);
1326
1754
  try {
@@ -1338,7 +1766,7 @@ function useAgents(autoFetch = true) {
1338
1766
  setIsLoading(false);
1339
1767
  }
1340
1768
  }, [fetchWithAuth]);
1341
- useEffect5(() => {
1769
+ useEffect6(() => {
1342
1770
  if (autoFetch) {
1343
1771
  void fetchAgents();
1344
1772
  }
@@ -1352,13 +1780,13 @@ function useAgents(autoFetch = true) {
1352
1780
  }
1353
1781
 
1354
1782
  // src/hooks/useConnection.ts
1355
- import { useCallback as useCallback6, useEffect as useEffect6, useState as useState6 } from "react";
1783
+ import { useCallback as useCallback7, useEffect as useEffect7, useState as useState7 } from "react";
1356
1784
  function useConnection(autoCheck = true) {
1357
1785
  const { fetchWithAuth } = usePersonaContext();
1358
- const [health, setHealth] = useState6(null);
1359
- const [isConnected, setIsConnected] = useState6(false);
1360
- const [isLoading, setIsLoading] = useState6(false);
1361
- const checkHealth = useCallback6(async () => {
1786
+ const [health, setHealth] = useState7(null);
1787
+ const [isConnected, setIsConnected] = useState7(false);
1788
+ const [isLoading, setIsLoading] = useState7(false);
1789
+ const checkHealth = useCallback7(async () => {
1362
1790
  setIsLoading(true);
1363
1791
  try {
1364
1792
  const res = await fetchWithAuth("/health");
@@ -1377,7 +1805,7 @@ function useConnection(autoCheck = true) {
1377
1805
  setIsLoading(false);
1378
1806
  }
1379
1807
  }, [fetchWithAuth]);
1380
- useEffect6(() => {
1808
+ useEffect7(() => {
1381
1809
  if (autoCheck) {
1382
1810
  void checkHealth();
1383
1811
  }
@@ -1391,15 +1819,15 @@ function useConnection(autoCheck = true) {
1391
1819
  }
1392
1820
 
1393
1821
  // src/hooks/useMcpConnections.ts
1394
- import { useCallback as useCallback7, useEffect as useEffect7, useState as useState7 } from "react";
1822
+ import { useCallback as useCallback8, useEffect as useEffect8, useState as useState8 } from "react";
1395
1823
  function useMcpConnections(options = {}) {
1396
1824
  const { defaultAgentId, fetchWithAuth } = usePersonaContext();
1397
1825
  const agentId = options.agentId ?? defaultAgentId;
1398
1826
  const autoFetch = options.autoFetch ?? true;
1399
- const [connections, setConnections] = useState7([]);
1400
- const [isLoading, setIsLoading] = useState7(false);
1401
- const [error, setError] = useState7(null);
1402
- const fetchConnections = useCallback7(async () => {
1827
+ const [connections, setConnections] = useState8([]);
1828
+ const [isLoading, setIsLoading] = useState8(false);
1829
+ const [error, setError] = useState8(null);
1830
+ const fetchConnections = useCallback8(async () => {
1403
1831
  if (!agentId) return [];
1404
1832
  setIsLoading(true);
1405
1833
  setError(null);
@@ -1423,7 +1851,7 @@ function useMcpConnections(options = {}) {
1423
1851
  setIsLoading(false);
1424
1852
  }
1425
1853
  }, [agentId, fetchWithAuth, options.returnTo]);
1426
- useEffect7(() => {
1854
+ useEffect8(() => {
1427
1855
  if (autoFetch) void fetchConnections();
1428
1856
  }, [autoFetch, fetchConnections]);
1429
1857
  return {
@@ -1444,7 +1872,7 @@ import {
1444
1872
  getLogLevel,
1445
1873
  isLevelEnabled
1446
1874
  } from "@personaai/logger";
1447
- var VERSION = "0.6.0";
1875
+ var VERSION = "0.7.0";
1448
1876
  export {
1449
1877
  PersonaProvider,
1450
1878
  VERSION,
@@ -1462,6 +1890,7 @@ export {
1462
1890
  useMcpConnections,
1463
1891
  useMemory,
1464
1892
  usePersonaContext,
1465
- useThreads
1893
+ useThreads,
1894
+ useVoice
1466
1895
  };
1467
1896
  //# sourceMappingURL=index.js.map