@xinghunm/ai-chat 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +98 -114
- package/dist/index.mjs +118 -134
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -729,96 +729,112 @@ var getNextDisplayedUnitCount = ({
|
|
|
729
729
|
var splitMarkdownBlocks = (content) => content.split(/\n{2,}/).map((block) => block.trim()).filter(Boolean);
|
|
730
730
|
|
|
731
731
|
// src/components/chat-thread/hooks/use-chat-message-reveal.ts
|
|
732
|
+
var createRevealState = ({
|
|
733
|
+
isAssistantStreaming,
|
|
734
|
+
targetUnitCount
|
|
735
|
+
}) => {
|
|
736
|
+
const initialDisplayedUnitCount = isAssistantStreaming ? 0 : targetUnitCount;
|
|
737
|
+
return {
|
|
738
|
+
batchedTargetUnitCount: initialDisplayedUnitCount,
|
|
739
|
+
displayedUnitCount: initialDisplayedUnitCount,
|
|
740
|
+
isFreshBlockActive: false
|
|
741
|
+
};
|
|
742
|
+
};
|
|
743
|
+
var revealReducer = (state, action) => {
|
|
744
|
+
switch (action.type) {
|
|
745
|
+
case "reset-message":
|
|
746
|
+
return createRevealState(action);
|
|
747
|
+
case "commit-batched-target": {
|
|
748
|
+
const nextDisplayedUnitCount = action.role === "assistant" ? getNextDisplayedUnitCount({
|
|
749
|
+
currentUnits: state.displayedUnitCount,
|
|
750
|
+
targetUnits: action.nextTargetUnitCount,
|
|
751
|
+
isStreaming: action.isAssistantStreaming,
|
|
752
|
+
minimumStep: state.displayedUnitCount > 0 && action.isAssistantStreaming ? 2 : 1
|
|
753
|
+
}) : action.nextTargetUnitCount;
|
|
754
|
+
return {
|
|
755
|
+
...state,
|
|
756
|
+
batchedTargetUnitCount: action.nextTargetUnitCount,
|
|
757
|
+
displayedUnitCount: nextDisplayedUnitCount
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
case "set-fresh-block-active":
|
|
761
|
+
return state.isFreshBlockActive === action.isActive ? state : {
|
|
762
|
+
...state,
|
|
763
|
+
isFreshBlockActive: action.isActive
|
|
764
|
+
};
|
|
765
|
+
case "sync-displayed-target":
|
|
766
|
+
return state.displayedUnitCount === state.batchedTargetUnitCount ? state : {
|
|
767
|
+
...state,
|
|
768
|
+
displayedUnitCount: state.batchedTargetUnitCount
|
|
769
|
+
};
|
|
770
|
+
case "advance-reveal": {
|
|
771
|
+
if (state.displayedUnitCount >= state.batchedTargetUnitCount) {
|
|
772
|
+
return state;
|
|
773
|
+
}
|
|
774
|
+
return {
|
|
775
|
+
...state,
|
|
776
|
+
displayedUnitCount: Math.min(
|
|
777
|
+
state.batchedTargetUnitCount,
|
|
778
|
+
getNextDisplayedUnitCount({
|
|
779
|
+
currentUnits: state.displayedUnitCount,
|
|
780
|
+
targetUnits: state.batchedTargetUnitCount,
|
|
781
|
+
isStreaming: action.isAssistantStreaming
|
|
782
|
+
})
|
|
783
|
+
)
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
default:
|
|
787
|
+
return state;
|
|
788
|
+
}
|
|
789
|
+
};
|
|
732
790
|
var useChatMessageReveal = (message) => {
|
|
733
791
|
const isAssistantStreaming = message.role === "assistant" && message.status === "streaming";
|
|
734
792
|
const targetContent = message.content || "";
|
|
735
793
|
const targetUnits = (0, import_react5.useMemo)(() => Array.from(targetContent), [targetContent]);
|
|
736
|
-
const resetSnapshot = (0, import_react5.useMemo)(
|
|
737
|
-
() => ({
|
|
738
|
-
messageId: message.id,
|
|
739
|
-
initialTargetUnitCount: targetUnits.length,
|
|
740
|
-
initialBatchedTargetUnitCount: isAssistantStreaming ? 0 : targetUnits.length
|
|
741
|
-
}),
|
|
742
|
-
[isAssistantStreaming, message.id, targetUnits.length]
|
|
743
|
-
);
|
|
744
794
|
const pendingTargetUnitCountRef = (0, import_react5.useRef)(targetUnits.length);
|
|
745
795
|
const batchedTargetUnitCountRef = (0, import_react5.useRef)(isAssistantStreaming ? 0 : targetUnits.length);
|
|
746
796
|
const inputBatchTimeoutRef = (0, import_react5.useRef)(null);
|
|
747
|
-
const commitAnimationFrameRef = (0, import_react5.useRef)(null);
|
|
748
|
-
const freshBlockActivationFrameRef = (0, import_react5.useRef)(null);
|
|
749
|
-
const displayedUnitSyncFrameRef = (0, import_react5.useRef)(null);
|
|
750
|
-
const resetAnimationFrameRef = (0, import_react5.useRef)(null);
|
|
751
|
-
const [batchedTargetUnitCount, setBatchedTargetUnitCount] = (0, import_react5.useState)(
|
|
752
|
-
() => isAssistantStreaming ? 0 : targetUnits.length
|
|
753
|
-
);
|
|
754
797
|
const lastDisplayedBlockCountRef = (0, import_react5.useRef)(0);
|
|
755
|
-
const
|
|
756
|
-
|
|
798
|
+
const previousMessageIdRef = (0, import_react5.useRef)(message.id);
|
|
799
|
+
const [state, dispatch] = (0, import_react5.useReducer)(
|
|
800
|
+
revealReducer,
|
|
801
|
+
{
|
|
802
|
+
isAssistantStreaming,
|
|
803
|
+
targetUnitCount: targetUnits.length
|
|
804
|
+
},
|
|
805
|
+
createRevealState
|
|
757
806
|
);
|
|
758
|
-
const
|
|
807
|
+
const { batchedTargetUnitCount, displayedUnitCount, isFreshBlockActive } = state;
|
|
759
808
|
const commitBatchedTargetUnitCount = (0, import_react5.useCallback)(
|
|
760
809
|
(nextTargetUnitCount) => {
|
|
761
810
|
batchedTargetUnitCountRef.current = nextTargetUnitCount;
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
isStreaming: isAssistantStreaming,
|
|
768
|
-
minimumStep: current > 0 && isAssistantStreaming ? 2 : 1
|
|
769
|
-
}) : nextTargetUnitCount
|
|
770
|
-
);
|
|
771
|
-
},
|
|
772
|
-
[isAssistantStreaming, message.role]
|
|
773
|
-
);
|
|
774
|
-
const scheduleBatchedTargetUnitCountCommit = (0, import_react5.useCallback)(
|
|
775
|
-
(nextTargetUnitCount) => {
|
|
776
|
-
if (commitAnimationFrameRef.current !== null) {
|
|
777
|
-
window.cancelAnimationFrame(commitAnimationFrameRef.current);
|
|
778
|
-
}
|
|
779
|
-
commitAnimationFrameRef.current = window.requestAnimationFrame(() => {
|
|
780
|
-
commitAnimationFrameRef.current = null;
|
|
781
|
-
commitBatchedTargetUnitCount(nextTargetUnitCount);
|
|
811
|
+
dispatch({
|
|
812
|
+
type: "commit-batched-target",
|
|
813
|
+
isAssistantStreaming,
|
|
814
|
+
nextTargetUnitCount,
|
|
815
|
+
role: message.role
|
|
782
816
|
});
|
|
783
817
|
},
|
|
784
|
-
[
|
|
818
|
+
[isAssistantStreaming, message.role]
|
|
785
819
|
);
|
|
786
820
|
(0, import_react5.useEffect)(() => {
|
|
787
|
-
|
|
788
|
-
|
|
821
|
+
if (previousMessageIdRef.current === message.id) {
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
previousMessageIdRef.current = message.id;
|
|
825
|
+
pendingTargetUnitCountRef.current = targetUnits.length;
|
|
826
|
+
batchedTargetUnitCountRef.current = isAssistantStreaming ? 0 : targetUnits.length;
|
|
789
827
|
lastDisplayedBlockCountRef.current = 0;
|
|
790
828
|
if (inputBatchTimeoutRef.current !== null) {
|
|
791
829
|
window.clearTimeout(inputBatchTimeoutRef.current);
|
|
792
830
|
inputBatchTimeoutRef.current = null;
|
|
793
831
|
}
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
if (freshBlockActivationFrameRef.current !== null) {
|
|
799
|
-
window.cancelAnimationFrame(freshBlockActivationFrameRef.current);
|
|
800
|
-
freshBlockActivationFrameRef.current = null;
|
|
801
|
-
}
|
|
802
|
-
if (displayedUnitSyncFrameRef.current !== null) {
|
|
803
|
-
window.cancelAnimationFrame(displayedUnitSyncFrameRef.current);
|
|
804
|
-
displayedUnitSyncFrameRef.current = null;
|
|
805
|
-
}
|
|
806
|
-
if (resetAnimationFrameRef.current !== null) {
|
|
807
|
-
window.cancelAnimationFrame(resetAnimationFrameRef.current);
|
|
808
|
-
}
|
|
809
|
-
resetAnimationFrameRef.current = window.requestAnimationFrame(() => {
|
|
810
|
-
resetAnimationFrameRef.current = null;
|
|
811
|
-
setBatchedTargetUnitCount(resetSnapshot.initialBatchedTargetUnitCount);
|
|
812
|
-
setDisplayedUnitCount(resetSnapshot.initialBatchedTargetUnitCount);
|
|
813
|
-
setIsFreshBlockActive(false);
|
|
832
|
+
dispatch({
|
|
833
|
+
type: "reset-message",
|
|
834
|
+
isAssistantStreaming,
|
|
835
|
+
targetUnitCount: targetUnits.length
|
|
814
836
|
});
|
|
815
|
-
|
|
816
|
-
if (resetAnimationFrameRef.current !== null) {
|
|
817
|
-
window.cancelAnimationFrame(resetAnimationFrameRef.current);
|
|
818
|
-
resetAnimationFrameRef.current = null;
|
|
819
|
-
}
|
|
820
|
-
};
|
|
821
|
-
}, [resetSnapshot]);
|
|
837
|
+
}, [isAssistantStreaming, message.id, targetUnits.length]);
|
|
822
838
|
(0, import_react5.useEffect)(() => {
|
|
823
839
|
pendingTargetUnitCountRef.current = targetUnits.length;
|
|
824
840
|
if (message.role !== "assistant" || !isAssistantStreaming) {
|
|
@@ -826,14 +842,14 @@ var useChatMessageReveal = (message) => {
|
|
|
826
842
|
window.clearTimeout(inputBatchTimeoutRef.current);
|
|
827
843
|
inputBatchTimeoutRef.current = null;
|
|
828
844
|
}
|
|
829
|
-
|
|
845
|
+
commitBatchedTargetUnitCount(targetUnits.length);
|
|
830
846
|
return;
|
|
831
847
|
}
|
|
832
848
|
if (targetUnits.length <= batchedTargetUnitCountRef.current) {
|
|
833
849
|
return;
|
|
834
850
|
}
|
|
835
851
|
if (batchedTargetUnitCountRef.current === 0) {
|
|
836
|
-
|
|
852
|
+
commitBatchedTargetUnitCount(targetUnits.length);
|
|
837
853
|
return;
|
|
838
854
|
}
|
|
839
855
|
if (inputBatchTimeoutRef.current !== null) {
|
|
@@ -849,13 +865,7 @@ var useChatMessageReveal = (message) => {
|
|
|
849
865
|
inputBatchTimeoutRef.current = null;
|
|
850
866
|
}
|
|
851
867
|
};
|
|
852
|
-
}, [
|
|
853
|
-
commitBatchedTargetUnitCount,
|
|
854
|
-
isAssistantStreaming,
|
|
855
|
-
message.role,
|
|
856
|
-
scheduleBatchedTargetUnitCountCommit,
|
|
857
|
-
targetUnits.length
|
|
858
|
-
]);
|
|
868
|
+
}, [commitBatchedTargetUnitCount, isAssistantStreaming, message.role, targetUnits.length]);
|
|
859
869
|
const displayedContent = (0, import_react5.useMemo)(
|
|
860
870
|
() => targetUnits.slice(0, displayedUnitCount).join(""),
|
|
861
871
|
[displayedUnitCount, targetUnits]
|
|
@@ -867,18 +877,11 @@ var useChatMessageReveal = (message) => {
|
|
|
867
877
|
if (!hasNewDisplayedBlock) {
|
|
868
878
|
return;
|
|
869
879
|
}
|
|
870
|
-
|
|
871
|
-
freshBlockActivationFrameRef.current = null;
|
|
872
|
-
setIsFreshBlockActive(true);
|
|
873
|
-
});
|
|
880
|
+
dispatch({ type: "set-fresh-block-active", isActive: true });
|
|
874
881
|
const timer = window.setTimeout(() => {
|
|
875
|
-
|
|
882
|
+
dispatch({ type: "set-fresh-block-active", isActive: false });
|
|
876
883
|
}, STREAM_FRESH_BLOCK_SETTLE_MS);
|
|
877
884
|
return () => {
|
|
878
|
-
if (freshBlockActivationFrameRef.current !== null) {
|
|
879
|
-
window.cancelAnimationFrame(freshBlockActivationFrameRef.current);
|
|
880
|
-
freshBlockActivationFrameRef.current = null;
|
|
881
|
-
}
|
|
882
885
|
window.clearTimeout(timer);
|
|
883
886
|
};
|
|
884
887
|
}, [contentBlocks.length, message.role]);
|
|
@@ -886,40 +889,19 @@ var useChatMessageReveal = (message) => {
|
|
|
886
889
|
const shouldAnimateReveal = message.role === "assistant" && displayedUnitCount < batchedTargetUnitCount && (isAssistantStreaming || displayedUnitCount > 0);
|
|
887
890
|
if (!shouldAnimateReveal) {
|
|
888
891
|
if (displayedUnitCount !== batchedTargetUnitCount) {
|
|
889
|
-
|
|
890
|
-
displayedUnitSyncFrameRef.current = null;
|
|
891
|
-
setDisplayedUnitCount(batchedTargetUnitCount);
|
|
892
|
-
});
|
|
892
|
+
dispatch({ type: "sync-displayed-target" });
|
|
893
893
|
}
|
|
894
|
-
return
|
|
895
|
-
if (displayedUnitSyncFrameRef.current !== null) {
|
|
896
|
-
window.cancelAnimationFrame(displayedUnitSyncFrameRef.current);
|
|
897
|
-
displayedUnitSyncFrameRef.current = null;
|
|
898
|
-
}
|
|
899
|
-
};
|
|
894
|
+
return;
|
|
900
895
|
}
|
|
901
896
|
const timer = window.setInterval(() => {
|
|
902
|
-
|
|
903
|
-
if (current >= batchedTargetUnitCount) {
|
|
904
|
-
window.clearInterval(timer);
|
|
905
|
-
return current;
|
|
906
|
-
}
|
|
907
|
-
return Math.min(
|
|
908
|
-
batchedTargetUnitCount,
|
|
909
|
-
getNextDisplayedUnitCount({
|
|
910
|
-
currentUnits: current,
|
|
911
|
-
targetUnits: batchedTargetUnitCount,
|
|
912
|
-
isStreaming: isAssistantStreaming
|
|
913
|
-
})
|
|
914
|
-
);
|
|
915
|
-
});
|
|
897
|
+
dispatch({ type: "advance-reveal", isAssistantStreaming });
|
|
916
898
|
}, STREAM_REVEAL_TICK_MS);
|
|
917
899
|
return () => {
|
|
918
900
|
window.clearInterval(timer);
|
|
919
901
|
};
|
|
920
902
|
}, [batchedTargetUnitCount, displayedUnitCount, isAssistantStreaming, message.role]);
|
|
921
903
|
const settledContent = isFreshBlockActive ? contentBlocks.slice(0, -1).join("\n\n") : displayedContent;
|
|
922
|
-
const freshContent = isFreshBlockActive ? contentBlocks.
|
|
904
|
+
const freshContent = isFreshBlockActive ? contentBlocks[contentBlocks.length - 1] ?? "" : "";
|
|
923
905
|
return {
|
|
924
906
|
isAssistantStreaming,
|
|
925
907
|
displayedContent,
|
|
@@ -1877,11 +1859,13 @@ var ChatMessageItemView = ({
|
|
|
1877
1859
|
const attachments = message.attachments ?? [];
|
|
1878
1860
|
const blocks = message.blocks ?? [];
|
|
1879
1861
|
const hasStructuredBlocks = blocks.length > 0;
|
|
1862
|
+
const hasMarkdownOnlyBlocks = hasStructuredBlocks && blocks.every((block) => block.type === "markdown");
|
|
1880
1863
|
const hasTextContent = Boolean(settledContent || freshContent || displayedContent);
|
|
1864
|
+
const shouldRenderStructuredBlocks = hasStructuredBlocks && !(isAssistantStreaming && hasMarkdownOnlyBlocks && hasTextContent);
|
|
1881
1865
|
const isPlanMode = mode === "plan";
|
|
1882
1866
|
const canSubmitConfirmation = isPlanMode && typeof onConfirmationSubmit === "function";
|
|
1883
1867
|
const canSubmitQuestionnaire = isPlanMode && typeof onQuestionnaireSubmit === "function";
|
|
1884
|
-
const shouldShowStreamingCaret = isAssistantStreaming && (!
|
|
1868
|
+
const shouldShowStreamingCaret = isAssistantStreaming && (!shouldRenderStructuredBlocks || hasTextContent);
|
|
1885
1869
|
const renderChatMessageBlock = (block, index) => {
|
|
1886
1870
|
switch (block.type) {
|
|
1887
1871
|
case "markdown":
|
|
@@ -1961,8 +1945,8 @@ var ChatMessageItemView = ({
|
|
|
1961
1945
|
isStoppedAssistant ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StatusTag, { "data-testid": "chat-message-stopped-tag", children: labels.stoppedResponse }) : null
|
|
1962
1946
|
] }),
|
|
1963
1947
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Content, { "data-testid": "chat-message-content", children: [
|
|
1964
|
-
|
|
1965
|
-
|
|
1948
|
+
shouldRenderStructuredBlocks || hasTextContent ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(ContentStack, { "data-testid": "chat-message-body-stack", children: [
|
|
1949
|
+
shouldRenderStructuredBlocks ? blocks.map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1966
1950
|
ContentSegment,
|
|
1967
1951
|
{
|
|
1968
1952
|
"data-testid": "chat-message-content-segment",
|
package/dist/index.mjs
CHANGED
|
@@ -590,7 +590,7 @@ var AiChatProvider = (props) => {
|
|
|
590
590
|
};
|
|
591
591
|
|
|
592
592
|
// src/components/chat-thread/index.tsx
|
|
593
|
-
import { useCallback as useCallback2, useLayoutEffect, useMemo as useMemo3, useRef as useRef4, useState as
|
|
593
|
+
import { useCallback as useCallback2, useLayoutEffect, useMemo as useMemo3, useRef as useRef4, useState as useState4 } from "react";
|
|
594
594
|
import styled10 from "@emotion/styled";
|
|
595
595
|
|
|
596
596
|
// src/context/use-chat-context.ts
|
|
@@ -627,7 +627,7 @@ var calculateChatThreadScrollSpacerHeight = ({
|
|
|
627
627
|
);
|
|
628
628
|
|
|
629
629
|
// src/components/chat-thread/components/chat-message-item.tsx
|
|
630
|
-
import { Fragment, memo, useState as
|
|
630
|
+
import { Fragment, memo, useState as useState3 } from "react";
|
|
631
631
|
import styled7 from "@emotion/styled";
|
|
632
632
|
import { keyframes } from "@emotion/react";
|
|
633
633
|
import ReactMarkdown from "react-markdown";
|
|
@@ -636,7 +636,7 @@ import remarkMath from "remark-math";
|
|
|
636
636
|
import rehypeKatex from "rehype-katex";
|
|
637
637
|
|
|
638
638
|
// src/components/chat-thread/hooks/use-chat-message-reveal.ts
|
|
639
|
-
import { useCallback, useEffect, useMemo as useMemo2, useRef as useRef2
|
|
639
|
+
import { useCallback, useEffect, useMemo as useMemo2, useReducer, useRef as useRef2 } from "react";
|
|
640
640
|
|
|
641
641
|
// src/components/chat-thread/lib/message-reveal.ts
|
|
642
642
|
var STREAM_REVEAL_TICK_MS = 36;
|
|
@@ -683,96 +683,112 @@ var getNextDisplayedUnitCount = ({
|
|
|
683
683
|
var splitMarkdownBlocks = (content) => content.split(/\n{2,}/).map((block) => block.trim()).filter(Boolean);
|
|
684
684
|
|
|
685
685
|
// src/components/chat-thread/hooks/use-chat-message-reveal.ts
|
|
686
|
+
var createRevealState = ({
|
|
687
|
+
isAssistantStreaming,
|
|
688
|
+
targetUnitCount
|
|
689
|
+
}) => {
|
|
690
|
+
const initialDisplayedUnitCount = isAssistantStreaming ? 0 : targetUnitCount;
|
|
691
|
+
return {
|
|
692
|
+
batchedTargetUnitCount: initialDisplayedUnitCount,
|
|
693
|
+
displayedUnitCount: initialDisplayedUnitCount,
|
|
694
|
+
isFreshBlockActive: false
|
|
695
|
+
};
|
|
696
|
+
};
|
|
697
|
+
var revealReducer = (state, action) => {
|
|
698
|
+
switch (action.type) {
|
|
699
|
+
case "reset-message":
|
|
700
|
+
return createRevealState(action);
|
|
701
|
+
case "commit-batched-target": {
|
|
702
|
+
const nextDisplayedUnitCount = action.role === "assistant" ? getNextDisplayedUnitCount({
|
|
703
|
+
currentUnits: state.displayedUnitCount,
|
|
704
|
+
targetUnits: action.nextTargetUnitCount,
|
|
705
|
+
isStreaming: action.isAssistantStreaming,
|
|
706
|
+
minimumStep: state.displayedUnitCount > 0 && action.isAssistantStreaming ? 2 : 1
|
|
707
|
+
}) : action.nextTargetUnitCount;
|
|
708
|
+
return {
|
|
709
|
+
...state,
|
|
710
|
+
batchedTargetUnitCount: action.nextTargetUnitCount,
|
|
711
|
+
displayedUnitCount: nextDisplayedUnitCount
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
case "set-fresh-block-active":
|
|
715
|
+
return state.isFreshBlockActive === action.isActive ? state : {
|
|
716
|
+
...state,
|
|
717
|
+
isFreshBlockActive: action.isActive
|
|
718
|
+
};
|
|
719
|
+
case "sync-displayed-target":
|
|
720
|
+
return state.displayedUnitCount === state.batchedTargetUnitCount ? state : {
|
|
721
|
+
...state,
|
|
722
|
+
displayedUnitCount: state.batchedTargetUnitCount
|
|
723
|
+
};
|
|
724
|
+
case "advance-reveal": {
|
|
725
|
+
if (state.displayedUnitCount >= state.batchedTargetUnitCount) {
|
|
726
|
+
return state;
|
|
727
|
+
}
|
|
728
|
+
return {
|
|
729
|
+
...state,
|
|
730
|
+
displayedUnitCount: Math.min(
|
|
731
|
+
state.batchedTargetUnitCount,
|
|
732
|
+
getNextDisplayedUnitCount({
|
|
733
|
+
currentUnits: state.displayedUnitCount,
|
|
734
|
+
targetUnits: state.batchedTargetUnitCount,
|
|
735
|
+
isStreaming: action.isAssistantStreaming
|
|
736
|
+
})
|
|
737
|
+
)
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
default:
|
|
741
|
+
return state;
|
|
742
|
+
}
|
|
743
|
+
};
|
|
686
744
|
var useChatMessageReveal = (message) => {
|
|
687
745
|
const isAssistantStreaming = message.role === "assistant" && message.status === "streaming";
|
|
688
746
|
const targetContent = message.content || "";
|
|
689
747
|
const targetUnits = useMemo2(() => Array.from(targetContent), [targetContent]);
|
|
690
|
-
const resetSnapshot = useMemo2(
|
|
691
|
-
() => ({
|
|
692
|
-
messageId: message.id,
|
|
693
|
-
initialTargetUnitCount: targetUnits.length,
|
|
694
|
-
initialBatchedTargetUnitCount: isAssistantStreaming ? 0 : targetUnits.length
|
|
695
|
-
}),
|
|
696
|
-
[isAssistantStreaming, message.id, targetUnits.length]
|
|
697
|
-
);
|
|
698
748
|
const pendingTargetUnitCountRef = useRef2(targetUnits.length);
|
|
699
749
|
const batchedTargetUnitCountRef = useRef2(isAssistantStreaming ? 0 : targetUnits.length);
|
|
700
750
|
const inputBatchTimeoutRef = useRef2(null);
|
|
701
|
-
const commitAnimationFrameRef = useRef2(null);
|
|
702
|
-
const freshBlockActivationFrameRef = useRef2(null);
|
|
703
|
-
const displayedUnitSyncFrameRef = useRef2(null);
|
|
704
|
-
const resetAnimationFrameRef = useRef2(null);
|
|
705
|
-
const [batchedTargetUnitCount, setBatchedTargetUnitCount] = useState2(
|
|
706
|
-
() => isAssistantStreaming ? 0 : targetUnits.length
|
|
707
|
-
);
|
|
708
751
|
const lastDisplayedBlockCountRef = useRef2(0);
|
|
709
|
-
const
|
|
710
|
-
|
|
752
|
+
const previousMessageIdRef = useRef2(message.id);
|
|
753
|
+
const [state, dispatch] = useReducer(
|
|
754
|
+
revealReducer,
|
|
755
|
+
{
|
|
756
|
+
isAssistantStreaming,
|
|
757
|
+
targetUnitCount: targetUnits.length
|
|
758
|
+
},
|
|
759
|
+
createRevealState
|
|
711
760
|
);
|
|
712
|
-
const
|
|
761
|
+
const { batchedTargetUnitCount, displayedUnitCount, isFreshBlockActive } = state;
|
|
713
762
|
const commitBatchedTargetUnitCount = useCallback(
|
|
714
763
|
(nextTargetUnitCount) => {
|
|
715
764
|
batchedTargetUnitCountRef.current = nextTargetUnitCount;
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
isStreaming: isAssistantStreaming,
|
|
722
|
-
minimumStep: current > 0 && isAssistantStreaming ? 2 : 1
|
|
723
|
-
}) : nextTargetUnitCount
|
|
724
|
-
);
|
|
725
|
-
},
|
|
726
|
-
[isAssistantStreaming, message.role]
|
|
727
|
-
);
|
|
728
|
-
const scheduleBatchedTargetUnitCountCommit = useCallback(
|
|
729
|
-
(nextTargetUnitCount) => {
|
|
730
|
-
if (commitAnimationFrameRef.current !== null) {
|
|
731
|
-
window.cancelAnimationFrame(commitAnimationFrameRef.current);
|
|
732
|
-
}
|
|
733
|
-
commitAnimationFrameRef.current = window.requestAnimationFrame(() => {
|
|
734
|
-
commitAnimationFrameRef.current = null;
|
|
735
|
-
commitBatchedTargetUnitCount(nextTargetUnitCount);
|
|
765
|
+
dispatch({
|
|
766
|
+
type: "commit-batched-target",
|
|
767
|
+
isAssistantStreaming,
|
|
768
|
+
nextTargetUnitCount,
|
|
769
|
+
role: message.role
|
|
736
770
|
});
|
|
737
771
|
},
|
|
738
|
-
[
|
|
772
|
+
[isAssistantStreaming, message.role]
|
|
739
773
|
);
|
|
740
774
|
useEffect(() => {
|
|
741
|
-
|
|
742
|
-
|
|
775
|
+
if (previousMessageIdRef.current === message.id) {
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
previousMessageIdRef.current = message.id;
|
|
779
|
+
pendingTargetUnitCountRef.current = targetUnits.length;
|
|
780
|
+
batchedTargetUnitCountRef.current = isAssistantStreaming ? 0 : targetUnits.length;
|
|
743
781
|
lastDisplayedBlockCountRef.current = 0;
|
|
744
782
|
if (inputBatchTimeoutRef.current !== null) {
|
|
745
783
|
window.clearTimeout(inputBatchTimeoutRef.current);
|
|
746
784
|
inputBatchTimeoutRef.current = null;
|
|
747
785
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
if (freshBlockActivationFrameRef.current !== null) {
|
|
753
|
-
window.cancelAnimationFrame(freshBlockActivationFrameRef.current);
|
|
754
|
-
freshBlockActivationFrameRef.current = null;
|
|
755
|
-
}
|
|
756
|
-
if (displayedUnitSyncFrameRef.current !== null) {
|
|
757
|
-
window.cancelAnimationFrame(displayedUnitSyncFrameRef.current);
|
|
758
|
-
displayedUnitSyncFrameRef.current = null;
|
|
759
|
-
}
|
|
760
|
-
if (resetAnimationFrameRef.current !== null) {
|
|
761
|
-
window.cancelAnimationFrame(resetAnimationFrameRef.current);
|
|
762
|
-
}
|
|
763
|
-
resetAnimationFrameRef.current = window.requestAnimationFrame(() => {
|
|
764
|
-
resetAnimationFrameRef.current = null;
|
|
765
|
-
setBatchedTargetUnitCount(resetSnapshot.initialBatchedTargetUnitCount);
|
|
766
|
-
setDisplayedUnitCount(resetSnapshot.initialBatchedTargetUnitCount);
|
|
767
|
-
setIsFreshBlockActive(false);
|
|
786
|
+
dispatch({
|
|
787
|
+
type: "reset-message",
|
|
788
|
+
isAssistantStreaming,
|
|
789
|
+
targetUnitCount: targetUnits.length
|
|
768
790
|
});
|
|
769
|
-
|
|
770
|
-
if (resetAnimationFrameRef.current !== null) {
|
|
771
|
-
window.cancelAnimationFrame(resetAnimationFrameRef.current);
|
|
772
|
-
resetAnimationFrameRef.current = null;
|
|
773
|
-
}
|
|
774
|
-
};
|
|
775
|
-
}, [resetSnapshot]);
|
|
791
|
+
}, [isAssistantStreaming, message.id, targetUnits.length]);
|
|
776
792
|
useEffect(() => {
|
|
777
793
|
pendingTargetUnitCountRef.current = targetUnits.length;
|
|
778
794
|
if (message.role !== "assistant" || !isAssistantStreaming) {
|
|
@@ -780,14 +796,14 @@ var useChatMessageReveal = (message) => {
|
|
|
780
796
|
window.clearTimeout(inputBatchTimeoutRef.current);
|
|
781
797
|
inputBatchTimeoutRef.current = null;
|
|
782
798
|
}
|
|
783
|
-
|
|
799
|
+
commitBatchedTargetUnitCount(targetUnits.length);
|
|
784
800
|
return;
|
|
785
801
|
}
|
|
786
802
|
if (targetUnits.length <= batchedTargetUnitCountRef.current) {
|
|
787
803
|
return;
|
|
788
804
|
}
|
|
789
805
|
if (batchedTargetUnitCountRef.current === 0) {
|
|
790
|
-
|
|
806
|
+
commitBatchedTargetUnitCount(targetUnits.length);
|
|
791
807
|
return;
|
|
792
808
|
}
|
|
793
809
|
if (inputBatchTimeoutRef.current !== null) {
|
|
@@ -803,13 +819,7 @@ var useChatMessageReveal = (message) => {
|
|
|
803
819
|
inputBatchTimeoutRef.current = null;
|
|
804
820
|
}
|
|
805
821
|
};
|
|
806
|
-
}, [
|
|
807
|
-
commitBatchedTargetUnitCount,
|
|
808
|
-
isAssistantStreaming,
|
|
809
|
-
message.role,
|
|
810
|
-
scheduleBatchedTargetUnitCountCommit,
|
|
811
|
-
targetUnits.length
|
|
812
|
-
]);
|
|
822
|
+
}, [commitBatchedTargetUnitCount, isAssistantStreaming, message.role, targetUnits.length]);
|
|
813
823
|
const displayedContent = useMemo2(
|
|
814
824
|
() => targetUnits.slice(0, displayedUnitCount).join(""),
|
|
815
825
|
[displayedUnitCount, targetUnits]
|
|
@@ -821,18 +831,11 @@ var useChatMessageReveal = (message) => {
|
|
|
821
831
|
if (!hasNewDisplayedBlock) {
|
|
822
832
|
return;
|
|
823
833
|
}
|
|
824
|
-
|
|
825
|
-
freshBlockActivationFrameRef.current = null;
|
|
826
|
-
setIsFreshBlockActive(true);
|
|
827
|
-
});
|
|
834
|
+
dispatch({ type: "set-fresh-block-active", isActive: true });
|
|
828
835
|
const timer = window.setTimeout(() => {
|
|
829
|
-
|
|
836
|
+
dispatch({ type: "set-fresh-block-active", isActive: false });
|
|
830
837
|
}, STREAM_FRESH_BLOCK_SETTLE_MS);
|
|
831
838
|
return () => {
|
|
832
|
-
if (freshBlockActivationFrameRef.current !== null) {
|
|
833
|
-
window.cancelAnimationFrame(freshBlockActivationFrameRef.current);
|
|
834
|
-
freshBlockActivationFrameRef.current = null;
|
|
835
|
-
}
|
|
836
839
|
window.clearTimeout(timer);
|
|
837
840
|
};
|
|
838
841
|
}, [contentBlocks.length, message.role]);
|
|
@@ -840,40 +843,19 @@ var useChatMessageReveal = (message) => {
|
|
|
840
843
|
const shouldAnimateReveal = message.role === "assistant" && displayedUnitCount < batchedTargetUnitCount && (isAssistantStreaming || displayedUnitCount > 0);
|
|
841
844
|
if (!shouldAnimateReveal) {
|
|
842
845
|
if (displayedUnitCount !== batchedTargetUnitCount) {
|
|
843
|
-
|
|
844
|
-
displayedUnitSyncFrameRef.current = null;
|
|
845
|
-
setDisplayedUnitCount(batchedTargetUnitCount);
|
|
846
|
-
});
|
|
846
|
+
dispatch({ type: "sync-displayed-target" });
|
|
847
847
|
}
|
|
848
|
-
return
|
|
849
|
-
if (displayedUnitSyncFrameRef.current !== null) {
|
|
850
|
-
window.cancelAnimationFrame(displayedUnitSyncFrameRef.current);
|
|
851
|
-
displayedUnitSyncFrameRef.current = null;
|
|
852
|
-
}
|
|
853
|
-
};
|
|
848
|
+
return;
|
|
854
849
|
}
|
|
855
850
|
const timer = window.setInterval(() => {
|
|
856
|
-
|
|
857
|
-
if (current >= batchedTargetUnitCount) {
|
|
858
|
-
window.clearInterval(timer);
|
|
859
|
-
return current;
|
|
860
|
-
}
|
|
861
|
-
return Math.min(
|
|
862
|
-
batchedTargetUnitCount,
|
|
863
|
-
getNextDisplayedUnitCount({
|
|
864
|
-
currentUnits: current,
|
|
865
|
-
targetUnits: batchedTargetUnitCount,
|
|
866
|
-
isStreaming: isAssistantStreaming
|
|
867
|
-
})
|
|
868
|
-
);
|
|
869
|
-
});
|
|
851
|
+
dispatch({ type: "advance-reveal", isAssistantStreaming });
|
|
870
852
|
}, STREAM_REVEAL_TICK_MS);
|
|
871
853
|
return () => {
|
|
872
854
|
window.clearInterval(timer);
|
|
873
855
|
};
|
|
874
856
|
}, [batchedTargetUnitCount, displayedUnitCount, isAssistantStreaming, message.role]);
|
|
875
857
|
const settledContent = isFreshBlockActive ? contentBlocks.slice(0, -1).join("\n\n") : displayedContent;
|
|
876
|
-
const freshContent = isFreshBlockActive ? contentBlocks.
|
|
858
|
+
const freshContent = isFreshBlockActive ? contentBlocks[contentBlocks.length - 1] ?? "" : "";
|
|
877
859
|
return {
|
|
878
860
|
isAssistantStreaming,
|
|
879
861
|
displayedContent,
|
|
@@ -1092,7 +1074,7 @@ var Value = styled3.span`
|
|
|
1092
1074
|
`;
|
|
1093
1075
|
|
|
1094
1076
|
// src/components/chat-thread/components/pde-ai-questionnaire-card.tsx
|
|
1095
|
-
import { useState as
|
|
1077
|
+
import { useState as useState2 } from "react";
|
|
1096
1078
|
import styled4 from "@emotion/styled";
|
|
1097
1079
|
import { jsx as jsx5, jsxs as jsxs3 } from "@emotion/react/jsx-runtime";
|
|
1098
1080
|
var OTHER_OPTION_VALUE = "__other__";
|
|
@@ -1194,10 +1176,10 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1194
1176
|
interactive = false,
|
|
1195
1177
|
onSubmit
|
|
1196
1178
|
}) => {
|
|
1197
|
-
const [answers, setAnswers] =
|
|
1179
|
+
const [answers, setAnswers] = useState2(
|
|
1198
1180
|
() => createInitialAnswers(questionnaire)
|
|
1199
1181
|
);
|
|
1200
|
-
const [errorMessage, setErrorMessage] =
|
|
1182
|
+
const [errorMessage, setErrorMessage] = useState2(null);
|
|
1201
1183
|
const handleSubmit = () => {
|
|
1202
1184
|
const missingQuestions = questionnaire.questions.filter(
|
|
1203
1185
|
(question) => question.required && isMissingRequiredAnswer(question, answers)
|
|
@@ -1825,17 +1807,19 @@ var ChatMessageItemView = ({
|
|
|
1825
1807
|
renderMessageBlock
|
|
1826
1808
|
}) => {
|
|
1827
1809
|
const { labels } = useChatContext();
|
|
1828
|
-
const [activeImage, setActiveImage] =
|
|
1810
|
+
const [activeImage, setActiveImage] = useState3(void 0);
|
|
1829
1811
|
const { displayedContent, freshContent, isAssistantStreaming, settledContent } = useChatMessageReveal(message);
|
|
1830
1812
|
const isStoppedAssistant = message.role === "assistant" && message.status === "stopped";
|
|
1831
1813
|
const attachments = message.attachments ?? [];
|
|
1832
1814
|
const blocks = message.blocks ?? [];
|
|
1833
1815
|
const hasStructuredBlocks = blocks.length > 0;
|
|
1816
|
+
const hasMarkdownOnlyBlocks = hasStructuredBlocks && blocks.every((block) => block.type === "markdown");
|
|
1834
1817
|
const hasTextContent = Boolean(settledContent || freshContent || displayedContent);
|
|
1818
|
+
const shouldRenderStructuredBlocks = hasStructuredBlocks && !(isAssistantStreaming && hasMarkdownOnlyBlocks && hasTextContent);
|
|
1835
1819
|
const isPlanMode = mode === "plan";
|
|
1836
1820
|
const canSubmitConfirmation = isPlanMode && typeof onConfirmationSubmit === "function";
|
|
1837
1821
|
const canSubmitQuestionnaire = isPlanMode && typeof onQuestionnaireSubmit === "function";
|
|
1838
|
-
const shouldShowStreamingCaret = isAssistantStreaming && (!
|
|
1822
|
+
const shouldShowStreamingCaret = isAssistantStreaming && (!shouldRenderStructuredBlocks || hasTextContent);
|
|
1839
1823
|
const renderChatMessageBlock = (block, index) => {
|
|
1840
1824
|
switch (block.type) {
|
|
1841
1825
|
case "markdown":
|
|
@@ -1915,8 +1899,8 @@ var ChatMessageItemView = ({
|
|
|
1915
1899
|
isStoppedAssistant ? /* @__PURE__ */ jsx8(StatusTag, { "data-testid": "chat-message-stopped-tag", children: labels.stoppedResponse }) : null
|
|
1916
1900
|
] }),
|
|
1917
1901
|
/* @__PURE__ */ jsxs5(Content, { "data-testid": "chat-message-content", children: [
|
|
1918
|
-
|
|
1919
|
-
|
|
1902
|
+
shouldRenderStructuredBlocks || hasTextContent ? /* @__PURE__ */ jsxs5(ContentStack, { "data-testid": "chat-message-body-stack", children: [
|
|
1903
|
+
shouldRenderStructuredBlocks ? blocks.map((block, index) => /* @__PURE__ */ jsx8(
|
|
1920
1904
|
ContentSegment,
|
|
1921
1905
|
{
|
|
1922
1906
|
"data-testid": "chat-message-content-segment",
|
|
@@ -2302,7 +2286,7 @@ var ChatThreadView = ({
|
|
|
2302
2286
|
const latestUserMessageRef = useRef4(null);
|
|
2303
2287
|
const pendingScrollUserMessageIdRef = useRef4(void 0);
|
|
2304
2288
|
const reservedSpaceFrameRef = useRef4(null);
|
|
2305
|
-
const [latestUserMessageReservedSpace, setLatestUserMessageReservedSpace] =
|
|
2289
|
+
const [latestUserMessageReservedSpace, setLatestUserMessageReservedSpace] = useState4({ messageId: void 0, value: 0 });
|
|
2306
2290
|
const reservedPaddingBottom = 24 + (latestUserMessageReservedSpace.messageId === latestUserMessageId ? latestUserMessageReservedSpace.value : 0);
|
|
2307
2291
|
const measureLatestUserMessageReservedSpace = useCallback2((messageId) => {
|
|
2308
2292
|
const container = containerRef.current;
|
|
@@ -2628,10 +2612,10 @@ var resolveSendSession = ({
|
|
|
2628
2612
|
};
|
|
2629
2613
|
|
|
2630
2614
|
// src/components/chat-composer/hooks/use-chat-composer.ts
|
|
2631
|
-
import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef6, useState as
|
|
2615
|
+
import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef6, useState as useState6 } from "react";
|
|
2632
2616
|
|
|
2633
2617
|
// src/components/chat-composer/hooks/use-composer-attachments.ts
|
|
2634
|
-
import { useEffect as useEffect3, useRef as useRef5, useState as
|
|
2618
|
+
import { useEffect as useEffect3, useRef as useRef5, useState as useState5 } from "react";
|
|
2635
2619
|
var SUPPORTED_IMAGE_MIME_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/webp"]);
|
|
2636
2620
|
var MAX_COMPOSER_ATTACHMENTS = 10;
|
|
2637
2621
|
var createObjectUrl = (file) => typeof URL !== "undefined" && typeof URL.createObjectURL === "function" ? URL.createObjectURL(file) : "";
|
|
@@ -2645,7 +2629,7 @@ var releaseComposerAttachments = (attachments) => {
|
|
|
2645
2629
|
attachments.forEach((attachment) => revokeObjectUrl(attachment.previewUrl));
|
|
2646
2630
|
};
|
|
2647
2631
|
var useComposerAttachments = () => {
|
|
2648
|
-
const [attachments, setAttachments] =
|
|
2632
|
+
const [attachments, setAttachments] = useState5([]);
|
|
2649
2633
|
const attachmentsRef = useRef5([]);
|
|
2650
2634
|
useEffect3(() => {
|
|
2651
2635
|
attachmentsRef.current = attachments;
|
|
@@ -2763,9 +2747,9 @@ var useChatComposer = () => {
|
|
|
2763
2747
|
const clearSessionError = useChatStore((s) => s.clearSessionError);
|
|
2764
2748
|
const setPreferredMode = useChatStore((s) => s.setPreferredMode);
|
|
2765
2749
|
const setSessionMode = useChatStore((s) => s.setSessionMode);
|
|
2766
|
-
const [availableModels, setAvailableModels] =
|
|
2767
|
-
const [isModelsLoading, setIsModelsLoading] =
|
|
2768
|
-
const [isModelsError, setIsModelsError] =
|
|
2750
|
+
const [availableModels, setAvailableModels] = useState6([]);
|
|
2751
|
+
const [isModelsLoading, setIsModelsLoading] = useState6(true);
|
|
2752
|
+
const [isModelsError, setIsModelsError] = useState6(false);
|
|
2769
2753
|
const fetchModels = useCallback3(async () => {
|
|
2770
2754
|
setIsModelsLoading(true);
|
|
2771
2755
|
setIsModelsError(false);
|
|
@@ -2782,10 +2766,10 @@ var useChatComposer = () => {
|
|
|
2782
2766
|
void fetchModels();
|
|
2783
2767
|
}, [fetchModels]);
|
|
2784
2768
|
const hasModels = availableModels.length > 0;
|
|
2785
|
-
const [value, setValue] =
|
|
2786
|
-
const [selectedModel, setSelectedModel] =
|
|
2787
|
-
const [selectedMode, setSelectedModeLocal] =
|
|
2788
|
-
const [attachmentNotice, setAttachmentNotice] =
|
|
2769
|
+
const [value, setValue] = useState6("");
|
|
2770
|
+
const [selectedModel, setSelectedModel] = useState6("");
|
|
2771
|
+
const [selectedMode, setSelectedModeLocal] = useState6(DEFAULT_CHAT_AGENT_MODE);
|
|
2772
|
+
const [attachmentNotice, setAttachmentNotice] = useState6(null);
|
|
2789
2773
|
const { attachments, appendFiles, removeAttachment, takeMessageAttachments } = useComposerAttachments();
|
|
2790
2774
|
const abortControllerRef = useRef6(null);
|
|
2791
2775
|
const stopRequestRef = useRef6(null);
|
|
@@ -3081,14 +3065,14 @@ var useChatComposer = () => {
|
|
|
3081
3065
|
};
|
|
3082
3066
|
|
|
3083
3067
|
// src/components/chat-composer/components/chat-composer-attachment-list.tsx
|
|
3084
|
-
import { useState as
|
|
3068
|
+
import { useState as useState7 } from "react";
|
|
3085
3069
|
import styled11 from "@emotion/styled";
|
|
3086
3070
|
import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs8 } from "@emotion/react/jsx-runtime";
|
|
3087
3071
|
var ChatComposerAttachmentList = ({
|
|
3088
3072
|
attachments,
|
|
3089
3073
|
onRemoveAttachment
|
|
3090
3074
|
}) => {
|
|
3091
|
-
const [activeImage, setActiveImage] =
|
|
3075
|
+
const [activeImage, setActiveImage] = useState7(null);
|
|
3092
3076
|
if (!attachments.length) {
|
|
3093
3077
|
return null;
|
|
3094
3078
|
}
|