@personaai/react 0.6.0 → 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 +34 -9
- package/dist/index.cjs +457 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -2
- package/dist/index.d.ts +66 -2
- package/dist/index.js +455 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1210,15 +1210,438 @@ 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 [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
|
+
|
|
1213
1636
|
// src/hooks/useFiles.ts
|
|
1214
|
-
import { useCallback as
|
|
1637
|
+
import { useCallback as useCallback5, useEffect as useEffect5, useState as useState5 } from "react";
|
|
1215
1638
|
function useFiles(autoFetch = true) {
|
|
1216
1639
|
const { fetchWithAuth } = usePersonaContext();
|
|
1217
|
-
const [files, setFiles] =
|
|
1218
|
-
const [isLoading, setIsLoading] =
|
|
1219
|
-
const [isUploading, setIsUploading] =
|
|
1220
|
-
const [error, setError] =
|
|
1221
|
-
const fetchFiles =
|
|
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 () => {
|
|
1222
1645
|
setIsLoading(true);
|
|
1223
1646
|
setError(null);
|
|
1224
1647
|
try {
|
|
@@ -1236,7 +1659,7 @@ function useFiles(autoFetch = true) {
|
|
|
1236
1659
|
setIsLoading(false);
|
|
1237
1660
|
}
|
|
1238
1661
|
}, [fetchWithAuth]);
|
|
1239
|
-
const uploadFile =
|
|
1662
|
+
const uploadFile = useCallback5(
|
|
1240
1663
|
async (fileOrFormData) => {
|
|
1241
1664
|
setIsUploading(true);
|
|
1242
1665
|
setError(null);
|
|
@@ -1269,7 +1692,7 @@ function useFiles(autoFetch = true) {
|
|
|
1269
1692
|
},
|
|
1270
1693
|
[fetchWithAuth, fetchFiles]
|
|
1271
1694
|
);
|
|
1272
|
-
const deleteFile =
|
|
1695
|
+
const deleteFile = useCallback5(
|
|
1273
1696
|
async (fileId) => {
|
|
1274
1697
|
const res = await fetchWithAuth(`/files/${fileId}`, { method: "DELETE" });
|
|
1275
1698
|
if (!res.ok) throw new Error(`Failed to delete file: ${res.statusText}`);
|
|
@@ -1277,7 +1700,7 @@ function useFiles(autoFetch = true) {
|
|
|
1277
1700
|
},
|
|
1278
1701
|
[fetchWithAuth]
|
|
1279
1702
|
);
|
|
1280
|
-
const bulkDeleteFiles =
|
|
1703
|
+
const bulkDeleteFiles = useCallback5(
|
|
1281
1704
|
async (fileIds) => {
|
|
1282
1705
|
const res = await fetchWithAuth("/files/bulk-delete", {
|
|
1283
1706
|
method: "POST",
|
|
@@ -1292,10 +1715,10 @@ function useFiles(autoFetch = true) {
|
|
|
1292
1715
|
},
|
|
1293
1716
|
[fetchWithAuth]
|
|
1294
1717
|
);
|
|
1295
|
-
const getDownloadUrl =
|
|
1718
|
+
const getDownloadUrl = useCallback5((fileId) => {
|
|
1296
1719
|
return `/files/${fileId}`;
|
|
1297
1720
|
}, []);
|
|
1298
|
-
|
|
1721
|
+
useEffect5(() => {
|
|
1299
1722
|
if (autoFetch) {
|
|
1300
1723
|
void fetchFiles();
|
|
1301
1724
|
}
|
|
@@ -1314,13 +1737,13 @@ function useFiles(autoFetch = true) {
|
|
|
1314
1737
|
}
|
|
1315
1738
|
|
|
1316
1739
|
// src/hooks/useAgents.ts
|
|
1317
|
-
import { useCallback as
|
|
1740
|
+
import { useCallback as useCallback6, useEffect as useEffect6, useState as useState6 } from "react";
|
|
1318
1741
|
function useAgents(autoFetch = true) {
|
|
1319
1742
|
const { fetchWithAuth } = usePersonaContext();
|
|
1320
|
-
const [agents, setAgents] =
|
|
1321
|
-
const [isLoading, setIsLoading] =
|
|
1322
|
-
const [error, setError] =
|
|
1323
|
-
const fetchAgents =
|
|
1743
|
+
const [agents, setAgents] = useState6([]);
|
|
1744
|
+
const [isLoading, setIsLoading] = useState6(false);
|
|
1745
|
+
const [error, setError] = useState6(null);
|
|
1746
|
+
const fetchAgents = useCallback6(async () => {
|
|
1324
1747
|
setIsLoading(true);
|
|
1325
1748
|
setError(null);
|
|
1326
1749
|
try {
|
|
@@ -1338,7 +1761,7 @@ function useAgents(autoFetch = true) {
|
|
|
1338
1761
|
setIsLoading(false);
|
|
1339
1762
|
}
|
|
1340
1763
|
}, [fetchWithAuth]);
|
|
1341
|
-
|
|
1764
|
+
useEffect6(() => {
|
|
1342
1765
|
if (autoFetch) {
|
|
1343
1766
|
void fetchAgents();
|
|
1344
1767
|
}
|
|
@@ -1352,13 +1775,13 @@ function useAgents(autoFetch = true) {
|
|
|
1352
1775
|
}
|
|
1353
1776
|
|
|
1354
1777
|
// src/hooks/useConnection.ts
|
|
1355
|
-
import { useCallback as
|
|
1778
|
+
import { useCallback as useCallback7, useEffect as useEffect7, useState as useState7 } from "react";
|
|
1356
1779
|
function useConnection(autoCheck = true) {
|
|
1357
1780
|
const { fetchWithAuth } = usePersonaContext();
|
|
1358
|
-
const [health, setHealth] =
|
|
1359
|
-
const [isConnected, setIsConnected] =
|
|
1360
|
-
const [isLoading, setIsLoading] =
|
|
1361
|
-
const checkHealth =
|
|
1781
|
+
const [health, setHealth] = useState7(null);
|
|
1782
|
+
const [isConnected, setIsConnected] = useState7(false);
|
|
1783
|
+
const [isLoading, setIsLoading] = useState7(false);
|
|
1784
|
+
const checkHealth = useCallback7(async () => {
|
|
1362
1785
|
setIsLoading(true);
|
|
1363
1786
|
try {
|
|
1364
1787
|
const res = await fetchWithAuth("/health");
|
|
@@ -1377,7 +1800,7 @@ function useConnection(autoCheck = true) {
|
|
|
1377
1800
|
setIsLoading(false);
|
|
1378
1801
|
}
|
|
1379
1802
|
}, [fetchWithAuth]);
|
|
1380
|
-
|
|
1803
|
+
useEffect7(() => {
|
|
1381
1804
|
if (autoCheck) {
|
|
1382
1805
|
void checkHealth();
|
|
1383
1806
|
}
|
|
@@ -1391,15 +1814,15 @@ function useConnection(autoCheck = true) {
|
|
|
1391
1814
|
}
|
|
1392
1815
|
|
|
1393
1816
|
// src/hooks/useMcpConnections.ts
|
|
1394
|
-
import { useCallback as
|
|
1817
|
+
import { useCallback as useCallback8, useEffect as useEffect8, useState as useState8 } from "react";
|
|
1395
1818
|
function useMcpConnections(options = {}) {
|
|
1396
1819
|
const { defaultAgentId, fetchWithAuth } = usePersonaContext();
|
|
1397
1820
|
const agentId = options.agentId ?? defaultAgentId;
|
|
1398
1821
|
const autoFetch = options.autoFetch ?? true;
|
|
1399
|
-
const [connections, setConnections] =
|
|
1400
|
-
const [isLoading, setIsLoading] =
|
|
1401
|
-
const [error, setError] =
|
|
1402
|
-
const fetchConnections =
|
|
1822
|
+
const [connections, setConnections] = useState8([]);
|
|
1823
|
+
const [isLoading, setIsLoading] = useState8(false);
|
|
1824
|
+
const [error, setError] = useState8(null);
|
|
1825
|
+
const fetchConnections = useCallback8(async () => {
|
|
1403
1826
|
if (!agentId) return [];
|
|
1404
1827
|
setIsLoading(true);
|
|
1405
1828
|
setError(null);
|
|
@@ -1423,7 +1846,7 @@ function useMcpConnections(options = {}) {
|
|
|
1423
1846
|
setIsLoading(false);
|
|
1424
1847
|
}
|
|
1425
1848
|
}, [agentId, fetchWithAuth, options.returnTo]);
|
|
1426
|
-
|
|
1849
|
+
useEffect8(() => {
|
|
1427
1850
|
if (autoFetch) void fetchConnections();
|
|
1428
1851
|
}, [autoFetch, fetchConnections]);
|
|
1429
1852
|
return {
|
|
@@ -1444,7 +1867,7 @@ import {
|
|
|
1444
1867
|
getLogLevel,
|
|
1445
1868
|
isLevelEnabled
|
|
1446
1869
|
} from "@personaai/logger";
|
|
1447
|
-
var VERSION = "0.
|
|
1870
|
+
var VERSION = "0.7.0";
|
|
1448
1871
|
export {
|
|
1449
1872
|
PersonaProvider,
|
|
1450
1873
|
VERSION,
|
|
@@ -1462,6 +1885,7 @@ export {
|
|
|
1462
1885
|
useMcpConnections,
|
|
1463
1886
|
useMemory,
|
|
1464
1887
|
usePersonaContext,
|
|
1465
|
-
useThreads
|
|
1888
|
+
useThreads,
|
|
1889
|
+
useVoice
|
|
1466
1890
|
};
|
|
1467
1891
|
//# sourceMappingURL=index.js.map
|