@xinghunm/ai-chat 0.2.2 → 0.4.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 +58 -9
- package/dist/index.d.mts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +497 -91
- package/dist/index.mjs +447 -42
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ __export(src_exports, {
|
|
|
33
33
|
AiChat: () => AiChat,
|
|
34
34
|
AiChatProvider: () => AiChatProvider,
|
|
35
35
|
CHAT_AGENT_MODES: () => CHAT_AGENT_MODES,
|
|
36
|
+
CHAT_MESSAGE_RENDER_ORDERS: () => CHAT_MESSAGE_RENDER_ORDERS,
|
|
36
37
|
ChatComposer: () => ChatComposer,
|
|
37
38
|
ChatConversationList: () => ChatConversationList,
|
|
38
39
|
ChatThread: () => ChatThread,
|
|
@@ -62,6 +63,7 @@ var import_vanilla = require("zustand/vanilla");
|
|
|
62
63
|
// src/types/index.ts
|
|
63
64
|
var CHAT_AGENT_MODES = ["ask", "plan", "agent"];
|
|
64
65
|
var DEFAULT_CHAT_AGENT_MODE = "agent";
|
|
66
|
+
var CHAT_MESSAGE_RENDER_ORDERS = ["blocks-first", "timeline"];
|
|
65
67
|
var DEFAULT_AI_CHAT_LABELS = {
|
|
66
68
|
sendButton: "Send",
|
|
67
69
|
stopButton: "Stop",
|
|
@@ -563,7 +565,14 @@ var createDefaultChatTransport = ({
|
|
|
563
565
|
// src/components/ai-chat-provider/index.tsx
|
|
564
566
|
var import_jsx_runtime = require("@emotion/react/jsx-runtime");
|
|
565
567
|
var AiChatProvider = (props) => {
|
|
566
|
-
const {
|
|
568
|
+
const {
|
|
569
|
+
defaultMode,
|
|
570
|
+
labels,
|
|
571
|
+
renderMessageBlock,
|
|
572
|
+
messageRenderOrder,
|
|
573
|
+
enableImageAttachments = true,
|
|
574
|
+
children
|
|
575
|
+
} = props;
|
|
567
576
|
const [store] = (0, import_react2.useState)(
|
|
568
577
|
() => createChatStore(defaultMode ? { preferredMode: defaultMode } : void 0)
|
|
569
578
|
);
|
|
@@ -615,6 +624,7 @@ var AiChatProvider = (props) => {
|
|
|
615
624
|
sendRef,
|
|
616
625
|
retryRef,
|
|
617
626
|
renderMessageBlock,
|
|
627
|
+
messageRenderOrder,
|
|
618
628
|
transformStreamPacket: defaultTransformStreamPacket,
|
|
619
629
|
enableImageAttachments
|
|
620
630
|
}),
|
|
@@ -625,6 +635,7 @@ var AiChatProvider = (props) => {
|
|
|
625
635
|
defaultTransformStreamPacket,
|
|
626
636
|
enableImageAttachments,
|
|
627
637
|
labels,
|
|
638
|
+
messageRenderOrder,
|
|
628
639
|
renderMessageBlock,
|
|
629
640
|
sendRef,
|
|
630
641
|
retryRef,
|
|
@@ -636,7 +647,7 @@ var AiChatProvider = (props) => {
|
|
|
636
647
|
};
|
|
637
648
|
|
|
638
649
|
// src/components/chat-thread/index.tsx
|
|
639
|
-
var
|
|
650
|
+
var import_react11 = require("react");
|
|
640
651
|
var import_styled9 = __toESM(require("@emotion/styled"));
|
|
641
652
|
|
|
642
653
|
// src/context/use-chat-context.ts
|
|
@@ -657,9 +668,9 @@ var useChatStore = (selector) => {
|
|
|
657
668
|
var CHAT_THREAD_SCROLL_TOP_GAP = 16;
|
|
658
669
|
|
|
659
670
|
// src/components/chat-thread/components/chat-message-item.tsx
|
|
660
|
-
var
|
|
671
|
+
var import_react9 = require("react");
|
|
661
672
|
var import_styled7 = __toESM(require("@emotion/styled"));
|
|
662
|
-
var
|
|
673
|
+
var import_react10 = require("@emotion/react");
|
|
663
674
|
var import_react_markdown = __toESM(require("react-markdown"));
|
|
664
675
|
var import_remark_gfm = __toESM(require("remark-gfm"));
|
|
665
676
|
var import_remark_math = __toESM(require("remark-math"));
|
|
@@ -897,6 +908,7 @@ var useChatMessageReveal = (message) => {
|
|
|
897
908
|
];
|
|
898
909
|
return {
|
|
899
910
|
isAssistantStreaming,
|
|
911
|
+
isFreshBlockActive,
|
|
900
912
|
displayedContent,
|
|
901
913
|
settledContent,
|
|
902
914
|
freshContent,
|
|
@@ -904,6 +916,325 @@ var useChatMessageReveal = (message) => {
|
|
|
904
916
|
};
|
|
905
917
|
};
|
|
906
918
|
|
|
919
|
+
// src/components/chat-thread/hooks/use-timeline-block-anchors.ts
|
|
920
|
+
var import_react6 = require("react");
|
|
921
|
+
|
|
922
|
+
// src/components/chat-thread/lib/chat-message-timeline.ts
|
|
923
|
+
var stringifyTimelineKeyPart = (value) => {
|
|
924
|
+
if (value === null || value === void 0) {
|
|
925
|
+
return String(value);
|
|
926
|
+
}
|
|
927
|
+
if (Array.isArray(value)) {
|
|
928
|
+
return `[${value.map((item) => stringifyTimelineKeyPart(item)).join(",")}]`;
|
|
929
|
+
}
|
|
930
|
+
if (typeof value === "object") {
|
|
931
|
+
return `{${Object.entries(value).sort(([leftKey], [rightKey]) => leftKey.localeCompare(rightKey)).map(([key, nestedValue]) => `${key}:${stringifyTimelineKeyPart(nestedValue)}`).join(",")}}`;
|
|
932
|
+
}
|
|
933
|
+
return String(value);
|
|
934
|
+
};
|
|
935
|
+
var getTimelineBlockKey = (block, index) => {
|
|
936
|
+
switch (block.type) {
|
|
937
|
+
case "markdown":
|
|
938
|
+
return null;
|
|
939
|
+
case "notice":
|
|
940
|
+
return `${index}:notice:${block.tone}:${block.text}`;
|
|
941
|
+
case "parameter_summary":
|
|
942
|
+
return `${index}:parameter_summary:${block.items.map((item) => `${item.label}:${item.value}:${item.fieldPath ?? ""}`).join("|")}`;
|
|
943
|
+
case "confirmation_card":
|
|
944
|
+
return `${index}:confirmation_card:${block.proposal.proposalId}`;
|
|
945
|
+
case "result_summary":
|
|
946
|
+
return `${index}:result_summary:${block.summary.taskId}:${block.summary.status}`;
|
|
947
|
+
case "questionnaire":
|
|
948
|
+
return `${index}:questionnaire:${block.questionnaire.questionnaireId}`;
|
|
949
|
+
case "custom":
|
|
950
|
+
return `${index}:custom:${block.kind}:${stringifyTimelineKeyPart(block.data)}`;
|
|
951
|
+
default:
|
|
952
|
+
return null;
|
|
953
|
+
}
|
|
954
|
+
};
|
|
955
|
+
var getTimelineConsumedText = (blocks) => blocks.filter(
|
|
956
|
+
(block) => block.type === "markdown"
|
|
957
|
+
).map((block) => block.text).join("\n\n");
|
|
958
|
+
var getTimelineTextStream = (content, blocks) => {
|
|
959
|
+
const consumedText = getTimelineConsumedText(blocks);
|
|
960
|
+
if (consumedText.length > 0 && content.startsWith(consumedText)) {
|
|
961
|
+
return content.slice(consumedText.length);
|
|
962
|
+
}
|
|
963
|
+
return content;
|
|
964
|
+
};
|
|
965
|
+
var buildTimelineTextDisplay = (content, isAssistantStreaming, isFreshBlockActive = isAssistantStreaming) => {
|
|
966
|
+
const contentBlocks = splitMarkdownBlocks(content);
|
|
967
|
+
const settledContent = isAssistantStreaming && isFreshBlockActive && contentBlocks.length > 1 ? contentBlocks.slice(0, -1).join("\n\n") : content;
|
|
968
|
+
const freshContent = isAssistantStreaming && isFreshBlockActive && contentBlocks.length > 1 ? contentBlocks[contentBlocks.length - 1] ?? "" : "";
|
|
969
|
+
const displayedBlocks = contentBlocks.length > 1 ? contentBlocks.map((blockContent, index) => ({
|
|
970
|
+
content: blockContent,
|
|
971
|
+
tone: isAssistantStreaming && isFreshBlockActive && freshContent && index === contentBlocks.length - 1 ? "fresh" : "settled"
|
|
972
|
+
})) : [{ content, tone: "settled" }];
|
|
973
|
+
return {
|
|
974
|
+
settledContent,
|
|
975
|
+
freshContent,
|
|
976
|
+
displayedBlocks
|
|
977
|
+
};
|
|
978
|
+
};
|
|
979
|
+
var getTimelineDisplayUnitCount = (content) => splitMarkdownBlocks(content).reduce((count, block) => count + Array.from(block).length, 0);
|
|
980
|
+
var buildAnchoredTimelineSegments = ({
|
|
981
|
+
blocks,
|
|
982
|
+
timelineBlockAnchors,
|
|
983
|
+
timelineDisplayedBlocks,
|
|
984
|
+
visibleTimelineBlockKeys
|
|
985
|
+
}) => {
|
|
986
|
+
const orderedTimelineSegments = [];
|
|
987
|
+
const totalTimelineUnits = timelineDisplayedBlocks.reduce(
|
|
988
|
+
(count, block) => count + Array.from(block.content).length,
|
|
989
|
+
0
|
|
990
|
+
);
|
|
991
|
+
let textCursor = 0;
|
|
992
|
+
const buildTextSegment = (start, end, options) => {
|
|
993
|
+
if (end <= start) {
|
|
994
|
+
return null;
|
|
995
|
+
}
|
|
996
|
+
const displayedBlocks = [];
|
|
997
|
+
let blockCursor = 0;
|
|
998
|
+
for (const block of timelineDisplayedBlocks) {
|
|
999
|
+
const blockUnits = Array.from(block.content);
|
|
1000
|
+
const blockStart = blockCursor;
|
|
1001
|
+
const blockEnd = blockCursor + blockUnits.length;
|
|
1002
|
+
if (blockEnd <= start) {
|
|
1003
|
+
blockCursor = blockEnd;
|
|
1004
|
+
continue;
|
|
1005
|
+
}
|
|
1006
|
+
if (blockStart >= end) {
|
|
1007
|
+
break;
|
|
1008
|
+
}
|
|
1009
|
+
const sliceStart = Math.max(0, start - blockStart);
|
|
1010
|
+
const sliceEnd = Math.min(blockUnits.length, end - blockStart);
|
|
1011
|
+
const slicedContent = blockUnits.slice(sliceStart, sliceEnd).join("");
|
|
1012
|
+
if (slicedContent) {
|
|
1013
|
+
displayedBlocks.push({
|
|
1014
|
+
content: slicedContent,
|
|
1015
|
+
tone: options?.forceSettled ? "settled" : block.tone
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
blockCursor = blockEnd;
|
|
1019
|
+
}
|
|
1020
|
+
const content = displayedBlocks.map((block) => block.content).join("\n\n");
|
|
1021
|
+
if (!content) {
|
|
1022
|
+
return null;
|
|
1023
|
+
}
|
|
1024
|
+
return {
|
|
1025
|
+
type: "text",
|
|
1026
|
+
content,
|
|
1027
|
+
displayedBlocks,
|
|
1028
|
+
useTimelineSegmentation: true
|
|
1029
|
+
};
|
|
1030
|
+
};
|
|
1031
|
+
let trailingCutoff = totalTimelineUnits;
|
|
1032
|
+
for (const [index, block] of blocks.entries()) {
|
|
1033
|
+
if (block.type === "markdown") {
|
|
1034
|
+
orderedTimelineSegments.push({
|
|
1035
|
+
type: "markdown",
|
|
1036
|
+
content: block.text
|
|
1037
|
+
});
|
|
1038
|
+
continue;
|
|
1039
|
+
}
|
|
1040
|
+
const blockKey = getTimelineBlockKey(block, index);
|
|
1041
|
+
const anchor = blockKey !== null ? timelineBlockAnchors[blockKey] ?? totalTimelineUnits : totalTimelineUnits;
|
|
1042
|
+
const isBlockVisible = blockKey !== null && visibleTimelineBlockKeys?.[blockKey] ? true : anchor <= totalTimelineUnits;
|
|
1043
|
+
if (anchor > textCursor) {
|
|
1044
|
+
const textSegment = buildTextSegment(textCursor, Math.min(anchor, totalTimelineUnits), {
|
|
1045
|
+
forceSettled: isBlockVisible
|
|
1046
|
+
});
|
|
1047
|
+
if (textSegment) {
|
|
1048
|
+
orderedTimelineSegments.push(textSegment);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
if (!isBlockVisible) {
|
|
1052
|
+
textCursor = Math.min(anchor, totalTimelineUnits);
|
|
1053
|
+
trailingCutoff = Math.min(trailingCutoff, textCursor);
|
|
1054
|
+
continue;
|
|
1055
|
+
}
|
|
1056
|
+
trailingCutoff = totalTimelineUnits;
|
|
1057
|
+
orderedTimelineSegments.push({
|
|
1058
|
+
type: "block",
|
|
1059
|
+
block,
|
|
1060
|
+
index
|
|
1061
|
+
});
|
|
1062
|
+
textCursor = Math.max(textCursor, anchor);
|
|
1063
|
+
}
|
|
1064
|
+
const trailingTextSegment = buildTextSegment(textCursor, trailingCutoff);
|
|
1065
|
+
if (trailingTextSegment) {
|
|
1066
|
+
orderedTimelineSegments.push(trailingTextSegment);
|
|
1067
|
+
}
|
|
1068
|
+
return orderedTimelineSegments;
|
|
1069
|
+
};
|
|
1070
|
+
|
|
1071
|
+
// src/components/chat-thread/hooks/use-timeline-block-anchors.ts
|
|
1072
|
+
var createTimelineAnchorState = ({
|
|
1073
|
+
messageId,
|
|
1074
|
+
currentBlockKeys
|
|
1075
|
+
}) => ({
|
|
1076
|
+
messageId,
|
|
1077
|
+
previousBlockKeys: currentBlockKeys,
|
|
1078
|
+
timelineBlockAnchors: {},
|
|
1079
|
+
visibleTimelineBlockKeys: {}
|
|
1080
|
+
});
|
|
1081
|
+
var timelineAnchorReducer = (state, action) => {
|
|
1082
|
+
switch (action.type) {
|
|
1083
|
+
case "reset-message":
|
|
1084
|
+
if (state.messageId === action.messageId) {
|
|
1085
|
+
return state;
|
|
1086
|
+
}
|
|
1087
|
+
return createTimelineAnchorState(action);
|
|
1088
|
+
case "sync-anchors": {
|
|
1089
|
+
const previousBlockKeys = new Set(state.previousBlockKeys);
|
|
1090
|
+
const nextAnchors = action.currentBlockKeys.reduce(
|
|
1091
|
+
(acc, blockKey) => {
|
|
1092
|
+
const existingAnchor = state.timelineBlockAnchors[blockKey];
|
|
1093
|
+
if (existingAnchor !== void 0) {
|
|
1094
|
+
acc[blockKey] = existingAnchor;
|
|
1095
|
+
return acc;
|
|
1096
|
+
}
|
|
1097
|
+
if (!previousBlockKeys.has(blockKey)) {
|
|
1098
|
+
acc[blockKey] = action.timelineTextStreamLength;
|
|
1099
|
+
}
|
|
1100
|
+
return acc;
|
|
1101
|
+
},
|
|
1102
|
+
{}
|
|
1103
|
+
);
|
|
1104
|
+
const hasAnchorChanged = Object.keys(nextAnchors).length !== Object.keys(state.timelineBlockAnchors).length || Object.entries(nextAnchors).some(
|
|
1105
|
+
([blockKey, anchor]) => state.timelineBlockAnchors[blockKey] !== anchor
|
|
1106
|
+
);
|
|
1107
|
+
const hasPreviousKeysChanged = action.currentBlockKeys.length !== state.previousBlockKeys.length || action.currentBlockKeys.some(
|
|
1108
|
+
(blockKey, index) => state.previousBlockKeys[index] !== blockKey
|
|
1109
|
+
);
|
|
1110
|
+
if (!hasAnchorChanged && !hasPreviousKeysChanged) {
|
|
1111
|
+
return state;
|
|
1112
|
+
}
|
|
1113
|
+
return {
|
|
1114
|
+
...state,
|
|
1115
|
+
previousBlockKeys: action.currentBlockKeys,
|
|
1116
|
+
timelineBlockAnchors: hasAnchorChanged ? nextAnchors : state.timelineBlockAnchors
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
case "sync-visible": {
|
|
1120
|
+
const nextVisibleBlockKeys = action.currentBlockKeys.reduce(
|
|
1121
|
+
(acc, blockKey) => {
|
|
1122
|
+
if (state.visibleTimelineBlockKeys[blockKey]) {
|
|
1123
|
+
acc[blockKey] = true;
|
|
1124
|
+
return acc;
|
|
1125
|
+
}
|
|
1126
|
+
const anchor = action.effectiveTimelineBlockAnchors[blockKey];
|
|
1127
|
+
if (anchor !== void 0 && anchor <= action.displayedTimelineTextLength) {
|
|
1128
|
+
acc[blockKey] = true;
|
|
1129
|
+
}
|
|
1130
|
+
return acc;
|
|
1131
|
+
},
|
|
1132
|
+
{}
|
|
1133
|
+
);
|
|
1134
|
+
const hasVisibleBlockChanged = Object.keys(nextVisibleBlockKeys).length !== Object.keys(state.visibleTimelineBlockKeys).length || Object.keys(nextVisibleBlockKeys).some(
|
|
1135
|
+
(blockKey) => !state.visibleTimelineBlockKeys[blockKey]
|
|
1136
|
+
);
|
|
1137
|
+
if (!hasVisibleBlockChanged) {
|
|
1138
|
+
return state;
|
|
1139
|
+
}
|
|
1140
|
+
return {
|
|
1141
|
+
...state,
|
|
1142
|
+
visibleTimelineBlockKeys: nextVisibleBlockKeys
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
default:
|
|
1146
|
+
return state;
|
|
1147
|
+
}
|
|
1148
|
+
};
|
|
1149
|
+
var useTimelineBlockAnchors = ({
|
|
1150
|
+
blocks,
|
|
1151
|
+
displayedTimelineTextLength,
|
|
1152
|
+
isAssistantStreaming,
|
|
1153
|
+
message,
|
|
1154
|
+
messageRenderOrder
|
|
1155
|
+
}) => {
|
|
1156
|
+
const currentTimelineBlockKeys = (0, import_react6.useMemo)(
|
|
1157
|
+
() => blocks.map((block, index) => getTimelineBlockKey(block, index)).filter((blockKey) => Boolean(blockKey)),
|
|
1158
|
+
[blocks]
|
|
1159
|
+
);
|
|
1160
|
+
const timelineTextStreamLength = (0, import_react6.useMemo)(
|
|
1161
|
+
() => getTimelineDisplayUnitCount(getTimelineTextStream(message.content, blocks)),
|
|
1162
|
+
[blocks, message.content]
|
|
1163
|
+
);
|
|
1164
|
+
const [state, dispatch] = (0, import_react6.useReducer)(
|
|
1165
|
+
timelineAnchorReducer,
|
|
1166
|
+
{
|
|
1167
|
+
messageId: message.id,
|
|
1168
|
+
currentBlockKeys: currentTimelineBlockKeys
|
|
1169
|
+
},
|
|
1170
|
+
createTimelineAnchorState
|
|
1171
|
+
);
|
|
1172
|
+
const effectiveTimelineBlockAnchors = (0, import_react6.useMemo)(() => {
|
|
1173
|
+
if (messageRenderOrder !== "timeline" || !isAssistantStreaming) {
|
|
1174
|
+
return state.timelineBlockAnchors;
|
|
1175
|
+
}
|
|
1176
|
+
const previousBlockKeys = new Set(state.previousBlockKeys);
|
|
1177
|
+
return currentTimelineBlockKeys.reduce(
|
|
1178
|
+
(acc, blockKey) => {
|
|
1179
|
+
const existingAnchor = state.timelineBlockAnchors[blockKey];
|
|
1180
|
+
if (existingAnchor !== void 0) {
|
|
1181
|
+
acc[blockKey] = existingAnchor;
|
|
1182
|
+
return acc;
|
|
1183
|
+
}
|
|
1184
|
+
if (!previousBlockKeys.has(blockKey)) {
|
|
1185
|
+
acc[blockKey] = timelineTextStreamLength;
|
|
1186
|
+
}
|
|
1187
|
+
return acc;
|
|
1188
|
+
},
|
|
1189
|
+
{ ...state.timelineBlockAnchors }
|
|
1190
|
+
);
|
|
1191
|
+
}, [
|
|
1192
|
+
currentTimelineBlockKeys,
|
|
1193
|
+
isAssistantStreaming,
|
|
1194
|
+
messageRenderOrder,
|
|
1195
|
+
state.previousBlockKeys,
|
|
1196
|
+
state.timelineBlockAnchors,
|
|
1197
|
+
timelineTextStreamLength
|
|
1198
|
+
]);
|
|
1199
|
+
(0, import_react6.useEffect)(() => {
|
|
1200
|
+
dispatch({
|
|
1201
|
+
type: "reset-message",
|
|
1202
|
+
messageId: message.id,
|
|
1203
|
+
currentBlockKeys: currentTimelineBlockKeys
|
|
1204
|
+
});
|
|
1205
|
+
}, [currentTimelineBlockKeys, message.id]);
|
|
1206
|
+
(0, import_react6.useEffect)(() => {
|
|
1207
|
+
if (messageRenderOrder !== "timeline" || !isAssistantStreaming) {
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
1210
|
+
dispatch({
|
|
1211
|
+
type: "sync-anchors",
|
|
1212
|
+
currentBlockKeys: currentTimelineBlockKeys,
|
|
1213
|
+
timelineTextStreamLength
|
|
1214
|
+
});
|
|
1215
|
+
}, [currentTimelineBlockKeys, isAssistantStreaming, messageRenderOrder, timelineTextStreamLength]);
|
|
1216
|
+
(0, import_react6.useEffect)(() => {
|
|
1217
|
+
if (messageRenderOrder !== "timeline") {
|
|
1218
|
+
return;
|
|
1219
|
+
}
|
|
1220
|
+
dispatch({
|
|
1221
|
+
type: "sync-visible",
|
|
1222
|
+
currentBlockKeys: currentTimelineBlockKeys,
|
|
1223
|
+
effectiveTimelineBlockAnchors,
|
|
1224
|
+
displayedTimelineTextLength
|
|
1225
|
+
});
|
|
1226
|
+
}, [
|
|
1227
|
+
currentTimelineBlockKeys,
|
|
1228
|
+
displayedTimelineTextLength,
|
|
1229
|
+
effectiveTimelineBlockAnchors,
|
|
1230
|
+
messageRenderOrder
|
|
1231
|
+
]);
|
|
1232
|
+
return {
|
|
1233
|
+
timelineBlockAnchors: messageRenderOrder === "timeline" ? effectiveTimelineBlockAnchors : {},
|
|
1234
|
+
visibleTimelineBlockKeys: messageRenderOrder === "timeline" ? state.visibleTimelineBlockKeys : {}
|
|
1235
|
+
};
|
|
1236
|
+
};
|
|
1237
|
+
|
|
907
1238
|
// src/components/chat-thread/components/pde-ai-execution-confirmation-card.tsx
|
|
908
1239
|
var import_styled = __toESM(require("@emotion/styled"));
|
|
909
1240
|
var import_jsx_runtime2 = require("@emotion/react/jsx-runtime");
|
|
@@ -1114,7 +1445,7 @@ var Value = import_styled3.default.span`
|
|
|
1114
1445
|
`;
|
|
1115
1446
|
|
|
1116
1447
|
// src/components/chat-thread/components/pde-ai-questionnaire-card.tsx
|
|
1117
|
-
var
|
|
1448
|
+
var import_react7 = require("react");
|
|
1118
1449
|
var import_styled4 = __toESM(require("@emotion/styled"));
|
|
1119
1450
|
var import_jsx_runtime5 = require("@emotion/react/jsx-runtime");
|
|
1120
1451
|
var OTHER_OPTION_VALUE = "__other__";
|
|
@@ -1216,10 +1547,10 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1216
1547
|
interactive = false,
|
|
1217
1548
|
onSubmit
|
|
1218
1549
|
}) => {
|
|
1219
|
-
const [answers, setAnswers] = (0,
|
|
1550
|
+
const [answers, setAnswers] = (0, import_react7.useState)(
|
|
1220
1551
|
() => createInitialAnswers(questionnaire)
|
|
1221
1552
|
);
|
|
1222
|
-
const [errorMessage, setErrorMessage] = (0,
|
|
1553
|
+
const [errorMessage, setErrorMessage] = (0, import_react7.useState)(null);
|
|
1223
1554
|
const handleSubmit = () => {
|
|
1224
1555
|
const missingQuestions = questionnaire.questions.filter(
|
|
1225
1556
|
(question) => question.required && isMissingRequiredAnswer(question, answers)
|
|
@@ -1655,7 +1986,7 @@ var Detail = import_styled5.default.li`
|
|
|
1655
1986
|
|
|
1656
1987
|
// src/components/chat-thread/components/image-viewer.tsx
|
|
1657
1988
|
var import_styled6 = __toESM(require("@emotion/styled"));
|
|
1658
|
-
var
|
|
1989
|
+
var import_react8 = require("react");
|
|
1659
1990
|
var import_jsx_runtime7 = require("@emotion/react/jsx-runtime");
|
|
1660
1991
|
var Overlay = import_styled6.default.div`
|
|
1661
1992
|
position: fixed;
|
|
@@ -1674,8 +2005,8 @@ var Img = import_styled6.default.img`
|
|
|
1674
2005
|
border-radius: 4px;
|
|
1675
2006
|
`;
|
|
1676
2007
|
var ImageViewer = ({ src, alt, onClose }) => {
|
|
1677
|
-
const overlayRef = (0,
|
|
1678
|
-
(0,
|
|
2008
|
+
const overlayRef = (0, import_react8.useRef)(null);
|
|
2009
|
+
(0, import_react8.useEffect)(() => {
|
|
1679
2010
|
const handleKey = (e) => {
|
|
1680
2011
|
if (e.key === "Escape")
|
|
1681
2012
|
onClose();
|
|
@@ -1683,7 +2014,7 @@ var ImageViewer = ({ src, alt, onClose }) => {
|
|
|
1683
2014
|
document.addEventListener("keydown", handleKey);
|
|
1684
2015
|
return () => document.removeEventListener("keydown", handleKey);
|
|
1685
2016
|
}, [onClose]);
|
|
1686
|
-
(0,
|
|
2017
|
+
(0, import_react8.useEffect)(() => {
|
|
1687
2018
|
overlayRef.current?.focus();
|
|
1688
2019
|
}, []);
|
|
1689
2020
|
const stopPropagation = (e) => e.stopPropagation();
|
|
@@ -1846,9 +2177,16 @@ var ChatMessageItemView = ({
|
|
|
1846
2177
|
onQuestionnaireSubmit,
|
|
1847
2178
|
renderMessageBlock
|
|
1848
2179
|
}) => {
|
|
1849
|
-
const { labels } = useChatContext();
|
|
1850
|
-
const [activeImage, setActiveImage] = (0,
|
|
1851
|
-
const {
|
|
2180
|
+
const { labels, messageRenderOrder = "blocks-first" } = useChatContext();
|
|
2181
|
+
const [activeImage, setActiveImage] = (0, import_react9.useState)(void 0);
|
|
2182
|
+
const {
|
|
2183
|
+
displayedBlocks,
|
|
2184
|
+
displayedContent,
|
|
2185
|
+
freshContent,
|
|
2186
|
+
isAssistantStreaming,
|
|
2187
|
+
isFreshBlockActive,
|
|
2188
|
+
settledContent
|
|
2189
|
+
} = useChatMessageReveal(message);
|
|
1852
2190
|
const isStoppedAssistant = message.role === "assistant" && message.status === "stopped";
|
|
1853
2191
|
const attachments = message.attachments ?? [];
|
|
1854
2192
|
const blocks = message.blocks ?? [];
|
|
@@ -1860,6 +2198,22 @@ var ChatMessageItemView = ({
|
|
|
1860
2198
|
const canSubmitConfirmation = isPlanMode && typeof onConfirmationSubmit === "function";
|
|
1861
2199
|
const canSubmitQuestionnaire = isPlanMode && typeof onQuestionnaireSubmit === "function";
|
|
1862
2200
|
const shouldShowStreamingCaret = isAssistantStreaming && (!shouldRenderStructuredBlocks || hasTextContent);
|
|
2201
|
+
const timelineConsumedText = messageRenderOrder === "timeline" ? getTimelineConsumedText(blocks) : "";
|
|
2202
|
+
const hasConsumedTimelineText = timelineConsumedText.length > 0 && displayedContent.startsWith(timelineConsumedText);
|
|
2203
|
+
const timelineDisplayedContent = hasConsumedTimelineText ? displayedContent.slice(timelineConsumedText.length) : displayedContent;
|
|
2204
|
+
const timelineTextDisplay = buildTimelineTextDisplay(
|
|
2205
|
+
timelineDisplayedContent,
|
|
2206
|
+
isAssistantStreaming,
|
|
2207
|
+
isFreshBlockActive
|
|
2208
|
+
);
|
|
2209
|
+
const displayedTimelineTextLength = getTimelineDisplayUnitCount(timelineDisplayedContent);
|
|
2210
|
+
const { timelineBlockAnchors, visibleTimelineBlockKeys } = useTimelineBlockAnchors({
|
|
2211
|
+
blocks,
|
|
2212
|
+
displayedTimelineTextLength,
|
|
2213
|
+
isAssistantStreaming,
|
|
2214
|
+
message,
|
|
2215
|
+
messageRenderOrder
|
|
2216
|
+
});
|
|
1863
2217
|
const renderChatMessageBlock = (block, index) => {
|
|
1864
2218
|
switch (block.type) {
|
|
1865
2219
|
case "markdown":
|
|
@@ -1873,11 +2227,11 @@ var ChatMessageItemView = ({
|
|
|
1873
2227
|
`markdown-${index}`
|
|
1874
2228
|
);
|
|
1875
2229
|
case "notice":
|
|
1876
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2230
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PDEAINoticeCard, { text: block.text, tone: block.tone }) }, `notice-${index}`);
|
|
1877
2231
|
case "parameter_summary":
|
|
1878
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2232
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PDEAIParameterSummaryCard, { items: block.items }) }, `parameter-summary-${index}`);
|
|
1879
2233
|
case "confirmation_card":
|
|
1880
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2234
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1881
2235
|
PDEAIExecutionConfirmationCard,
|
|
1882
2236
|
{
|
|
1883
2237
|
proposal: block.proposal,
|
|
@@ -1890,9 +2244,9 @@ var ChatMessageItemView = ({
|
|
|
1890
2244
|
}
|
|
1891
2245
|
) }, `confirmation-card-${index}`);
|
|
1892
2246
|
case "result_summary":
|
|
1893
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2247
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PDEAIResultSummaryCard, { summary: block.summary }) }, `result-summary-${index}`);
|
|
1894
2248
|
case "questionnaire":
|
|
1895
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2249
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1896
2250
|
PDEAIQuestionnaireCard,
|
|
1897
2251
|
{
|
|
1898
2252
|
questionnaire: block.questionnaire,
|
|
@@ -1904,7 +2258,7 @@ var ChatMessageItemView = ({
|
|
|
1904
2258
|
}
|
|
1905
2259
|
) }, `questionnaire-${index}`);
|
|
1906
2260
|
case "custom":
|
|
1907
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2261
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: renderMessageBlock?.({
|
|
1908
2262
|
block,
|
|
1909
2263
|
index,
|
|
1910
2264
|
message,
|
|
@@ -1916,19 +2270,69 @@ var ChatMessageItemView = ({
|
|
|
1916
2270
|
return null;
|
|
1917
2271
|
}
|
|
1918
2272
|
};
|
|
1919
|
-
const renderTextContent = () =>
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
2273
|
+
const renderTextContent = (options) => {
|
|
2274
|
+
const textContent = options?.content ?? displayedContent;
|
|
2275
|
+
const localTimelineTextDisplay = options?.displayedBlocks ? void 0 : options?.useTimelineSegmentation && options.content !== void 0 ? buildTimelineTextDisplay(options.content, isAssistantStreaming, isFreshBlockActive) : void 0;
|
|
2276
|
+
const textBlocks = options?.displayedBlocks ?? localTimelineTextDisplay?.displayedBlocks ?? displayedBlocks;
|
|
2277
|
+
const settledText = localTimelineTextDisplay?.settledContent ?? settledContent;
|
|
2278
|
+
const freshText = localTimelineTextDisplay?.freshContent ?? freshContent;
|
|
2279
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2280
|
+
textBlocks.filter((block) => block.content).map((block, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2281
|
+
ContentBlock,
|
|
2282
|
+
{
|
|
2283
|
+
"data-testid": block.tone === "fresh" ? "chat-message-fresh-block" : "chat-message-settled-block",
|
|
2284
|
+
"data-block-tone": block.tone,
|
|
2285
|
+
"data-block-index": index,
|
|
2286
|
+
children: renderMarkdownContent(block.content)
|
|
2287
|
+
},
|
|
2288
|
+
`${block.tone}-${index}`
|
|
2289
|
+
)),
|
|
2290
|
+
!textBlocks.some((block) => block.content) && !settledText && !freshText && Boolean(textContent) ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ContentBlock, { "data-testid": "chat-message-settled-block", "data-block-tone": "settled", children: renderMarkdownContent(textContent) }) : null
|
|
2291
|
+
] });
|
|
2292
|
+
};
|
|
2293
|
+
const renderStaticTextSegment = (content) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ContentBlock, { "data-testid": "chat-message-settled-block", "data-block-tone": "settled", children: renderMarkdownContent(content) });
|
|
2294
|
+
const bodySegments = (() => {
|
|
2295
|
+
if (!shouldRenderStructuredBlocks && hasTextContent) {
|
|
2296
|
+
return [{ type: "text" }];
|
|
2297
|
+
}
|
|
2298
|
+
if (!shouldRenderStructuredBlocks) {
|
|
2299
|
+
return [];
|
|
2300
|
+
}
|
|
2301
|
+
if (messageRenderOrder === "timeline" && hasTextContent) {
|
|
2302
|
+
const hasAnchoredStructuredBlocks = blocks.some((block, index) => {
|
|
2303
|
+
const blockKey = getTimelineBlockKey(block, index);
|
|
2304
|
+
return blockKey ? timelineBlockAnchors[blockKey] !== void 0 : false;
|
|
2305
|
+
});
|
|
2306
|
+
if (hasAnchoredStructuredBlocks) {
|
|
2307
|
+
return buildAnchoredTimelineSegments({
|
|
2308
|
+
blocks,
|
|
2309
|
+
timelineBlockAnchors,
|
|
2310
|
+
timelineDisplayedBlocks: timelineTextDisplay.displayedBlocks,
|
|
2311
|
+
visibleTimelineBlockKeys
|
|
2312
|
+
});
|
|
2313
|
+
}
|
|
2314
|
+
const orderedTimelineSegments = blocks.map(
|
|
2315
|
+
(block, index) => block.type === "markdown" ? {
|
|
2316
|
+
type: "markdown",
|
|
2317
|
+
content: block.text
|
|
2318
|
+
} : {
|
|
2319
|
+
type: "block",
|
|
2320
|
+
block,
|
|
2321
|
+
index
|
|
2322
|
+
}
|
|
2323
|
+
);
|
|
2324
|
+
if (!timelineConsumedText) {
|
|
2325
|
+
return displayedContent ? [{ type: "text", content: displayedContent }, ...orderedTimelineSegments] : orderedTimelineSegments;
|
|
2326
|
+
}
|
|
2327
|
+
return timelineDisplayedContent ? [...orderedTimelineSegments, { type: "text", content: timelineDisplayedContent }] : orderedTimelineSegments;
|
|
2328
|
+
}
|
|
2329
|
+
const orderedBlocks = blocks.map((block, index) => ({
|
|
2330
|
+
type: "block",
|
|
2331
|
+
block,
|
|
2332
|
+
index
|
|
2333
|
+
}));
|
|
2334
|
+
return hasTextContent ? [...orderedBlocks, { type: "text" }] : orderedBlocks;
|
|
2335
|
+
})();
|
|
1932
2336
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
1933
2337
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Bubble, { "data-role": message.role, "data-status": message.status ?? "done", children: [
|
|
1934
2338
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Header2, { children: [
|
|
@@ -1947,17 +2351,18 @@ var ChatMessageItemView = ({
|
|
|
1947
2351
|
isStoppedAssistant ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StatusTag, { "data-testid": "chat-message-stopped-tag", children: labels.stoppedResponse }) : null
|
|
1948
2352
|
] }),
|
|
1949
2353
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Content, { "data-testid": "chat-message-content", children: [
|
|
1950
|
-
shouldRenderStructuredBlocks || hasTextContent ? /* @__PURE__ */ (0, import_jsx_runtime8.
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
2354
|
+
shouldRenderStructuredBlocks || hasTextContent ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ContentStack, { "data-testid": "chat-message-body-stack", children: bodySegments.map((segment, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2355
|
+
ContentSegment,
|
|
2356
|
+
{
|
|
2357
|
+
"data-testid": "chat-message-content-segment",
|
|
2358
|
+
children: segment.type === "block" ? renderChatMessageBlock(segment.block, segment.index) : segment.type === "text" ? segment.content !== void 0 ? segment.useTimelineSegmentation ? renderTextContent({
|
|
2359
|
+
content: segment.content,
|
|
2360
|
+
displayedBlocks: segment.displayedBlocks,
|
|
2361
|
+
useTimelineSegmentation: true
|
|
2362
|
+
}) : renderStaticTextSegment(segment.content) : renderTextContent() : renderStaticTextSegment(segment.content)
|
|
2363
|
+
},
|
|
2364
|
+
segment.type === "text" ? `text-${index}` : segment.type === "markdown" ? `markdown-${index}` : `${segment.block.type}-${segment.index}`
|
|
2365
|
+
)) }) : null,
|
|
1961
2366
|
attachments.length ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(AttachmentGrid, { "data-testid": "chat-message-attachment-grid", children: attachments.map((attachment) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1962
2367
|
AttachmentButton,
|
|
1963
2368
|
{
|
|
@@ -1984,7 +2389,7 @@ var ChatMessageItemView = ({
|
|
|
1984
2389
|
) : null
|
|
1985
2390
|
] });
|
|
1986
2391
|
};
|
|
1987
|
-
var ChatMessageItem = (0,
|
|
2392
|
+
var ChatMessageItem = (0, import_react9.memo)(
|
|
1988
2393
|
ChatMessageItemView,
|
|
1989
2394
|
(previousProps, nextProps) => isSameMessage(
|
|
1990
2395
|
previousProps.message,
|
|
@@ -2129,7 +2534,7 @@ var AttachmentImage = import_styled7.default.img`
|
|
|
2129
2534
|
var TableWrapper = import_styled7.default.div`
|
|
2130
2535
|
overflow-x: auto;
|
|
2131
2536
|
`;
|
|
2132
|
-
var caretBlink =
|
|
2537
|
+
var caretBlink = import_react10.keyframes`
|
|
2133
2538
|
0%, 49% {
|
|
2134
2539
|
opacity: 1;
|
|
2135
2540
|
}
|
|
@@ -2138,7 +2543,7 @@ var caretBlink = import_react9.keyframes`
|
|
|
2138
2543
|
opacity: 0.2;
|
|
2139
2544
|
}
|
|
2140
2545
|
`;
|
|
2141
|
-
var shimmer =
|
|
2546
|
+
var shimmer = import_react10.keyframes`
|
|
2142
2547
|
0%, 100% {
|
|
2143
2548
|
transform: scale(0.9) rotate(0deg);
|
|
2144
2549
|
opacity: 0.55;
|
|
@@ -2349,18 +2754,18 @@ var ChatThreadView = ({
|
|
|
2349
2754
|
onQuestionnaireSubmit,
|
|
2350
2755
|
renderMessageBlock
|
|
2351
2756
|
}) => {
|
|
2352
|
-
const containerRef = (0,
|
|
2353
|
-
const conversationTurns = (0,
|
|
2757
|
+
const containerRef = (0, import_react11.useRef)(null);
|
|
2758
|
+
const conversationTurns = (0, import_react11.useMemo)(
|
|
2354
2759
|
() => groupConversationTurns(historyMessages, streamingMessage),
|
|
2355
2760
|
[historyMessages, streamingMessage]
|
|
2356
2761
|
);
|
|
2357
2762
|
const latestTurn = conversationTurns[conversationTurns.length - 1];
|
|
2358
2763
|
const previousTurns = conversationTurns.slice(0, -1);
|
|
2359
2764
|
const latestUserMessageId = latestTurn?.userMessage?.id;
|
|
2360
|
-
const latestUserMessageRef = (0,
|
|
2361
|
-
const reservedSpaceFrameRef = (0,
|
|
2362
|
-
const [latestTurnMinHeight, setLatestTurnMinHeight] = (0,
|
|
2363
|
-
const measureLatestTurnMinHeight = (0,
|
|
2765
|
+
const latestUserMessageRef = (0, import_react11.useRef)(null);
|
|
2766
|
+
const reservedSpaceFrameRef = (0, import_react11.useRef)(null);
|
|
2767
|
+
const [latestTurnMinHeight, setLatestTurnMinHeight] = (0, import_react11.useState)(0);
|
|
2768
|
+
const measureLatestTurnMinHeight = (0, import_react11.useCallback)(() => {
|
|
2364
2769
|
const container = containerRef.current;
|
|
2365
2770
|
if (!container)
|
|
2366
2771
|
return;
|
|
@@ -2370,7 +2775,7 @@ var ChatThreadView = ({
|
|
|
2370
2775
|
const nextMinHeight = Math.max(0, container.clientHeight - paddingTop - paddingBottom);
|
|
2371
2776
|
setLatestTurnMinHeight((current) => current === nextMinHeight ? current : nextMinHeight);
|
|
2372
2777
|
}, []);
|
|
2373
|
-
const scrollLatestUserMessageToTop = (0,
|
|
2778
|
+
const scrollLatestUserMessageToTop = (0, import_react11.useCallback)(() => {
|
|
2374
2779
|
const container = containerRef.current;
|
|
2375
2780
|
const target = latestUserMessageRef.current;
|
|
2376
2781
|
if (!container || !target)
|
|
@@ -2390,7 +2795,7 @@ var ChatThreadView = ({
|
|
|
2390
2795
|
}
|
|
2391
2796
|
container.scrollTop = nextScrollTop;
|
|
2392
2797
|
}, []);
|
|
2393
|
-
(0,
|
|
2798
|
+
(0, import_react11.useLayoutEffect)(() => {
|
|
2394
2799
|
if (reservedSpaceFrameRef.current !== null) {
|
|
2395
2800
|
window.cancelAnimationFrame(reservedSpaceFrameRef.current);
|
|
2396
2801
|
reservedSpaceFrameRef.current = null;
|
|
@@ -2419,7 +2824,7 @@ var ChatThreadView = ({
|
|
|
2419
2824
|
}
|
|
2420
2825
|
};
|
|
2421
2826
|
}, [latestUserMessageId, measureLatestTurnMinHeight, scrollLatestUserMessageToTop]);
|
|
2422
|
-
(0,
|
|
2827
|
+
(0, import_react11.useLayoutEffect)(() => {
|
|
2423
2828
|
if (!latestUserMessageId)
|
|
2424
2829
|
return;
|
|
2425
2830
|
const handleResize = () => {
|
|
@@ -2507,13 +2912,13 @@ var ChatThread = () => {
|
|
|
2507
2912
|
const updateQA = useChatStore((s) => s.updateQuestionnaireAnswers);
|
|
2508
2913
|
const clearSessionError = useChatStore((s) => s.clearSessionError);
|
|
2509
2914
|
const { sendRef, retryRef, renderMessageBlock, labels } = useChatContext();
|
|
2510
|
-
const handleRetry = (0,
|
|
2915
|
+
const handleRetry = (0, import_react11.useCallback)(() => {
|
|
2511
2916
|
if (!activeSessionId)
|
|
2512
2917
|
return;
|
|
2513
2918
|
clearSessionError(activeSessionId);
|
|
2514
2919
|
void retryRef.current();
|
|
2515
2920
|
}, [activeSessionId, clearSessionError, retryRef]);
|
|
2516
|
-
const handleQuestionnaireSubmit = (0,
|
|
2921
|
+
const handleQuestionnaireSubmit = (0, import_react11.useCallback)(
|
|
2517
2922
|
(submission) => {
|
|
2518
2923
|
if (activeSessionId && submission.sourceMessageId) {
|
|
2519
2924
|
updateQA(
|
|
@@ -2527,7 +2932,7 @@ var ChatThread = () => {
|
|
|
2527
2932
|
},
|
|
2528
2933
|
[activeSessionId, updateQA, sendRef]
|
|
2529
2934
|
);
|
|
2530
|
-
const handleConfirmationSubmit = (0,
|
|
2935
|
+
const handleConfirmationSubmit = (0, import_react11.useCallback)(
|
|
2531
2936
|
(submission) => {
|
|
2532
2937
|
void sendRef.current(submission.content);
|
|
2533
2938
|
},
|
|
@@ -2612,7 +3017,7 @@ var RetryButton = import_styled9.default.button`
|
|
|
2612
3017
|
`;
|
|
2613
3018
|
|
|
2614
3019
|
// src/components/chat-composer/index.tsx
|
|
2615
|
-
var
|
|
3020
|
+
var import_react15 = require("react");
|
|
2616
3021
|
var import_styled14 = __toESM(require("@emotion/styled"));
|
|
2617
3022
|
|
|
2618
3023
|
// src/components/chat-composer/lib/chat-composer.ts
|
|
@@ -2724,10 +3129,10 @@ var resolveSendSession = ({
|
|
|
2724
3129
|
};
|
|
2725
3130
|
|
|
2726
3131
|
// src/components/chat-composer/hooks/use-chat-composer.ts
|
|
2727
|
-
var
|
|
3132
|
+
var import_react13 = require("react");
|
|
2728
3133
|
|
|
2729
3134
|
// src/components/chat-composer/hooks/use-composer-attachments.ts
|
|
2730
|
-
var
|
|
3135
|
+
var import_react12 = require("react");
|
|
2731
3136
|
var SUPPORTED_IMAGE_MIME_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/webp"]);
|
|
2732
3137
|
var MAX_COMPOSER_ATTACHMENTS = 10;
|
|
2733
3138
|
var createObjectUrl = (file) => typeof URL !== "undefined" && typeof URL.createObjectURL === "function" ? URL.createObjectURL(file) : "";
|
|
@@ -2741,12 +3146,12 @@ var releaseComposerAttachments = (attachments) => {
|
|
|
2741
3146
|
attachments.forEach((attachment) => revokeObjectUrl(attachment.previewUrl));
|
|
2742
3147
|
};
|
|
2743
3148
|
var useComposerAttachments = () => {
|
|
2744
|
-
const [attachments, setAttachments] = (0,
|
|
2745
|
-
const attachmentsRef = (0,
|
|
2746
|
-
(0,
|
|
3149
|
+
const [attachments, setAttachments] = (0, import_react12.useState)([]);
|
|
3150
|
+
const attachmentsRef = (0, import_react12.useRef)([]);
|
|
3151
|
+
(0, import_react12.useEffect)(() => {
|
|
2747
3152
|
attachmentsRef.current = attachments;
|
|
2748
3153
|
}, [attachments]);
|
|
2749
|
-
(0,
|
|
3154
|
+
(0, import_react12.useEffect)(
|
|
2750
3155
|
() => () => {
|
|
2751
3156
|
releaseComposerAttachments(attachmentsRef.current);
|
|
2752
3157
|
},
|
|
@@ -2859,10 +3264,10 @@ var useChatComposer = () => {
|
|
|
2859
3264
|
const clearSessionError = useChatStore((s) => s.clearSessionError);
|
|
2860
3265
|
const setPreferredMode = useChatStore((s) => s.setPreferredMode);
|
|
2861
3266
|
const setSessionMode = useChatStore((s) => s.setSessionMode);
|
|
2862
|
-
const [availableModels, setAvailableModels] = (0,
|
|
2863
|
-
const [isModelsLoading, setIsModelsLoading] = (0,
|
|
2864
|
-
const [isModelsError, setIsModelsError] = (0,
|
|
2865
|
-
const fetchModels = (0,
|
|
3267
|
+
const [availableModels, setAvailableModels] = (0, import_react13.useState)([]);
|
|
3268
|
+
const [isModelsLoading, setIsModelsLoading] = (0, import_react13.useState)(true);
|
|
3269
|
+
const [isModelsError, setIsModelsError] = (0, import_react13.useState)(false);
|
|
3270
|
+
const fetchModels = (0, import_react13.useCallback)(async () => {
|
|
2866
3271
|
setIsModelsLoading(true);
|
|
2867
3272
|
setIsModelsError(false);
|
|
2868
3273
|
try {
|
|
@@ -2874,31 +3279,31 @@ var useChatComposer = () => {
|
|
|
2874
3279
|
setIsModelsLoading(false);
|
|
2875
3280
|
}
|
|
2876
3281
|
}, [transport]);
|
|
2877
|
-
(0,
|
|
3282
|
+
(0, import_react13.useEffect)(() => {
|
|
2878
3283
|
void fetchModels();
|
|
2879
3284
|
}, [fetchModels]);
|
|
2880
3285
|
const hasModels = availableModels.length > 0;
|
|
2881
|
-
const [value, setValue] = (0,
|
|
2882
|
-
const [selectedModel, setSelectedModel] = (0,
|
|
2883
|
-
const [selectedMode, setSelectedModeLocal] = (0,
|
|
2884
|
-
const [attachmentNotice, setAttachmentNotice] = (0,
|
|
3286
|
+
const [value, setValue] = (0, import_react13.useState)("");
|
|
3287
|
+
const [selectedModel, setSelectedModel] = (0, import_react13.useState)("");
|
|
3288
|
+
const [selectedMode, setSelectedModeLocal] = (0, import_react13.useState)(DEFAULT_CHAT_AGENT_MODE);
|
|
3289
|
+
const [attachmentNotice, setAttachmentNotice] = (0, import_react13.useState)(null);
|
|
2885
3290
|
const { attachments, appendFiles, removeAttachment, takeMessageAttachments } = useComposerAttachments();
|
|
2886
|
-
const abortControllerRef = (0,
|
|
2887
|
-
const stopRequestRef = (0,
|
|
2888
|
-
const lastRequestRef = (0,
|
|
2889
|
-
(0,
|
|
3291
|
+
const abortControllerRef = (0, import_react13.useRef)(null);
|
|
3292
|
+
const stopRequestRef = (0, import_react13.useRef)(null);
|
|
3293
|
+
const lastRequestRef = (0, import_react13.useRef)(null);
|
|
3294
|
+
(0, import_react13.useEffect)(() => {
|
|
2890
3295
|
setSelectedModel(
|
|
2891
3296
|
(current) => resolveSelectedChatModel({ currentModel: current, availableModels, isModelsLoading })
|
|
2892
3297
|
);
|
|
2893
3298
|
}, [availableModels, isModelsLoading]);
|
|
2894
|
-
(0,
|
|
3299
|
+
(0, import_react13.useEffect)(() => {
|
|
2895
3300
|
if (activeSession) {
|
|
2896
3301
|
setSelectedModeLocal(activeSession.mode ?? DEFAULT_CHAT_AGENT_MODE);
|
|
2897
3302
|
return;
|
|
2898
3303
|
}
|
|
2899
3304
|
setSelectedModeLocal(preferredMode ?? DEFAULT_CHAT_AGENT_MODE);
|
|
2900
3305
|
}, [activeSession, preferredMode]);
|
|
2901
|
-
(0,
|
|
3306
|
+
(0, import_react13.useEffect)(() => {
|
|
2902
3307
|
if (!attachmentNotice)
|
|
2903
3308
|
return;
|
|
2904
3309
|
const timeoutId = window.setTimeout(
|
|
@@ -2917,7 +3322,7 @@ var useChatComposer = () => {
|
|
|
2917
3322
|
stopRequestRef.current.timeoutId = null;
|
|
2918
3323
|
}
|
|
2919
3324
|
};
|
|
2920
|
-
const clearStopRequest = (0,
|
|
3325
|
+
const clearStopRequest = (0, import_react13.useCallback)((sessionId) => {
|
|
2921
3326
|
if (!stopRequestRef.current)
|
|
2922
3327
|
return;
|
|
2923
3328
|
if (sessionId && stopRequestRef.current.sessionId !== sessionId)
|
|
@@ -2925,7 +3330,7 @@ var useChatComposer = () => {
|
|
|
2925
3330
|
clearStopTimeout(sessionId);
|
|
2926
3331
|
stopRequestRef.current = null;
|
|
2927
3332
|
}, []);
|
|
2928
|
-
const finalizeStop = (0,
|
|
3333
|
+
const finalizeStop = (0, import_react13.useCallback)(
|
|
2929
3334
|
(sessionId) => {
|
|
2930
3335
|
if (stopRequestRef.current?.sessionId === sessionId) {
|
|
2931
3336
|
if (stopRequestRef.current.finalized)
|
|
@@ -2940,7 +3345,7 @@ var useChatComposer = () => {
|
|
|
2940
3345
|
},
|
|
2941
3346
|
[clearStopRequest, finalizeStoppedStreamingMessage]
|
|
2942
3347
|
);
|
|
2943
|
-
const runStream = (0,
|
|
3348
|
+
const runStream = (0, import_react13.useCallback)(
|
|
2944
3349
|
async ({
|
|
2945
3350
|
localSessionId,
|
|
2946
3351
|
sessionId,
|
|
@@ -3029,7 +3434,7 @@ var useChatComposer = () => {
|
|
|
3029
3434
|
setSessionError
|
|
3030
3435
|
]
|
|
3031
3436
|
);
|
|
3032
|
-
const send = (0,
|
|
3437
|
+
const send = (0, import_react13.useCallback)(
|
|
3033
3438
|
async (contentOverride) => {
|
|
3034
3439
|
const content = (contentOverride ?? value).trim();
|
|
3035
3440
|
const hasText = Boolean(content);
|
|
@@ -3177,14 +3582,14 @@ var useChatComposer = () => {
|
|
|
3177
3582
|
};
|
|
3178
3583
|
|
|
3179
3584
|
// src/components/chat-composer/components/chat-composer-attachment-list.tsx
|
|
3180
|
-
var
|
|
3585
|
+
var import_react14 = require("react");
|
|
3181
3586
|
var import_styled10 = __toESM(require("@emotion/styled"));
|
|
3182
3587
|
var import_jsx_runtime11 = require("@emotion/react/jsx-runtime");
|
|
3183
3588
|
var ChatComposerAttachmentList = ({
|
|
3184
3589
|
attachments,
|
|
3185
3590
|
onRemoveAttachment
|
|
3186
3591
|
}) => {
|
|
3187
|
-
const [activeImage, setActiveImage] = (0,
|
|
3592
|
+
const [activeImage, setActiveImage] = (0, import_react14.useState)(null);
|
|
3188
3593
|
if (!attachments.length) {
|
|
3189
3594
|
return null;
|
|
3190
3595
|
}
|
|
@@ -3676,7 +4081,7 @@ var ChatComposerView = ({
|
|
|
3676
4081
|
onStop,
|
|
3677
4082
|
onSend
|
|
3678
4083
|
}) => {
|
|
3679
|
-
const imageInputRef = (0,
|
|
4084
|
+
const imageInputRef = (0, import_react15.useRef)(null);
|
|
3680
4085
|
const canSend = canSendChatMessage({
|
|
3681
4086
|
value,
|
|
3682
4087
|
attachmentCount: attachments.length,
|
|
@@ -3788,7 +4193,7 @@ var ChatComposer = () => {
|
|
|
3788
4193
|
const { labels, sendRef, retryRef, enableImageAttachments } = useChatContext();
|
|
3789
4194
|
const { state, actions } = useChatComposer();
|
|
3790
4195
|
const { send, retry } = actions;
|
|
3791
|
-
(0,
|
|
4196
|
+
(0, import_react15.useEffect)(() => {
|
|
3792
4197
|
sendRef.current = send;
|
|
3793
4198
|
retryRef.current = async () => {
|
|
3794
4199
|
retry();
|
|
@@ -3909,10 +4314,10 @@ var AttachButton = import_styled14.default.button`
|
|
|
3909
4314
|
var import_styled16 = __toESM(require("@emotion/styled"));
|
|
3910
4315
|
|
|
3911
4316
|
// src/components/chat-conversation-list/components/chat-session-item.tsx
|
|
3912
|
-
var
|
|
4317
|
+
var import_react16 = require("react");
|
|
3913
4318
|
var import_styled15 = __toESM(require("@emotion/styled"));
|
|
3914
4319
|
var import_jsx_runtime16 = require("@emotion/react/jsx-runtime");
|
|
3915
|
-
var ChatSessionItem = (0,
|
|
4320
|
+
var ChatSessionItem = (0, import_react16.memo)(
|
|
3916
4321
|
({ session, isActive, modeLabel, onClick }) => {
|
|
3917
4322
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
3918
4323
|
SessionButton,
|
|
@@ -4108,6 +4513,7 @@ var Workspace = import_styled17.default.section`
|
|
|
4108
4513
|
AiChat,
|
|
4109
4514
|
AiChatProvider,
|
|
4110
4515
|
CHAT_AGENT_MODES,
|
|
4516
|
+
CHAT_MESSAGE_RENDER_ORDERS,
|
|
4111
4517
|
ChatComposer,
|
|
4112
4518
|
ChatConversationList,
|
|
4113
4519
|
ChatThread,
|