@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/README.md +73 -9
- package/dist/index.cjs +462 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -2
- package/dist/index.d.ts +74 -2
- package/dist/index.js +460 -31
- package/dist/index.js.map +1 -1
- package/package.json +82 -82
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
|
|
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] =
|
|
1218
|
-
const [isLoading, setIsLoading] =
|
|
1219
|
-
const [isUploading, setIsUploading] =
|
|
1220
|
-
const [error, setError] =
|
|
1221
|
-
const fetchFiles =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
1723
|
+
const getDownloadUrl = useCallback5((fileId) => {
|
|
1296
1724
|
return `/files/${fileId}`;
|
|
1297
1725
|
}, []);
|
|
1298
|
-
|
|
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
|
|
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] =
|
|
1321
|
-
const [isLoading, setIsLoading] =
|
|
1322
|
-
const [error, setError] =
|
|
1323
|
-
const fetchAgents =
|
|
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
|
-
|
|
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
|
|
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] =
|
|
1359
|
-
const [isConnected, setIsConnected] =
|
|
1360
|
-
const [isLoading, setIsLoading] =
|
|
1361
|
-
const checkHealth =
|
|
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
|
-
|
|
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
|
|
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] =
|
|
1400
|
-
const [isLoading, setIsLoading] =
|
|
1401
|
-
const [error, setError] =
|
|
1402
|
-
const fetchConnections =
|
|
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
|
-
|
|
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.
|
|
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
|