@personaai/react 0.9.0 → 0.10.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 +23 -0
- package/dist/index.cjs +905 -347
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -2
- package/dist/index.d.ts +79 -2
- package/dist/index.js +903 -347
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
ARCHITECT_AGENT_ID: () => ARCHITECT_AGENT_ID,
|
|
23
24
|
PersonaProvider: () => PersonaProvider,
|
|
24
25
|
VERSION: () => VERSION,
|
|
25
26
|
createLogger: () => import_logger2.createLogger,
|
|
@@ -30,6 +31,7 @@ __export(index_exports, {
|
|
|
30
31
|
setLogLevel: () => import_logger2.setLogLevel,
|
|
31
32
|
supportsStreamingFetch: () => supportsStreamingFetch,
|
|
32
33
|
useAgents: () => useAgents,
|
|
34
|
+
useArchitectChat: () => useArchitectChat,
|
|
33
35
|
useChat: () => useChat,
|
|
34
36
|
useConnection: () => useConnection,
|
|
35
37
|
useFiles: () => useFiles,
|
|
@@ -334,7 +336,7 @@ async function openSSEStream(opts) {
|
|
|
334
336
|
};
|
|
335
337
|
}
|
|
336
338
|
|
|
337
|
-
// src/hooks/
|
|
339
|
+
// src/hooks/streamEventHelpers.ts
|
|
338
340
|
function isErrorToolContent(content) {
|
|
339
341
|
if (typeof content !== "string" || !content.trim().startsWith("{"))
|
|
340
342
|
return false;
|
|
@@ -380,6 +382,38 @@ function parsePresentedFile(content) {
|
|
|
380
382
|
return null;
|
|
381
383
|
}
|
|
382
384
|
}
|
|
385
|
+
function normalizeWorkspaceFiles(raw) {
|
|
386
|
+
const normalized = {};
|
|
387
|
+
for (const [path, file] of Object.entries(raw || {})) {
|
|
388
|
+
normalized[path] = {
|
|
389
|
+
content: file.content,
|
|
390
|
+
size: file.size,
|
|
391
|
+
createdAt: file.created_at,
|
|
392
|
+
modifiedAt: file.modified_at
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
return normalized;
|
|
396
|
+
}
|
|
397
|
+
function normalizePendingInterrupt(pending) {
|
|
398
|
+
if (!pending || typeof pending !== "object") return null;
|
|
399
|
+
const p = pending;
|
|
400
|
+
if (p.kind === "hitl") {
|
|
401
|
+
return {
|
|
402
|
+
kind: "hitl",
|
|
403
|
+
actionRequests: p.value?.actionRequests ?? [],
|
|
404
|
+
reviewConfigs: p.value?.reviewConfigs ?? []
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
if (p.kind === "clarification") {
|
|
408
|
+
return {
|
|
409
|
+
kind: "clarification",
|
|
410
|
+
questions: p.value?.questions ?? []
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// src/hooks/useChat.ts
|
|
383
417
|
function parseSandboxCommand(tc) {
|
|
384
418
|
let command = tc.args ?? "";
|
|
385
419
|
try {
|
|
@@ -411,36 +445,6 @@ function parseSandboxCommand(tc) {
|
|
|
411
445
|
seq: tc.seq
|
|
412
446
|
};
|
|
413
447
|
}
|
|
414
|
-
function normalizeWorkspaceFiles(raw) {
|
|
415
|
-
const normalized = {};
|
|
416
|
-
for (const [path, file] of Object.entries(raw || {})) {
|
|
417
|
-
normalized[path] = {
|
|
418
|
-
content: file.content,
|
|
419
|
-
size: file.size,
|
|
420
|
-
createdAt: file.created_at,
|
|
421
|
-
modifiedAt: file.modified_at
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
return normalized;
|
|
425
|
-
}
|
|
426
|
-
function normalizePendingInterrupt(pending) {
|
|
427
|
-
if (!pending || typeof pending !== "object") return null;
|
|
428
|
-
const p = pending;
|
|
429
|
-
if (p.kind === "hitl") {
|
|
430
|
-
return {
|
|
431
|
-
kind: "hitl",
|
|
432
|
-
actionRequests: p.value?.actionRequests ?? [],
|
|
433
|
-
reviewConfigs: p.value?.reviewConfigs ?? []
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
if (p.kind === "clarification") {
|
|
437
|
-
return {
|
|
438
|
-
kind: "clarification",
|
|
439
|
-
questions: p.value?.questions ?? []
|
|
440
|
-
};
|
|
441
|
-
}
|
|
442
|
-
return null;
|
|
443
|
-
}
|
|
444
448
|
function useChat(options = {}) {
|
|
445
449
|
const { defaultAgentId, fetchWithAuth, baseUrl, getAuthToken, logger } = usePersonaContext();
|
|
446
450
|
const chatLogger = (0, import_react2.useMemo)(() => logger.child("chat"), [logger]);
|
|
@@ -505,7 +509,707 @@ function useChat(options = {}) {
|
|
|
505
509
|
chatLogger.trace("stop called \u2014 no active stream");
|
|
506
510
|
}
|
|
507
511
|
}, [chatLogger]);
|
|
508
|
-
const clear = (0, import_react2.useCallback)(() => {
|
|
512
|
+
const clear = (0, import_react2.useCallback)(() => {
|
|
513
|
+
chatLogger.info("clear chat", { messageCount: messages.length });
|
|
514
|
+
chatLogger.debug("clear", { messageCount: messages.length });
|
|
515
|
+
stop();
|
|
516
|
+
setMessages([]);
|
|
517
|
+
setError(null);
|
|
518
|
+
setInterrupt(null);
|
|
519
|
+
setFiles({});
|
|
520
|
+
setTodos([]);
|
|
521
|
+
setPresentedFile(null);
|
|
522
|
+
loadedThreadIdRef.current = void 0;
|
|
523
|
+
}, [stop, chatLogger, messages.length]);
|
|
524
|
+
const startNewChat = (0, import_react2.useCallback)(() => {
|
|
525
|
+
chatLogger.info("startNewChat \u2014 entering ephemeral mode");
|
|
526
|
+
stop();
|
|
527
|
+
setMessages([]);
|
|
528
|
+
setError(null);
|
|
529
|
+
setInterrupt(null);
|
|
530
|
+
setFiles({});
|
|
531
|
+
setTodos([]);
|
|
532
|
+
setPresentedFile(null);
|
|
533
|
+
setInput("");
|
|
534
|
+
loadedThreadIdRef.current = void 0;
|
|
535
|
+
voiceThreadRef.current = void 0;
|
|
536
|
+
voicePrevLenRef.current = 0;
|
|
537
|
+
voiceStreamingIdRef.current = null;
|
|
538
|
+
voiceUserPartialIdRef.current = null;
|
|
539
|
+
setInternalThreadId(void 0);
|
|
540
|
+
}, [stop, chatLogger]);
|
|
541
|
+
const loadThreadMessages = (0, import_react2.useCallback)(
|
|
542
|
+
async (id) => {
|
|
543
|
+
chatLogger.debug("loadThreadMessages start", { threadId: id });
|
|
544
|
+
chatLogger.trace("loadThreadMessages", { threadId: id });
|
|
545
|
+
setIsLoadingHistory(true);
|
|
546
|
+
setError(null);
|
|
547
|
+
try {
|
|
548
|
+
const res = await fetchWithAuth(`/threads/${id}/messages`);
|
|
549
|
+
if (!res.ok)
|
|
550
|
+
throw new Error(`Failed to load thread history: ${res.statusText}`);
|
|
551
|
+
const body = await res.json();
|
|
552
|
+
const data = body?.data ?? body;
|
|
553
|
+
const raw = data?.messages ?? [];
|
|
554
|
+
const subagentTraces = data?.subagentTraces ?? {};
|
|
555
|
+
const loaded = raw.map((m, i) => ({
|
|
556
|
+
id: m.id || `history-${id}-${i}`,
|
|
557
|
+
role: m.role,
|
|
558
|
+
content: m.content,
|
|
559
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
560
|
+
toolCalls: m.toolCalls?.map((tc) => {
|
|
561
|
+
const trace = subagentTraces[tc.toolCallId];
|
|
562
|
+
return Array.isArray(trace) && trace.length > 0 ? {
|
|
563
|
+
...tc,
|
|
564
|
+
subagentActivity: persistedTraceToActivityEntries(trace)
|
|
565
|
+
} : tc;
|
|
566
|
+
})
|
|
567
|
+
}));
|
|
568
|
+
setMessages(loaded);
|
|
569
|
+
setInterrupt(normalizePendingInterrupt(data?.pendingInterrupt));
|
|
570
|
+
setFiles(normalizeWorkspaceFiles(data?.state?.files ?? {}));
|
|
571
|
+
setTodos(data?.state?.todos ?? []);
|
|
572
|
+
loadedThreadIdRef.current = id;
|
|
573
|
+
chatLogger.info("loadThreadMessages succeeded", {
|
|
574
|
+
threadId: id,
|
|
575
|
+
messageCount: loaded.length
|
|
576
|
+
});
|
|
577
|
+
chatLogger.debug("loadThreadMessages completed", {
|
|
578
|
+
threadId: id,
|
|
579
|
+
messageCount: loaded.length
|
|
580
|
+
});
|
|
581
|
+
return loaded;
|
|
582
|
+
} catch (err) {
|
|
583
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
584
|
+
chatLogger.warn("loadThreadMessages failed", {
|
|
585
|
+
threadId: id,
|
|
586
|
+
error: errorObj.message
|
|
587
|
+
});
|
|
588
|
+
chatLogger.error("loadThreadMessages error", {
|
|
589
|
+
threadId: id,
|
|
590
|
+
error: errorObj.message
|
|
591
|
+
});
|
|
592
|
+
setError(errorObj);
|
|
593
|
+
if (loadedThreadIdRef.current === id) loadedThreadIdRef.current = void 0;
|
|
594
|
+
return [];
|
|
595
|
+
} finally {
|
|
596
|
+
setIsLoadingHistory(false);
|
|
597
|
+
chatLogger.trace("loadThreadMessages end", { threadId: id });
|
|
598
|
+
}
|
|
599
|
+
},
|
|
600
|
+
[fetchWithAuth, chatLogger]
|
|
601
|
+
);
|
|
602
|
+
(0, import_react2.useEffect)(() => {
|
|
603
|
+
if (!effectiveThreadId || isStreaming) {
|
|
604
|
+
chatLogger.trace("auto-load skipped", { threadId: effectiveThreadId, isStreaming });
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
if (loadedThreadIdRef.current === effectiveThreadId) {
|
|
608
|
+
chatLogger.trace("auto-load already loaded", { threadId: effectiveThreadId });
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
if (messages.length > 0) {
|
|
612
|
+
chatLogger.trace("auto-load has messages", {
|
|
613
|
+
threadId: effectiveThreadId,
|
|
614
|
+
count: messages.length
|
|
615
|
+
});
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
chatLogger.info("auto-load thread history", { threadId: effectiveThreadId });
|
|
619
|
+
chatLogger.debug("loadThreadMessages trigger", { threadId: effectiveThreadId });
|
|
620
|
+
void loadThreadMessages(effectiveThreadId);
|
|
621
|
+
}, [effectiveThreadId, isStreaming, messages.length, loadThreadMessages, chatLogger]);
|
|
622
|
+
const voice = options.voice;
|
|
623
|
+
(0, import_react2.useEffect)(() => {
|
|
624
|
+
if (!voice) return;
|
|
625
|
+
if (voiceThreadRef.current !== effectiveThreadId) {
|
|
626
|
+
voiceThreadRef.current = effectiveThreadId;
|
|
627
|
+
voicePrevLenRef.current = voice.transcript.length;
|
|
628
|
+
voiceStreamingIdRef.current = null;
|
|
629
|
+
voiceUserPartialIdRef.current = null;
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
const isVoiceActive = voice.state !== "idle" && voice.state !== "ended" && voice.state !== "error";
|
|
633
|
+
const curLen = voice.transcript.length;
|
|
634
|
+
if (curLen < voicePrevLenRef.current) {
|
|
635
|
+
voicePrevLenRef.current = 0;
|
|
636
|
+
voiceStreamingIdRef.current = null;
|
|
637
|
+
voiceUserPartialIdRef.current = null;
|
|
638
|
+
}
|
|
639
|
+
if (!isVoiceActive) {
|
|
640
|
+
if (curLen > voicePrevLenRef.current) {
|
|
641
|
+
const pendingLines = voice.transcript.slice(voicePrevLenRef.current);
|
|
642
|
+
voicePrevLenRef.current = curLen;
|
|
643
|
+
for (const line of pendingLines) {
|
|
644
|
+
const text = (line.text || "").trim();
|
|
645
|
+
if (!text) continue;
|
|
646
|
+
const role = line.speaker === "user" ? "user" : "assistant";
|
|
647
|
+
const voiceId = `voice-${line.id}`;
|
|
648
|
+
setMessages((prev) => {
|
|
649
|
+
if (prev.some((m) => m.id === voiceId)) return prev;
|
|
650
|
+
if (prev.some((m) => !m.id.startsWith("voice-") && m.role === role && m.content.trim() === text)) return prev;
|
|
651
|
+
const last = prev[prev.length - 1];
|
|
652
|
+
if (last?.id.startsWith("voice-") && last.role === "assistant" && role === "assistant") {
|
|
653
|
+
const merged = text.startsWith(last.content) ? text : `${last.content} ${text}`.trim();
|
|
654
|
+
return [...prev.slice(0, -1), { ...last, content: merged, isStreaming: false }];
|
|
655
|
+
}
|
|
656
|
+
return [...prev, { id: voiceId, role, content: text, createdAt: /* @__PURE__ */ new Date() }];
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
} else {
|
|
660
|
+
voicePrevLenRef.current = voice.transcript.length;
|
|
661
|
+
}
|
|
662
|
+
if (voiceStreamingIdRef.current) {
|
|
663
|
+
const doneId = voiceStreamingIdRef.current;
|
|
664
|
+
voiceStreamingIdRef.current = null;
|
|
665
|
+
setMessages((prev) => prev.map((m) => m.id === doneId ? { ...m, isStreaming: false } : m));
|
|
666
|
+
}
|
|
667
|
+
if (voiceUserPartialIdRef.current) {
|
|
668
|
+
const doneId = voiceUserPartialIdRef.current;
|
|
669
|
+
voiceUserPartialIdRef.current = null;
|
|
670
|
+
setMessages((prev) => prev.map((m) => m.id === doneId ? { ...m, isStreaming: false } : m));
|
|
671
|
+
}
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
if (curLen > voicePrevLenRef.current) {
|
|
675
|
+
const newLines = voice.transcript.slice(voicePrevLenRef.current);
|
|
676
|
+
voicePrevLenRef.current = curLen;
|
|
677
|
+
for (const line of newLines) {
|
|
678
|
+
const text = (line.text || "").trim();
|
|
679
|
+
if (!text) continue;
|
|
680
|
+
const role = line.speaker === "user" ? "user" : "assistant";
|
|
681
|
+
const voiceId = `voice-${line.id}`;
|
|
682
|
+
setMessages((prev) => {
|
|
683
|
+
if (prev.some((m) => m.id === voiceId)) return prev;
|
|
684
|
+
if (prev.some(
|
|
685
|
+
(m) => !m.id.startsWith("voice-") && m.role === role && m.content.trim() === text
|
|
686
|
+
))
|
|
687
|
+
return prev;
|
|
688
|
+
const last = prev[prev.length - 1];
|
|
689
|
+
if (last?.id.startsWith("voice-") && last.role === "assistant" && role === "assistant") {
|
|
690
|
+
const merged = text.startsWith(last.content) ? text : `${last.content} ${text}`.trim();
|
|
691
|
+
return [...prev.slice(0, -1), { ...last, content: merged, isStreaming: false }];
|
|
692
|
+
}
|
|
693
|
+
return [...prev, { id: voiceId, role, content: text, createdAt: /* @__PURE__ */ new Date() }];
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
const agentPartialText = voice.partial?.speaker === "agent" ? voice.partial.text.trim() : "";
|
|
698
|
+
const userPartialText = voice.partial?.speaker === "user" ? voice.partial.text.trim() : "";
|
|
699
|
+
if (agentPartialText) {
|
|
700
|
+
if (voiceUserPartialIdRef.current) {
|
|
701
|
+
const doneId = voiceUserPartialIdRef.current;
|
|
702
|
+
voiceUserPartialIdRef.current = null;
|
|
703
|
+
setMessages((prev) => prev.map((m) => m.id === doneId ? { ...m, isStreaming: false } : m));
|
|
704
|
+
}
|
|
705
|
+
setMessages((prev) => {
|
|
706
|
+
const last = prev[prev.length - 1];
|
|
707
|
+
if (last?.id.startsWith("voice-") && last.role === "assistant") {
|
|
708
|
+
voiceStreamingIdRef.current = last.id;
|
|
709
|
+
return [...prev.slice(0, -1), { ...last, content: agentPartialText, isStreaming: true }];
|
|
710
|
+
}
|
|
711
|
+
const id = voiceStreamingIdRef.current || `voice-partial-${Date.now()}`;
|
|
712
|
+
voiceStreamingIdRef.current = id;
|
|
713
|
+
return [...prev, { id, role: "assistant", content: agentPartialText, isStreaming: true, createdAt: /* @__PURE__ */ new Date() }];
|
|
714
|
+
});
|
|
715
|
+
} else if (userPartialText) {
|
|
716
|
+
if (voiceStreamingIdRef.current) {
|
|
717
|
+
const doneId = voiceStreamingIdRef.current;
|
|
718
|
+
voiceStreamingIdRef.current = null;
|
|
719
|
+
setMessages((prev) => prev.map((m) => m.id === doneId ? { ...m, isStreaming: false } : m));
|
|
720
|
+
}
|
|
721
|
+
setMessages((prev) => {
|
|
722
|
+
const last = prev[prev.length - 1];
|
|
723
|
+
if (last?.id.startsWith("voice-") && last.role === "user" && last.isStreaming) {
|
|
724
|
+
voiceUserPartialIdRef.current = last.id;
|
|
725
|
+
return [...prev.slice(0, -1), { ...last, content: userPartialText, isStreaming: true }];
|
|
726
|
+
}
|
|
727
|
+
const id = voiceUserPartialIdRef.current || `voice-partial-user-${Date.now()}`;
|
|
728
|
+
voiceUserPartialIdRef.current = id;
|
|
729
|
+
return [...prev, { id, role: "user", content: userPartialText, isStreaming: true, createdAt: /* @__PURE__ */ new Date() }];
|
|
730
|
+
});
|
|
731
|
+
} else {
|
|
732
|
+
if (voiceStreamingIdRef.current && voice.state !== "speaking") {
|
|
733
|
+
const doneId = voiceStreamingIdRef.current;
|
|
734
|
+
voiceStreamingIdRef.current = null;
|
|
735
|
+
setMessages((prev) => prev.map((m) => m.id === doneId ? { ...m, isStreaming: false } : m));
|
|
736
|
+
}
|
|
737
|
+
if (voiceUserPartialIdRef.current) {
|
|
738
|
+
const doneId = voiceUserPartialIdRef.current;
|
|
739
|
+
voiceUserPartialIdRef.current = null;
|
|
740
|
+
setMessages((prev) => prev.map((m) => m.id === doneId ? { ...m, isStreaming: false } : m));
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}, [voice?.transcript, voice?.partial, voice?.state, effectiveThreadId]);
|
|
744
|
+
const doSend = (0, import_react2.useCallback)(
|
|
745
|
+
async (prompt, baseMessages, overrideOptions) => {
|
|
746
|
+
const targetAgentId = overrideOptions?.agentId || agentId;
|
|
747
|
+
if (!targetAgentId) {
|
|
748
|
+
const err = new Error("No Agent ID specified for useChat.");
|
|
749
|
+
chatLogger.warn("sendMessage no agentId", {});
|
|
750
|
+
chatLogger.error("sendMessage failed \u2014 no agent", { error: err.message });
|
|
751
|
+
setError(err);
|
|
752
|
+
options.onError?.(err);
|
|
753
|
+
return false;
|
|
754
|
+
}
|
|
755
|
+
chatLogger.debug("sendMessage start", {
|
|
756
|
+
promptPreview: prompt.slice(0, 100),
|
|
757
|
+
agentId: targetAgentId,
|
|
758
|
+
threadId: effectiveThreadId ?? overrideOptions?.threadId,
|
|
759
|
+
hasResume: !!overrideOptions?.resume,
|
|
760
|
+
hasContextOverride: !!overrideOptions?.contextOverride,
|
|
761
|
+
messageCount: baseMessages.length
|
|
762
|
+
});
|
|
763
|
+
chatLogger.trace("sendMessage details", {
|
|
764
|
+
agentId: targetAgentId,
|
|
765
|
+
promptPreview: prompt.slice(0, 200),
|
|
766
|
+
hasResume: !!overrideOptions?.resume,
|
|
767
|
+
hasContextOverride: !!overrideOptions?.contextOverride
|
|
768
|
+
});
|
|
769
|
+
const userMessage = {
|
|
770
|
+
id: `user-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
771
|
+
role: "user",
|
|
772
|
+
content: prompt,
|
|
773
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
774
|
+
};
|
|
775
|
+
const assistantMessageId = `assistant-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
776
|
+
const placeholderAssistant = {
|
|
777
|
+
id: assistantMessageId,
|
|
778
|
+
role: "assistant",
|
|
779
|
+
content: "",
|
|
780
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
781
|
+
isStreaming: true,
|
|
782
|
+
toolCalls: []
|
|
783
|
+
};
|
|
784
|
+
const nextMessages = [...baseMessages, userMessage];
|
|
785
|
+
setMessages([...nextMessages, placeholderAssistant]);
|
|
786
|
+
setInput("");
|
|
787
|
+
setIsStreaming(true);
|
|
788
|
+
setError(null);
|
|
789
|
+
setInterrupt(null);
|
|
790
|
+
const controller = new AbortController();
|
|
791
|
+
abortControllerRef.current = controller;
|
|
792
|
+
const finalizeReasoning = () => {
|
|
793
|
+
setMessages(
|
|
794
|
+
(prev) => prev.map((m) => m.role === "reasoning" && m.isStreaming ? { ...m, isStreaming: false } : m)
|
|
795
|
+
);
|
|
796
|
+
};
|
|
797
|
+
try {
|
|
798
|
+
const payloadMessages = nextMessages.filter((m) => m.role !== "reasoning").map((m) => ({
|
|
799
|
+
role: m.role === "assistant" ? "assistant" : "user",
|
|
800
|
+
content: m.content
|
|
801
|
+
}));
|
|
802
|
+
let resolvedThreadId = await overrideOptions?.threadId ?? effectiveThreadId;
|
|
803
|
+
if (!resolvedThreadId) {
|
|
804
|
+
chatLogger.info("minting real thread for ephemeral chat", { agentId: targetAgentId });
|
|
805
|
+
const createRes = await fetchWithAuth("/threads", {
|
|
806
|
+
method: "POST",
|
|
807
|
+
headers: { "Content-Type": "application/json" },
|
|
808
|
+
body: JSON.stringify({ agentId: targetAgentId })
|
|
809
|
+
});
|
|
810
|
+
if (!createRes.ok) throw new Error(`Failed to create thread: ${createRes.statusText}`);
|
|
811
|
+
const createBody = await createRes.json();
|
|
812
|
+
const created = createBody?.data ?? createBody;
|
|
813
|
+
resolvedThreadId = created._id ?? created.id;
|
|
814
|
+
if (!resolvedThreadId) throw new Error("Thread creation returned no id");
|
|
815
|
+
setInternalThreadId(resolvedThreadId);
|
|
816
|
+
loadedThreadIdRef.current = resolvedThreadId;
|
|
817
|
+
options.onThreadCreated?.(resolvedThreadId);
|
|
818
|
+
chatLogger.info("ephemeral chat minted", { threadId: resolvedThreadId });
|
|
819
|
+
}
|
|
820
|
+
chatLogger.trace("resolved threadId", { threadId: resolvedThreadId });
|
|
821
|
+
const token = getAuthToken ? await getAuthToken() : null;
|
|
822
|
+
const resolvedHookContext = typeof options.context === "function" ? options.context() : options.context;
|
|
823
|
+
const mergedContext = { ...resolvedHookContext, ...overrideOptions?.context };
|
|
824
|
+
const hasContext = Object.keys(mergedContext).length > 0;
|
|
825
|
+
chatLogger.debug("opening SSE stream", {
|
|
826
|
+
agentId: targetAgentId,
|
|
827
|
+
hasToken: !!token,
|
|
828
|
+
hasThreadId: !!resolvedThreadId,
|
|
829
|
+
hasContext
|
|
830
|
+
});
|
|
831
|
+
const stream = await openSSEStream({
|
|
832
|
+
url: `${baseUrl}/chat`,
|
|
833
|
+
headers: {
|
|
834
|
+
"Content-Type": "application/json",
|
|
835
|
+
...token ? { Authorization: `Bearer ${token}` } : {}
|
|
836
|
+
},
|
|
837
|
+
body: JSON.stringify({
|
|
838
|
+
agentId: targetAgentId,
|
|
839
|
+
messages: payloadMessages,
|
|
840
|
+
threadId: resolvedThreadId,
|
|
841
|
+
resume: overrideOptions?.resume,
|
|
842
|
+
contextOverride: overrideOptions?.contextOverride,
|
|
843
|
+
...hasContext ? { context: mergedContext } : {}
|
|
844
|
+
}),
|
|
845
|
+
signal: controller.signal
|
|
846
|
+
});
|
|
847
|
+
if (!stream.ok) {
|
|
848
|
+
chatLogger.warn("SSE stream not ok", { status: stream.status, errorText: stream.errorText });
|
|
849
|
+
chatLogger.error("chat stream failed", { agentId: targetAgentId, status: stream.status, error: stream.errorText });
|
|
850
|
+
throw new Error(`Chat error (${stream.status}): ${stream.errorText ?? "Stream failed"}`);
|
|
851
|
+
}
|
|
852
|
+
chatLogger.debug("SSE stream opened", { agentId: targetAgentId, status: stream.status });
|
|
853
|
+
chatLogger.info("chat stream started", { agentId: targetAgentId, threadId: resolvedThreadId });
|
|
854
|
+
const reader = stream.reader;
|
|
855
|
+
let buffer = "";
|
|
856
|
+
let accumulatedText = "";
|
|
857
|
+
const toolCallsMap = /* @__PURE__ */ new Map();
|
|
858
|
+
let streamSeq = 0;
|
|
859
|
+
let activeReasoningId = null;
|
|
860
|
+
const reasoningById = /* @__PURE__ */ new Map();
|
|
861
|
+
const patchAssistant = (patch) => {
|
|
862
|
+
setMessages(
|
|
863
|
+
(prev) => prev.map(
|
|
864
|
+
(msg) => msg.id === assistantMessageId ? { ...msg, toolCalls: Array.from(toolCallsMap.values()), ...patch } : msg
|
|
865
|
+
)
|
|
866
|
+
);
|
|
867
|
+
};
|
|
868
|
+
const insertReasoningMessage = (id, seq) => {
|
|
869
|
+
const msg = { id, role: "reasoning", content: "", createdAt: /* @__PURE__ */ new Date(), isStreaming: true, seq };
|
|
870
|
+
setMessages((prev) => {
|
|
871
|
+
const idx = prev.findIndex((m) => m.id === assistantMessageId);
|
|
872
|
+
if (idx === -1) return [...prev, msg];
|
|
873
|
+
const next = [...prev];
|
|
874
|
+
next.splice(idx, 0, msg);
|
|
875
|
+
return next;
|
|
876
|
+
});
|
|
877
|
+
};
|
|
878
|
+
while (true) {
|
|
879
|
+
const { done, value } = await reader.read();
|
|
880
|
+
if (done) break;
|
|
881
|
+
buffer += value ?? "";
|
|
882
|
+
const lines = buffer.split("\n");
|
|
883
|
+
buffer = lines.pop() ?? "";
|
|
884
|
+
for (const line of lines) {
|
|
885
|
+
const trimmed = line.trim();
|
|
886
|
+
if (!trimmed || !trimmed.startsWith("data:")) continue;
|
|
887
|
+
const raw = trimmed.replace(/^data:\s*/, "");
|
|
888
|
+
if (raw === "[DONE]") break;
|
|
889
|
+
try {
|
|
890
|
+
const event = JSON.parse(raw);
|
|
891
|
+
chatLogger.trace("stream event", { type: event.type, event });
|
|
892
|
+
options.onEvent?.(event);
|
|
893
|
+
if (event.type === "TEXT_MESSAGE_CHUNK" && event.delta) {
|
|
894
|
+
chatLogger.debug("text chunk", { deltaLength: event.delta.length });
|
|
895
|
+
accumulatedText += event.delta;
|
|
896
|
+
patchAssistant({ content: accumulatedText, isStreaming: true });
|
|
897
|
+
} else if (event.type === "TOOL_CALL_CHUNK" && event.toolCallId) {
|
|
898
|
+
chatLogger.debug("tool call chunk", { toolCallId: event.toolCallId, toolCallName: event.toolCallName });
|
|
899
|
+
const existing = toolCallsMap.get(event.toolCallId);
|
|
900
|
+
if (existing) {
|
|
901
|
+
existing.args = (existing.args || "") + (event.delta || "");
|
|
902
|
+
} else {
|
|
903
|
+
toolCallsMap.set(event.toolCallId, {
|
|
904
|
+
toolCallId: event.toolCallId,
|
|
905
|
+
toolName: event.toolCallName || "",
|
|
906
|
+
args: event.delta || "",
|
|
907
|
+
seq: streamSeq++
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
patchAssistant({});
|
|
911
|
+
} else if (event.type === "TOOL_CALL_RESULT") {
|
|
912
|
+
chatLogger.debug("tool call result", { toolCallId: event.toolCallId });
|
|
913
|
+
const existing = toolCallsMap.get(event.toolCallId);
|
|
914
|
+
if (existing) {
|
|
915
|
+
existing.result = event.content;
|
|
916
|
+
existing.isError = isErrorToolContent(event.content);
|
|
917
|
+
if (existing.isError) chatLogger.warn("tool call error", { toolCallId: event.toolCallId });
|
|
918
|
+
if (existing.toolName === "present_file" && !existing.isError) {
|
|
919
|
+
const presented = parsePresentedFile(event.content);
|
|
920
|
+
if (presented) {
|
|
921
|
+
chatLogger.info("present_file", { path: presented.path });
|
|
922
|
+
setPresentedFile(presented);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
patchAssistant({});
|
|
926
|
+
}
|
|
927
|
+
} else if (event.type === "STATE_SNAPSHOT") {
|
|
928
|
+
chatLogger.debug("state snapshot", {
|
|
929
|
+
fileCount: Object.keys(event.snapshot.files ?? {}).length,
|
|
930
|
+
todoCount: event.snapshot.todos?.length ?? 0
|
|
931
|
+
});
|
|
932
|
+
setFiles(normalizeWorkspaceFiles(event.snapshot.files ?? {}));
|
|
933
|
+
setTodos(event.snapshot.todos ?? []);
|
|
934
|
+
} else if (event.type === "REASONING_MESSAGE_START" && event.messageId) {
|
|
935
|
+
chatLogger.debug("reasoning start", { messageId: event.messageId });
|
|
936
|
+
activeReasoningId = event.messageId;
|
|
937
|
+
reasoningById.set(event.messageId, { content: "" });
|
|
938
|
+
insertReasoningMessage(event.messageId, streamSeq++);
|
|
939
|
+
} else if (event.type === "REASONING_MESSAGE_CONTENT") {
|
|
940
|
+
let rid = event.messageId || activeReasoningId || "";
|
|
941
|
+
if (!rid || !reasoningById.has(rid)) {
|
|
942
|
+
rid = rid || `reasoning-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
943
|
+
activeReasoningId = rid;
|
|
944
|
+
reasoningById.set(rid, { content: "" });
|
|
945
|
+
insertReasoningMessage(rid, streamSeq++);
|
|
946
|
+
chatLogger.debug("reasoning lazy start", { messageId: rid });
|
|
947
|
+
}
|
|
948
|
+
const entry = reasoningById.get(rid);
|
|
949
|
+
entry.content += event.delta;
|
|
950
|
+
chatLogger.trace("reasoning content", { messageId: rid, deltaLength: event.delta?.length ?? 0 });
|
|
951
|
+
setMessages((prev) => prev.map((m) => m.id === rid ? { ...m, content: entry.content, isStreaming: true } : m));
|
|
952
|
+
} else if (event.type === "REASONING_END") {
|
|
953
|
+
chatLogger.debug("reasoning end", { messageId: activeReasoningId });
|
|
954
|
+
const rid = activeReasoningId;
|
|
955
|
+
activeReasoningId = null;
|
|
956
|
+
if (rid) {
|
|
957
|
+
setMessages((prev) => prev.map((m) => m.id === rid ? { ...m, isStreaming: false } : m));
|
|
958
|
+
}
|
|
959
|
+
} else if (event.type === "CUSTOM") {
|
|
960
|
+
chatLogger.debug("custom event", { name: event.name });
|
|
961
|
+
if (event.name === "hitl_request") {
|
|
962
|
+
const value2 = event.value;
|
|
963
|
+
chatLogger.info("hitl interrupt", { actionCount: value2.actionRequests?.length ?? 0 });
|
|
964
|
+
setInterrupt({ kind: "hitl", actionRequests: value2.actionRequests, reviewConfigs: value2.reviewConfigs });
|
|
965
|
+
} else if (event.name === "clarification_request") {
|
|
966
|
+
const value2 = event.value;
|
|
967
|
+
chatLogger.info("clarification interrupt", { questionCount: value2.questions?.length ?? 0 });
|
|
968
|
+
setInterrupt({ kind: "clarification", questions: value2.questions });
|
|
969
|
+
} else if (event.name === "subagent_activity") {
|
|
970
|
+
const { toolCallId, ...entry } = event.value;
|
|
971
|
+
chatLogger.trace("subagent activity", { toolCallId, kind: entry.kind });
|
|
972
|
+
const existing = toolCallsMap.get(toolCallId);
|
|
973
|
+
if (existing) {
|
|
974
|
+
existing.subagentActivity = [...existing.subagentActivity || [], entry];
|
|
975
|
+
patchAssistant({});
|
|
976
|
+
}
|
|
977
|
+
} else if (event.name === "mcp_app") {
|
|
978
|
+
const val = event.value;
|
|
979
|
+
if (val?.toolCallId && val?.resourceUri && val?.mcpId) {
|
|
980
|
+
const existing = toolCallsMap.get(val.toolCallId);
|
|
981
|
+
if (existing) {
|
|
982
|
+
existing.mcpApp = { resourceUri: val.resourceUri, mcpId: val.mcpId };
|
|
983
|
+
patchAssistant({});
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
} else if (event.type === "title") {
|
|
988
|
+
const title = event.title;
|
|
989
|
+
if (typeof title === "string" && title.trim()) {
|
|
990
|
+
chatLogger.info("auto title", { title });
|
|
991
|
+
options.onTitle?.(title);
|
|
992
|
+
}
|
|
993
|
+
} else if (event.type === "RUN_ERROR") {
|
|
994
|
+
chatLogger.warn("run error", { message: event.message, code: event.code });
|
|
995
|
+
chatLogger.error("stream run error", { code: event.code, message: event.message });
|
|
996
|
+
throw new Error(event.message || "Stream error from agent");
|
|
997
|
+
} else {
|
|
998
|
+
chatLogger.trace("unhandled event", { type: event.type });
|
|
999
|
+
}
|
|
1000
|
+
} catch (e) {
|
|
1001
|
+
if (e instanceof Error && e.message.startsWith("Stream error")) throw e;
|
|
1002
|
+
chatLogger.warn("event parse error", { raw: raw.slice(0, 200), error: e instanceof Error ? e.message : String(e) });
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
const finalMessage = {
|
|
1007
|
+
id: assistantMessageId,
|
|
1008
|
+
role: "assistant",
|
|
1009
|
+
content: accumulatedText,
|
|
1010
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1011
|
+
isStreaming: false,
|
|
1012
|
+
toolCalls: Array.from(toolCallsMap.values())
|
|
1013
|
+
};
|
|
1014
|
+
setMessages((prev) => prev.map((msg) => msg.id === assistantMessageId ? finalMessage : msg));
|
|
1015
|
+
chatLogger.info("sendMessage succeeded", { agentId: targetAgentId, textLength: accumulatedText.length, toolCallCount: toolCallsMap.size });
|
|
1016
|
+
chatLogger.debug("sendMessage completed", { agentId: targetAgentId, textLength: accumulatedText.length, eventCount: toolCallsMap.size + 1 });
|
|
1017
|
+
options.onFinish?.(finalMessage);
|
|
1018
|
+
return true;
|
|
1019
|
+
} catch (err) {
|
|
1020
|
+
if (controller.signal.aborted) {
|
|
1021
|
+
chatLogger.info("sendMessage aborted", { agentId: targetAgentId });
|
|
1022
|
+
chatLogger.debug("stream aborted", { agentId: targetAgentId });
|
|
1023
|
+
setMessages((prev) => prev.map((msg) => msg.id === assistantMessageId ? { ...msg, isStreaming: false } : msg));
|
|
1024
|
+
return false;
|
|
1025
|
+
}
|
|
1026
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
1027
|
+
chatLogger.warn("sendMessage failed", { agentId: targetAgentId, error: errorObj.message });
|
|
1028
|
+
chatLogger.error("sendMessage error", { agentId: targetAgentId, error: errorObj.message });
|
|
1029
|
+
setError(errorObj);
|
|
1030
|
+
options.onError?.(errorObj);
|
|
1031
|
+
setMessages(
|
|
1032
|
+
(prev) => prev.map(
|
|
1033
|
+
(msg) => msg.id === assistantMessageId ? { ...msg, content: msg.content || `\u26A0\uFE0F Error: ${errorObj.message || "Failed to get response."}`, isStreaming: false } : msg
|
|
1034
|
+
)
|
|
1035
|
+
);
|
|
1036
|
+
return false;
|
|
1037
|
+
} finally {
|
|
1038
|
+
setIsStreaming(false);
|
|
1039
|
+
abortControllerRef.current = null;
|
|
1040
|
+
finalizeReasoning();
|
|
1041
|
+
chatLogger.debug("sendMessage finally", { agentId: targetAgentId, isStreaming: false });
|
|
1042
|
+
chatLogger.trace("sendMessage end", { agentId: targetAgentId });
|
|
1043
|
+
}
|
|
1044
|
+
},
|
|
1045
|
+
[agentId, baseUrl, getAuthToken, fetchWithAuth, options, chatLogger, effectiveThreadId]
|
|
1046
|
+
);
|
|
1047
|
+
const sendMessage = (0, import_react2.useCallback)(
|
|
1048
|
+
async (contentToSend, overrideOptions) => {
|
|
1049
|
+
const prompt = (contentToSend ?? input).trim();
|
|
1050
|
+
if (!prompt || isStreaming) {
|
|
1051
|
+
chatLogger.trace("sendMessage skipped", {
|
|
1052
|
+
hasPrompt: !!prompt,
|
|
1053
|
+
isStreaming
|
|
1054
|
+
});
|
|
1055
|
+
if (isStreaming) {
|
|
1056
|
+
chatLogger.warn("sendMessage dropped while streaming \u2014 caller should queue or disable send", {});
|
|
1057
|
+
}
|
|
1058
|
+
return false;
|
|
1059
|
+
}
|
|
1060
|
+
return doSend(prompt, messages, overrideOptions);
|
|
1061
|
+
},
|
|
1062
|
+
[input, isStreaming, messages, doSend, chatLogger]
|
|
1063
|
+
);
|
|
1064
|
+
const handleInputChange = (0, import_react2.useCallback)(
|
|
1065
|
+
(e) => {
|
|
1066
|
+
chatLogger.trace("handleInputChange", { length: e.target.value.length });
|
|
1067
|
+
setInput(e.target.value);
|
|
1068
|
+
},
|
|
1069
|
+
[chatLogger]
|
|
1070
|
+
);
|
|
1071
|
+
const handleSubmit = (0, import_react2.useCallback)(
|
|
1072
|
+
(e) => {
|
|
1073
|
+
if (e) e.preventDefault();
|
|
1074
|
+
chatLogger.debug("handleSubmit", {});
|
|
1075
|
+
void sendMessage();
|
|
1076
|
+
},
|
|
1077
|
+
[sendMessage, chatLogger]
|
|
1078
|
+
);
|
|
1079
|
+
const reload = (0, import_react2.useCallback)(async () => {
|
|
1080
|
+
if (messages.length === 0 || isStreaming) {
|
|
1081
|
+
chatLogger.trace("reload skipped", {
|
|
1082
|
+
messageCount: messages.length,
|
|
1083
|
+
isStreaming
|
|
1084
|
+
});
|
|
1085
|
+
return false;
|
|
1086
|
+
}
|
|
1087
|
+
let lastUserIndex = -1;
|
|
1088
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1089
|
+
if (messages[i].role === "user") {
|
|
1090
|
+
lastUserIndex = i;
|
|
1091
|
+
break;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
if (lastUserIndex === -1) {
|
|
1095
|
+
chatLogger.warn("reload no user message", {});
|
|
1096
|
+
return false;
|
|
1097
|
+
}
|
|
1098
|
+
const lastUserMessage = messages[lastUserIndex];
|
|
1099
|
+
const truncated = messages.slice(0, lastUserIndex);
|
|
1100
|
+
chatLogger.info("reload", { messageId: lastUserMessage.id });
|
|
1101
|
+
chatLogger.debug("reload last user", {
|
|
1102
|
+
preview: lastUserMessage.content.slice(0, 100)
|
|
1103
|
+
});
|
|
1104
|
+
return doSend(lastUserMessage.content, truncated);
|
|
1105
|
+
}, [isStreaming, messages, doSend, chatLogger]);
|
|
1106
|
+
const resumeInterrupt = (0, import_react2.useCallback)(
|
|
1107
|
+
(resume, displayContent) => {
|
|
1108
|
+
chatLogger.info("resumeInterrupt", {
|
|
1109
|
+
kind: resume.decisions ? "hitl" : "clarification",
|
|
1110
|
+
preview: displayContent.slice(0, 50)
|
|
1111
|
+
});
|
|
1112
|
+
return sendMessage(displayContent, { resume });
|
|
1113
|
+
},
|
|
1114
|
+
[sendMessage, chatLogger]
|
|
1115
|
+
);
|
|
1116
|
+
const dismissPresentedFile = (0, import_react2.useCallback)(() => {
|
|
1117
|
+
chatLogger.debug("dismissPresentedFile", {});
|
|
1118
|
+
setPresentedFile(null);
|
|
1119
|
+
}, [chatLogger]);
|
|
1120
|
+
const openWorkspaceFile = (0, import_react2.useCallback)(
|
|
1121
|
+
(path) => {
|
|
1122
|
+
chatLogger.debug("openWorkspaceFile", { path });
|
|
1123
|
+
setPresentedFile({
|
|
1124
|
+
path,
|
|
1125
|
+
title: path.split("/").pop() || path,
|
|
1126
|
+
description: ""
|
|
1127
|
+
});
|
|
1128
|
+
},
|
|
1129
|
+
[chatLogger]
|
|
1130
|
+
);
|
|
1131
|
+
return {
|
|
1132
|
+
messages,
|
|
1133
|
+
input,
|
|
1134
|
+
setInput,
|
|
1135
|
+
handleInputChange,
|
|
1136
|
+
handleSubmit,
|
|
1137
|
+
sendMessage,
|
|
1138
|
+
isStreaming,
|
|
1139
|
+
isLoading: isStreaming,
|
|
1140
|
+
isLoadingHistory,
|
|
1141
|
+
error,
|
|
1142
|
+
interrupt,
|
|
1143
|
+
resumeInterrupt,
|
|
1144
|
+
files,
|
|
1145
|
+
todos,
|
|
1146
|
+
presentedFile,
|
|
1147
|
+
dismissPresentedFile,
|
|
1148
|
+
openWorkspaceFile,
|
|
1149
|
+
sandboxCommands,
|
|
1150
|
+
stop,
|
|
1151
|
+
reload,
|
|
1152
|
+
clear,
|
|
1153
|
+
startNewChat,
|
|
1154
|
+
currentThreadId: effectiveThreadId,
|
|
1155
|
+
isEphemeral: !effectiveThreadId,
|
|
1156
|
+
setMessages,
|
|
1157
|
+
loadThreadMessages
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
// src/hooks/useArchitectChat.ts
|
|
1162
|
+
var import_react3 = require("react");
|
|
1163
|
+
var ARCHITECT_AGENT_ID = "000000000000000000000002";
|
|
1164
|
+
function useArchitectChat(options = {}) {
|
|
1165
|
+
const { fetchWithAuth, baseUrl, getAuthToken, logger } = usePersonaContext();
|
|
1166
|
+
const chatLogger = (0, import_react3.useMemo)(() => logger.child("architect"), [logger]);
|
|
1167
|
+
const threadId = options.threadId;
|
|
1168
|
+
const [internalThreadId, setInternalThreadId] = (0, import_react3.useState)(void 0);
|
|
1169
|
+
const effectiveThreadId = threadId ?? internalThreadId;
|
|
1170
|
+
(0, import_react3.useEffect)(() => {
|
|
1171
|
+
if (threadId !== void 0) setInternalThreadId(threadId);
|
|
1172
|
+
}, [threadId]);
|
|
1173
|
+
const didLogInitRef = (0, import_react3.useRef)(false);
|
|
1174
|
+
if (!didLogInitRef.current) {
|
|
1175
|
+
didLogInitRef.current = true;
|
|
1176
|
+
chatLogger.debug("useArchitectChat init", {
|
|
1177
|
+
threadId,
|
|
1178
|
+
hasInitialMessages: !!options.initialMessages?.length
|
|
1179
|
+
});
|
|
1180
|
+
chatLogger.trace("useArchitectChat options", {
|
|
1181
|
+
threadId,
|
|
1182
|
+
initialMessageCount: options.initialMessages?.length ?? 0
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
const [messages, setMessages] = (0, import_react3.useState)(
|
|
1186
|
+
options.initialMessages || []
|
|
1187
|
+
);
|
|
1188
|
+
const [input, setInput] = (0, import_react3.useState)("");
|
|
1189
|
+
const [isStreaming, setIsStreaming] = (0, import_react3.useState)(false);
|
|
1190
|
+
const [isLoadingHistory, setIsLoadingHistory] = (0, import_react3.useState)(false);
|
|
1191
|
+
const [error, setError] = (0, import_react3.useState)(null);
|
|
1192
|
+
const [interrupt, setInterrupt] = (0, import_react3.useState)(null);
|
|
1193
|
+
const [files, setFiles] = (0, import_react3.useState)({});
|
|
1194
|
+
const [todos, setTodos] = (0, import_react3.useState)([]);
|
|
1195
|
+
const [presentedFile, setPresentedFile] = (0, import_react3.useState)(null);
|
|
1196
|
+
const abortControllerRef = (0, import_react3.useRef)(null);
|
|
1197
|
+
const loadedThreadIdRef = (0, import_react3.useRef)(void 0);
|
|
1198
|
+
const stop = (0, import_react3.useCallback)(() => {
|
|
1199
|
+
if (abortControllerRef.current) {
|
|
1200
|
+
chatLogger.info("stop streaming", {});
|
|
1201
|
+
chatLogger.debug("abort controller", {
|
|
1202
|
+
hasController: !!abortControllerRef.current
|
|
1203
|
+
});
|
|
1204
|
+
abortControllerRef.current.abort();
|
|
1205
|
+
abortControllerRef.current = null;
|
|
1206
|
+
setIsStreaming(false);
|
|
1207
|
+
chatLogger.debug("streaming stopped");
|
|
1208
|
+
} else {
|
|
1209
|
+
chatLogger.trace("stop called \u2014 no active stream");
|
|
1210
|
+
}
|
|
1211
|
+
}, [chatLogger]);
|
|
1212
|
+
const clear = (0, import_react3.useCallback)(() => {
|
|
509
1213
|
chatLogger.info("clear chat", { messageCount: messages.length });
|
|
510
1214
|
chatLogger.debug("clear", { messageCount: messages.length });
|
|
511
1215
|
stop();
|
|
@@ -517,7 +1221,7 @@ function useChat(options = {}) {
|
|
|
517
1221
|
setPresentedFile(null);
|
|
518
1222
|
loadedThreadIdRef.current = void 0;
|
|
519
1223
|
}, [stop, chatLogger, messages.length]);
|
|
520
|
-
const startNewChat = (0,
|
|
1224
|
+
const startNewChat = (0, import_react3.useCallback)(() => {
|
|
521
1225
|
chatLogger.info("startNewChat \u2014 entering ephemeral mode");
|
|
522
1226
|
stop();
|
|
523
1227
|
setMessages([]);
|
|
@@ -528,13 +1232,9 @@ function useChat(options = {}) {
|
|
|
528
1232
|
setPresentedFile(null);
|
|
529
1233
|
setInput("");
|
|
530
1234
|
loadedThreadIdRef.current = void 0;
|
|
531
|
-
voiceThreadRef.current = void 0;
|
|
532
|
-
voicePrevLenRef.current = 0;
|
|
533
|
-
voiceStreamingIdRef.current = null;
|
|
534
|
-
voiceUserPartialIdRef.current = null;
|
|
535
1235
|
setInternalThreadId(void 0);
|
|
536
1236
|
}, [stop, chatLogger]);
|
|
537
|
-
const loadThreadMessages = (0,
|
|
1237
|
+
const loadThreadMessages = (0, import_react3.useCallback)(
|
|
538
1238
|
async (id) => {
|
|
539
1239
|
chatLogger.debug("loadThreadMessages start", { threadId: id });
|
|
540
1240
|
chatLogger.trace("loadThreadMessages", { threadId: id });
|
|
@@ -595,7 +1295,7 @@ function useChat(options = {}) {
|
|
|
595
1295
|
},
|
|
596
1296
|
[fetchWithAuth, chatLogger]
|
|
597
1297
|
);
|
|
598
|
-
(0,
|
|
1298
|
+
(0, import_react3.useEffect)(() => {
|
|
599
1299
|
if (!effectiveThreadId || isStreaming) {
|
|
600
1300
|
chatLogger.trace("auto-load skipped", { threadId: effectiveThreadId, isStreaming });
|
|
601
1301
|
return;
|
|
@@ -615,152 +1315,17 @@ function useChat(options = {}) {
|
|
|
615
1315
|
chatLogger.debug("loadThreadMessages trigger", { threadId: effectiveThreadId });
|
|
616
1316
|
void loadThreadMessages(effectiveThreadId);
|
|
617
1317
|
}, [effectiveThreadId, isStreaming, messages.length, loadThreadMessages, chatLogger]);
|
|
618
|
-
const
|
|
619
|
-
(0, import_react2.useEffect)(() => {
|
|
620
|
-
if (!voice) return;
|
|
621
|
-
if (voiceThreadRef.current !== effectiveThreadId) {
|
|
622
|
-
voiceThreadRef.current = effectiveThreadId;
|
|
623
|
-
voicePrevLenRef.current = voice.transcript.length;
|
|
624
|
-
voiceStreamingIdRef.current = null;
|
|
625
|
-
voiceUserPartialIdRef.current = null;
|
|
626
|
-
return;
|
|
627
|
-
}
|
|
628
|
-
const isVoiceActive = voice.state !== "idle" && voice.state !== "ended" && voice.state !== "error";
|
|
629
|
-
const curLen = voice.transcript.length;
|
|
630
|
-
if (curLen < voicePrevLenRef.current) {
|
|
631
|
-
voicePrevLenRef.current = 0;
|
|
632
|
-
voiceStreamingIdRef.current = null;
|
|
633
|
-
voiceUserPartialIdRef.current = null;
|
|
634
|
-
}
|
|
635
|
-
if (!isVoiceActive) {
|
|
636
|
-
if (curLen > voicePrevLenRef.current) {
|
|
637
|
-
const pendingLines = voice.transcript.slice(voicePrevLenRef.current);
|
|
638
|
-
voicePrevLenRef.current = curLen;
|
|
639
|
-
for (const line of pendingLines) {
|
|
640
|
-
const text = (line.text || "").trim();
|
|
641
|
-
if (!text) continue;
|
|
642
|
-
const role = line.speaker === "user" ? "user" : "assistant";
|
|
643
|
-
const voiceId = `voice-${line.id}`;
|
|
644
|
-
setMessages((prev) => {
|
|
645
|
-
if (prev.some((m) => m.id === voiceId)) return prev;
|
|
646
|
-
if (prev.some((m) => !m.id.startsWith("voice-") && m.role === role && m.content.trim() === text)) return prev;
|
|
647
|
-
const last = prev[prev.length - 1];
|
|
648
|
-
if (last?.id.startsWith("voice-") && last.role === "assistant" && role === "assistant") {
|
|
649
|
-
const merged = text.startsWith(last.content) ? text : `${last.content} ${text}`.trim();
|
|
650
|
-
return [...prev.slice(0, -1), { ...last, content: merged, isStreaming: false }];
|
|
651
|
-
}
|
|
652
|
-
return [...prev, { id: voiceId, role, content: text, createdAt: /* @__PURE__ */ new Date() }];
|
|
653
|
-
});
|
|
654
|
-
}
|
|
655
|
-
} else {
|
|
656
|
-
voicePrevLenRef.current = voice.transcript.length;
|
|
657
|
-
}
|
|
658
|
-
if (voiceStreamingIdRef.current) {
|
|
659
|
-
const doneId = voiceStreamingIdRef.current;
|
|
660
|
-
voiceStreamingIdRef.current = null;
|
|
661
|
-
setMessages((prev) => prev.map((m) => m.id === doneId ? { ...m, isStreaming: false } : m));
|
|
662
|
-
}
|
|
663
|
-
if (voiceUserPartialIdRef.current) {
|
|
664
|
-
const doneId = voiceUserPartialIdRef.current;
|
|
665
|
-
voiceUserPartialIdRef.current = null;
|
|
666
|
-
setMessages((prev) => prev.map((m) => m.id === doneId ? { ...m, isStreaming: false } : m));
|
|
667
|
-
}
|
|
668
|
-
return;
|
|
669
|
-
}
|
|
670
|
-
if (curLen > voicePrevLenRef.current) {
|
|
671
|
-
const newLines = voice.transcript.slice(voicePrevLenRef.current);
|
|
672
|
-
voicePrevLenRef.current = curLen;
|
|
673
|
-
for (const line of newLines) {
|
|
674
|
-
const text = (line.text || "").trim();
|
|
675
|
-
if (!text) continue;
|
|
676
|
-
const role = line.speaker === "user" ? "user" : "assistant";
|
|
677
|
-
const voiceId = `voice-${line.id}`;
|
|
678
|
-
setMessages((prev) => {
|
|
679
|
-
if (prev.some((m) => m.id === voiceId)) return prev;
|
|
680
|
-
if (prev.some(
|
|
681
|
-
(m) => !m.id.startsWith("voice-") && m.role === role && m.content.trim() === text
|
|
682
|
-
))
|
|
683
|
-
return prev;
|
|
684
|
-
const last = prev[prev.length - 1];
|
|
685
|
-
if (last?.id.startsWith("voice-") && last.role === "assistant" && role === "assistant") {
|
|
686
|
-
const merged = text.startsWith(last.content) ? text : `${last.content} ${text}`.trim();
|
|
687
|
-
return [...prev.slice(0, -1), { ...last, content: merged, isStreaming: false }];
|
|
688
|
-
}
|
|
689
|
-
return [...prev, { id: voiceId, role, content: text, createdAt: /* @__PURE__ */ new Date() }];
|
|
690
|
-
});
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
const agentPartialText = voice.partial?.speaker === "agent" ? voice.partial.text.trim() : "";
|
|
694
|
-
const userPartialText = voice.partial?.speaker === "user" ? voice.partial.text.trim() : "";
|
|
695
|
-
if (agentPartialText) {
|
|
696
|
-
if (voiceUserPartialIdRef.current) {
|
|
697
|
-
const doneId = voiceUserPartialIdRef.current;
|
|
698
|
-
voiceUserPartialIdRef.current = null;
|
|
699
|
-
setMessages((prev) => prev.map((m) => m.id === doneId ? { ...m, isStreaming: false } : m));
|
|
700
|
-
}
|
|
701
|
-
setMessages((prev) => {
|
|
702
|
-
const last = prev[prev.length - 1];
|
|
703
|
-
if (last?.id.startsWith("voice-") && last.role === "assistant") {
|
|
704
|
-
voiceStreamingIdRef.current = last.id;
|
|
705
|
-
return [...prev.slice(0, -1), { ...last, content: agentPartialText, isStreaming: true }];
|
|
706
|
-
}
|
|
707
|
-
const id = voiceStreamingIdRef.current || `voice-partial-${Date.now()}`;
|
|
708
|
-
voiceStreamingIdRef.current = id;
|
|
709
|
-
return [...prev, { id, role: "assistant", content: agentPartialText, isStreaming: true, createdAt: /* @__PURE__ */ new Date() }];
|
|
710
|
-
});
|
|
711
|
-
} else if (userPartialText) {
|
|
712
|
-
if (voiceStreamingIdRef.current) {
|
|
713
|
-
const doneId = voiceStreamingIdRef.current;
|
|
714
|
-
voiceStreamingIdRef.current = null;
|
|
715
|
-
setMessages((prev) => prev.map((m) => m.id === doneId ? { ...m, isStreaming: false } : m));
|
|
716
|
-
}
|
|
717
|
-
setMessages((prev) => {
|
|
718
|
-
const last = prev[prev.length - 1];
|
|
719
|
-
if (last?.id.startsWith("voice-") && last.role === "user" && last.isStreaming) {
|
|
720
|
-
voiceUserPartialIdRef.current = last.id;
|
|
721
|
-
return [...prev.slice(0, -1), { ...last, content: userPartialText, isStreaming: true }];
|
|
722
|
-
}
|
|
723
|
-
const id = voiceUserPartialIdRef.current || `voice-partial-user-${Date.now()}`;
|
|
724
|
-
voiceUserPartialIdRef.current = id;
|
|
725
|
-
return [...prev, { id, role: "user", content: userPartialText, isStreaming: true, createdAt: /* @__PURE__ */ new Date() }];
|
|
726
|
-
});
|
|
727
|
-
} else {
|
|
728
|
-
if (voiceStreamingIdRef.current && voice.state !== "speaking") {
|
|
729
|
-
const doneId = voiceStreamingIdRef.current;
|
|
730
|
-
voiceStreamingIdRef.current = null;
|
|
731
|
-
setMessages((prev) => prev.map((m) => m.id === doneId ? { ...m, isStreaming: false } : m));
|
|
732
|
-
}
|
|
733
|
-
if (voiceUserPartialIdRef.current) {
|
|
734
|
-
const doneId = voiceUserPartialIdRef.current;
|
|
735
|
-
voiceUserPartialIdRef.current = null;
|
|
736
|
-
setMessages((prev) => prev.map((m) => m.id === doneId ? { ...m, isStreaming: false } : m));
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
}, [voice?.transcript, voice?.partial, voice?.state, effectiveThreadId]);
|
|
740
|
-
const doSend = (0, import_react2.useCallback)(
|
|
1318
|
+
const doSend = (0, import_react3.useCallback)(
|
|
741
1319
|
async (prompt, baseMessages, overrideOptions) => {
|
|
742
|
-
const targetAgentId = overrideOptions?.agentId || agentId;
|
|
743
|
-
if (!targetAgentId) {
|
|
744
|
-
const err = new Error("No Agent ID specified for useChat.");
|
|
745
|
-
chatLogger.warn("sendMessage no agentId", {});
|
|
746
|
-
chatLogger.error("sendMessage failed \u2014 no agent", { error: err.message });
|
|
747
|
-
setError(err);
|
|
748
|
-
options.onError?.(err);
|
|
749
|
-
return false;
|
|
750
|
-
}
|
|
751
1320
|
chatLogger.debug("sendMessage start", {
|
|
752
1321
|
promptPreview: prompt.slice(0, 100),
|
|
753
|
-
agentId: targetAgentId,
|
|
754
1322
|
threadId: effectiveThreadId ?? overrideOptions?.threadId,
|
|
755
1323
|
hasResume: !!overrideOptions?.resume,
|
|
756
|
-
hasContextOverride: !!overrideOptions?.contextOverride,
|
|
757
1324
|
messageCount: baseMessages.length
|
|
758
1325
|
});
|
|
759
1326
|
chatLogger.trace("sendMessage details", {
|
|
760
|
-
agentId: targetAgentId,
|
|
761
1327
|
promptPreview: prompt.slice(0, 200),
|
|
762
|
-
hasResume: !!overrideOptions?.resume
|
|
763
|
-
hasContextOverride: !!overrideOptions?.contextOverride
|
|
1328
|
+
hasResume: !!overrideOptions?.resume
|
|
764
1329
|
});
|
|
765
1330
|
const userMessage = {
|
|
766
1331
|
id: `user-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
@@ -797,11 +1362,11 @@ function useChat(options = {}) {
|
|
|
797
1362
|
}));
|
|
798
1363
|
let resolvedThreadId = await overrideOptions?.threadId ?? effectiveThreadId;
|
|
799
1364
|
if (!resolvedThreadId) {
|
|
800
|
-
chatLogger.info("minting real thread for ephemeral chat", {
|
|
1365
|
+
chatLogger.info("minting real thread for ephemeral architect chat", {});
|
|
801
1366
|
const createRes = await fetchWithAuth("/threads", {
|
|
802
1367
|
method: "POST",
|
|
803
1368
|
headers: { "Content-Type": "application/json" },
|
|
804
|
-
body: JSON.stringify({ agentId:
|
|
1369
|
+
body: JSON.stringify({ agentId: ARCHITECT_AGENT_ID })
|
|
805
1370
|
});
|
|
806
1371
|
if (!createRes.ok) throw new Error(`Failed to create thread: ${createRes.statusText}`);
|
|
807
1372
|
const createBody = await createRes.json();
|
|
@@ -811,42 +1376,34 @@ function useChat(options = {}) {
|
|
|
811
1376
|
setInternalThreadId(resolvedThreadId);
|
|
812
1377
|
loadedThreadIdRef.current = resolvedThreadId;
|
|
813
1378
|
options.onThreadCreated?.(resolvedThreadId);
|
|
814
|
-
chatLogger.info("ephemeral chat minted", { threadId: resolvedThreadId });
|
|
1379
|
+
chatLogger.info("ephemeral architect chat minted", { threadId: resolvedThreadId });
|
|
815
1380
|
}
|
|
816
1381
|
chatLogger.trace("resolved threadId", { threadId: resolvedThreadId });
|
|
817
1382
|
const token = getAuthToken ? await getAuthToken() : null;
|
|
818
|
-
const resolvedHookContext = typeof options.context === "function" ? options.context() : options.context;
|
|
819
|
-
const mergedContext = { ...resolvedHookContext, ...overrideOptions?.context };
|
|
820
|
-
const hasContext = Object.keys(mergedContext).length > 0;
|
|
821
1383
|
chatLogger.debug("opening SSE stream", {
|
|
822
|
-
agentId: targetAgentId,
|
|
823
1384
|
hasToken: !!token,
|
|
824
|
-
hasThreadId: !!resolvedThreadId
|
|
825
|
-
hasContext
|
|
1385
|
+
hasThreadId: !!resolvedThreadId
|
|
826
1386
|
});
|
|
827
1387
|
const stream = await openSSEStream({
|
|
828
|
-
url: `${baseUrl}/
|
|
1388
|
+
url: `${baseUrl}/architect`,
|
|
829
1389
|
headers: {
|
|
830
1390
|
"Content-Type": "application/json",
|
|
831
1391
|
...token ? { Authorization: `Bearer ${token}` } : {}
|
|
832
1392
|
},
|
|
833
1393
|
body: JSON.stringify({
|
|
834
|
-
agentId: targetAgentId,
|
|
835
1394
|
messages: payloadMessages,
|
|
836
1395
|
threadId: resolvedThreadId,
|
|
837
|
-
resume: overrideOptions?.resume
|
|
838
|
-
contextOverride: overrideOptions?.contextOverride,
|
|
839
|
-
...hasContext ? { context: mergedContext } : {}
|
|
1396
|
+
resume: overrideOptions?.resume
|
|
840
1397
|
}),
|
|
841
1398
|
signal: controller.signal
|
|
842
1399
|
});
|
|
843
1400
|
if (!stream.ok) {
|
|
844
1401
|
chatLogger.warn("SSE stream not ok", { status: stream.status, errorText: stream.errorText });
|
|
845
|
-
chatLogger.error("
|
|
846
|
-
throw new Error(`
|
|
1402
|
+
chatLogger.error("architect stream failed", { status: stream.status, error: stream.errorText });
|
|
1403
|
+
throw new Error(`Architect error (${stream.status}): ${stream.errorText ?? "Stream failed"}`);
|
|
847
1404
|
}
|
|
848
|
-
chatLogger.debug("SSE stream opened", {
|
|
849
|
-
chatLogger.info("
|
|
1405
|
+
chatLogger.debug("SSE stream opened", { status: stream.status });
|
|
1406
|
+
chatLogger.info("architect stream started", { threadId: resolvedThreadId });
|
|
850
1407
|
const reader = stream.reader;
|
|
851
1408
|
let buffer = "";
|
|
852
1409
|
let accumulatedText = "";
|
|
@@ -1008,20 +1565,20 @@ function useChat(options = {}) {
|
|
|
1008
1565
|
toolCalls: Array.from(toolCallsMap.values())
|
|
1009
1566
|
};
|
|
1010
1567
|
setMessages((prev) => prev.map((msg) => msg.id === assistantMessageId ? finalMessage : msg));
|
|
1011
|
-
chatLogger.info("sendMessage succeeded", {
|
|
1012
|
-
chatLogger.debug("sendMessage completed", {
|
|
1568
|
+
chatLogger.info("sendMessage succeeded", { textLength: accumulatedText.length, toolCallCount: toolCallsMap.size });
|
|
1569
|
+
chatLogger.debug("sendMessage completed", { textLength: accumulatedText.length, eventCount: toolCallsMap.size + 1 });
|
|
1013
1570
|
options.onFinish?.(finalMessage);
|
|
1014
1571
|
return true;
|
|
1015
1572
|
} catch (err) {
|
|
1016
1573
|
if (controller.signal.aborted) {
|
|
1017
|
-
chatLogger.info("sendMessage aborted", {
|
|
1018
|
-
chatLogger.debug("stream aborted", {
|
|
1574
|
+
chatLogger.info("sendMessage aborted", {});
|
|
1575
|
+
chatLogger.debug("stream aborted", {});
|
|
1019
1576
|
setMessages((prev) => prev.map((msg) => msg.id === assistantMessageId ? { ...msg, isStreaming: false } : msg));
|
|
1020
1577
|
return false;
|
|
1021
1578
|
}
|
|
1022
1579
|
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
1023
|
-
chatLogger.warn("sendMessage failed", {
|
|
1024
|
-
chatLogger.error("sendMessage error", {
|
|
1580
|
+
chatLogger.warn("sendMessage failed", { error: errorObj.message });
|
|
1581
|
+
chatLogger.error("sendMessage error", { error: errorObj.message });
|
|
1025
1582
|
setError(errorObj);
|
|
1026
1583
|
options.onError?.(errorObj);
|
|
1027
1584
|
setMessages(
|
|
@@ -1034,13 +1591,13 @@ function useChat(options = {}) {
|
|
|
1034
1591
|
setIsStreaming(false);
|
|
1035
1592
|
abortControllerRef.current = null;
|
|
1036
1593
|
finalizeReasoning();
|
|
1037
|
-
chatLogger.debug("sendMessage finally", {
|
|
1038
|
-
chatLogger.trace("sendMessage end", {
|
|
1594
|
+
chatLogger.debug("sendMessage finally", { isStreaming: false });
|
|
1595
|
+
chatLogger.trace("sendMessage end", {});
|
|
1039
1596
|
}
|
|
1040
1597
|
},
|
|
1041
|
-
[
|
|
1598
|
+
[baseUrl, getAuthToken, fetchWithAuth, options, chatLogger, effectiveThreadId]
|
|
1042
1599
|
);
|
|
1043
|
-
const sendMessage = (0,
|
|
1600
|
+
const sendMessage = (0, import_react3.useCallback)(
|
|
1044
1601
|
async (contentToSend, overrideOptions) => {
|
|
1045
1602
|
const prompt = (contentToSend ?? input).trim();
|
|
1046
1603
|
if (!prompt || isStreaming) {
|
|
@@ -1057,14 +1614,14 @@ function useChat(options = {}) {
|
|
|
1057
1614
|
},
|
|
1058
1615
|
[input, isStreaming, messages, doSend, chatLogger]
|
|
1059
1616
|
);
|
|
1060
|
-
const handleInputChange = (0,
|
|
1617
|
+
const handleInputChange = (0, import_react3.useCallback)(
|
|
1061
1618
|
(e) => {
|
|
1062
1619
|
chatLogger.trace("handleInputChange", { length: e.target.value.length });
|
|
1063
1620
|
setInput(e.target.value);
|
|
1064
1621
|
},
|
|
1065
1622
|
[chatLogger]
|
|
1066
1623
|
);
|
|
1067
|
-
const handleSubmit = (0,
|
|
1624
|
+
const handleSubmit = (0, import_react3.useCallback)(
|
|
1068
1625
|
(e) => {
|
|
1069
1626
|
if (e) e.preventDefault();
|
|
1070
1627
|
chatLogger.debug("handleSubmit", {});
|
|
@@ -1072,7 +1629,7 @@ function useChat(options = {}) {
|
|
|
1072
1629
|
},
|
|
1073
1630
|
[sendMessage, chatLogger]
|
|
1074
1631
|
);
|
|
1075
|
-
const reload = (0,
|
|
1632
|
+
const reload = (0, import_react3.useCallback)(async () => {
|
|
1076
1633
|
if (messages.length === 0 || isStreaming) {
|
|
1077
1634
|
chatLogger.trace("reload skipped", {
|
|
1078
1635
|
messageCount: messages.length,
|
|
@@ -1099,7 +1656,7 @@ function useChat(options = {}) {
|
|
|
1099
1656
|
});
|
|
1100
1657
|
return doSend(lastUserMessage.content, truncated);
|
|
1101
1658
|
}, [isStreaming, messages, doSend, chatLogger]);
|
|
1102
|
-
const resumeInterrupt = (0,
|
|
1659
|
+
const resumeInterrupt = (0, import_react3.useCallback)(
|
|
1103
1660
|
(resume, displayContent) => {
|
|
1104
1661
|
chatLogger.info("resumeInterrupt", {
|
|
1105
1662
|
kind: resume.decisions ? "hitl" : "clarification",
|
|
@@ -1109,11 +1666,11 @@ function useChat(options = {}) {
|
|
|
1109
1666
|
},
|
|
1110
1667
|
[sendMessage, chatLogger]
|
|
1111
1668
|
);
|
|
1112
|
-
const dismissPresentedFile = (0,
|
|
1669
|
+
const dismissPresentedFile = (0, import_react3.useCallback)(() => {
|
|
1113
1670
|
chatLogger.debug("dismissPresentedFile", {});
|
|
1114
1671
|
setPresentedFile(null);
|
|
1115
1672
|
}, [chatLogger]);
|
|
1116
|
-
const openWorkspaceFile = (0,
|
|
1673
|
+
const openWorkspaceFile = (0, import_react3.useCallback)(
|
|
1117
1674
|
(path) => {
|
|
1118
1675
|
chatLogger.debug("openWorkspaceFile", { path });
|
|
1119
1676
|
setPresentedFile({
|
|
@@ -1142,7 +1699,6 @@ function useChat(options = {}) {
|
|
|
1142
1699
|
presentedFile,
|
|
1143
1700
|
dismissPresentedFile,
|
|
1144
1701
|
openWorkspaceFile,
|
|
1145
|
-
sandboxCommands,
|
|
1146
1702
|
stop,
|
|
1147
1703
|
reload,
|
|
1148
1704
|
clear,
|
|
@@ -1155,16 +1711,16 @@ function useChat(options = {}) {
|
|
|
1155
1711
|
}
|
|
1156
1712
|
|
|
1157
1713
|
// src/hooks/useMemory.ts
|
|
1158
|
-
var
|
|
1714
|
+
var import_react4 = require("react");
|
|
1159
1715
|
function useMemory(autoFetch = true) {
|
|
1160
1716
|
const { fetchWithAuth } = usePersonaContext();
|
|
1161
|
-
const [memory, setMemory] = (0,
|
|
1717
|
+
const [memory, setMemory] = (0, import_react4.useState)({
|
|
1162
1718
|
userFiles: [],
|
|
1163
1719
|
agentMemories: []
|
|
1164
1720
|
});
|
|
1165
|
-
const [isLoading, setIsLoading] = (0,
|
|
1166
|
-
const [error, setError] = (0,
|
|
1167
|
-
const fetchMemory = (0,
|
|
1721
|
+
const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
|
|
1722
|
+
const [error, setError] = (0, import_react4.useState)(null);
|
|
1723
|
+
const fetchMemory = (0, import_react4.useCallback)(async () => {
|
|
1168
1724
|
setIsLoading(true);
|
|
1169
1725
|
setError(null);
|
|
1170
1726
|
try {
|
|
@@ -1183,7 +1739,7 @@ function useMemory(autoFetch = true) {
|
|
|
1183
1739
|
setIsLoading(false);
|
|
1184
1740
|
}
|
|
1185
1741
|
}, [fetchWithAuth]);
|
|
1186
|
-
const getFile = (0,
|
|
1742
|
+
const getFile = (0, import_react4.useCallback)(
|
|
1187
1743
|
async (params) => {
|
|
1188
1744
|
const query = new URLSearchParams({ path: params.path });
|
|
1189
1745
|
if (params.scope) query.set("scope", params.scope);
|
|
@@ -1195,7 +1751,7 @@ function useMemory(autoFetch = true) {
|
|
|
1195
1751
|
},
|
|
1196
1752
|
[fetchWithAuth]
|
|
1197
1753
|
);
|
|
1198
|
-
const writeFile = (0,
|
|
1754
|
+
const writeFile = (0, import_react4.useCallback)(
|
|
1199
1755
|
async (params) => {
|
|
1200
1756
|
const res = await fetchWithAuth("/memory/file", {
|
|
1201
1757
|
method: "PUT",
|
|
@@ -1210,7 +1766,7 @@ function useMemory(autoFetch = true) {
|
|
|
1210
1766
|
},
|
|
1211
1767
|
[fetchWithAuth, fetchMemory]
|
|
1212
1768
|
);
|
|
1213
|
-
const deleteFile = (0,
|
|
1769
|
+
const deleteFile = (0, import_react4.useCallback)(
|
|
1214
1770
|
async (params) => {
|
|
1215
1771
|
const query = new URLSearchParams({ path: params.path });
|
|
1216
1772
|
if (params.scope) query.set("scope", params.scope);
|
|
@@ -1224,7 +1780,7 @@ function useMemory(autoFetch = true) {
|
|
|
1224
1780
|
},
|
|
1225
1781
|
[fetchWithAuth, fetchMemory]
|
|
1226
1782
|
);
|
|
1227
|
-
(0,
|
|
1783
|
+
(0, import_react4.useEffect)(() => {
|
|
1228
1784
|
if (autoFetch) {
|
|
1229
1785
|
void fetchMemory();
|
|
1230
1786
|
}
|
|
@@ -1241,13 +1797,13 @@ function useMemory(autoFetch = true) {
|
|
|
1241
1797
|
}
|
|
1242
1798
|
|
|
1243
1799
|
// src/hooks/useThreads.ts
|
|
1244
|
-
var
|
|
1800
|
+
var import_react5 = require("react");
|
|
1245
1801
|
function useThreads(autoFetch = true) {
|
|
1246
1802
|
const { fetchWithAuth, defaultAgentId } = usePersonaContext();
|
|
1247
|
-
const [threads, setThreads] = (0,
|
|
1248
|
-
const [isLoading, setIsLoading] = (0,
|
|
1249
|
-
const [error, setError] = (0,
|
|
1250
|
-
const fetchThreads = (0,
|
|
1803
|
+
const [threads, setThreads] = (0, import_react5.useState)([]);
|
|
1804
|
+
const [isLoading, setIsLoading] = (0, import_react5.useState)(false);
|
|
1805
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
1806
|
+
const fetchThreads = (0, import_react5.useCallback)(async () => {
|
|
1251
1807
|
setIsLoading(true);
|
|
1252
1808
|
setError(null);
|
|
1253
1809
|
try {
|
|
@@ -1265,7 +1821,7 @@ function useThreads(autoFetch = true) {
|
|
|
1265
1821
|
setIsLoading(false);
|
|
1266
1822
|
}
|
|
1267
1823
|
}, [fetchWithAuth]);
|
|
1268
|
-
const createThread = (0,
|
|
1824
|
+
const createThread = (0, import_react5.useCallback)(
|
|
1269
1825
|
async (agentId) => {
|
|
1270
1826
|
const targetAgentId = agentId || defaultAgentId;
|
|
1271
1827
|
const res = await fetchWithAuth("/threads", {
|
|
@@ -1282,7 +1838,7 @@ function useThreads(autoFetch = true) {
|
|
|
1282
1838
|
},
|
|
1283
1839
|
[fetchWithAuth, defaultAgentId, fetchThreads]
|
|
1284
1840
|
);
|
|
1285
|
-
const deleteThread = (0,
|
|
1841
|
+
const deleteThread = (0, import_react5.useCallback)(
|
|
1286
1842
|
async (threadId) => {
|
|
1287
1843
|
const res = await fetchWithAuth(`/threads/${threadId}`, {
|
|
1288
1844
|
method: "DELETE"
|
|
@@ -1293,7 +1849,7 @@ function useThreads(autoFetch = true) {
|
|
|
1293
1849
|
},
|
|
1294
1850
|
[fetchWithAuth]
|
|
1295
1851
|
);
|
|
1296
|
-
const bulkDeleteThreads = (0,
|
|
1852
|
+
const bulkDeleteThreads = (0, import_react5.useCallback)(
|
|
1297
1853
|
async (threadIds) => {
|
|
1298
1854
|
const res = await fetchWithAuth("/threads/bulk-delete", {
|
|
1299
1855
|
method: "POST",
|
|
@@ -1310,13 +1866,13 @@ function useThreads(autoFetch = true) {
|
|
|
1310
1866
|
},
|
|
1311
1867
|
[fetchWithAuth]
|
|
1312
1868
|
);
|
|
1313
|
-
const deleteAllThreads = (0,
|
|
1869
|
+
const deleteAllThreads = (0, import_react5.useCallback)(async () => {
|
|
1314
1870
|
const ids = threads.map((t) => t._id);
|
|
1315
1871
|
for (let i = 0; i < ids.length; i += 100) {
|
|
1316
1872
|
await bulkDeleteThreads(ids.slice(i, i + 100));
|
|
1317
1873
|
}
|
|
1318
1874
|
}, [threads, bulkDeleteThreads]);
|
|
1319
|
-
const updateThread = (0,
|
|
1875
|
+
const updateThread = (0, import_react5.useCallback)(
|
|
1320
1876
|
async (threadId, input) => {
|
|
1321
1877
|
const res = await fetchWithAuth(`/threads/${threadId}`, {
|
|
1322
1878
|
method: "PATCH",
|
|
@@ -1334,11 +1890,11 @@ function useThreads(autoFetch = true) {
|
|
|
1334
1890
|
},
|
|
1335
1891
|
[fetchWithAuth]
|
|
1336
1892
|
);
|
|
1337
|
-
const renameThread = (0,
|
|
1893
|
+
const renameThread = (0, import_react5.useCallback)(
|
|
1338
1894
|
(threadId, title) => updateThread(threadId, { title }),
|
|
1339
1895
|
[updateThread]
|
|
1340
1896
|
);
|
|
1341
|
-
const resetThread = (0,
|
|
1897
|
+
const resetThread = (0, import_react5.useCallback)(
|
|
1342
1898
|
async (threadId) => {
|
|
1343
1899
|
const res = await fetchWithAuth(`/threads/${threadId}/reset`, {
|
|
1344
1900
|
method: "POST"
|
|
@@ -1353,7 +1909,7 @@ function useThreads(autoFetch = true) {
|
|
|
1353
1909
|
},
|
|
1354
1910
|
[fetchWithAuth]
|
|
1355
1911
|
);
|
|
1356
|
-
const getThread = (0,
|
|
1912
|
+
const getThread = (0, import_react5.useCallback)(
|
|
1357
1913
|
async (threadId) => {
|
|
1358
1914
|
const res = await fetchWithAuth(`/threads/${threadId}`);
|
|
1359
1915
|
if (!res.ok) throw new Error(`Failed to fetch thread: ${res.statusText}`);
|
|
@@ -1362,7 +1918,7 @@ function useThreads(autoFetch = true) {
|
|
|
1362
1918
|
},
|
|
1363
1919
|
[fetchWithAuth]
|
|
1364
1920
|
);
|
|
1365
|
-
(0,
|
|
1921
|
+
(0, import_react5.useEffect)(() => {
|
|
1366
1922
|
if (autoFetch) {
|
|
1367
1923
|
void fetchThreads();
|
|
1368
1924
|
}
|
|
@@ -1384,7 +1940,7 @@ function useThreads(autoFetch = true) {
|
|
|
1384
1940
|
}
|
|
1385
1941
|
|
|
1386
1942
|
// src/hooks/useVoice.ts
|
|
1387
|
-
var
|
|
1943
|
+
var import_react6 = require("react");
|
|
1388
1944
|
|
|
1389
1945
|
// src/hooks/voiceWorklets.ts
|
|
1390
1946
|
var RECORDER_WORKLET_SOURCE = `
|
|
@@ -1487,42 +2043,42 @@ function mergeTranscriptText(prev, next) {
|
|
|
1487
2043
|
}
|
|
1488
2044
|
function useVoice(options = {}) {
|
|
1489
2045
|
const { defaultAgentId, fetchWithAuth, logger } = usePersonaContext();
|
|
1490
|
-
const voiceLogger = (0,
|
|
2046
|
+
const voiceLogger = (0, import_react6.useMemo)(() => logger.child("voice"), [logger]);
|
|
1491
2047
|
const agentId = options.agentId || defaultAgentId;
|
|
1492
2048
|
const threadId = options.threadId;
|
|
1493
2049
|
const contextOverride = options.contextOverride;
|
|
1494
2050
|
const context = options.context;
|
|
1495
|
-
const [state, setState] = (0,
|
|
1496
|
-
const [isMuted, setIsMuted] = (0,
|
|
1497
|
-
const [transcript, setTranscript] = (0,
|
|
2051
|
+
const [state, setState] = (0, import_react6.useState)("idle");
|
|
2052
|
+
const [isMuted, setIsMuted] = (0, import_react6.useState)(false);
|
|
2053
|
+
const [transcript, setTranscript] = (0, import_react6.useState)(
|
|
1498
2054
|
[]
|
|
1499
2055
|
);
|
|
1500
|
-
const [partial, setPartial] = (0,
|
|
2056
|
+
const [partial, setPartial] = (0, import_react6.useState)(
|
|
1501
2057
|
null
|
|
1502
2058
|
);
|
|
1503
|
-
const [toolCalls, setToolCalls] = (0,
|
|
1504
|
-
const [error, setError] = (0,
|
|
1505
|
-
const [endReason, setEndReason] = (0,
|
|
2059
|
+
const [toolCalls, setToolCalls] = (0, import_react6.useState)([]);
|
|
2060
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
2061
|
+
const [endReason, setEndReason] = (0, import_react6.useState)(
|
|
1506
2062
|
null
|
|
1507
2063
|
);
|
|
1508
|
-
const wsRef = (0,
|
|
1509
|
-
const streamRef = (0,
|
|
1510
|
-
const inputCtxRef = (0,
|
|
1511
|
-
const outputCtxRef = (0,
|
|
1512
|
-
const recorderNodeRef = (0,
|
|
1513
|
-
const playerNodeRef = (0,
|
|
1514
|
-
const acceptedTurnSeqRef = (0,
|
|
1515
|
-
const mountedRef = (0,
|
|
1516
|
-
const lastFinalTurnRef = (0,
|
|
2064
|
+
const wsRef = (0, import_react6.useRef)(null);
|
|
2065
|
+
const streamRef = (0, import_react6.useRef)(null);
|
|
2066
|
+
const inputCtxRef = (0, import_react6.useRef)(null);
|
|
2067
|
+
const outputCtxRef = (0, import_react6.useRef)(null);
|
|
2068
|
+
const recorderNodeRef = (0, import_react6.useRef)(null);
|
|
2069
|
+
const playerNodeRef = (0, import_react6.useRef)(null);
|
|
2070
|
+
const acceptedTurnSeqRef = (0, import_react6.useRef)(0);
|
|
2071
|
+
const mountedRef = (0, import_react6.useRef)(true);
|
|
2072
|
+
const lastFinalTurnRef = (0, import_react6.useRef)(
|
|
1517
2073
|
null
|
|
1518
2074
|
);
|
|
1519
|
-
(0,
|
|
2075
|
+
(0, import_react6.useEffect)(() => {
|
|
1520
2076
|
mountedRef.current = true;
|
|
1521
2077
|
return () => {
|
|
1522
2078
|
mountedRef.current = false;
|
|
1523
2079
|
};
|
|
1524
2080
|
}, []);
|
|
1525
|
-
const teardownAudio = (0,
|
|
2081
|
+
const teardownAudio = (0, import_react6.useCallback)(() => {
|
|
1526
2082
|
try {
|
|
1527
2083
|
streamRef.current?.getTracks().forEach((track) => track.stop());
|
|
1528
2084
|
} catch {
|
|
@@ -1549,7 +2105,7 @@ function useVoice(options = {}) {
|
|
|
1549
2105
|
}
|
|
1550
2106
|
outputCtxRef.current = null;
|
|
1551
2107
|
}, []);
|
|
1552
|
-
const stop = (0,
|
|
2108
|
+
const stop = (0, import_react6.useCallback)(() => {
|
|
1553
2109
|
voiceLogger.debug("stop() called");
|
|
1554
2110
|
try {
|
|
1555
2111
|
wsRef.current?.close(1e3, "client_stop");
|
|
@@ -1559,8 +2115,8 @@ function useVoice(options = {}) {
|
|
|
1559
2115
|
teardownAudio();
|
|
1560
2116
|
if (mountedRef.current) setState("idle");
|
|
1561
2117
|
}, [teardownAudio, voiceLogger]);
|
|
1562
|
-
(0,
|
|
1563
|
-
const startCapture = (0,
|
|
2118
|
+
(0, import_react6.useEffect)(() => stop, [stop]);
|
|
2119
|
+
const startCapture = (0, import_react6.useCallback)(async (inputSampleRate) => {
|
|
1564
2120
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
1565
2121
|
audio: {
|
|
1566
2122
|
echoCancellation: true,
|
|
@@ -1586,7 +2142,7 @@ function useVoice(options = {}) {
|
|
|
1586
2142
|
recorderNodeRef.current = recorderNode;
|
|
1587
2143
|
source.connect(recorderNode);
|
|
1588
2144
|
}, []);
|
|
1589
|
-
const setupPlayback = (0,
|
|
2145
|
+
const setupPlayback = (0, import_react6.useCallback)(async (outputSampleRate) => {
|
|
1590
2146
|
const outputCtx = new AudioContext({ sampleRate: outputSampleRate });
|
|
1591
2147
|
outputCtxRef.current = outputCtx;
|
|
1592
2148
|
await outputCtx.audioWorklet.addModule(playerWorkletUrl());
|
|
@@ -1594,7 +2150,7 @@ function useVoice(options = {}) {
|
|
|
1594
2150
|
playerNode.connect(outputCtx.destination);
|
|
1595
2151
|
playerNodeRef.current = playerNode;
|
|
1596
2152
|
}, []);
|
|
1597
|
-
const upsertToolCall = (0,
|
|
2153
|
+
const upsertToolCall = (0, import_react6.useCallback)(
|
|
1598
2154
|
(id, patch) => {
|
|
1599
2155
|
setToolCalls((prev) => {
|
|
1600
2156
|
const idx = prev.findIndex((t) => t.id === id);
|
|
@@ -1606,7 +2162,7 @@ function useVoice(options = {}) {
|
|
|
1606
2162
|
},
|
|
1607
2163
|
[]
|
|
1608
2164
|
);
|
|
1609
|
-
const handleTranscript = (0,
|
|
2165
|
+
const handleTranscript = (0, import_react6.useCallback)((value) => {
|
|
1610
2166
|
const { speaker, text, isFinal, turnSeq } = value;
|
|
1611
2167
|
if (!isFinal) {
|
|
1612
2168
|
setPartial({ id: "partial", speaker, text });
|
|
@@ -1629,7 +2185,7 @@ function useVoice(options = {}) {
|
|
|
1629
2185
|
});
|
|
1630
2186
|
lastFinalTurnRef.current = { speaker, turnSeq };
|
|
1631
2187
|
}, []);
|
|
1632
|
-
const handleCustomEvent = (0,
|
|
2188
|
+
const handleCustomEvent = (0, import_react6.useCallback)(
|
|
1633
2189
|
(name, value) => {
|
|
1634
2190
|
switch (name) {
|
|
1635
2191
|
case "voice_session_ready":
|
|
@@ -1687,7 +2243,7 @@ function useVoice(options = {}) {
|
|
|
1687
2243
|
},
|
|
1688
2244
|
[handleTranscript, setupPlayback, startCapture, teardownAudio, voiceLogger]
|
|
1689
2245
|
);
|
|
1690
|
-
const handleMessage = (0,
|
|
2246
|
+
const handleMessage = (0, import_react6.useCallback)(
|
|
1691
2247
|
(event) => {
|
|
1692
2248
|
if (typeof event.data !== "string") {
|
|
1693
2249
|
const buf = event.data;
|
|
@@ -1745,7 +2301,7 @@ function useVoice(options = {}) {
|
|
|
1745
2301
|
},
|
|
1746
2302
|
[handleCustomEvent, upsertToolCall, voiceLogger]
|
|
1747
2303
|
);
|
|
1748
|
-
const start = (0,
|
|
2304
|
+
const start = (0, import_react6.useCallback)(async () => {
|
|
1749
2305
|
if (!agentId) {
|
|
1750
2306
|
const err = new Error(
|
|
1751
2307
|
"useVoice: no agentId provided and no defaultAgentId set on PersonaProvider"
|
|
@@ -1812,17 +2368,17 @@ function useVoice(options = {}) {
|
|
|
1812
2368
|
teardownAudio();
|
|
1813
2369
|
}
|
|
1814
2370
|
}, [agentId, threadId, contextOverride, context, fetchWithAuth, handleMessage, teardownAudio, voiceLogger]);
|
|
1815
|
-
const mute = (0,
|
|
2371
|
+
const mute = (0, import_react6.useCallback)((muted) => {
|
|
1816
2372
|
setIsMuted(muted);
|
|
1817
2373
|
streamRef.current?.getAudioTracks().forEach((track) => {
|
|
1818
2374
|
track.enabled = !muted;
|
|
1819
2375
|
});
|
|
1820
2376
|
}, []);
|
|
1821
|
-
const sendText = (0,
|
|
2377
|
+
const sendText = (0, import_react6.useCallback)((text) => {
|
|
1822
2378
|
if (!text?.trim() || wsRef.current?.readyState !== WebSocket.OPEN) return;
|
|
1823
2379
|
wsRef.current.send(JSON.stringify({ type: "voice.text", text }));
|
|
1824
2380
|
}, []);
|
|
1825
|
-
const updateContext = (0,
|
|
2381
|
+
const updateContext = (0, import_react6.useCallback)((newContext) => {
|
|
1826
2382
|
if (wsRef.current?.readyState !== WebSocket.OPEN) return;
|
|
1827
2383
|
wsRef.current.send(JSON.stringify({ type: "voice.context", context: newContext }));
|
|
1828
2384
|
}, []);
|
|
@@ -1843,14 +2399,14 @@ function useVoice(options = {}) {
|
|
|
1843
2399
|
}
|
|
1844
2400
|
|
|
1845
2401
|
// src/hooks/useFiles.ts
|
|
1846
|
-
var
|
|
2402
|
+
var import_react7 = require("react");
|
|
1847
2403
|
function useFiles(autoFetch = true) {
|
|
1848
2404
|
const { fetchWithAuth } = usePersonaContext();
|
|
1849
|
-
const [files, setFiles] = (0,
|
|
1850
|
-
const [isLoading, setIsLoading] = (0,
|
|
1851
|
-
const [isUploading, setIsUploading] = (0,
|
|
1852
|
-
const [error, setError] = (0,
|
|
1853
|
-
const fetchFiles = (0,
|
|
2405
|
+
const [files, setFiles] = (0, import_react7.useState)([]);
|
|
2406
|
+
const [isLoading, setIsLoading] = (0, import_react7.useState)(false);
|
|
2407
|
+
const [isUploading, setIsUploading] = (0, import_react7.useState)(false);
|
|
2408
|
+
const [error, setError] = (0, import_react7.useState)(null);
|
|
2409
|
+
const fetchFiles = (0, import_react7.useCallback)(async () => {
|
|
1854
2410
|
setIsLoading(true);
|
|
1855
2411
|
setError(null);
|
|
1856
2412
|
try {
|
|
@@ -1868,7 +2424,7 @@ function useFiles(autoFetch = true) {
|
|
|
1868
2424
|
setIsLoading(false);
|
|
1869
2425
|
}
|
|
1870
2426
|
}, [fetchWithAuth]);
|
|
1871
|
-
const uploadFile = (0,
|
|
2427
|
+
const uploadFile = (0, import_react7.useCallback)(
|
|
1872
2428
|
async (fileOrFormData) => {
|
|
1873
2429
|
setIsUploading(true);
|
|
1874
2430
|
setError(null);
|
|
@@ -1901,7 +2457,7 @@ function useFiles(autoFetch = true) {
|
|
|
1901
2457
|
},
|
|
1902
2458
|
[fetchWithAuth, fetchFiles]
|
|
1903
2459
|
);
|
|
1904
|
-
const deleteFile = (0,
|
|
2460
|
+
const deleteFile = (0, import_react7.useCallback)(
|
|
1905
2461
|
async (fileId) => {
|
|
1906
2462
|
const res = await fetchWithAuth(`/files/${fileId}`, { method: "DELETE" });
|
|
1907
2463
|
if (!res.ok) throw new Error(`Failed to delete file: ${res.statusText}`);
|
|
@@ -1909,7 +2465,7 @@ function useFiles(autoFetch = true) {
|
|
|
1909
2465
|
},
|
|
1910
2466
|
[fetchWithAuth]
|
|
1911
2467
|
);
|
|
1912
|
-
const bulkDeleteFiles = (0,
|
|
2468
|
+
const bulkDeleteFiles = (0, import_react7.useCallback)(
|
|
1913
2469
|
async (fileIds) => {
|
|
1914
2470
|
const res = await fetchWithAuth("/files/bulk-delete", {
|
|
1915
2471
|
method: "POST",
|
|
@@ -1924,10 +2480,10 @@ function useFiles(autoFetch = true) {
|
|
|
1924
2480
|
},
|
|
1925
2481
|
[fetchWithAuth]
|
|
1926
2482
|
);
|
|
1927
|
-
const getDownloadUrl = (0,
|
|
2483
|
+
const getDownloadUrl = (0, import_react7.useCallback)((fileId) => {
|
|
1928
2484
|
return `/files/${fileId}`;
|
|
1929
2485
|
}, []);
|
|
1930
|
-
(0,
|
|
2486
|
+
(0, import_react7.useEffect)(() => {
|
|
1931
2487
|
if (autoFetch) {
|
|
1932
2488
|
void fetchFiles();
|
|
1933
2489
|
}
|
|
@@ -1946,13 +2502,13 @@ function useFiles(autoFetch = true) {
|
|
|
1946
2502
|
}
|
|
1947
2503
|
|
|
1948
2504
|
// src/hooks/useAgents.ts
|
|
1949
|
-
var
|
|
2505
|
+
var import_react8 = require("react");
|
|
1950
2506
|
function useAgents(autoFetch = true) {
|
|
1951
2507
|
const { fetchWithAuth } = usePersonaContext();
|
|
1952
|
-
const [agents, setAgents] = (0,
|
|
1953
|
-
const [isLoading, setIsLoading] = (0,
|
|
1954
|
-
const [error, setError] = (0,
|
|
1955
|
-
const fetchAgents = (0,
|
|
2508
|
+
const [agents, setAgents] = (0, import_react8.useState)([]);
|
|
2509
|
+
const [isLoading, setIsLoading] = (0, import_react8.useState)(false);
|
|
2510
|
+
const [error, setError] = (0, import_react8.useState)(null);
|
|
2511
|
+
const fetchAgents = (0, import_react8.useCallback)(async () => {
|
|
1956
2512
|
setIsLoading(true);
|
|
1957
2513
|
setError(null);
|
|
1958
2514
|
try {
|
|
@@ -1970,7 +2526,7 @@ function useAgents(autoFetch = true) {
|
|
|
1970
2526
|
setIsLoading(false);
|
|
1971
2527
|
}
|
|
1972
2528
|
}, [fetchWithAuth]);
|
|
1973
|
-
(0,
|
|
2529
|
+
(0, import_react8.useEffect)(() => {
|
|
1974
2530
|
if (autoFetch) {
|
|
1975
2531
|
void fetchAgents();
|
|
1976
2532
|
}
|
|
@@ -1984,13 +2540,13 @@ function useAgents(autoFetch = true) {
|
|
|
1984
2540
|
}
|
|
1985
2541
|
|
|
1986
2542
|
// src/hooks/useConnection.ts
|
|
1987
|
-
var
|
|
2543
|
+
var import_react9 = require("react");
|
|
1988
2544
|
function useConnection(autoCheck = true) {
|
|
1989
2545
|
const { fetchWithAuth } = usePersonaContext();
|
|
1990
|
-
const [health, setHealth] = (0,
|
|
1991
|
-
const [isConnected, setIsConnected] = (0,
|
|
1992
|
-
const [isLoading, setIsLoading] = (0,
|
|
1993
|
-
const checkHealth = (0,
|
|
2546
|
+
const [health, setHealth] = (0, import_react9.useState)(null);
|
|
2547
|
+
const [isConnected, setIsConnected] = (0, import_react9.useState)(false);
|
|
2548
|
+
const [isLoading, setIsLoading] = (0, import_react9.useState)(false);
|
|
2549
|
+
const checkHealth = (0, import_react9.useCallback)(async () => {
|
|
1994
2550
|
setIsLoading(true);
|
|
1995
2551
|
try {
|
|
1996
2552
|
const res = await fetchWithAuth("/health");
|
|
@@ -2009,7 +2565,7 @@ function useConnection(autoCheck = true) {
|
|
|
2009
2565
|
setIsLoading(false);
|
|
2010
2566
|
}
|
|
2011
2567
|
}, [fetchWithAuth]);
|
|
2012
|
-
(0,
|
|
2568
|
+
(0, import_react9.useEffect)(() => {
|
|
2013
2569
|
if (autoCheck) {
|
|
2014
2570
|
void checkHealth();
|
|
2015
2571
|
}
|
|
@@ -2023,15 +2579,15 @@ function useConnection(autoCheck = true) {
|
|
|
2023
2579
|
}
|
|
2024
2580
|
|
|
2025
2581
|
// src/hooks/useMcpConnections.ts
|
|
2026
|
-
var
|
|
2582
|
+
var import_react10 = require("react");
|
|
2027
2583
|
function useMcpConnections(options = {}) {
|
|
2028
2584
|
const { defaultAgentId, fetchWithAuth } = usePersonaContext();
|
|
2029
2585
|
const agentId = options.agentId ?? defaultAgentId;
|
|
2030
2586
|
const autoFetch = options.autoFetch ?? true;
|
|
2031
|
-
const [connections, setConnections] = (0,
|
|
2032
|
-
const [isLoading, setIsLoading] = (0,
|
|
2033
|
-
const [error, setError] = (0,
|
|
2034
|
-
const fetchConnections = (0,
|
|
2587
|
+
const [connections, setConnections] = (0, import_react10.useState)([]);
|
|
2588
|
+
const [isLoading, setIsLoading] = (0, import_react10.useState)(false);
|
|
2589
|
+
const [error, setError] = (0, import_react10.useState)(null);
|
|
2590
|
+
const fetchConnections = (0, import_react10.useCallback)(async () => {
|
|
2035
2591
|
if (!agentId) return [];
|
|
2036
2592
|
setIsLoading(true);
|
|
2037
2593
|
setError(null);
|
|
@@ -2055,7 +2611,7 @@ function useMcpConnections(options = {}) {
|
|
|
2055
2611
|
setIsLoading(false);
|
|
2056
2612
|
}
|
|
2057
2613
|
}, [agentId, fetchWithAuth, options.returnTo]);
|
|
2058
|
-
(0,
|
|
2614
|
+
(0, import_react10.useEffect)(() => {
|
|
2059
2615
|
if (autoFetch) void fetchConnections();
|
|
2060
2616
|
}, [autoFetch, fetchConnections]);
|
|
2061
2617
|
return {
|
|
@@ -2069,11 +2625,11 @@ function useMcpConnections(options = {}) {
|
|
|
2069
2625
|
}
|
|
2070
2626
|
|
|
2071
2627
|
// src/hooks/useMcp.ts
|
|
2072
|
-
var
|
|
2628
|
+
var import_react11 = require("react");
|
|
2073
2629
|
function useMcp(options = {}) {
|
|
2074
2630
|
const { fetchWithAuth } = usePersonaContext();
|
|
2075
2631
|
const defaultMcpId = options.mcpId;
|
|
2076
|
-
const readResource = (0,
|
|
2632
|
+
const readResource = (0, import_react11.useCallback)(
|
|
2077
2633
|
async (uri, mcpId) => {
|
|
2078
2634
|
const id = mcpId ?? defaultMcpId;
|
|
2079
2635
|
if (!id) throw new Error("MCP server ID is required to read resource");
|
|
@@ -2087,7 +2643,7 @@ function useMcp(options = {}) {
|
|
|
2087
2643
|
},
|
|
2088
2644
|
[fetchWithAuth, defaultMcpId]
|
|
2089
2645
|
);
|
|
2090
|
-
const callTool = (0,
|
|
2646
|
+
const callTool = (0, import_react11.useCallback)(
|
|
2091
2647
|
async (name, args, mcpId) => {
|
|
2092
2648
|
const id = mcpId ?? defaultMcpId;
|
|
2093
2649
|
if (!id) throw new Error("MCP server ID is required to call tool");
|
|
@@ -2110,21 +2666,21 @@ function useMcp(options = {}) {
|
|
|
2110
2666
|
}
|
|
2111
2667
|
|
|
2112
2668
|
// src/hooks/useWorkflows.ts
|
|
2113
|
-
var
|
|
2669
|
+
var import_react12 = require("react");
|
|
2114
2670
|
function useWorkflows(options) {
|
|
2115
2671
|
const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
|
|
2116
2672
|
const { autoFetch = true, search, status, page, limit } = opts;
|
|
2117
2673
|
const { fetchWithAuth } = usePersonaContext();
|
|
2118
|
-
const [workflows, setWorkflows] = (0,
|
|
2119
|
-
const [pagination, setPagination] = (0,
|
|
2674
|
+
const [workflows, setWorkflows] = (0, import_react12.useState)([]);
|
|
2675
|
+
const [pagination, setPagination] = (0, import_react12.useState)({
|
|
2120
2676
|
page: page ?? 1,
|
|
2121
2677
|
limit: limit ?? 20,
|
|
2122
2678
|
total: 0,
|
|
2123
2679
|
totalPages: 0
|
|
2124
2680
|
});
|
|
2125
|
-
const [isLoading, setIsLoading] = (0,
|
|
2126
|
-
const [error, setError] = (0,
|
|
2127
|
-
const fetchWorkflows = (0,
|
|
2681
|
+
const [isLoading, setIsLoading] = (0, import_react12.useState)(false);
|
|
2682
|
+
const [error, setError] = (0, import_react12.useState)(null);
|
|
2683
|
+
const fetchWorkflows = (0, import_react12.useCallback)(async () => {
|
|
2128
2684
|
setIsLoading(true);
|
|
2129
2685
|
setError(null);
|
|
2130
2686
|
try {
|
|
@@ -2165,7 +2721,7 @@ function useWorkflows(options) {
|
|
|
2165
2721
|
setIsLoading(false);
|
|
2166
2722
|
}
|
|
2167
2723
|
}, [fetchWithAuth, search, status, page, limit]);
|
|
2168
|
-
const createWorkflow = (0,
|
|
2724
|
+
const createWorkflow = (0, import_react12.useCallback)(
|
|
2169
2725
|
async (input) => {
|
|
2170
2726
|
setError(null);
|
|
2171
2727
|
try {
|
|
@@ -2189,7 +2745,7 @@ function useWorkflows(options) {
|
|
|
2189
2745
|
},
|
|
2190
2746
|
[fetchWithAuth]
|
|
2191
2747
|
);
|
|
2192
|
-
(0,
|
|
2748
|
+
(0, import_react12.useEffect)(() => {
|
|
2193
2749
|
if (autoFetch) {
|
|
2194
2750
|
void fetchWorkflows();
|
|
2195
2751
|
}
|
|
@@ -2205,17 +2761,17 @@ function useWorkflows(options) {
|
|
|
2205
2761
|
}
|
|
2206
2762
|
|
|
2207
2763
|
// src/hooks/useWorkflow.ts
|
|
2208
|
-
var
|
|
2764
|
+
var import_react13 = require("react");
|
|
2209
2765
|
function useWorkflow(workflowId, options) {
|
|
2210
2766
|
const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
|
|
2211
2767
|
const { autoFetch = true } = opts;
|
|
2212
2768
|
const { fetchWithAuth } = usePersonaContext();
|
|
2213
|
-
const [workflow, setWorkflow] = (0,
|
|
2214
|
-
const [versions, setVersions] = (0,
|
|
2215
|
-
const [mermaid, setMermaid] = (0,
|
|
2216
|
-
const [isLoading, setIsLoading] = (0,
|
|
2217
|
-
const [error, setError] = (0,
|
|
2218
|
-
const fetchWorkflow = (0,
|
|
2769
|
+
const [workflow, setWorkflow] = (0, import_react13.useState)(null);
|
|
2770
|
+
const [versions, setVersions] = (0, import_react13.useState)([]);
|
|
2771
|
+
const [mermaid, setMermaid] = (0, import_react13.useState)(null);
|
|
2772
|
+
const [isLoading, setIsLoading] = (0, import_react13.useState)(false);
|
|
2773
|
+
const [error, setError] = (0, import_react13.useState)(null);
|
|
2774
|
+
const fetchWorkflow = (0, import_react13.useCallback)(async () => {
|
|
2219
2775
|
if (!workflowId) return null;
|
|
2220
2776
|
setIsLoading(true);
|
|
2221
2777
|
setError(null);
|
|
@@ -2235,7 +2791,7 @@ function useWorkflow(workflowId, options) {
|
|
|
2235
2791
|
setIsLoading(false);
|
|
2236
2792
|
}
|
|
2237
2793
|
}, [fetchWithAuth, workflowId]);
|
|
2238
|
-
const fetchVersions = (0,
|
|
2794
|
+
const fetchVersions = (0, import_react13.useCallback)(async () => {
|
|
2239
2795
|
if (!workflowId) return [];
|
|
2240
2796
|
try {
|
|
2241
2797
|
const res = await fetchWithAuth(`/workflows/${workflowId}/versions`);
|
|
@@ -2248,7 +2804,7 @@ function useWorkflow(workflowId, options) {
|
|
|
2248
2804
|
return [];
|
|
2249
2805
|
}
|
|
2250
2806
|
}, [fetchWithAuth, workflowId]);
|
|
2251
|
-
const fetchMermaid = (0,
|
|
2807
|
+
const fetchMermaid = (0, import_react13.useCallback)(async () => {
|
|
2252
2808
|
if (!workflowId) return "";
|
|
2253
2809
|
try {
|
|
2254
2810
|
const res = await fetchWithAuth(`/workflows/${workflowId}/mermaid`);
|
|
@@ -2261,7 +2817,7 @@ function useWorkflow(workflowId, options) {
|
|
|
2261
2817
|
return "";
|
|
2262
2818
|
}
|
|
2263
2819
|
}, [fetchWithAuth, workflowId]);
|
|
2264
|
-
const saveDraft = (0,
|
|
2820
|
+
const saveDraft = (0, import_react13.useCallback)(
|
|
2265
2821
|
async (draft) => {
|
|
2266
2822
|
if (!workflowId) throw new Error("Workflow ID is required");
|
|
2267
2823
|
setError(null);
|
|
@@ -2280,7 +2836,7 @@ function useWorkflow(workflowId, options) {
|
|
|
2280
2836
|
},
|
|
2281
2837
|
[fetchWithAuth, workflowId]
|
|
2282
2838
|
);
|
|
2283
|
-
const publish = (0,
|
|
2839
|
+
const publish = (0, import_react13.useCallback)(
|
|
2284
2840
|
async (summary) => {
|
|
2285
2841
|
if (!workflowId) throw new Error("Workflow ID is required");
|
|
2286
2842
|
setError(null);
|
|
@@ -2300,7 +2856,7 @@ function useWorkflow(workflowId, options) {
|
|
|
2300
2856
|
},
|
|
2301
2857
|
[fetchWithAuth, workflowId, fetchWorkflow, fetchVersions]
|
|
2302
2858
|
);
|
|
2303
|
-
const deleteWorkflow = (0,
|
|
2859
|
+
const deleteWorkflow = (0, import_react13.useCallback)(async () => {
|
|
2304
2860
|
if (!workflowId) throw new Error("Workflow ID is required");
|
|
2305
2861
|
setError(null);
|
|
2306
2862
|
const res = await fetchWithAuth(`/workflows/${workflowId}`, {
|
|
@@ -2311,7 +2867,7 @@ function useWorkflow(workflowId, options) {
|
|
|
2311
2867
|
}
|
|
2312
2868
|
setWorkflow(null);
|
|
2313
2869
|
}, [fetchWithAuth, workflowId]);
|
|
2314
|
-
(0,
|
|
2870
|
+
(0, import_react13.useEffect)(() => {
|
|
2315
2871
|
if (autoFetch && workflowId) {
|
|
2316
2872
|
void fetchWorkflow();
|
|
2317
2873
|
}
|
|
@@ -2332,25 +2888,25 @@ function useWorkflow(workflowId, options) {
|
|
|
2332
2888
|
}
|
|
2333
2889
|
|
|
2334
2890
|
// src/hooks/useWorkflowStream.ts
|
|
2335
|
-
var
|
|
2891
|
+
var import_react14 = require("react");
|
|
2336
2892
|
function useWorkflowStream(workflowId, options) {
|
|
2337
2893
|
const { baseUrl, getAuthToken, fetchWithAuth, logger } = usePersonaContext();
|
|
2338
|
-
const [status, setStatus] = (0,
|
|
2339
|
-
const [runId, setRunId] = (0,
|
|
2340
|
-
const [activeNodeId, setActiveNodeId] = (0,
|
|
2341
|
-
const [nodeRuns, setNodeRuns] = (0,
|
|
2894
|
+
const [status, setStatus] = (0, import_react14.useState)("idle");
|
|
2895
|
+
const [runId, setRunId] = (0, import_react14.useState)(null);
|
|
2896
|
+
const [activeNodeId, setActiveNodeId] = (0, import_react14.useState)(null);
|
|
2897
|
+
const [nodeRuns, setNodeRuns] = (0, import_react14.useState)(
|
|
2342
2898
|
{}
|
|
2343
2899
|
);
|
|
2344
|
-
const [text, setText] = (0,
|
|
2345
|
-
const [output, setOutput] = (0,
|
|
2346
|
-
const [error, setError] = (0,
|
|
2347
|
-
const [events, setEvents] = (0,
|
|
2348
|
-
const abortControllerRef = (0,
|
|
2349
|
-
const currentRunIdRef = (0,
|
|
2900
|
+
const [text, setText] = (0, import_react14.useState)("");
|
|
2901
|
+
const [output, setOutput] = (0, import_react14.useState)(null);
|
|
2902
|
+
const [error, setError] = (0, import_react14.useState)(null);
|
|
2903
|
+
const [events, setEvents] = (0, import_react14.useState)([]);
|
|
2904
|
+
const abortControllerRef = (0, import_react14.useRef)(null);
|
|
2905
|
+
const currentRunIdRef = (0, import_react14.useRef)(null);
|
|
2350
2906
|
currentRunIdRef.current = runId;
|
|
2351
|
-
const optionsRef = (0,
|
|
2907
|
+
const optionsRef = (0, import_react14.useRef)(options);
|
|
2352
2908
|
optionsRef.current = options;
|
|
2353
|
-
const cancel = (0,
|
|
2909
|
+
const cancel = (0, import_react14.useCallback)(async () => {
|
|
2354
2910
|
if (abortControllerRef.current) {
|
|
2355
2911
|
abortControllerRef.current.abort();
|
|
2356
2912
|
abortControllerRef.current = null;
|
|
@@ -2371,7 +2927,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
2371
2927
|
setStatus("cancelled");
|
|
2372
2928
|
setActiveNodeId(null);
|
|
2373
2929
|
}, [fetchWithAuth, logger]);
|
|
2374
|
-
const reset = (0,
|
|
2930
|
+
const reset = (0, import_react14.useCallback)(() => {
|
|
2375
2931
|
if (abortControllerRef.current) {
|
|
2376
2932
|
abortControllerRef.current.abort();
|
|
2377
2933
|
abortControllerRef.current = null;
|
|
@@ -2385,7 +2941,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
2385
2941
|
setError(null);
|
|
2386
2942
|
setEvents([]);
|
|
2387
2943
|
}, []);
|
|
2388
|
-
const processStream = (0,
|
|
2944
|
+
const processStream = (0, import_react14.useCallback)(
|
|
2389
2945
|
async (url, method, body, targetRunId) => {
|
|
2390
2946
|
if (abortControllerRef.current) {
|
|
2391
2947
|
abortControllerRef.current.abort();
|
|
@@ -2550,7 +3106,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
2550
3106
|
},
|
|
2551
3107
|
[getAuthToken]
|
|
2552
3108
|
);
|
|
2553
|
-
const start = (0,
|
|
3109
|
+
const start = (0, import_react14.useCallback)(
|
|
2554
3110
|
async (input, opts) => {
|
|
2555
3111
|
const targetWfId = opts?.workflowId || workflowId;
|
|
2556
3112
|
if (!targetWfId) {
|
|
@@ -2571,7 +3127,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
2571
3127
|
},
|
|
2572
3128
|
[workflowId, baseUrl, processStream]
|
|
2573
3129
|
);
|
|
2574
|
-
const resume = (0,
|
|
3130
|
+
const resume = (0, import_react14.useCallback)(
|
|
2575
3131
|
async (targetRunId, sinceSeq) => {
|
|
2576
3132
|
if (!targetRunId) {
|
|
2577
3133
|
throw new Error("Run ID is required to resume stream");
|
|
@@ -2584,7 +3140,7 @@ function useWorkflowStream(workflowId, options) {
|
|
|
2584
3140
|
},
|
|
2585
3141
|
[baseUrl, processStream]
|
|
2586
3142
|
);
|
|
2587
|
-
(0,
|
|
3143
|
+
(0, import_react14.useEffect)(() => {
|
|
2588
3144
|
return () => {
|
|
2589
3145
|
if (abortControllerRef.current) {
|
|
2590
3146
|
abortControllerRef.current.abort();
|
|
@@ -2609,21 +3165,21 @@ function useWorkflowStream(workflowId, options) {
|
|
|
2609
3165
|
}
|
|
2610
3166
|
|
|
2611
3167
|
// src/hooks/useWorkflowRuns.ts
|
|
2612
|
-
var
|
|
3168
|
+
var import_react15 = require("react");
|
|
2613
3169
|
function useWorkflowRuns(workflowId, options) {
|
|
2614
3170
|
const opts = typeof options === "boolean" ? { autoFetch: options } : options ?? {};
|
|
2615
3171
|
const { autoFetch = true, page = 1, limit = 20 } = opts;
|
|
2616
3172
|
const { fetchWithAuth } = usePersonaContext();
|
|
2617
|
-
const [runs, setRuns] = (0,
|
|
2618
|
-
const [pagination, setPagination] = (0,
|
|
3173
|
+
const [runs, setRuns] = (0, import_react15.useState)([]);
|
|
3174
|
+
const [pagination, setPagination] = (0, import_react15.useState)({
|
|
2619
3175
|
page,
|
|
2620
3176
|
limit,
|
|
2621
3177
|
total: 0,
|
|
2622
3178
|
totalPages: 0
|
|
2623
3179
|
});
|
|
2624
|
-
const [isLoading, setIsLoading] = (0,
|
|
2625
|
-
const [error, setError] = (0,
|
|
2626
|
-
const fetchRuns = (0,
|
|
3180
|
+
const [isLoading, setIsLoading] = (0, import_react15.useState)(false);
|
|
3181
|
+
const [error, setError] = (0, import_react15.useState)(null);
|
|
3182
|
+
const fetchRuns = (0, import_react15.useCallback)(async () => {
|
|
2627
3183
|
if (!workflowId) return [];
|
|
2628
3184
|
setIsLoading(true);
|
|
2629
3185
|
setError(null);
|
|
@@ -2653,7 +3209,7 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
2653
3209
|
setIsLoading(false);
|
|
2654
3210
|
}
|
|
2655
3211
|
}, [fetchWithAuth, workflowId, page, limit]);
|
|
2656
|
-
const getRun = (0,
|
|
3212
|
+
const getRun = (0, import_react15.useCallback)(
|
|
2657
3213
|
async (runId) => {
|
|
2658
3214
|
if (!runId) throw new Error("Run ID is required");
|
|
2659
3215
|
const res = await fetchWithAuth(`/workflows/runs/${runId}`);
|
|
@@ -2664,7 +3220,7 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
2664
3220
|
},
|
|
2665
3221
|
[fetchWithAuth]
|
|
2666
3222
|
);
|
|
2667
|
-
const cancelRun = (0,
|
|
3223
|
+
const cancelRun = (0, import_react15.useCallback)(
|
|
2668
3224
|
async (runId) => {
|
|
2669
3225
|
if (!runId) throw new Error("Run ID is required");
|
|
2670
3226
|
const res = await fetchWithAuth(`/workflows/runs/${runId}/cancel`, {
|
|
@@ -2679,7 +3235,7 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
2679
3235
|
},
|
|
2680
3236
|
[fetchWithAuth]
|
|
2681
3237
|
);
|
|
2682
|
-
(0,
|
|
3238
|
+
(0, import_react15.useEffect)(() => {
|
|
2683
3239
|
if (autoFetch && workflowId) {
|
|
2684
3240
|
void fetchRuns();
|
|
2685
3241
|
}
|
|
@@ -2697,9 +3253,10 @@ function useWorkflowRuns(workflowId, options) {
|
|
|
2697
3253
|
|
|
2698
3254
|
// src/index.ts
|
|
2699
3255
|
var import_logger2 = require("@personaai/logger");
|
|
2700
|
-
var VERSION = "0.
|
|
3256
|
+
var VERSION = "0.10.0";
|
|
2701
3257
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2702
3258
|
0 && (module.exports = {
|
|
3259
|
+
ARCHITECT_AGENT_ID,
|
|
2703
3260
|
PersonaProvider,
|
|
2704
3261
|
VERSION,
|
|
2705
3262
|
createLogger,
|
|
@@ -2710,6 +3267,7 @@ var VERSION = "0.9.0";
|
|
|
2710
3267
|
setLogLevel,
|
|
2711
3268
|
supportsStreamingFetch,
|
|
2712
3269
|
useAgents,
|
|
3270
|
+
useArchitectChat,
|
|
2713
3271
|
useChat,
|
|
2714
3272
|
useConnection,
|
|
2715
3273
|
useFiles,
|