@personaai/react 0.7.0 → 0.7.2
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 +39 -0
- package/dist/index.cjs +45 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +45 -24
- package/dist/index.js.map +1 -1
- package/package.json +82 -82
package/dist/index.d.cts
CHANGED
|
@@ -300,6 +300,14 @@ type PersonaVoiceEndReason = "client_closed" | "agent_ended" | "max_duration" |
|
|
|
300
300
|
interface UseVoiceOptions {
|
|
301
301
|
/** Falls back to `PersonaProvider`'s `defaultAgentId` if omitted. */
|
|
302
302
|
agentId?: string;
|
|
303
|
+
/**
|
|
304
|
+
* Resume an existing conversation over voice instead of starting fresh.
|
|
305
|
+
* `start()` mints the session with this thread id (same value `useChat`'s
|
|
306
|
+
* `threadId` uses), so voice turns are persisted back into that thread's
|
|
307
|
+
* history — a later text message on the same thread sees them. Omit (or
|
|
308
|
+
* leave undefined) to start a fresh conversation.
|
|
309
|
+
*/
|
|
310
|
+
threadId?: string;
|
|
303
311
|
}
|
|
304
312
|
interface UseVoiceResult {
|
|
305
313
|
state: PersonaVoiceState;
|
|
@@ -566,6 +574,6 @@ declare function supportsStreamingFetch(): boolean;
|
|
|
566
574
|
*/
|
|
567
575
|
declare function openSSEStream(opts: OpenSSEOptions): Promise<SSEStream>;
|
|
568
576
|
|
|
569
|
-
declare const VERSION = "0.7.
|
|
577
|
+
declare const VERSION = "0.7.2";
|
|
570
578
|
|
|
571
579
|
export { type OpenSSEOptions, type PersonaAgentSummary, type PersonaClarificationQuestion, type PersonaFileItem, type PersonaHealthInfo, type PersonaHitlActionRequest, type PersonaInterrupt, type PersonaMcpConnection, type PersonaMemoryAgentGroup, type PersonaMemoryFile, type PersonaMemoryList, type PersonaMessage, type PersonaPresentedFile, PersonaProvider, type PersonaProviderProps, type PersonaResumeValue, type PersonaRole, type PersonaStreamingEvent, type PersonaSubagentActivityEntry, type PersonaThread, type PersonaTodo, type PersonaToolCall, type PersonaVoiceEndReason, type PersonaVoiceState, type PersonaVoiceToolCall, type PersonaVoiceTranscriptLine, type PersonaWorkspaceFile, type SSEReader, type SSEStream, type SendMessageOverride, type UseChatOptions, type UseMcpConnectionsOptions, type UseVoiceOptions, type UseVoiceResult, VERSION, openSSEStream, supportsStreamingFetch, useAgents, useChat, useConnection, useFiles, useMcpConnections, useMemory, usePersonaContext, useThreads, useVoice };
|
package/dist/index.d.ts
CHANGED
|
@@ -300,6 +300,14 @@ type PersonaVoiceEndReason = "client_closed" | "agent_ended" | "max_duration" |
|
|
|
300
300
|
interface UseVoiceOptions {
|
|
301
301
|
/** Falls back to `PersonaProvider`'s `defaultAgentId` if omitted. */
|
|
302
302
|
agentId?: string;
|
|
303
|
+
/**
|
|
304
|
+
* Resume an existing conversation over voice instead of starting fresh.
|
|
305
|
+
* `start()` mints the session with this thread id (same value `useChat`'s
|
|
306
|
+
* `threadId` uses), so voice turns are persisted back into that thread's
|
|
307
|
+
* history — a later text message on the same thread sees them. Omit (or
|
|
308
|
+
* leave undefined) to start a fresh conversation.
|
|
309
|
+
*/
|
|
310
|
+
threadId?: string;
|
|
303
311
|
}
|
|
304
312
|
interface UseVoiceResult {
|
|
305
313
|
state: PersonaVoiceState;
|
|
@@ -566,6 +574,6 @@ declare function supportsStreamingFetch(): boolean;
|
|
|
566
574
|
*/
|
|
567
575
|
declare function openSSEStream(opts: OpenSSEOptions): Promise<SSEStream>;
|
|
568
576
|
|
|
569
|
-
declare const VERSION = "0.7.
|
|
577
|
+
declare const VERSION = "0.7.2";
|
|
570
578
|
|
|
571
579
|
export { type OpenSSEOptions, type PersonaAgentSummary, type PersonaClarificationQuestion, type PersonaFileItem, type PersonaHealthInfo, type PersonaHitlActionRequest, type PersonaInterrupt, type PersonaMcpConnection, type PersonaMemoryAgentGroup, type PersonaMemoryFile, type PersonaMemoryList, type PersonaMessage, type PersonaPresentedFile, PersonaProvider, type PersonaProviderProps, type PersonaResumeValue, type PersonaRole, type PersonaStreamingEvent, type PersonaSubagentActivityEntry, type PersonaThread, type PersonaTodo, type PersonaToolCall, type PersonaVoiceEndReason, type PersonaVoiceState, type PersonaVoiceToolCall, type PersonaVoiceTranscriptLine, type PersonaWorkspaceFile, type SSEReader, type SSEStream, type SendMessageOverride, type UseChatOptions, type UseMcpConnectionsOptions, type UseVoiceOptions, type UseVoiceResult, VERSION, openSSEStream, supportsStreamingFetch, useAgents, useChat, useConnection, useFiles, useMcpConnections, useMemory, usePersonaContext, useThreads, useVoice };
|
package/dist/index.js
CHANGED
|
@@ -1304,10 +1304,19 @@ function playerWorkletUrl() {
|
|
|
1304
1304
|
}
|
|
1305
1305
|
|
|
1306
1306
|
// src/hooks/useVoice.ts
|
|
1307
|
+
function mergeTranscriptText(prev, next) {
|
|
1308
|
+
if (!prev) return next;
|
|
1309
|
+
if (!next) return prev;
|
|
1310
|
+
if (next === prev || prev.endsWith(next)) return prev;
|
|
1311
|
+
if (next.startsWith(prev)) return next;
|
|
1312
|
+
const needSpace = !/\s$/.test(prev) && !/^\s/.test(next);
|
|
1313
|
+
return prev + (needSpace ? " " : "") + next;
|
|
1314
|
+
}
|
|
1307
1315
|
function useVoice(options = {}) {
|
|
1308
1316
|
const { defaultAgentId, fetchWithAuth, logger } = usePersonaContext();
|
|
1309
1317
|
const voiceLogger = useMemo3(() => logger.child("voice"), [logger]);
|
|
1310
1318
|
const agentId = options.agentId || defaultAgentId;
|
|
1319
|
+
const threadId = options.threadId;
|
|
1311
1320
|
const [state, setState] = useState4("idle");
|
|
1312
1321
|
const [isMuted, setIsMuted] = useState4(false);
|
|
1313
1322
|
const [transcript, setTranscript] = useState4(
|
|
@@ -1329,6 +1338,9 @@ function useVoice(options = {}) {
|
|
|
1329
1338
|
const playerNodeRef = useRef2(null);
|
|
1330
1339
|
const acceptedTurnSeqRef = useRef2(0);
|
|
1331
1340
|
const mountedRef = useRef2(true);
|
|
1341
|
+
const lastFinalTurnRef = useRef2(
|
|
1342
|
+
null
|
|
1343
|
+
);
|
|
1332
1344
|
useEffect4(() => {
|
|
1333
1345
|
mountedRef.current = true;
|
|
1334
1346
|
return () => {
|
|
@@ -1411,8 +1423,7 @@ function useVoice(options = {}) {
|
|
|
1411
1423
|
(id, patch) => {
|
|
1412
1424
|
setToolCalls((prev) => {
|
|
1413
1425
|
const idx = prev.findIndex((t) => t.id === id);
|
|
1414
|
-
if (idx === -1)
|
|
1415
|
-
return [...prev, { id, status: "running", ...patch }];
|
|
1426
|
+
if (idx === -1) return [...prev, { id, status: "running", ...patch }];
|
|
1416
1427
|
const next = [...prev];
|
|
1417
1428
|
next[idx] = { ...next[idx], ...patch };
|
|
1418
1429
|
return next;
|
|
@@ -1420,21 +1431,28 @@ function useVoice(options = {}) {
|
|
|
1420
1431
|
},
|
|
1421
1432
|
[]
|
|
1422
1433
|
);
|
|
1423
|
-
const handleTranscript = useCallback4(
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
+
const handleTranscript = useCallback4((value) => {
|
|
1435
|
+
const { speaker, text, isFinal, turnSeq } = value;
|
|
1436
|
+
if (!isFinal) {
|
|
1437
|
+
setPartial({ id: "partial", speaker, text });
|
|
1438
|
+
return;
|
|
1439
|
+
}
|
|
1440
|
+
setPartial((prev) => prev?.speaker === speaker ? null : prev);
|
|
1441
|
+
const last = lastFinalTurnRef.current;
|
|
1442
|
+
const sameUtterance = last && last.speaker === speaker && last.turnSeq === turnSeq;
|
|
1443
|
+
setTranscript((prev) => {
|
|
1444
|
+
const tail = prev[prev.length - 1];
|
|
1445
|
+
if (sameUtterance && tail?.speaker === speaker) {
|
|
1446
|
+
const merged = mergeTranscriptText(tail.text, text);
|
|
1447
|
+
if (merged === tail.text) return prev;
|
|
1448
|
+
return prev.map(
|
|
1449
|
+
(l, i) => i === prev.length - 1 ? { ...l, text: merged } : l
|
|
1450
|
+
);
|
|
1434
1451
|
}
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1452
|
+
return [...prev, { id: `${speaker}-${prev.length}`, speaker, text }];
|
|
1453
|
+
});
|
|
1454
|
+
lastFinalTurnRef.current = { speaker, turnSeq };
|
|
1455
|
+
}, []);
|
|
1438
1456
|
const handleCustomEvent = useCallback4(
|
|
1439
1457
|
(name, value) => {
|
|
1440
1458
|
switch (name) {
|
|
@@ -1467,9 +1485,7 @@ function useVoice(options = {}) {
|
|
|
1467
1485
|
}
|
|
1468
1486
|
break;
|
|
1469
1487
|
case "voice_transcript":
|
|
1470
|
-
handleTranscript(
|
|
1471
|
-
value
|
|
1472
|
-
);
|
|
1488
|
+
handleTranscript(value);
|
|
1473
1489
|
break;
|
|
1474
1490
|
case "voice_interrupted":
|
|
1475
1491
|
acceptedTurnSeqRef.current = value.turnSeq;
|
|
@@ -1542,7 +1558,9 @@ function useVoice(options = {}) {
|
|
|
1542
1558
|
}
|
|
1543
1559
|
case "RUN_ERROR":
|
|
1544
1560
|
voiceLogger.warn("RUN_ERROR", { message: msg.message });
|
|
1545
|
-
setError(
|
|
1561
|
+
setError(
|
|
1562
|
+
new Error(msg.message || "The agent run failed.")
|
|
1563
|
+
);
|
|
1546
1564
|
setState("error");
|
|
1547
1565
|
break;
|
|
1548
1566
|
default:
|
|
@@ -1567,12 +1585,15 @@ function useVoice(options = {}) {
|
|
|
1567
1585
|
setToolCalls([]);
|
|
1568
1586
|
acceptedTurnSeqRef.current = 0;
|
|
1569
1587
|
setState("connecting");
|
|
1570
|
-
voiceLogger.debug("start() called", { agentId });
|
|
1588
|
+
voiceLogger.debug("start() called", { agentId, threadId });
|
|
1571
1589
|
try {
|
|
1572
1590
|
const res = await fetchWithAuth("/voice/sessions", {
|
|
1573
1591
|
method: "POST",
|
|
1574
1592
|
headers: { "Content-Type": "application/json" },
|
|
1575
|
-
body: JSON.stringify({
|
|
1593
|
+
body: JSON.stringify({
|
|
1594
|
+
agentId,
|
|
1595
|
+
...threadId ? { threadId } : {}
|
|
1596
|
+
})
|
|
1576
1597
|
});
|
|
1577
1598
|
if (!res.ok) {
|
|
1578
1599
|
throw new Error(`Failed to start voice session: ${res.statusText}`);
|
|
@@ -1607,7 +1628,7 @@ function useVoice(options = {}) {
|
|
|
1607
1628
|
}
|
|
1608
1629
|
teardownAudio();
|
|
1609
1630
|
}
|
|
1610
|
-
}, [agentId, fetchWithAuth, handleMessage, teardownAudio, voiceLogger]);
|
|
1631
|
+
}, [agentId, threadId, fetchWithAuth, handleMessage, teardownAudio, voiceLogger]);
|
|
1611
1632
|
const mute = useCallback4((muted) => {
|
|
1612
1633
|
setIsMuted(muted);
|
|
1613
1634
|
streamRef.current?.getAudioTracks().forEach((track) => {
|
|
@@ -1867,7 +1888,7 @@ import {
|
|
|
1867
1888
|
getLogLevel,
|
|
1868
1889
|
isLevelEnabled
|
|
1869
1890
|
} from "@personaai/logger";
|
|
1870
|
-
var VERSION = "0.7.
|
|
1891
|
+
var VERSION = "0.7.2";
|
|
1871
1892
|
export {
|
|
1872
1893
|
PersonaProvider,
|
|
1873
1894
|
VERSION,
|