@xinghunm/ai-chat 0.3.0 → 1.0.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/dist/index.d.mts +56 -7
- package/dist/index.d.ts +56 -7
- package/dist/index.js +733 -234
- package/dist/index.mjs +775 -276
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -31,10 +31,18 @@ var DEFAULT_AI_CHAT_LABELS = {
|
|
|
31
31
|
attachmentLimitNotice: "Images exceeded the limit. Only the first 10 images were kept.",
|
|
32
32
|
userRoleLabel: "User",
|
|
33
33
|
assistantRoleLabel: "Assistant",
|
|
34
|
+
expandMessageAriaLabel: "Expand message",
|
|
35
|
+
collapseMessageAriaLabel: "Collapse message",
|
|
36
|
+
expandComposerAriaLabel: "Expand composer",
|
|
37
|
+
collapseComposerAriaLabel: "Collapse composer",
|
|
34
38
|
stoppedResponse: "Response stopped",
|
|
35
39
|
assistantStreamingAriaLabel: "assistant streaming",
|
|
36
40
|
networkError: "Network request failed. Please try again.",
|
|
37
|
-
genericError: "Something went wrong. Please try again."
|
|
41
|
+
genericError: "Something went wrong. Please try again.",
|
|
42
|
+
questionnaireSubmitting: "Submitting...",
|
|
43
|
+
questionnaireSubmitted: "Selection submitted. Waiting for the plan to continue...",
|
|
44
|
+
questionnaireValidationPrefix: "Please complete:",
|
|
45
|
+
questionnaireSubmitFailed: "Failed to submit. Please try again."
|
|
38
46
|
};
|
|
39
47
|
|
|
40
48
|
// src/store/chat-store.ts
|
|
@@ -50,6 +58,24 @@ var resolveSessionTitleFromMessage = (message) => {
|
|
|
50
58
|
}
|
|
51
59
|
return DEFAULT_CHAT_SESSION_TITLE;
|
|
52
60
|
};
|
|
61
|
+
var mergeStreamingBlocks = (existingBlocks, incomingBlocks) => {
|
|
62
|
+
const nextBlocks = [...existingBlocks ?? []];
|
|
63
|
+
incomingBlocks.forEach((incomingBlock) => {
|
|
64
|
+
if (incomingBlock.type !== "questionnaire") {
|
|
65
|
+
nextBlocks.push(incomingBlock);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const existingIndex = nextBlocks.findIndex(
|
|
69
|
+
(block) => block.type === "questionnaire" && block.questionnaire.questionnaireId === incomingBlock.questionnaire.questionnaireId
|
|
70
|
+
);
|
|
71
|
+
if (existingIndex === -1) {
|
|
72
|
+
nextBlocks.push(incomingBlock);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
nextBlocks[existingIndex] = incomingBlock;
|
|
76
|
+
});
|
|
77
|
+
return nextBlocks;
|
|
78
|
+
};
|
|
53
79
|
var finalizeStreamingMessage = (state, sessionId, status, clearError = false) => {
|
|
54
80
|
const message = state.streamingMessageBySession[sessionId];
|
|
55
81
|
const hasRenderableMessagePayload = Boolean(
|
|
@@ -239,10 +265,15 @@ var createChatStore = (initialState) => createStore((set, get) => ({
|
|
|
239
265
|
const target = state.streamingMessageBySession[sessionId];
|
|
240
266
|
if (!target)
|
|
241
267
|
return;
|
|
268
|
+
const nextBlocks = patch.blocks !== void 0 ? mergeStreamingBlocks(target.blocks, patch.blocks) : target.blocks;
|
|
242
269
|
set({
|
|
243
270
|
streamingMessageBySession: {
|
|
244
271
|
...state.streamingMessageBySession,
|
|
245
|
-
[sessionId]: {
|
|
272
|
+
[sessionId]: {
|
|
273
|
+
...target,
|
|
274
|
+
...patch,
|
|
275
|
+
...patch.blocks !== void 0 ? { blocks: nextBlocks } : {}
|
|
276
|
+
}
|
|
246
277
|
}
|
|
247
278
|
});
|
|
248
279
|
},
|
|
@@ -462,9 +493,27 @@ var DEFAULT_CHAT_TRANSPORT_ENDPOINTS = {
|
|
|
462
493
|
completions: "/chat/completions",
|
|
463
494
|
terminate: "/chat/terminate"
|
|
464
495
|
};
|
|
496
|
+
var createToolExecutionHeaders = (policy) => {
|
|
497
|
+
if (!policy?.enabled) {
|
|
498
|
+
return {};
|
|
499
|
+
}
|
|
500
|
+
return {
|
|
501
|
+
"X-Tool-Approval-Required": String(Boolean(policy.approvalRequired)),
|
|
502
|
+
...typeof policy.approvalTimeoutSec === "number" ? { "X-Tool-Approval-Timeout": String(policy.approvalTimeoutSec) } : {}
|
|
503
|
+
};
|
|
504
|
+
};
|
|
505
|
+
var createModeDefaultHeaders = (mode) => {
|
|
506
|
+
if (mode === "ask" || mode === "plan") {
|
|
507
|
+
return {
|
|
508
|
+
"X-Tool-Approval-Required": "false"
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
return {};
|
|
512
|
+
};
|
|
465
513
|
var createDefaultChatTransport = ({
|
|
466
514
|
apiBaseUrl,
|
|
467
515
|
authToken,
|
|
516
|
+
toolExecutionPolicy,
|
|
468
517
|
streamHeaders,
|
|
469
518
|
transformStreamPacket,
|
|
470
519
|
endpoints,
|
|
@@ -475,6 +524,10 @@ var createDefaultChatTransport = ({
|
|
|
475
524
|
...DEFAULT_CHAT_TRANSPORT_ENDPOINTS,
|
|
476
525
|
...endpoints
|
|
477
526
|
};
|
|
527
|
+
const resolvedStreamHeaders = {
|
|
528
|
+
...createToolExecutionHeaders(toolExecutionPolicy),
|
|
529
|
+
...streamHeaders
|
|
530
|
+
};
|
|
478
531
|
return {
|
|
479
532
|
getModels: () => getChatModels(client, resolvedEndpoints.models),
|
|
480
533
|
startStream: async ({
|
|
@@ -488,12 +541,16 @@ var createDefaultChatTransport = ({
|
|
|
488
541
|
onDone,
|
|
489
542
|
onError
|
|
490
543
|
}) => {
|
|
544
|
+
const requestHeaders = {
|
|
545
|
+
...createModeDefaultHeaders(mode),
|
|
546
|
+
...resolvedStreamHeaders
|
|
547
|
+
};
|
|
491
548
|
await startChatStream({
|
|
492
549
|
apiBaseUrl,
|
|
493
550
|
endpointPath: resolvedEndpoints.completions,
|
|
494
551
|
sessionId,
|
|
495
552
|
authToken,
|
|
496
|
-
requestHeaders
|
|
553
|
+
requestHeaders,
|
|
497
554
|
model,
|
|
498
555
|
mode,
|
|
499
556
|
content,
|
|
@@ -522,6 +579,8 @@ var AiChatProvider = (props) => {
|
|
|
522
579
|
defaultMode,
|
|
523
580
|
labels,
|
|
524
581
|
renderMessageBlock,
|
|
582
|
+
handleQuestionnaireSubmit,
|
|
583
|
+
handleConfirmationSubmit,
|
|
525
584
|
messageRenderOrder,
|
|
526
585
|
enableImageAttachments = true,
|
|
527
586
|
children
|
|
@@ -577,6 +636,8 @@ var AiChatProvider = (props) => {
|
|
|
577
636
|
sendRef,
|
|
578
637
|
retryRef,
|
|
579
638
|
renderMessageBlock,
|
|
639
|
+
handleQuestionnaireSubmit,
|
|
640
|
+
handleConfirmationSubmit,
|
|
580
641
|
messageRenderOrder,
|
|
581
642
|
transformStreamPacket: defaultTransformStreamPacket,
|
|
582
643
|
enableImageAttachments
|
|
@@ -587,6 +648,8 @@ var AiChatProvider = (props) => {
|
|
|
587
648
|
defaultAuthToken,
|
|
588
649
|
defaultTransformStreamPacket,
|
|
589
650
|
enableImageAttachments,
|
|
651
|
+
handleConfirmationSubmit,
|
|
652
|
+
handleQuestionnaireSubmit,
|
|
590
653
|
labels,
|
|
591
654
|
messageRenderOrder,
|
|
592
655
|
renderMessageBlock,
|
|
@@ -600,7 +663,7 @@ var AiChatProvider = (props) => {
|
|
|
600
663
|
};
|
|
601
664
|
|
|
602
665
|
// src/components/chat-thread/index.tsx
|
|
603
|
-
import { useCallback as
|
|
666
|
+
import { useCallback as useCallback3, useLayoutEffect as useLayoutEffect2, useMemo as useMemo4, useRef as useRef4, useState as useState4 } from "react";
|
|
604
667
|
import styled9 from "@emotion/styled";
|
|
605
668
|
|
|
606
669
|
// src/context/use-chat-context.ts
|
|
@@ -621,7 +684,7 @@ var useChatStore = (selector) => {
|
|
|
621
684
|
var CHAT_THREAD_SCROLL_TOP_GAP = 16;
|
|
622
685
|
|
|
623
686
|
// src/components/chat-thread/components/chat-message-item.tsx
|
|
624
|
-
import { Fragment, memo, useState as
|
|
687
|
+
import { Fragment, memo, useCallback as useCallback2, useLayoutEffect, useState as useState3 } from "react";
|
|
625
688
|
import styled7 from "@emotion/styled";
|
|
626
689
|
import { keyframes } from "@emotion/react";
|
|
627
690
|
import ReactMarkdown from "react-markdown";
|
|
@@ -870,7 +933,7 @@ var useChatMessageReveal = (message) => {
|
|
|
870
933
|
};
|
|
871
934
|
|
|
872
935
|
// src/components/chat-thread/hooks/use-timeline-block-anchors.ts
|
|
873
|
-
import { useEffect as useEffect2, useMemo as useMemo3,
|
|
936
|
+
import { useEffect as useEffect2, useMemo as useMemo3, useReducer as useReducer2 } from "react";
|
|
874
937
|
|
|
875
938
|
// src/components/chat-thread/lib/chat-message-timeline.ts
|
|
876
939
|
var stringifyTimelineKeyPart = (value) => {
|
|
@@ -896,7 +959,7 @@ var getTimelineBlockKey = (block, index) => {
|
|
|
896
959
|
case "confirmation_card":
|
|
897
960
|
return `${index}:confirmation_card:${block.proposal.proposalId}`;
|
|
898
961
|
case "result_summary":
|
|
899
|
-
return `${index}:result_summary:${block.summary.
|
|
962
|
+
return `${index}:result_summary:${block.summary.summaryId}:${block.summary.status}`;
|
|
900
963
|
case "questionnaire":
|
|
901
964
|
return `${index}:questionnaire:${block.questionnaire.questionnaireId}`;
|
|
902
965
|
case "custom":
|
|
@@ -1022,6 +1085,83 @@ var buildAnchoredTimelineSegments = ({
|
|
|
1022
1085
|
};
|
|
1023
1086
|
|
|
1024
1087
|
// src/components/chat-thread/hooks/use-timeline-block-anchors.ts
|
|
1088
|
+
var createTimelineAnchorState = ({
|
|
1089
|
+
messageId,
|
|
1090
|
+
currentBlockKeys
|
|
1091
|
+
}) => ({
|
|
1092
|
+
messageId,
|
|
1093
|
+
previousBlockKeys: currentBlockKeys,
|
|
1094
|
+
timelineBlockAnchors: {},
|
|
1095
|
+
visibleTimelineBlockKeys: {}
|
|
1096
|
+
});
|
|
1097
|
+
var timelineAnchorReducer = (state, action) => {
|
|
1098
|
+
switch (action.type) {
|
|
1099
|
+
case "reset-message":
|
|
1100
|
+
if (state.messageId === action.messageId) {
|
|
1101
|
+
return state;
|
|
1102
|
+
}
|
|
1103
|
+
return createTimelineAnchorState(action);
|
|
1104
|
+
case "sync-anchors": {
|
|
1105
|
+
const previousBlockKeys = new Set(state.previousBlockKeys);
|
|
1106
|
+
const nextAnchors = action.currentBlockKeys.reduce(
|
|
1107
|
+
(acc, blockKey) => {
|
|
1108
|
+
const existingAnchor = state.timelineBlockAnchors[blockKey];
|
|
1109
|
+
if (existingAnchor !== void 0) {
|
|
1110
|
+
acc[blockKey] = existingAnchor;
|
|
1111
|
+
return acc;
|
|
1112
|
+
}
|
|
1113
|
+
if (!previousBlockKeys.has(blockKey)) {
|
|
1114
|
+
acc[blockKey] = action.timelineTextStreamLength;
|
|
1115
|
+
}
|
|
1116
|
+
return acc;
|
|
1117
|
+
},
|
|
1118
|
+
{}
|
|
1119
|
+
);
|
|
1120
|
+
const hasAnchorChanged = Object.keys(nextAnchors).length !== Object.keys(state.timelineBlockAnchors).length || Object.entries(nextAnchors).some(
|
|
1121
|
+
([blockKey, anchor]) => state.timelineBlockAnchors[blockKey] !== anchor
|
|
1122
|
+
);
|
|
1123
|
+
const hasPreviousKeysChanged = action.currentBlockKeys.length !== state.previousBlockKeys.length || action.currentBlockKeys.some(
|
|
1124
|
+
(blockKey, index) => state.previousBlockKeys[index] !== blockKey
|
|
1125
|
+
);
|
|
1126
|
+
if (!hasAnchorChanged && !hasPreviousKeysChanged) {
|
|
1127
|
+
return state;
|
|
1128
|
+
}
|
|
1129
|
+
return {
|
|
1130
|
+
...state,
|
|
1131
|
+
previousBlockKeys: action.currentBlockKeys,
|
|
1132
|
+
timelineBlockAnchors: hasAnchorChanged ? nextAnchors : state.timelineBlockAnchors
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
case "sync-visible": {
|
|
1136
|
+
const nextVisibleBlockKeys = action.currentBlockKeys.reduce(
|
|
1137
|
+
(acc, blockKey) => {
|
|
1138
|
+
if (state.visibleTimelineBlockKeys[blockKey]) {
|
|
1139
|
+
acc[blockKey] = true;
|
|
1140
|
+
return acc;
|
|
1141
|
+
}
|
|
1142
|
+
const anchor = action.effectiveTimelineBlockAnchors[blockKey];
|
|
1143
|
+
if (anchor !== void 0 && anchor <= action.displayedTimelineTextLength) {
|
|
1144
|
+
acc[blockKey] = true;
|
|
1145
|
+
}
|
|
1146
|
+
return acc;
|
|
1147
|
+
},
|
|
1148
|
+
{}
|
|
1149
|
+
);
|
|
1150
|
+
const hasVisibleBlockChanged = Object.keys(nextVisibleBlockKeys).length !== Object.keys(state.visibleTimelineBlockKeys).length || Object.keys(nextVisibleBlockKeys).some(
|
|
1151
|
+
(blockKey) => !state.visibleTimelineBlockKeys[blockKey]
|
|
1152
|
+
);
|
|
1153
|
+
if (!hasVisibleBlockChanged) {
|
|
1154
|
+
return state;
|
|
1155
|
+
}
|
|
1156
|
+
return {
|
|
1157
|
+
...state,
|
|
1158
|
+
visibleTimelineBlockKeys: nextVisibleBlockKeys
|
|
1159
|
+
};
|
|
1160
|
+
}
|
|
1161
|
+
default:
|
|
1162
|
+
return state;
|
|
1163
|
+
}
|
|
1164
|
+
};
|
|
1025
1165
|
var useTimelineBlockAnchors = ({
|
|
1026
1166
|
blocks,
|
|
1027
1167
|
displayedTimelineTextLength,
|
|
@@ -1029,8 +1169,6 @@ var useTimelineBlockAnchors = ({
|
|
|
1029
1169
|
message,
|
|
1030
1170
|
messageRenderOrder
|
|
1031
1171
|
}) => {
|
|
1032
|
-
const [timelineBlockAnchors, setTimelineBlockAnchors] = useState2({});
|
|
1033
|
-
const [visibleTimelineBlockKeys, setVisibleTimelineBlockKeys] = useState2({});
|
|
1034
1172
|
const currentTimelineBlockKeys = useMemo3(
|
|
1035
1173
|
() => blocks.map((block, index) => getTimelineBlockKey(block, index)).filter((blockKey) => Boolean(blockKey)),
|
|
1036
1174
|
[blocks]
|
|
@@ -1039,20 +1177,22 @@ var useTimelineBlockAnchors = ({
|
|
|
1039
1177
|
() => getTimelineDisplayUnitCount(getTimelineTextStream(message.content, blocks)),
|
|
1040
1178
|
[blocks, message.content]
|
|
1041
1179
|
);
|
|
1042
|
-
const
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1180
|
+
const [state, dispatch] = useReducer2(
|
|
1181
|
+
timelineAnchorReducer,
|
|
1182
|
+
{
|
|
1183
|
+
messageId: message.id,
|
|
1184
|
+
currentBlockKeys: currentTimelineBlockKeys
|
|
1185
|
+
},
|
|
1186
|
+
createTimelineAnchorState
|
|
1187
|
+
);
|
|
1047
1188
|
const effectiveTimelineBlockAnchors = useMemo3(() => {
|
|
1048
1189
|
if (messageRenderOrder !== "timeline" || !isAssistantStreaming) {
|
|
1049
|
-
return timelineBlockAnchors;
|
|
1190
|
+
return state.timelineBlockAnchors;
|
|
1050
1191
|
}
|
|
1051
|
-
const
|
|
1052
|
-
const previousBlockKeys = new Set(previousTimelineState.blockKeys);
|
|
1192
|
+
const previousBlockKeys = new Set(state.previousBlockKeys);
|
|
1053
1193
|
return currentTimelineBlockKeys.reduce(
|
|
1054
1194
|
(acc, blockKey) => {
|
|
1055
|
-
const existingAnchor = timelineBlockAnchors[blockKey];
|
|
1195
|
+
const existingAnchor = state.timelineBlockAnchors[blockKey];
|
|
1056
1196
|
if (existingAnchor !== void 0) {
|
|
1057
1197
|
acc[blockKey] = existingAnchor;
|
|
1058
1198
|
return acc;
|
|
@@ -1062,125 +1202,70 @@ var useTimelineBlockAnchors = ({
|
|
|
1062
1202
|
}
|
|
1063
1203
|
return acc;
|
|
1064
1204
|
},
|
|
1065
|
-
{ ...timelineBlockAnchors }
|
|
1205
|
+
{ ...state.timelineBlockAnchors }
|
|
1066
1206
|
);
|
|
1067
1207
|
}, [
|
|
1068
1208
|
currentTimelineBlockKeys,
|
|
1069
1209
|
isAssistantStreaming,
|
|
1070
1210
|
messageRenderOrder,
|
|
1071
|
-
|
|
1211
|
+
state.previousBlockKeys,
|
|
1212
|
+
state.timelineBlockAnchors,
|
|
1072
1213
|
timelineTextStreamLength
|
|
1073
1214
|
]);
|
|
1074
1215
|
useEffect2(() => {
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
previousTimelineStateRef.current = {
|
|
1084
|
-
messageId: message.id,
|
|
1085
|
-
blockKeys: currentTimelineBlockKeys,
|
|
1086
|
-
textLength: timelineTextStreamLength
|
|
1087
|
-
};
|
|
1216
|
+
dispatch({
|
|
1217
|
+
type: "reset-message",
|
|
1218
|
+
messageId: message.id,
|
|
1219
|
+
currentBlockKeys: currentTimelineBlockKeys
|
|
1220
|
+
});
|
|
1221
|
+
}, [currentTimelineBlockKeys, message.id]);
|
|
1222
|
+
useEffect2(() => {
|
|
1223
|
+
if (messageRenderOrder !== "timeline" || !isAssistantStreaming) {
|
|
1088
1224
|
return;
|
|
1089
1225
|
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
acc[blockKey] = existingAnchor;
|
|
1097
|
-
return acc;
|
|
1098
|
-
}
|
|
1099
|
-
if (!previousBlockKeys.has(blockKey)) {
|
|
1100
|
-
acc[blockKey] = timelineTextStreamLength;
|
|
1101
|
-
}
|
|
1102
|
-
return acc;
|
|
1103
|
-
},
|
|
1104
|
-
{}
|
|
1105
|
-
);
|
|
1106
|
-
const hasAnchorChanged = Object.keys(nextAnchors).length !== Object.keys(timelineBlockAnchors).length || Object.entries(nextAnchors).some(
|
|
1107
|
-
([blockKey, anchor]) => timelineBlockAnchors[blockKey] !== anchor
|
|
1108
|
-
);
|
|
1109
|
-
if (hasAnchorChanged) {
|
|
1110
|
-
setTimelineBlockAnchors(nextAnchors);
|
|
1111
|
-
}
|
|
1112
|
-
} else if (messageRenderOrder !== "timeline" && Object.keys(timelineBlockAnchors).length > 0) {
|
|
1113
|
-
setTimelineBlockAnchors({});
|
|
1114
|
-
}
|
|
1115
|
-
previousTimelineStateRef.current = {
|
|
1116
|
-
messageId: message.id,
|
|
1117
|
-
blockKeys: currentTimelineBlockKeys,
|
|
1118
|
-
textLength: timelineTextStreamLength
|
|
1119
|
-
};
|
|
1120
|
-
}, [
|
|
1121
|
-
currentTimelineBlockKeys,
|
|
1122
|
-
isAssistantStreaming,
|
|
1123
|
-
message.id,
|
|
1124
|
-
message.content,
|
|
1125
|
-
messageRenderOrder,
|
|
1126
|
-
timelineBlockAnchors,
|
|
1127
|
-
timelineTextStreamLength,
|
|
1128
|
-
visibleTimelineBlockKeys
|
|
1129
|
-
]);
|
|
1226
|
+
dispatch({
|
|
1227
|
+
type: "sync-anchors",
|
|
1228
|
+
currentBlockKeys: currentTimelineBlockKeys,
|
|
1229
|
+
timelineTextStreamLength
|
|
1230
|
+
});
|
|
1231
|
+
}, [currentTimelineBlockKeys, isAssistantStreaming, messageRenderOrder, timelineTextStreamLength]);
|
|
1130
1232
|
useEffect2(() => {
|
|
1131
1233
|
if (messageRenderOrder !== "timeline") {
|
|
1132
|
-
if (Object.keys(visibleTimelineBlockKeys).length > 0) {
|
|
1133
|
-
setVisibleTimelineBlockKeys({});
|
|
1134
|
-
}
|
|
1135
1234
|
return;
|
|
1136
1235
|
}
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
const anchor = effectiveTimelineBlockAnchors[blockKey];
|
|
1144
|
-
if (anchor !== void 0 && anchor <= displayedTimelineTextLength) {
|
|
1145
|
-
acc[blockKey] = true;
|
|
1146
|
-
}
|
|
1147
|
-
return acc;
|
|
1148
|
-
},
|
|
1149
|
-
{}
|
|
1150
|
-
);
|
|
1151
|
-
const hasVisibleBlockChanged = Object.keys(nextVisibleBlockKeys).length !== Object.keys(visibleTimelineBlockKeys).length || Object.keys(nextVisibleBlockKeys).some((blockKey) => !visibleTimelineBlockKeys[blockKey]);
|
|
1152
|
-
if (hasVisibleBlockChanged) {
|
|
1153
|
-
setVisibleTimelineBlockKeys(nextVisibleBlockKeys);
|
|
1154
|
-
}
|
|
1236
|
+
dispatch({
|
|
1237
|
+
type: "sync-visible",
|
|
1238
|
+
currentBlockKeys: currentTimelineBlockKeys,
|
|
1239
|
+
effectiveTimelineBlockAnchors,
|
|
1240
|
+
displayedTimelineTextLength
|
|
1241
|
+
});
|
|
1155
1242
|
}, [
|
|
1156
1243
|
currentTimelineBlockKeys,
|
|
1157
1244
|
displayedTimelineTextLength,
|
|
1158
1245
|
effectiveTimelineBlockAnchors,
|
|
1159
|
-
messageRenderOrder
|
|
1160
|
-
timelineBlockAnchors,
|
|
1161
|
-
visibleTimelineBlockKeys
|
|
1246
|
+
messageRenderOrder
|
|
1162
1247
|
]);
|
|
1163
1248
|
return {
|
|
1164
|
-
timelineBlockAnchors: effectiveTimelineBlockAnchors,
|
|
1165
|
-
visibleTimelineBlockKeys
|
|
1249
|
+
timelineBlockAnchors: messageRenderOrder === "timeline" ? effectiveTimelineBlockAnchors : {},
|
|
1250
|
+
visibleTimelineBlockKeys: messageRenderOrder === "timeline" ? state.visibleTimelineBlockKeys : {}
|
|
1166
1251
|
};
|
|
1167
1252
|
};
|
|
1168
1253
|
|
|
1169
|
-
// src/components/chat-thread/components/
|
|
1254
|
+
// src/components/chat-thread/components/execution-confirmation-card.tsx
|
|
1170
1255
|
import styled from "@emotion/styled";
|
|
1171
1256
|
import { jsx as jsx2, jsxs } from "@emotion/react/jsx-runtime";
|
|
1172
|
-
var
|
|
1257
|
+
var ExecutionConfirmationCard = ({
|
|
1173
1258
|
proposal,
|
|
1174
1259
|
interactive = false,
|
|
1175
1260
|
onApply,
|
|
1176
1261
|
onConfirm,
|
|
1177
1262
|
onRevise
|
|
1178
1263
|
}) => {
|
|
1179
|
-
return /* @__PURE__ */ jsxs(Card, { "data-testid": "
|
|
1264
|
+
return /* @__PURE__ */ jsxs(Card, { "data-testid": "execution-confirmation-card", children: [
|
|
1180
1265
|
/* @__PURE__ */ jsxs(Header, { children: [
|
|
1181
1266
|
/* @__PURE__ */ jsx2(Eyebrow, { children: "Execution Proposal" }),
|
|
1182
|
-
/* @__PURE__ */ jsx2(Title, { children: proposal.
|
|
1183
|
-
proposal.
|
|
1267
|
+
/* @__PURE__ */ jsx2(Title, { children: proposal.resourceName }),
|
|
1268
|
+
proposal.executorName ? /* @__PURE__ */ jsx2(Subtitle, { children: proposal.executorName }) : null
|
|
1184
1269
|
] }),
|
|
1185
1270
|
/* @__PURE__ */ jsx2(SummaryList, { children: proposal.parameterSummary.map((item) => /* @__PURE__ */ jsxs(SummaryItem, { children: [
|
|
1186
1271
|
/* @__PURE__ */ jsx2(SummaryLabel, { children: item.label }),
|
|
@@ -1188,21 +1273,13 @@ var PDEAIExecutionConfirmationCard = ({
|
|
|
1188
1273
|
] }, `${item.fieldPath ?? item.label}-${item.value}`)) }),
|
|
1189
1274
|
proposal.warnings?.length ? /* @__PURE__ */ jsx2(Warnings, { children: proposal.warnings.map((warning) => /* @__PURE__ */ jsx2(Warning, { children: warning }, warning)) }) : null,
|
|
1190
1275
|
interactive ? /* @__PURE__ */ jsxs(Actions, { children: [
|
|
1191
|
-
onApply && /* @__PURE__ */ jsx2(ActionButton, { type: "button", "data-testid": "
|
|
1192
|
-
onConfirm && /* @__PURE__ */ jsx2(
|
|
1193
|
-
ActionButton,
|
|
1194
|
-
{
|
|
1195
|
-
type: "button",
|
|
1196
|
-
"data-testid": "pde-ai-confirmation-confirm",
|
|
1197
|
-
onClick: onConfirm,
|
|
1198
|
-
children: "Confirm Execution"
|
|
1199
|
-
}
|
|
1200
|
-
),
|
|
1276
|
+
onApply && /* @__PURE__ */ jsx2(ActionButton, { type: "button", "data-testid": "confirmation-apply", onClick: onApply, children: "Apply to Parameters" }),
|
|
1277
|
+
onConfirm && /* @__PURE__ */ jsx2(ActionButton, { type: "button", "data-testid": "confirmation-confirm", onClick: onConfirm, children: "Confirm Execution" }),
|
|
1201
1278
|
onRevise && /* @__PURE__ */ jsx2(
|
|
1202
1279
|
SecondaryActionButton,
|
|
1203
1280
|
{
|
|
1204
1281
|
type: "button",
|
|
1205
|
-
"data-testid": "
|
|
1282
|
+
"data-testid": "confirmation-revise",
|
|
1206
1283
|
onClick: onRevise,
|
|
1207
1284
|
children: "Revise Plan"
|
|
1208
1285
|
}
|
|
@@ -1299,10 +1376,10 @@ var SecondaryActionButton = styled(ActionButton)`
|
|
|
1299
1376
|
border: 1px solid rgba(255, 255, 255, 0.14);
|
|
1300
1377
|
`;
|
|
1301
1378
|
|
|
1302
|
-
// src/components/chat-thread/components/
|
|
1379
|
+
// src/components/chat-thread/components/notice-card.tsx
|
|
1303
1380
|
import styled2 from "@emotion/styled";
|
|
1304
1381
|
import { jsx as jsx3 } from "@emotion/react/jsx-runtime";
|
|
1305
|
-
var
|
|
1382
|
+
var NoticeCard = ({ text, tone }) => /* @__PURE__ */ jsx3(Card2, { "data-testid": "notice-card", "data-tone": tone, children: text });
|
|
1306
1383
|
var Card2 = styled2.div`
|
|
1307
1384
|
padding: 12px 14px;
|
|
1308
1385
|
border-radius: 16px;
|
|
@@ -1328,10 +1405,10 @@ var Card2 = styled2.div`
|
|
|
1328
1405
|
}
|
|
1329
1406
|
`;
|
|
1330
1407
|
|
|
1331
|
-
// src/components/chat-thread/components/
|
|
1408
|
+
// src/components/chat-thread/components/parameter-summary-card.tsx
|
|
1332
1409
|
import styled3 from "@emotion/styled";
|
|
1333
1410
|
import { jsx as jsx4, jsxs as jsxs2 } from "@emotion/react/jsx-runtime";
|
|
1334
|
-
var
|
|
1411
|
+
var ParameterSummaryCard = ({ items }) => /* @__PURE__ */ jsxs2(Card3, { "data-testid": "parameter-summary-card", children: [
|
|
1335
1412
|
/* @__PURE__ */ jsx4(Title2, { children: "Parameter Summary" }),
|
|
1336
1413
|
/* @__PURE__ */ jsx4(List, { children: items.map((item) => /* @__PURE__ */ jsxs2(ListItem, { children: [
|
|
1337
1414
|
/* @__PURE__ */ jsx4(Label, { children: item.label }),
|
|
@@ -1375,11 +1452,17 @@ var Value = styled3.span`
|
|
|
1375
1452
|
text-align: right;
|
|
1376
1453
|
`;
|
|
1377
1454
|
|
|
1378
|
-
// src/components/chat-thread/components/
|
|
1379
|
-
import { useState as
|
|
1455
|
+
// src/components/chat-thread/components/questionnaire-card.tsx
|
|
1456
|
+
import { useState as useState2 } from "react";
|
|
1380
1457
|
import styled4 from "@emotion/styled";
|
|
1381
1458
|
import { jsx as jsx5, jsxs as jsxs3 } from "@emotion/react/jsx-runtime";
|
|
1382
1459
|
var OTHER_OPTION_VALUE = "__other__";
|
|
1460
|
+
var DEFAULT_QUESTIONNAIRE_CARD_LABELS = {
|
|
1461
|
+
submitting: "Submitting...",
|
|
1462
|
+
submitted: "Selection submitted. Waiting for the plan to continue...",
|
|
1463
|
+
validationPrefix: "Please complete:",
|
|
1464
|
+
submitFailed: "Failed to submit. Please try again."
|
|
1465
|
+
};
|
|
1383
1466
|
var createInitialAnswers = (questionnaire) => ({
|
|
1384
1467
|
...questionnaire.answers ?? {}
|
|
1385
1468
|
});
|
|
@@ -1473,26 +1556,40 @@ var normalizeQuestionAnswer = (question, answer) => {
|
|
|
1473
1556
|
return answer;
|
|
1474
1557
|
}
|
|
1475
1558
|
};
|
|
1476
|
-
var
|
|
1559
|
+
var QuestionnaireCardInner = ({
|
|
1477
1560
|
questionnaire,
|
|
1478
1561
|
interactive = false,
|
|
1479
|
-
onSubmit
|
|
1562
|
+
onSubmit,
|
|
1563
|
+
labels
|
|
1480
1564
|
}) => {
|
|
1481
|
-
const [answers, setAnswers] =
|
|
1565
|
+
const [answers, setAnswers] = useState2(
|
|
1482
1566
|
() => createInitialAnswers(questionnaire)
|
|
1483
1567
|
);
|
|
1484
|
-
const [errorMessage, setErrorMessage] =
|
|
1485
|
-
const
|
|
1568
|
+
const [errorMessage, setErrorMessage] = useState2(null);
|
|
1569
|
+
const [isSubmitting, setIsSubmitting] = useState2(false);
|
|
1570
|
+
const [isSubmitted, setIsSubmitted] = useState2(false);
|
|
1571
|
+
const resolvedLabels = {
|
|
1572
|
+
...DEFAULT_QUESTIONNAIRE_CARD_LABELS,
|
|
1573
|
+
...labels
|
|
1574
|
+
};
|
|
1575
|
+
const hasExternalFailureStatus = questionnaire.status === "expired" || questionnaire.status === "failed";
|
|
1576
|
+
const visibleErrorMessage = questionnaire.statusMessage ?? errorMessage;
|
|
1577
|
+
const isInteractionLocked = !interactive || isSubmitting || isSubmitted || hasExternalFailureStatus;
|
|
1578
|
+
const handleSubmit = async () => {
|
|
1579
|
+
if (isSubmitting || isSubmitted) {
|
|
1580
|
+
return;
|
|
1581
|
+
}
|
|
1486
1582
|
const missingQuestions = questionnaire.questions.filter(
|
|
1487
1583
|
(question) => question.required && isMissingRequiredAnswer(question, answers)
|
|
1488
1584
|
);
|
|
1489
1585
|
if (missingQuestions.length > 0) {
|
|
1490
1586
|
setErrorMessage(
|
|
1491
|
-
|
|
1587
|
+
`${resolvedLabels.validationPrefix} ${missingQuestions.map((question) => question.label).join(", ")}`
|
|
1492
1588
|
);
|
|
1493
1589
|
return;
|
|
1494
1590
|
}
|
|
1495
1591
|
setErrorMessage(null);
|
|
1592
|
+
setIsSubmitting(true);
|
|
1496
1593
|
const normalizedAnswers = Object.fromEntries(
|
|
1497
1594
|
questionnaire.questions.flatMap((question) => {
|
|
1498
1595
|
const value = normalizeQuestionAnswer(question, answers[question.id]);
|
|
@@ -1509,11 +1606,18 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1509
1606
|
return [`- ${question.label}: ${formatQuestionAnswer(question, value)}`];
|
|
1510
1607
|
})
|
|
1511
1608
|
];
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1609
|
+
try {
|
|
1610
|
+
await onSubmit?.({
|
|
1611
|
+
questionnaireId: questionnaire.questionnaireId,
|
|
1612
|
+
answers: normalizedAnswers,
|
|
1613
|
+
content: contentLines.join("\n")
|
|
1614
|
+
});
|
|
1615
|
+
setIsSubmitted(true);
|
|
1616
|
+
} catch (error) {
|
|
1617
|
+
setErrorMessage(error instanceof Error ? error.message : resolvedLabels.submitFailed);
|
|
1618
|
+
} finally {
|
|
1619
|
+
setIsSubmitting(false);
|
|
1620
|
+
}
|
|
1517
1621
|
};
|
|
1518
1622
|
const renderQuestion = (question) => {
|
|
1519
1623
|
const renderOptionChoice = ({
|
|
@@ -1528,13 +1632,13 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1528
1632
|
OptionChoiceItem,
|
|
1529
1633
|
{
|
|
1530
1634
|
role: "button",
|
|
1531
|
-
tabIndex:
|
|
1635
|
+
tabIndex: isInteractionLocked ? -1 : 0,
|
|
1532
1636
|
"aria-pressed": isSelected,
|
|
1533
1637
|
"data-selected": isSelected,
|
|
1534
1638
|
"data-tone": tone,
|
|
1535
|
-
"data-testid": `
|
|
1639
|
+
"data-testid": `question-option-${questionId}-${index}`,
|
|
1536
1640
|
onClick: (event) => {
|
|
1537
|
-
if (
|
|
1641
|
+
if (isInteractionLocked) {
|
|
1538
1642
|
return;
|
|
1539
1643
|
}
|
|
1540
1644
|
if (event.target instanceof HTMLElement && event.target.closest("input")) {
|
|
@@ -1543,7 +1647,7 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1543
1647
|
onClick();
|
|
1544
1648
|
},
|
|
1545
1649
|
onKeyDown: (event) => {
|
|
1546
|
-
if (
|
|
1650
|
+
if (isInteractionLocked) {
|
|
1547
1651
|
return;
|
|
1548
1652
|
}
|
|
1549
1653
|
if (event.key !== "Enter" && event.key !== " ") {
|
|
@@ -1602,11 +1706,11 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1602
1706
|
inlineInput: singleSelectDraft.selectedValue === OTHER_OPTION_VALUE ? /* @__PURE__ */ jsx5(
|
|
1603
1707
|
InlineOtherInput,
|
|
1604
1708
|
{
|
|
1605
|
-
"data-testid": `
|
|
1709
|
+
"data-testid": `question-input-${question.id}`,
|
|
1606
1710
|
type: "text",
|
|
1607
1711
|
value: singleSelectDraft.otherValue,
|
|
1608
1712
|
placeholder: "Other",
|
|
1609
|
-
readOnly:
|
|
1713
|
+
readOnly: isInteractionLocked,
|
|
1610
1714
|
onClick: (event) => {
|
|
1611
1715
|
event.stopPropagation();
|
|
1612
1716
|
},
|
|
@@ -1627,11 +1731,11 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1627
1731
|
return /* @__PURE__ */ jsx5(QuestionBody, { children: /* @__PURE__ */ jsx5(
|
|
1628
1732
|
TextInput,
|
|
1629
1733
|
{
|
|
1630
|
-
"data-testid": `
|
|
1734
|
+
"data-testid": `question-input-${question.id}`,
|
|
1631
1735
|
type: "text",
|
|
1632
1736
|
value: getTextInputValue(answers[question.id]),
|
|
1633
1737
|
placeholder: question.placeholder,
|
|
1634
|
-
readOnly:
|
|
1738
|
+
readOnly: isInteractionLocked,
|
|
1635
1739
|
onChange: (event) => {
|
|
1636
1740
|
setAnswers((current) => updateAnswerValue(current, question.id, event.target.value));
|
|
1637
1741
|
}
|
|
@@ -1642,11 +1746,11 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1642
1746
|
/* @__PURE__ */ jsx5(
|
|
1643
1747
|
TextInput,
|
|
1644
1748
|
{
|
|
1645
|
-
"data-testid": `
|
|
1749
|
+
"data-testid": `question-input-${question.id}`,
|
|
1646
1750
|
type: "number",
|
|
1647
1751
|
value: getNumberInputValue(answers[question.id]),
|
|
1648
1752
|
placeholder: question.placeholder,
|
|
1649
|
-
readOnly:
|
|
1753
|
+
readOnly: isInteractionLocked,
|
|
1650
1754
|
onChange: (event) => {
|
|
1651
1755
|
setAnswers(
|
|
1652
1756
|
(current) => updateAnswerValue(
|
|
@@ -1681,7 +1785,7 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1681
1785
|
return null;
|
|
1682
1786
|
}
|
|
1683
1787
|
};
|
|
1684
|
-
return /* @__PURE__ */ jsxs3(Card4, { "data-testid": "
|
|
1788
|
+
return /* @__PURE__ */ jsxs3(Card4, { "data-testid": "questionnaire-card", children: [
|
|
1685
1789
|
questionnaire.title ? /* @__PURE__ */ jsx5(Title3, { children: questionnaire.title }) : null,
|
|
1686
1790
|
questionnaire.description ? /* @__PURE__ */ jsx5(Description, { children: questionnaire.description }) : null,
|
|
1687
1791
|
/* @__PURE__ */ jsx5(QuestionList, { children: questionnaire.questions.map((question) => /* @__PURE__ */ jsxs3(QuestionCard, { children: [
|
|
@@ -1691,24 +1795,28 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1691
1795
|
] }),
|
|
1692
1796
|
renderQuestion(question)
|
|
1693
1797
|
] }, question.id)) }),
|
|
1694
|
-
|
|
1695
|
-
interactive ? /* @__PURE__ */ jsx5(
|
|
1798
|
+
visibleErrorMessage ? /* @__PURE__ */ jsx5(ErrorMessage, { "data-testid": "questionnaire-error", children: visibleErrorMessage }) : null,
|
|
1799
|
+
isSubmitted ? /* @__PURE__ */ jsx5(SuccessMessage, { "data-testid": "questionnaire-success", children: resolvedLabels.submitted }) : interactive && !hasExternalFailureStatus ? /* @__PURE__ */ jsx5(
|
|
1696
1800
|
SubmitButton,
|
|
1697
1801
|
{
|
|
1698
1802
|
type: "button",
|
|
1699
|
-
"data-testid": "
|
|
1700
|
-
|
|
1701
|
-
|
|
1803
|
+
"data-testid": "questionnaire-submit",
|
|
1804
|
+
disabled: isInteractionLocked,
|
|
1805
|
+
onClick: () => {
|
|
1806
|
+
void handleSubmit();
|
|
1807
|
+
},
|
|
1808
|
+
children: isSubmitting ? resolvedLabels.submitting : questionnaire.submitLabel ?? "Submit"
|
|
1702
1809
|
}
|
|
1703
1810
|
) : null
|
|
1704
1811
|
] });
|
|
1705
1812
|
};
|
|
1706
1813
|
var getQuestionnaireStateKey = (questionnaire) => JSON.stringify([
|
|
1707
1814
|
questionnaire.questionnaireId,
|
|
1708
|
-
questionnaire.
|
|
1709
|
-
questionnaire.
|
|
1815
|
+
questionnaire.questions,
|
|
1816
|
+
questionnaire.status,
|
|
1817
|
+
questionnaire.statusMessage
|
|
1710
1818
|
]);
|
|
1711
|
-
var
|
|
1819
|
+
var QuestionnaireCard = (props) => /* @__PURE__ */ jsx5(QuestionnaireCardInner, { ...props }, getQuestionnaireStateKey(props.questionnaire));
|
|
1712
1820
|
var Card4 = styled4.section`
|
|
1713
1821
|
display: grid;
|
|
1714
1822
|
gap: 14px;
|
|
@@ -1856,6 +1964,10 @@ var ErrorMessage = styled4.div`
|
|
|
1856
1964
|
color: rgba(255, 145, 145, 0.96);
|
|
1857
1965
|
font-size: 12px;
|
|
1858
1966
|
`;
|
|
1967
|
+
var SuccessMessage = styled4.div`
|
|
1968
|
+
color: rgba(164, 255, 210, 0.96);
|
|
1969
|
+
font-size: 12px;
|
|
1970
|
+
`;
|
|
1859
1971
|
var SubmitButton = styled4.button`
|
|
1860
1972
|
justify-self: flex-start;
|
|
1861
1973
|
border: none;
|
|
@@ -1866,12 +1978,17 @@ var SubmitButton = styled4.button`
|
|
|
1866
1978
|
font-weight: 700;
|
|
1867
1979
|
padding: 10px 14px;
|
|
1868
1980
|
cursor: pointer;
|
|
1981
|
+
|
|
1982
|
+
&:disabled {
|
|
1983
|
+
cursor: default;
|
|
1984
|
+
opacity: 0.72;
|
|
1985
|
+
}
|
|
1869
1986
|
`;
|
|
1870
1987
|
|
|
1871
|
-
// src/components/chat-thread/components/
|
|
1988
|
+
// src/components/chat-thread/components/result-summary-card.tsx
|
|
1872
1989
|
import styled5 from "@emotion/styled";
|
|
1873
1990
|
import { jsx as jsx6, jsxs as jsxs4 } from "@emotion/react/jsx-runtime";
|
|
1874
|
-
var
|
|
1991
|
+
var ResultSummaryCard = ({ summary }) => /* @__PURE__ */ jsxs4(Card5, { "data-testid": "result-summary-card", "data-status": summary.status, children: [
|
|
1875
1992
|
/* @__PURE__ */ jsx6(Eyebrow2, { children: summary.status }),
|
|
1876
1993
|
/* @__PURE__ */ jsx6(Headline, { children: summary.headline }),
|
|
1877
1994
|
/* @__PURE__ */ jsx6(Details, { children: summary.details.map((detail) => /* @__PURE__ */ jsx6(Detail, { children: detail }, detail)) })
|
|
@@ -1917,7 +2034,7 @@ var Detail = styled5.li`
|
|
|
1917
2034
|
|
|
1918
2035
|
// src/components/chat-thread/components/image-viewer.tsx
|
|
1919
2036
|
import styled6 from "@emotion/styled";
|
|
1920
|
-
import { useEffect as useEffect3, useRef as
|
|
2037
|
+
import { useEffect as useEffect3, useRef as useRef3 } from "react";
|
|
1921
2038
|
import { jsx as jsx7 } from "@emotion/react/jsx-runtime";
|
|
1922
2039
|
var Overlay = styled6.div`
|
|
1923
2040
|
position: fixed;
|
|
@@ -1936,7 +2053,7 @@ var Img = styled6.img`
|
|
|
1936
2053
|
border-radius: 4px;
|
|
1937
2054
|
`;
|
|
1938
2055
|
var ImageViewer = ({ src, alt, onClose }) => {
|
|
1939
|
-
const overlayRef =
|
|
2056
|
+
const overlayRef = useRef3(null);
|
|
1940
2057
|
useEffect3(() => {
|
|
1941
2058
|
const handleKey = (e) => {
|
|
1942
2059
|
if (e.key === "Escape")
|
|
@@ -1967,6 +2084,7 @@ var ImageViewer = ({ src, alt, onClose }) => {
|
|
|
1967
2084
|
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs5 } from "@emotion/react/jsx-runtime";
|
|
1968
2085
|
var MARKDOWN_REMARK_PLUGINS = [remarkGfm, remarkMath];
|
|
1969
2086
|
var MARKDOWN_REHYPE_PLUGINS = [rehypeKatex];
|
|
2087
|
+
var USER_MESSAGE_COLLAPSE_HEIGHT_PX = 120;
|
|
1970
2088
|
var MARKDOWN_COMPONENTS = {
|
|
1971
2089
|
table: ({ node: _node, ...props }) => /* @__PURE__ */ jsx8(TableWrapper, { children: /* @__PURE__ */ jsx8("table", { ...props }) })
|
|
1972
2090
|
};
|
|
@@ -1979,10 +2097,101 @@ var renderMarkdownContent = (content) => /* @__PURE__ */ jsx8(
|
|
|
1979
2097
|
children: content
|
|
1980
2098
|
}
|
|
1981
2099
|
);
|
|
2100
|
+
var renderPlainTextContent = (content) => content;
|
|
2101
|
+
var CollapseIcon = ({ expanded }) => /* @__PURE__ */ jsx8(
|
|
2102
|
+
"svg",
|
|
2103
|
+
{
|
|
2104
|
+
"aria-hidden": "true",
|
|
2105
|
+
width: "16",
|
|
2106
|
+
height: "16",
|
|
2107
|
+
viewBox: "0 0 16 16",
|
|
2108
|
+
fill: "none",
|
|
2109
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2110
|
+
children: /* @__PURE__ */ jsx8(
|
|
2111
|
+
"path",
|
|
2112
|
+
{
|
|
2113
|
+
d: "M4 6l4 4 4-4",
|
|
2114
|
+
stroke: "currentColor",
|
|
2115
|
+
strokeWidth: "1.6",
|
|
2116
|
+
strokeLinecap: "round",
|
|
2117
|
+
strokeLinejoin: "round",
|
|
2118
|
+
transform: expanded ? "rotate(180 8 8)" : void 0
|
|
2119
|
+
}
|
|
2120
|
+
)
|
|
2121
|
+
}
|
|
2122
|
+
);
|
|
2123
|
+
var useUserMessageCollapse = ({
|
|
2124
|
+
blocks,
|
|
2125
|
+
displayedBlocks,
|
|
2126
|
+
displayedContent,
|
|
2127
|
+
enabled,
|
|
2128
|
+
freshContent,
|
|
2129
|
+
settledContent
|
|
2130
|
+
}) => {
|
|
2131
|
+
const [isCollapsible, setIsCollapsible] = useState3(false);
|
|
2132
|
+
const [isExpanded, setIsExpanded] = useState3(false);
|
|
2133
|
+
const [bodyStackElement, setBodyStackElement] = useState3(null);
|
|
2134
|
+
const syncCollapseState = useCallback2(
|
|
2135
|
+
(element) => {
|
|
2136
|
+
const nextCollapsible = enabled && (element?.scrollHeight ?? 0) > USER_MESSAGE_COLLAPSE_HEIGHT_PX;
|
|
2137
|
+
setIsCollapsible(nextCollapsible);
|
|
2138
|
+
if (!nextCollapsible) {
|
|
2139
|
+
setIsExpanded(false);
|
|
2140
|
+
}
|
|
2141
|
+
},
|
|
2142
|
+
[enabled]
|
|
2143
|
+
);
|
|
2144
|
+
const bodyStackRef = useCallback2(
|
|
2145
|
+
(node) => {
|
|
2146
|
+
setBodyStackElement(node);
|
|
2147
|
+
syncCollapseState(node);
|
|
2148
|
+
},
|
|
2149
|
+
[syncCollapseState]
|
|
2150
|
+
);
|
|
2151
|
+
useLayoutEffect(() => {
|
|
2152
|
+
if (!bodyStackElement) {
|
|
2153
|
+
return;
|
|
2154
|
+
}
|
|
2155
|
+
const frameId = requestAnimationFrame(() => {
|
|
2156
|
+
syncCollapseState(bodyStackElement);
|
|
2157
|
+
});
|
|
2158
|
+
return () => {
|
|
2159
|
+
cancelAnimationFrame(frameId);
|
|
2160
|
+
};
|
|
2161
|
+
}, [
|
|
2162
|
+
blocks,
|
|
2163
|
+
bodyStackElement,
|
|
2164
|
+
displayedBlocks,
|
|
2165
|
+
displayedContent,
|
|
2166
|
+
enabled,
|
|
2167
|
+
freshContent,
|
|
2168
|
+
settledContent,
|
|
2169
|
+
syncCollapseState
|
|
2170
|
+
]);
|
|
2171
|
+
useLayoutEffect(() => {
|
|
2172
|
+
if (!bodyStackElement || !enabled || typeof ResizeObserver === "undefined") {
|
|
2173
|
+
return;
|
|
2174
|
+
}
|
|
2175
|
+
const observer = new ResizeObserver(() => {
|
|
2176
|
+
syncCollapseState(bodyStackElement);
|
|
2177
|
+
});
|
|
2178
|
+
observer.observe(bodyStackElement);
|
|
2179
|
+
return () => {
|
|
2180
|
+
observer.disconnect();
|
|
2181
|
+
};
|
|
2182
|
+
}, [bodyStackElement, enabled, syncCollapseState]);
|
|
2183
|
+
return {
|
|
2184
|
+
bodyStackRef,
|
|
2185
|
+
isCollapsed: isCollapsible && !isExpanded,
|
|
2186
|
+
isCollapsible,
|
|
2187
|
+
isExpanded,
|
|
2188
|
+
toggleExpanded: () => setIsExpanded((current) => !current)
|
|
2189
|
+
};
|
|
2190
|
+
};
|
|
1982
2191
|
var createExecutionConfirmationContent = (proposal) => [
|
|
1983
2192
|
"Execution confirmed",
|
|
1984
|
-
`- Equation: ${proposal.
|
|
1985
|
-
...proposal.
|
|
2193
|
+
`- Equation: ${proposal.resourceName}`,
|
|
2194
|
+
...proposal.executorName ? [`- Solver: ${proposal.executorName}`] : [],
|
|
1986
2195
|
`- Proposal ID: ${proposal.proposalId}`
|
|
1987
2196
|
].join("\n");
|
|
1988
2197
|
var areChatAttachmentsEqual = (previousAttachments, nextAttachments) => {
|
|
@@ -2004,10 +2213,10 @@ var areParameterSummaryItemsEqual = (previousItems, nextItems) => previousItems.
|
|
|
2004
2213
|
const nextItem = nextItems[index];
|
|
2005
2214
|
return item.label === nextItem?.label && item.value === nextItem.value && item.fieldPath === nextItem.fieldPath;
|
|
2006
2215
|
});
|
|
2007
|
-
var areExecutionProposalsEqual = (previousProposal, nextProposal) => previousProposal.proposalId === nextProposal.proposalId && previousProposal.
|
|
2216
|
+
var areExecutionProposalsEqual = (previousProposal, nextProposal) => previousProposal.proposalId === nextProposal.proposalId && previousProposal.resourceKey === nextProposal.resourceKey && previousProposal.resourceName === nextProposal.resourceName && previousProposal.executorName === nextProposal.executorName && previousProposal.requiresConfirmation === nextProposal.requiresConfirmation && areParameterSummaryItemsEqual(previousProposal.parameterSummary, nextProposal.parameterSummary) && (previousProposal.warnings ?? []).length === (nextProposal.warnings ?? []).length && (previousProposal.warnings ?? []).every(
|
|
2008
2217
|
(warning, index) => warning === nextProposal.warnings?.[index]
|
|
2009
2218
|
);
|
|
2010
|
-
var areResultSummariesEqual = (previousSummary, nextSummary) => previousSummary.
|
|
2219
|
+
var areResultSummariesEqual = (previousSummary, nextSummary) => previousSummary.summaryId === nextSummary.summaryId && previousSummary.status === nextSummary.status && previousSummary.headline === nextSummary.headline && previousSummary.details.length === nextSummary.details.length && previousSummary.details.every((detail, index) => detail === nextSummary.details[index]);
|
|
2011
2220
|
var areStringArraysEqual = (previousValues, nextValues) => previousValues.length === nextValues.length && previousValues.every((value, index) => value === nextValues[index]);
|
|
2012
2221
|
var areQuestionAnswersEqual = (previousAnswer, nextAnswer) => {
|
|
2013
2222
|
if (Array.isArray(previousAnswer) || Array.isArray(nextAnswer)) {
|
|
@@ -2048,7 +2257,7 @@ var arePlanQuestionsEqual = (previousQuestion, nextQuestion) => {
|
|
|
2048
2257
|
return false;
|
|
2049
2258
|
}
|
|
2050
2259
|
};
|
|
2051
|
-
var areQuestionnairesEqual = (previousQuestionnaire, nextQuestionnaire) => previousQuestionnaire.questionnaireId === nextQuestionnaire.questionnaireId && previousQuestionnaire.title === nextQuestionnaire.title && previousQuestionnaire.description === nextQuestionnaire.description && previousQuestionnaire.submitLabel === nextQuestionnaire.submitLabel && previousQuestionnaire.questions.length === nextQuestionnaire.questions.length && previousQuestionnaire.questions.every(
|
|
2260
|
+
var areQuestionnairesEqual = (previousQuestionnaire, nextQuestionnaire) => previousQuestionnaire.questionnaireId === nextQuestionnaire.questionnaireId && previousQuestionnaire.title === nextQuestionnaire.title && previousQuestionnaire.description === nextQuestionnaire.description && previousQuestionnaire.submitLabel === nextQuestionnaire.submitLabel && previousQuestionnaire.status === nextQuestionnaire.status && previousQuestionnaire.statusMessage === nextQuestionnaire.statusMessage && previousQuestionnaire.questions.length === nextQuestionnaire.questions.length && previousQuestionnaire.questions.every(
|
|
2052
2261
|
(question, index) => arePlanQuestionsEqual(question, nextQuestionnaire.questions[index])
|
|
2053
2262
|
) && areQuestionAnswerMapsEqual(previousQuestionnaire.answers, nextQuestionnaire.answers);
|
|
2054
2263
|
var areMessageBlocksEqual = (previousBlocks, nextBlocks) => {
|
|
@@ -2109,7 +2318,7 @@ var ChatMessageItemView = ({
|
|
|
2109
2318
|
renderMessageBlock
|
|
2110
2319
|
}) => {
|
|
2111
2320
|
const { labels, messageRenderOrder = "blocks-first" } = useChatContext();
|
|
2112
|
-
const [activeImage, setActiveImage] =
|
|
2321
|
+
const [activeImage, setActiveImage] = useState3(void 0);
|
|
2113
2322
|
const {
|
|
2114
2323
|
displayedBlocks,
|
|
2115
2324
|
displayedContent,
|
|
@@ -2129,6 +2338,8 @@ var ChatMessageItemView = ({
|
|
|
2129
2338
|
const canSubmitConfirmation = isPlanMode && typeof onConfirmationSubmit === "function";
|
|
2130
2339
|
const canSubmitQuestionnaire = isPlanMode && typeof onQuestionnaireSubmit === "function";
|
|
2131
2340
|
const shouldShowStreamingCaret = isAssistantStreaming && (!shouldRenderStructuredBlocks || hasTextContent);
|
|
2341
|
+
const isUserMessage = message.role === "user";
|
|
2342
|
+
const messageRenderMode = isUserMessage ? "plain-text" : "markdown";
|
|
2132
2343
|
const timelineConsumedText = messageRenderOrder === "timeline" ? getTimelineConsumedText(blocks) : "";
|
|
2133
2344
|
const hasConsumedTimelineText = timelineConsumedText.length > 0 && displayedContent.startsWith(timelineConsumedText);
|
|
2134
2345
|
const timelineDisplayedContent = hasConsumedTimelineText ? displayedContent.slice(timelineConsumedText.length) : displayedContent;
|
|
@@ -2145,6 +2356,21 @@ var ChatMessageItemView = ({
|
|
|
2145
2356
|
message,
|
|
2146
2357
|
messageRenderOrder
|
|
2147
2358
|
});
|
|
2359
|
+
const {
|
|
2360
|
+
bodyStackRef,
|
|
2361
|
+
isCollapsed: isUserMessageCollapsed,
|
|
2362
|
+
isCollapsible: isUserMessageCollapsible,
|
|
2363
|
+
isExpanded: isUserMessageExpanded,
|
|
2364
|
+
toggleExpanded: toggleUserMessageExpanded
|
|
2365
|
+
} = useUserMessageCollapse({
|
|
2366
|
+
blocks,
|
|
2367
|
+
displayedBlocks,
|
|
2368
|
+
displayedContent,
|
|
2369
|
+
enabled: isUserMessage,
|
|
2370
|
+
freshContent,
|
|
2371
|
+
settledContent
|
|
2372
|
+
});
|
|
2373
|
+
const renderMessageContent = (content) => messageRenderMode === "plain-text" ? renderPlainTextContent(content) : renderMarkdownContent(content);
|
|
2148
2374
|
const renderChatMessageBlock = (block, index) => {
|
|
2149
2375
|
switch (block.type) {
|
|
2150
2376
|
case "markdown":
|
|
@@ -2153,17 +2379,18 @@ var ChatMessageItemView = ({
|
|
|
2153
2379
|
{
|
|
2154
2380
|
"data-testid": `chat-message-block-${index}`,
|
|
2155
2381
|
"data-block-tone": "settled",
|
|
2156
|
-
|
|
2382
|
+
"data-render-mode": messageRenderMode,
|
|
2383
|
+
children: renderMessageContent(block.text)
|
|
2157
2384
|
},
|
|
2158
2385
|
`markdown-${index}`
|
|
2159
2386
|
);
|
|
2160
2387
|
case "notice":
|
|
2161
|
-
return /* @__PURE__ */ jsx8(Fragment, { children: /* @__PURE__ */ jsx8(
|
|
2388
|
+
return /* @__PURE__ */ jsx8(Fragment, { children: /* @__PURE__ */ jsx8(NoticeCard, { text: block.text, tone: block.tone }) }, `notice-${index}`);
|
|
2162
2389
|
case "parameter_summary":
|
|
2163
|
-
return /* @__PURE__ */ jsx8(Fragment, { children: /* @__PURE__ */ jsx8(
|
|
2390
|
+
return /* @__PURE__ */ jsx8(Fragment, { children: /* @__PURE__ */ jsx8(ParameterSummaryCard, { items: block.items }) }, `parameter-summary-${index}`);
|
|
2164
2391
|
case "confirmation_card":
|
|
2165
2392
|
return /* @__PURE__ */ jsx8(Fragment, { children: /* @__PURE__ */ jsx8(
|
|
2166
|
-
|
|
2393
|
+
ExecutionConfirmationCard,
|
|
2167
2394
|
{
|
|
2168
2395
|
proposal: block.proposal,
|
|
2169
2396
|
interactive: isPlanMode,
|
|
@@ -2175,13 +2402,19 @@ var ChatMessageItemView = ({
|
|
|
2175
2402
|
}
|
|
2176
2403
|
) }, `confirmation-card-${index}`);
|
|
2177
2404
|
case "result_summary":
|
|
2178
|
-
return /* @__PURE__ */ jsx8(Fragment, { children: /* @__PURE__ */ jsx8(
|
|
2405
|
+
return /* @__PURE__ */ jsx8(Fragment, { children: /* @__PURE__ */ jsx8(ResultSummaryCard, { summary: block.summary }) }, `result-summary-${index}`);
|
|
2179
2406
|
case "questionnaire":
|
|
2180
2407
|
return /* @__PURE__ */ jsx8(Fragment, { children: /* @__PURE__ */ jsx8(
|
|
2181
|
-
|
|
2408
|
+
QuestionnaireCard,
|
|
2182
2409
|
{
|
|
2183
2410
|
questionnaire: block.questionnaire,
|
|
2184
2411
|
interactive: canSubmitQuestionnaire,
|
|
2412
|
+
labels: {
|
|
2413
|
+
submitting: labels.questionnaireSubmitting,
|
|
2414
|
+
submitted: labels.questionnaireSubmitted,
|
|
2415
|
+
validationPrefix: labels.questionnaireValidationPrefix,
|
|
2416
|
+
submitFailed: labels.questionnaireSubmitFailed
|
|
2417
|
+
},
|
|
2185
2418
|
onSubmit: canSubmitQuestionnaire ? (submission) => onQuestionnaireSubmit({
|
|
2186
2419
|
...submission,
|
|
2187
2420
|
sourceMessageId: message.id
|
|
@@ -2214,14 +2447,31 @@ var ChatMessageItemView = ({
|
|
|
2214
2447
|
"data-testid": block.tone === "fresh" ? "chat-message-fresh-block" : "chat-message-settled-block",
|
|
2215
2448
|
"data-block-tone": block.tone,
|
|
2216
2449
|
"data-block-index": index,
|
|
2217
|
-
|
|
2450
|
+
"data-render-mode": messageRenderMode,
|
|
2451
|
+
children: renderMessageContent(block.content)
|
|
2218
2452
|
},
|
|
2219
2453
|
`${block.tone}-${index}`
|
|
2220
2454
|
)),
|
|
2221
|
-
!textBlocks.some((block) => block.content) && !settledText && !freshText && Boolean(textContent) ? /* @__PURE__ */ jsx8(
|
|
2455
|
+
!textBlocks.some((block) => block.content) && !settledText && !freshText && Boolean(textContent) ? /* @__PURE__ */ jsx8(
|
|
2456
|
+
ContentBlock,
|
|
2457
|
+
{
|
|
2458
|
+
"data-testid": "chat-message-settled-block",
|
|
2459
|
+
"data-block-tone": "settled",
|
|
2460
|
+
"data-render-mode": messageRenderMode,
|
|
2461
|
+
children: renderMessageContent(textContent)
|
|
2462
|
+
}
|
|
2463
|
+
) : null
|
|
2222
2464
|
] });
|
|
2223
2465
|
};
|
|
2224
|
-
const renderStaticTextSegment = (content) => /* @__PURE__ */ jsx8(
|
|
2466
|
+
const renderStaticTextSegment = (content) => /* @__PURE__ */ jsx8(
|
|
2467
|
+
ContentBlock,
|
|
2468
|
+
{
|
|
2469
|
+
"data-testid": "chat-message-settled-block",
|
|
2470
|
+
"data-block-tone": "settled",
|
|
2471
|
+
"data-render-mode": messageRenderMode,
|
|
2472
|
+
children: renderMessageContent(content)
|
|
2473
|
+
}
|
|
2474
|
+
);
|
|
2225
2475
|
const bodySegments = (() => {
|
|
2226
2476
|
if (!shouldRenderStructuredBlocks && hasTextContent) {
|
|
2227
2477
|
return [{ type: "text" }];
|
|
@@ -2279,21 +2529,40 @@ var ChatMessageItemView = ({
|
|
|
2279
2529
|
}
|
|
2280
2530
|
) : null,
|
|
2281
2531
|
/* @__PURE__ */ jsx8(Role, { children: message.role === "user" ? labels.userRoleLabel : labels.assistantRoleLabel }),
|
|
2532
|
+
isUserMessageCollapsible ? /* @__PURE__ */ jsx8(
|
|
2533
|
+
CollapseToggle,
|
|
2534
|
+
{
|
|
2535
|
+
type: "button",
|
|
2536
|
+
"data-testid": "chat-message-collapse-toggle",
|
|
2537
|
+
"aria-label": isUserMessageExpanded ? labels.collapseMessageAriaLabel : labels.expandMessageAriaLabel,
|
|
2538
|
+
"aria-expanded": isUserMessageExpanded,
|
|
2539
|
+
onClick: toggleUserMessageExpanded,
|
|
2540
|
+
children: /* @__PURE__ */ jsx8(CollapseIcon, { expanded: isUserMessageExpanded })
|
|
2541
|
+
}
|
|
2542
|
+
) : null,
|
|
2282
2543
|
isStoppedAssistant ? /* @__PURE__ */ jsx8(StatusTag, { "data-testid": "chat-message-stopped-tag", children: labels.stoppedResponse }) : null
|
|
2283
2544
|
] }),
|
|
2284
2545
|
/* @__PURE__ */ jsxs5(Content, { "data-testid": "chat-message-content", children: [
|
|
2285
|
-
shouldRenderStructuredBlocks || hasTextContent ? /* @__PURE__ */ jsx8(
|
|
2286
|
-
|
|
2546
|
+
shouldRenderStructuredBlocks || hasTextContent ? /* @__PURE__ */ jsx8(
|
|
2547
|
+
ContentStack,
|
|
2287
2548
|
{
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2549
|
+
ref: bodyStackRef,
|
|
2550
|
+
"data-testid": "chat-message-body-stack",
|
|
2551
|
+
"data-collapsed": isUserMessageCollapsed,
|
|
2552
|
+
children: bodySegments.map((segment, index) => /* @__PURE__ */ jsx8(
|
|
2553
|
+
ContentSegment,
|
|
2554
|
+
{
|
|
2555
|
+
"data-testid": "chat-message-content-segment",
|
|
2556
|
+
children: segment.type === "block" ? renderChatMessageBlock(segment.block, segment.index) : segment.type === "text" ? segment.content !== void 0 ? segment.useTimelineSegmentation ? renderTextContent({
|
|
2557
|
+
content: segment.content,
|
|
2558
|
+
displayedBlocks: segment.displayedBlocks,
|
|
2559
|
+
useTimelineSegmentation: true
|
|
2560
|
+
}) : renderStaticTextSegment(segment.content) : renderTextContent() : renderStaticTextSegment(segment.content)
|
|
2561
|
+
},
|
|
2562
|
+
segment.type === "text" ? `text-${index}` : segment.type === "markdown" ? `markdown-${index}` : `${segment.block.type}-${segment.index}`
|
|
2563
|
+
))
|
|
2564
|
+
}
|
|
2565
|
+
) : null,
|
|
2297
2566
|
attachments.length ? /* @__PURE__ */ jsx8(AttachmentGrid, { "data-testid": "chat-message-attachment-grid", children: attachments.map((attachment) => /* @__PURE__ */ jsx8(
|
|
2298
2567
|
AttachmentButton,
|
|
2299
2568
|
{
|
|
@@ -2378,6 +2647,29 @@ var StatusTag = styled7.span`
|
|
|
2378
2647
|
letter-spacing: 0.02em;
|
|
2379
2648
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
|
|
2380
2649
|
`;
|
|
2650
|
+
var CollapseToggle = styled7.button`
|
|
2651
|
+
margin-left: auto;
|
|
2652
|
+
width: 28px;
|
|
2653
|
+
height: 28px;
|
|
2654
|
+
display: inline-flex;
|
|
2655
|
+
align-items: center;
|
|
2656
|
+
justify-content: center;
|
|
2657
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
2658
|
+
border-radius: 999px;
|
|
2659
|
+
background: rgba(255, 255, 255, 0.06);
|
|
2660
|
+
color: rgba(255, 255, 255, 0.72);
|
|
2661
|
+
cursor: pointer;
|
|
2662
|
+
transition:
|
|
2663
|
+
background 160ms ease-out,
|
|
2664
|
+
border-color 160ms ease-out,
|
|
2665
|
+
color 160ms ease-out;
|
|
2666
|
+
|
|
2667
|
+
&:hover {
|
|
2668
|
+
background: rgba(255, 255, 255, 0.1);
|
|
2669
|
+
border-color: rgba(255, 255, 255, 0.18);
|
|
2670
|
+
color: rgba(255, 255, 255, 0.92);
|
|
2671
|
+
}
|
|
2672
|
+
`;
|
|
2381
2673
|
var Content = styled7.div`
|
|
2382
2674
|
color: rgba(255, 255, 255, 0.92);
|
|
2383
2675
|
line-height: 1.6;
|
|
@@ -2422,6 +2714,11 @@ var ContentStack = styled7.div`
|
|
|
2422
2714
|
display: flex;
|
|
2423
2715
|
flex-direction: column;
|
|
2424
2716
|
gap: 16px;
|
|
2717
|
+
|
|
2718
|
+
&[data-collapsed='true'] {
|
|
2719
|
+
max-height: ${USER_MESSAGE_COLLAPSE_HEIGHT_PX}px;
|
|
2720
|
+
overflow: hidden;
|
|
2721
|
+
}
|
|
2425
2722
|
`;
|
|
2426
2723
|
var ContentSegment = styled7.div`
|
|
2427
2724
|
min-width: 0;
|
|
@@ -2435,6 +2732,11 @@ var ContentBlock = styled7.div`
|
|
|
2435
2732
|
margin-top: 16px;
|
|
2436
2733
|
}
|
|
2437
2734
|
|
|
2735
|
+
&[data-render-mode='plain-text'] {
|
|
2736
|
+
white-space: pre-wrap;
|
|
2737
|
+
overflow-wrap: anywhere;
|
|
2738
|
+
}
|
|
2739
|
+
|
|
2438
2740
|
&[data-block-tone='fresh'] {
|
|
2439
2741
|
opacity: 0.85;
|
|
2440
2742
|
filter: brightness(0.82) saturate(0.88);
|
|
@@ -2685,7 +2987,7 @@ var ChatThreadView = ({
|
|
|
2685
2987
|
onQuestionnaireSubmit,
|
|
2686
2988
|
renderMessageBlock
|
|
2687
2989
|
}) => {
|
|
2688
|
-
const containerRef =
|
|
2990
|
+
const containerRef = useRef4(null);
|
|
2689
2991
|
const conversationTurns = useMemo4(
|
|
2690
2992
|
() => groupConversationTurns(historyMessages, streamingMessage),
|
|
2691
2993
|
[historyMessages, streamingMessage]
|
|
@@ -2693,10 +2995,10 @@ var ChatThreadView = ({
|
|
|
2693
2995
|
const latestTurn = conversationTurns[conversationTurns.length - 1];
|
|
2694
2996
|
const previousTurns = conversationTurns.slice(0, -1);
|
|
2695
2997
|
const latestUserMessageId = latestTurn?.userMessage?.id;
|
|
2696
|
-
const latestUserMessageRef =
|
|
2697
|
-
const reservedSpaceFrameRef =
|
|
2698
|
-
const [latestTurnMinHeight, setLatestTurnMinHeight] =
|
|
2699
|
-
const measureLatestTurnMinHeight =
|
|
2998
|
+
const latestUserMessageRef = useRef4(null);
|
|
2999
|
+
const reservedSpaceFrameRef = useRef4(null);
|
|
3000
|
+
const [latestTurnMinHeight, setLatestTurnMinHeight] = useState4(0);
|
|
3001
|
+
const measureLatestTurnMinHeight = useCallback3(() => {
|
|
2700
3002
|
const container = containerRef.current;
|
|
2701
3003
|
if (!container)
|
|
2702
3004
|
return;
|
|
@@ -2706,7 +3008,7 @@ var ChatThreadView = ({
|
|
|
2706
3008
|
const nextMinHeight = Math.max(0, container.clientHeight - paddingTop - paddingBottom);
|
|
2707
3009
|
setLatestTurnMinHeight((current) => current === nextMinHeight ? current : nextMinHeight);
|
|
2708
3010
|
}, []);
|
|
2709
|
-
const scrollLatestUserMessageToTop =
|
|
3011
|
+
const scrollLatestUserMessageToTop = useCallback3(() => {
|
|
2710
3012
|
const container = containerRef.current;
|
|
2711
3013
|
const target = latestUserMessageRef.current;
|
|
2712
3014
|
if (!container || !target)
|
|
@@ -2726,7 +3028,7 @@ var ChatThreadView = ({
|
|
|
2726
3028
|
}
|
|
2727
3029
|
container.scrollTop = nextScrollTop;
|
|
2728
3030
|
}, []);
|
|
2729
|
-
|
|
3031
|
+
useLayoutEffect2(() => {
|
|
2730
3032
|
if (reservedSpaceFrameRef.current !== null) {
|
|
2731
3033
|
window.cancelAnimationFrame(reservedSpaceFrameRef.current);
|
|
2732
3034
|
reservedSpaceFrameRef.current = null;
|
|
@@ -2755,7 +3057,7 @@ var ChatThreadView = ({
|
|
|
2755
3057
|
}
|
|
2756
3058
|
};
|
|
2757
3059
|
}, [latestUserMessageId, measureLatestTurnMinHeight, scrollLatestUserMessageToTop]);
|
|
2758
|
-
|
|
3060
|
+
useLayoutEffect2(() => {
|
|
2759
3061
|
if (!latestUserMessageId)
|
|
2760
3062
|
return;
|
|
2761
3063
|
const handleResize = () => {
|
|
@@ -2842,15 +3144,40 @@ var ChatThread = () => {
|
|
|
2842
3144
|
const error = useChatStore((s) => s.errorBySession[s.activeSessionId ?? ""]);
|
|
2843
3145
|
const updateQA = useChatStore((s) => s.updateQuestionnaireAnswers);
|
|
2844
3146
|
const clearSessionError = useChatStore((s) => s.clearSessionError);
|
|
2845
|
-
const {
|
|
2846
|
-
|
|
3147
|
+
const {
|
|
3148
|
+
sendRef,
|
|
3149
|
+
retryRef,
|
|
3150
|
+
renderMessageBlock,
|
|
3151
|
+
handleQuestionnaireSubmit: customQuestionnaireSubmit,
|
|
3152
|
+
handleConfirmationSubmit: customConfirmationSubmit,
|
|
3153
|
+
labels
|
|
3154
|
+
} = useChatContext();
|
|
3155
|
+
const handleRetry = useCallback3(() => {
|
|
2847
3156
|
if (!activeSessionId)
|
|
2848
3157
|
return;
|
|
2849
3158
|
clearSessionError(activeSessionId);
|
|
2850
3159
|
void retryRef.current();
|
|
2851
3160
|
}, [activeSessionId, clearSessionError, retryRef]);
|
|
2852
|
-
const handleQuestionnaireSubmit =
|
|
2853
|
-
(submission) => {
|
|
3161
|
+
const handleQuestionnaireSubmit = useCallback3(
|
|
3162
|
+
async (submission) => {
|
|
3163
|
+
if (customQuestionnaireSubmit) {
|
|
3164
|
+
const handled = await customQuestionnaireSubmit(submission, {
|
|
3165
|
+
sessionId: activeSessionId ?? void 0,
|
|
3166
|
+
mode: activeSessionMode
|
|
3167
|
+
});
|
|
3168
|
+
if (handled !== false) {
|
|
3169
|
+
if (activeSessionId && submission.sourceMessageId) {
|
|
3170
|
+
updateQA(
|
|
3171
|
+
activeSessionId,
|
|
3172
|
+
submission.sourceMessageId,
|
|
3173
|
+
submission.questionnaireId,
|
|
3174
|
+
submission.answers
|
|
3175
|
+
);
|
|
3176
|
+
}
|
|
3177
|
+
return;
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
await sendRef.current(submission.content);
|
|
2854
3181
|
if (activeSessionId && submission.sourceMessageId) {
|
|
2855
3182
|
updateQA(
|
|
2856
3183
|
activeSessionId,
|
|
@@ -2859,15 +3186,23 @@ var ChatThread = () => {
|
|
|
2859
3186
|
submission.answers
|
|
2860
3187
|
);
|
|
2861
3188
|
}
|
|
2862
|
-
void sendRef.current(submission.content);
|
|
2863
3189
|
},
|
|
2864
|
-
[activeSessionId, updateQA, sendRef]
|
|
3190
|
+
[activeSessionId, activeSessionMode, updateQA, sendRef, customQuestionnaireSubmit]
|
|
2865
3191
|
);
|
|
2866
|
-
const
|
|
2867
|
-
(submission) => {
|
|
2868
|
-
|
|
3192
|
+
const handleConfirmation = useCallback3(
|
|
3193
|
+
async (submission) => {
|
|
3194
|
+
if (customConfirmationSubmit) {
|
|
3195
|
+
const handled = await customConfirmationSubmit(submission, {
|
|
3196
|
+
sessionId: activeSessionId ?? void 0,
|
|
3197
|
+
mode: activeSessionMode
|
|
3198
|
+
});
|
|
3199
|
+
if (handled !== false) {
|
|
3200
|
+
return;
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3203
|
+
await sendRef.current(submission.content);
|
|
2869
3204
|
},
|
|
2870
|
-
[sendRef]
|
|
3205
|
+
[activeSessionId, activeSessionMode, sendRef, customConfirmationSubmit]
|
|
2871
3206
|
);
|
|
2872
3207
|
if (!hasSessions || messages.length === 0 && !streamingMessage) {
|
|
2873
3208
|
return /* @__PURE__ */ jsx10(ChatThreadEmptyState, {});
|
|
@@ -2881,7 +3216,7 @@ var ChatThread = () => {
|
|
|
2881
3216
|
error,
|
|
2882
3217
|
retryButtonLabel: labels.retryButton,
|
|
2883
3218
|
onRetry: handleRetry,
|
|
2884
|
-
onConfirmationSubmit:
|
|
3219
|
+
onConfirmationSubmit: handleConfirmation,
|
|
2885
3220
|
onQuestionnaireSubmit: handleQuestionnaireSubmit,
|
|
2886
3221
|
renderMessageBlock
|
|
2887
3222
|
}
|
|
@@ -2895,6 +3230,7 @@ var Container = styled9.div`
|
|
|
2895
3230
|
min-height: 0;
|
|
2896
3231
|
overflow: auto;
|
|
2897
3232
|
padding: 24px;
|
|
3233
|
+
margin-bottom: 24px;
|
|
2898
3234
|
overscroll-behavior: contain;
|
|
2899
3235
|
|
|
2900
3236
|
&::-webkit-scrollbar {
|
|
@@ -2948,7 +3284,7 @@ var RetryButton = styled9.button`
|
|
|
2948
3284
|
`;
|
|
2949
3285
|
|
|
2950
3286
|
// src/components/chat-composer/index.tsx
|
|
2951
|
-
import { useEffect as useEffect6, useRef as
|
|
3287
|
+
import { useEffect as useEffect6, useLayoutEffect as useLayoutEffect3, useRef as useRef7, useState as useState8 } from "react";
|
|
2952
3288
|
import styled14 from "@emotion/styled";
|
|
2953
3289
|
|
|
2954
3290
|
// src/components/chat-composer/lib/chat-composer.ts
|
|
@@ -3060,10 +3396,10 @@ var resolveSendSession = ({
|
|
|
3060
3396
|
};
|
|
3061
3397
|
|
|
3062
3398
|
// src/components/chat-composer/hooks/use-chat-composer.ts
|
|
3063
|
-
import { useCallback as
|
|
3399
|
+
import { useCallback as useCallback4, useEffect as useEffect5, useRef as useRef6, useState as useState6 } from "react";
|
|
3064
3400
|
|
|
3065
3401
|
// src/components/chat-composer/hooks/use-composer-attachments.ts
|
|
3066
|
-
import { useEffect as useEffect4, useRef as
|
|
3402
|
+
import { useEffect as useEffect4, useRef as useRef5, useState as useState5 } from "react";
|
|
3067
3403
|
var SUPPORTED_IMAGE_MIME_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/webp"]);
|
|
3068
3404
|
var MAX_COMPOSER_ATTACHMENTS = 10;
|
|
3069
3405
|
var createObjectUrl = (file) => typeof URL !== "undefined" && typeof URL.createObjectURL === "function" ? URL.createObjectURL(file) : "";
|
|
@@ -3077,8 +3413,8 @@ var releaseComposerAttachments = (attachments) => {
|
|
|
3077
3413
|
attachments.forEach((attachment) => revokeObjectUrl(attachment.previewUrl));
|
|
3078
3414
|
};
|
|
3079
3415
|
var useComposerAttachments = () => {
|
|
3080
|
-
const [attachments, setAttachments] =
|
|
3081
|
-
const attachmentsRef =
|
|
3416
|
+
const [attachments, setAttachments] = useState5([]);
|
|
3417
|
+
const attachmentsRef = useRef5([]);
|
|
3082
3418
|
useEffect4(() => {
|
|
3083
3419
|
attachmentsRef.current = attachments;
|
|
3084
3420
|
}, [attachments]);
|
|
@@ -3195,10 +3531,10 @@ var useChatComposer = () => {
|
|
|
3195
3531
|
const clearSessionError = useChatStore((s) => s.clearSessionError);
|
|
3196
3532
|
const setPreferredMode = useChatStore((s) => s.setPreferredMode);
|
|
3197
3533
|
const setSessionMode = useChatStore((s) => s.setSessionMode);
|
|
3198
|
-
const [availableModels, setAvailableModels] =
|
|
3199
|
-
const [isModelsLoading, setIsModelsLoading] =
|
|
3200
|
-
const [isModelsError, setIsModelsError] =
|
|
3201
|
-
const fetchModels =
|
|
3534
|
+
const [availableModels, setAvailableModels] = useState6([]);
|
|
3535
|
+
const [isModelsLoading, setIsModelsLoading] = useState6(true);
|
|
3536
|
+
const [isModelsError, setIsModelsError] = useState6(false);
|
|
3537
|
+
const fetchModels = useCallback4(async () => {
|
|
3202
3538
|
setIsModelsLoading(true);
|
|
3203
3539
|
setIsModelsError(false);
|
|
3204
3540
|
try {
|
|
@@ -3214,14 +3550,14 @@ var useChatComposer = () => {
|
|
|
3214
3550
|
void fetchModels();
|
|
3215
3551
|
}, [fetchModels]);
|
|
3216
3552
|
const hasModels = availableModels.length > 0;
|
|
3217
|
-
const [value, setValue] =
|
|
3218
|
-
const [selectedModel, setSelectedModel] =
|
|
3219
|
-
const [selectedMode, setSelectedModeLocal] =
|
|
3220
|
-
const [attachmentNotice, setAttachmentNotice] =
|
|
3553
|
+
const [value, setValue] = useState6("");
|
|
3554
|
+
const [selectedModel, setSelectedModel] = useState6("");
|
|
3555
|
+
const [selectedMode, setSelectedModeLocal] = useState6(DEFAULT_CHAT_AGENT_MODE);
|
|
3556
|
+
const [attachmentNotice, setAttachmentNotice] = useState6(null);
|
|
3221
3557
|
const { attachments, appendFiles, removeAttachment, takeMessageAttachments } = useComposerAttachments();
|
|
3222
|
-
const abortControllerRef =
|
|
3223
|
-
const stopRequestRef =
|
|
3224
|
-
const lastRequestRef =
|
|
3558
|
+
const abortControllerRef = useRef6(null);
|
|
3559
|
+
const stopRequestRef = useRef6(null);
|
|
3560
|
+
const lastRequestRef = useRef6(null);
|
|
3225
3561
|
useEffect5(() => {
|
|
3226
3562
|
setSelectedModel(
|
|
3227
3563
|
(current) => resolveSelectedChatModel({ currentModel: current, availableModels, isModelsLoading })
|
|
@@ -3253,7 +3589,7 @@ var useChatComposer = () => {
|
|
|
3253
3589
|
stopRequestRef.current.timeoutId = null;
|
|
3254
3590
|
}
|
|
3255
3591
|
};
|
|
3256
|
-
const clearStopRequest =
|
|
3592
|
+
const clearStopRequest = useCallback4((sessionId) => {
|
|
3257
3593
|
if (!stopRequestRef.current)
|
|
3258
3594
|
return;
|
|
3259
3595
|
if (sessionId && stopRequestRef.current.sessionId !== sessionId)
|
|
@@ -3261,7 +3597,7 @@ var useChatComposer = () => {
|
|
|
3261
3597
|
clearStopTimeout(sessionId);
|
|
3262
3598
|
stopRequestRef.current = null;
|
|
3263
3599
|
}, []);
|
|
3264
|
-
const finalizeStop =
|
|
3600
|
+
const finalizeStop = useCallback4(
|
|
3265
3601
|
(sessionId) => {
|
|
3266
3602
|
if (stopRequestRef.current?.sessionId === sessionId) {
|
|
3267
3603
|
if (stopRequestRef.current.finalized)
|
|
@@ -3276,7 +3612,7 @@ var useChatComposer = () => {
|
|
|
3276
3612
|
},
|
|
3277
3613
|
[clearStopRequest, finalizeStoppedStreamingMessage]
|
|
3278
3614
|
);
|
|
3279
|
-
const runStream =
|
|
3615
|
+
const runStream = useCallback4(
|
|
3280
3616
|
async ({
|
|
3281
3617
|
localSessionId,
|
|
3282
3618
|
sessionId,
|
|
@@ -3365,7 +3701,7 @@ var useChatComposer = () => {
|
|
|
3365
3701
|
setSessionError
|
|
3366
3702
|
]
|
|
3367
3703
|
);
|
|
3368
|
-
const send =
|
|
3704
|
+
const send = useCallback4(
|
|
3369
3705
|
async (contentOverride) => {
|
|
3370
3706
|
const content = (contentOverride ?? value).trim();
|
|
3371
3707
|
const hasText = Boolean(content);
|
|
@@ -3513,14 +3849,14 @@ var useChatComposer = () => {
|
|
|
3513
3849
|
};
|
|
3514
3850
|
|
|
3515
3851
|
// src/components/chat-composer/components/chat-composer-attachment-list.tsx
|
|
3516
|
-
import { useState as
|
|
3852
|
+
import { useState as useState7 } from "react";
|
|
3517
3853
|
import styled10 from "@emotion/styled";
|
|
3518
3854
|
import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs8 } from "@emotion/react/jsx-runtime";
|
|
3519
3855
|
var ChatComposerAttachmentList = ({
|
|
3520
3856
|
attachments,
|
|
3521
3857
|
onRemoveAttachment
|
|
3522
3858
|
}) => {
|
|
3523
|
-
const [activeImage, setActiveImage] =
|
|
3859
|
+
const [activeImage, setActiveImage] = useState7(null);
|
|
3524
3860
|
if (!attachments.length) {
|
|
3525
3861
|
return null;
|
|
3526
3862
|
}
|
|
@@ -3974,6 +4310,27 @@ var StopSpinner = styled13.span`
|
|
|
3974
4310
|
|
|
3975
4311
|
// src/components/chat-composer/index.tsx
|
|
3976
4312
|
import { jsx as jsx15, jsxs as jsxs10 } from "@emotion/react/jsx-runtime";
|
|
4313
|
+
var CHAT_COMPOSER_LINE_HEIGHT_PX = 20;
|
|
4314
|
+
var CHAT_COMPOSER_MAX_ROWS = 7;
|
|
4315
|
+
var CHAT_COMPOSER_PADDING_TOP_PX = 8;
|
|
4316
|
+
var CHAT_COMPOSER_PADDING_BOTTOM_PX = 12;
|
|
4317
|
+
var CHAT_COMPOSER_PADDING_BLOCK_PX = CHAT_COMPOSER_PADDING_TOP_PX + CHAT_COMPOSER_PADDING_BOTTOM_PX;
|
|
4318
|
+
var CHAT_COMPOSER_MIN_ROWS = 4;
|
|
4319
|
+
var CHAT_COMPOSER_EXPANDED_MAX_ROWS = 60;
|
|
4320
|
+
var CHAT_COMPOSER_EXPANDED_MAX_VIEWPORT_RATIO = 0.7;
|
|
4321
|
+
var CHAT_COMPOSER_EXPANDED_RESERVED_SPACE_PX = 96;
|
|
4322
|
+
var CHAT_COMPOSER_MAX_HEIGHT_PX = CHAT_COMPOSER_MAX_ROWS * CHAT_COMPOSER_LINE_HEIGHT_PX + CHAT_COMPOSER_PADDING_BLOCK_PX;
|
|
4323
|
+
var CHAT_COMPOSER_EXPANDED_ROWS_HEIGHT_PX = CHAT_COMPOSER_EXPANDED_MAX_ROWS * CHAT_COMPOSER_LINE_HEIGHT_PX + CHAT_COMPOSER_PADDING_BLOCK_PX;
|
|
4324
|
+
var getExpandedComposerHeightPx = () => {
|
|
4325
|
+
if (typeof window === "undefined") {
|
|
4326
|
+
return CHAT_COMPOSER_EXPANDED_ROWS_HEIGHT_PX;
|
|
4327
|
+
}
|
|
4328
|
+
const viewportLimitedHeight = window.innerHeight * CHAT_COMPOSER_EXPANDED_MAX_VIEWPORT_RATIO - CHAT_COMPOSER_EXPANDED_RESERVED_SPACE_PX;
|
|
4329
|
+
return Math.max(
|
|
4330
|
+
CHAT_COMPOSER_MAX_HEIGHT_PX,
|
|
4331
|
+
Math.floor(Math.min(CHAT_COMPOSER_EXPANDED_ROWS_HEIGHT_PX, viewportLimitedHeight))
|
|
4332
|
+
);
|
|
4333
|
+
};
|
|
3977
4334
|
var PlusIcon = () => /* @__PURE__ */ jsx15(
|
|
3978
4335
|
"svg",
|
|
3979
4336
|
{
|
|
@@ -3986,6 +4343,36 @@ var PlusIcon = () => /* @__PURE__ */ jsx15(
|
|
|
3986
4343
|
children: /* @__PURE__ */ jsx15("path", { d: "M8 3v10M3 8h10", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" })
|
|
3987
4344
|
}
|
|
3988
4345
|
);
|
|
4346
|
+
var ComposerExpandIcon = ({ expanded }) => /* @__PURE__ */ jsx15(
|
|
4347
|
+
"svg",
|
|
4348
|
+
{
|
|
4349
|
+
"aria-hidden": "true",
|
|
4350
|
+
width: "16",
|
|
4351
|
+
height: "16",
|
|
4352
|
+
viewBox: "0 0 16 16",
|
|
4353
|
+
fill: "none",
|
|
4354
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4355
|
+
children: expanded ? /* @__PURE__ */ jsx15(
|
|
4356
|
+
"path",
|
|
4357
|
+
{
|
|
4358
|
+
d: "M14 6h-4V2M10 6l4-4M2 10h4v4M6 10l-4 4",
|
|
4359
|
+
stroke: "currentColor",
|
|
4360
|
+
strokeWidth: "1.5",
|
|
4361
|
+
strokeLinecap: "round",
|
|
4362
|
+
strokeLinejoin: "round"
|
|
4363
|
+
}
|
|
4364
|
+
) : /* @__PURE__ */ jsx15(
|
|
4365
|
+
"path",
|
|
4366
|
+
{
|
|
4367
|
+
d: "M10 2h4v4M14 2L9 7M6 14H2v-4M2 14l5-5",
|
|
4368
|
+
stroke: "currentColor",
|
|
4369
|
+
strokeWidth: "1.5",
|
|
4370
|
+
strokeLinecap: "round",
|
|
4371
|
+
strokeLinejoin: "round"
|
|
4372
|
+
}
|
|
4373
|
+
)
|
|
4374
|
+
}
|
|
4375
|
+
);
|
|
3989
4376
|
var ChatComposerView = ({
|
|
3990
4377
|
value,
|
|
3991
4378
|
placeholder,
|
|
@@ -4002,6 +4389,8 @@ var ChatComposerView = ({
|
|
|
4002
4389
|
isStopping,
|
|
4003
4390
|
enableImageAttachments,
|
|
4004
4391
|
modeLabels,
|
|
4392
|
+
expandComposerAriaLabel,
|
|
4393
|
+
collapseComposerAriaLabel,
|
|
4005
4394
|
onValueChange,
|
|
4006
4395
|
onPickImages,
|
|
4007
4396
|
onPasteImages,
|
|
@@ -4012,7 +4401,10 @@ var ChatComposerView = ({
|
|
|
4012
4401
|
onStop,
|
|
4013
4402
|
onSend
|
|
4014
4403
|
}) => {
|
|
4015
|
-
const imageInputRef =
|
|
4404
|
+
const imageInputRef = useRef7(null);
|
|
4405
|
+
const inputRef = useRef7(null);
|
|
4406
|
+
const [isComposerExpandable, setIsComposerExpandable] = useState8(false);
|
|
4407
|
+
const [isComposerExpanded, setIsComposerExpanded] = useState8(false);
|
|
4016
4408
|
const canSend = canSendChatMessage({
|
|
4017
4409
|
value,
|
|
4018
4410
|
attachmentCount: attachments.length,
|
|
@@ -4020,6 +4412,26 @@ var ChatComposerView = ({
|
|
|
4020
4412
|
isModelsError,
|
|
4021
4413
|
hasModels
|
|
4022
4414
|
});
|
|
4415
|
+
useLayoutEffect3(() => {
|
|
4416
|
+
const element = inputRef.current;
|
|
4417
|
+
if (!element) {
|
|
4418
|
+
return;
|
|
4419
|
+
}
|
|
4420
|
+
if (!isComposerExpanded) {
|
|
4421
|
+
element.style.height = "0px";
|
|
4422
|
+
}
|
|
4423
|
+
const scrollHeight = element.scrollHeight;
|
|
4424
|
+
const nextExpandable = scrollHeight > CHAT_COMPOSER_MAX_HEIGHT_PX;
|
|
4425
|
+
const expandedHeight = getExpandedComposerHeightPx();
|
|
4426
|
+
const nextHeight = isComposerExpanded ? expandedHeight : Math.min(scrollHeight, CHAT_COMPOSER_MAX_HEIGHT_PX);
|
|
4427
|
+
setIsComposerExpandable(nextExpandable);
|
|
4428
|
+
element.style.height = `${nextHeight}px`;
|
|
4429
|
+
element.style.overflowY = !isComposerExpanded && scrollHeight > CHAT_COMPOSER_MAX_HEIGHT_PX ? "auto" : "hidden";
|
|
4430
|
+
}, [isComposerExpanded, value]);
|
|
4431
|
+
const handleSend = async () => {
|
|
4432
|
+
setIsComposerExpanded(false);
|
|
4433
|
+
await onSend();
|
|
4434
|
+
};
|
|
4023
4435
|
const handleKeyDown = (event) => {
|
|
4024
4436
|
if (shouldStopChatComposer({ key: event.key, shiftKey: event.shiftKey, isStreaming })) {
|
|
4025
4437
|
event.preventDefault();
|
|
@@ -4029,7 +4441,7 @@ var ChatComposerView = ({
|
|
|
4029
4441
|
if (!shouldSubmitChatComposer({ key: event.key, shiftKey: event.shiftKey, canSend }))
|
|
4030
4442
|
return;
|
|
4031
4443
|
event.preventDefault();
|
|
4032
|
-
void
|
|
4444
|
+
void handleSend();
|
|
4033
4445
|
};
|
|
4034
4446
|
const handlePickImages = (event) => {
|
|
4035
4447
|
if (event.target.files?.length)
|
|
@@ -4064,60 +4476,77 @@ var ChatComposerView = ({
|
|
|
4064
4476
|
}
|
|
4065
4477
|
),
|
|
4066
4478
|
attachmentNotice === "limit_reached" ? /* @__PURE__ */ jsx15(AttachmentNotice, { "data-testid": "chat-composer-attachment-notice", children: attachmentLimitNotice }) : null,
|
|
4067
|
-
/* @__PURE__ */
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
"data-testid": "chat-composer-input",
|
|
4071
|
-
value,
|
|
4072
|
-
onChange: (event) => onValueChange(event.target.value),
|
|
4073
|
-
onKeyDown: handleKeyDown,
|
|
4074
|
-
onPaste: enableImageAttachments ? handlePaste : void 0,
|
|
4075
|
-
placeholder
|
|
4076
|
-
}
|
|
4077
|
-
),
|
|
4078
|
-
/* @__PURE__ */ jsx15(Footer, { children: /* @__PURE__ */ jsxs10(Actions2, { "data-testid": "chat-composer-actions", children: [
|
|
4079
|
-
enableImageAttachments ? /* @__PURE__ */ jsx15(
|
|
4080
|
-
AttachButton,
|
|
4479
|
+
/* @__PURE__ */ jsxs10(InputArea, { "data-testid": "chat-composer-input-area", children: [
|
|
4480
|
+
isComposerExpanded || isComposerExpandable ? /* @__PURE__ */ jsx15(
|
|
4481
|
+
ComposerExpandButton,
|
|
4081
4482
|
{
|
|
4082
4483
|
type: "button",
|
|
4083
|
-
"data-testid": "chat-composer-
|
|
4084
|
-
"aria-label":
|
|
4085
|
-
|
|
4086
|
-
|
|
4484
|
+
"data-testid": "chat-composer-expand-toggle",
|
|
4485
|
+
"aria-label": isComposerExpanded ? collapseComposerAriaLabel : expandComposerAriaLabel,
|
|
4486
|
+
"aria-expanded": isComposerExpanded,
|
|
4487
|
+
onClick: () => setIsComposerExpanded((current) => !current),
|
|
4488
|
+
children: /* @__PURE__ */ jsx15(ComposerExpandIcon, { expanded: isComposerExpanded })
|
|
4087
4489
|
}
|
|
4088
4490
|
) : null,
|
|
4089
4491
|
/* @__PURE__ */ jsx15(
|
|
4090
|
-
|
|
4091
|
-
{
|
|
4092
|
-
value: selectedMode,
|
|
4093
|
-
disabled: isStreaming,
|
|
4094
|
-
labels: modeLabels,
|
|
4095
|
-
onChange: onSelectedModeChange
|
|
4096
|
-
}
|
|
4097
|
-
),
|
|
4098
|
-
/* @__PURE__ */ jsx15(
|
|
4099
|
-
ChatModelControl,
|
|
4492
|
+
Input,
|
|
4100
4493
|
{
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4494
|
+
ref: inputRef,
|
|
4495
|
+
"data-testid": "chat-composer-input",
|
|
4496
|
+
"data-expanded": isComposerExpanded,
|
|
4497
|
+
value,
|
|
4498
|
+
onChange: (event) => onValueChange(event.target.value),
|
|
4499
|
+
onKeyDown: handleKeyDown,
|
|
4500
|
+
onPaste: enableImageAttachments ? handlePaste : void 0,
|
|
4501
|
+
placeholder
|
|
4108
4502
|
}
|
|
4109
|
-
)
|
|
4110
|
-
|
|
4111
|
-
|
|
4503
|
+
)
|
|
4504
|
+
] }),
|
|
4505
|
+
/* @__PURE__ */ jsxs10(Footer, { children: [
|
|
4506
|
+
/* @__PURE__ */ jsx15(LeadingActions, { "data-testid": "chat-composer-leading-actions", children: enableImageAttachments ? /* @__PURE__ */ jsx15(
|
|
4507
|
+
AttachButton,
|
|
4112
4508
|
{
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4509
|
+
type: "button",
|
|
4510
|
+
"data-testid": "chat-composer-attach-image",
|
|
4511
|
+
"aria-label": "Attach image",
|
|
4512
|
+
onClick: () => imageInputRef.current?.click(),
|
|
4513
|
+
children: /* @__PURE__ */ jsx15(PlusIcon, {})
|
|
4118
4514
|
}
|
|
4119
|
-
)
|
|
4120
|
-
|
|
4515
|
+
) : null }),
|
|
4516
|
+
/* @__PURE__ */ jsxs10(TrailingActions, { "data-testid": "chat-composer-trailing-actions", children: [
|
|
4517
|
+
/* @__PURE__ */ jsx15(
|
|
4518
|
+
ChatModeControl,
|
|
4519
|
+
{
|
|
4520
|
+
value: selectedMode,
|
|
4521
|
+
disabled: isStreaming,
|
|
4522
|
+
labels: modeLabels,
|
|
4523
|
+
onChange: onSelectedModeChange
|
|
4524
|
+
}
|
|
4525
|
+
),
|
|
4526
|
+
/* @__PURE__ */ jsx15(
|
|
4527
|
+
ChatModelControl,
|
|
4528
|
+
{
|
|
4529
|
+
selectedModel,
|
|
4530
|
+
availableModels,
|
|
4531
|
+
isModelsLoading,
|
|
4532
|
+
isModelsError,
|
|
4533
|
+
hasModels,
|
|
4534
|
+
onSelectedModelChange,
|
|
4535
|
+
onReloadModels
|
|
4536
|
+
}
|
|
4537
|
+
),
|
|
4538
|
+
/* @__PURE__ */ jsx15(
|
|
4539
|
+
ChatSendActions,
|
|
4540
|
+
{
|
|
4541
|
+
canSend,
|
|
4542
|
+
isStreaming,
|
|
4543
|
+
isStopping,
|
|
4544
|
+
onStop,
|
|
4545
|
+
onSend: handleSend
|
|
4546
|
+
}
|
|
4547
|
+
)
|
|
4548
|
+
] })
|
|
4549
|
+
] })
|
|
4121
4550
|
] }) });
|
|
4122
4551
|
};
|
|
4123
4552
|
var ChatComposer = () => {
|
|
@@ -4153,6 +4582,8 @@ var ChatComposer = () => {
|
|
|
4153
4582
|
isStopping: state.isStopping,
|
|
4154
4583
|
enableImageAttachments,
|
|
4155
4584
|
modeLabels,
|
|
4585
|
+
expandComposerAriaLabel: labels.expandComposerAriaLabel,
|
|
4586
|
+
collapseComposerAriaLabel: labels.collapseComposerAriaLabel,
|
|
4156
4587
|
onValueChange: actions.setValue,
|
|
4157
4588
|
onPickImages: actions.pickImages,
|
|
4158
4589
|
onPasteImages: actions.pasteImages,
|
|
@@ -4169,6 +4600,16 @@ var Container2 = styled14.div`
|
|
|
4169
4600
|
padding: 0 16px 16px;
|
|
4170
4601
|
`;
|
|
4171
4602
|
var Surface = styled14.div`
|
|
4603
|
+
display: grid;
|
|
4604
|
+
grid-template-columns: minmax(0, 1fr);
|
|
4605
|
+
grid-template-areas:
|
|
4606
|
+
'attachments'
|
|
4607
|
+
'notice'
|
|
4608
|
+
'input'
|
|
4609
|
+
'footer';
|
|
4610
|
+
width: 100%;
|
|
4611
|
+
max-width: 760px;
|
|
4612
|
+
margin: 0 auto;
|
|
4172
4613
|
background: var(--border-color);
|
|
4173
4614
|
border-radius: 20px;
|
|
4174
4615
|
border: 1px solid var(--border-hover);
|
|
@@ -4178,6 +4619,7 @@ var Surface = styled14.div`
|
|
|
4178
4619
|
backdrop-filter: blur(10px);
|
|
4179
4620
|
`;
|
|
4180
4621
|
var AttachmentNotice = styled14.div`
|
|
4622
|
+
grid-area: notice;
|
|
4181
4623
|
margin: 10px 12px 0;
|
|
4182
4624
|
padding: 8px 10px;
|
|
4183
4625
|
border-radius: 10px;
|
|
@@ -4187,19 +4629,45 @@ var AttachmentNotice = styled14.div`
|
|
|
4187
4629
|
font-size: 12px;
|
|
4188
4630
|
line-height: 1.4;
|
|
4189
4631
|
`;
|
|
4632
|
+
var InputArea = styled14.div`
|
|
4633
|
+
grid-area: input;
|
|
4634
|
+
position: relative;
|
|
4635
|
+
`;
|
|
4190
4636
|
var Input = styled14.textarea`
|
|
4637
|
+
--textarea-line-height: ${CHAT_COMPOSER_LINE_HEIGHT_PX}px;
|
|
4638
|
+
--textarea-min-rows: ${CHAT_COMPOSER_MIN_ROWS};
|
|
4639
|
+
--textarea-max-rows: ${CHAT_COMPOSER_MAX_ROWS};
|
|
4640
|
+
--textarea-expanded-max-rows: ${CHAT_COMPOSER_EXPANDED_MAX_ROWS};
|
|
4641
|
+
--textarea-padding-top: ${CHAT_COMPOSER_PADDING_TOP_PX}px;
|
|
4642
|
+
--textarea-padding-bottom: ${CHAT_COMPOSER_PADDING_BOTTOM_PX}px;
|
|
4643
|
+
--textarea-padding-block: calc(var(--textarea-padding-top) + var(--textarea-padding-bottom));
|
|
4644
|
+
--textarea-max-height: calc(
|
|
4645
|
+
var(--textarea-max-rows) * var(--textarea-line-height) + var(--textarea-padding-block)
|
|
4646
|
+
);
|
|
4647
|
+
--textarea-expanded-max-height: min(
|
|
4648
|
+
calc(
|
|
4649
|
+
var(--textarea-expanded-max-rows) * var(--textarea-line-height) +
|
|
4650
|
+
var(--textarea-padding-block)
|
|
4651
|
+
),
|
|
4652
|
+
calc(70vh - ${CHAT_COMPOSER_EXPANDED_RESERVED_SPACE_PX}px)
|
|
4653
|
+
);
|
|
4191
4654
|
width: 100%;
|
|
4192
|
-
min-height:
|
|
4655
|
+
min-height: calc(
|
|
4656
|
+
var(--textarea-min-rows) * var(--textarea-line-height) + var(--textarea-padding-block)
|
|
4657
|
+
);
|
|
4658
|
+
max-height: var(--textarea-max-height);
|
|
4659
|
+
box-sizing: border-box;
|
|
4193
4660
|
resize: none;
|
|
4194
4661
|
appearance: none;
|
|
4195
4662
|
border: 0;
|
|
4196
4663
|
outline: 0;
|
|
4197
4664
|
background: transparent;
|
|
4198
|
-
padding:
|
|
4665
|
+
padding: var(--textarea-padding-top) 44px var(--textarea-padding-bottom) 12px;
|
|
4199
4666
|
font-weight: 400;
|
|
4200
4667
|
font-size: 14px;
|
|
4201
4668
|
color: var(--text-primary);
|
|
4202
|
-
line-height:
|
|
4669
|
+
line-height: var(--textarea-line-height);
|
|
4670
|
+
overflow-y: hidden;
|
|
4203
4671
|
|
|
4204
4672
|
&::placeholder {
|
|
4205
4673
|
color: var(--text-secondary);
|
|
@@ -4208,19 +4676,50 @@ var Input = styled14.textarea`
|
|
|
4208
4676
|
&::-webkit-resizer {
|
|
4209
4677
|
display: none;
|
|
4210
4678
|
}
|
|
4679
|
+
|
|
4680
|
+
&[data-expanded='true'] {
|
|
4681
|
+
max-height: var(--textarea-expanded-max-height);
|
|
4682
|
+
}
|
|
4683
|
+
`;
|
|
4684
|
+
var ComposerExpandButton = styled14.button`
|
|
4685
|
+
position: absolute;
|
|
4686
|
+
top: 8px;
|
|
4687
|
+
right: 10px;
|
|
4688
|
+
width: 28px;
|
|
4689
|
+
height: 28px;
|
|
4690
|
+
display: grid;
|
|
4691
|
+
place-items: center;
|
|
4692
|
+
border: none;
|
|
4693
|
+
border-radius: 999px;
|
|
4694
|
+
background: transparent;
|
|
4695
|
+
color: rgba(255, 255, 255, 0.72);
|
|
4696
|
+
cursor: pointer;
|
|
4697
|
+
z-index: 1;
|
|
4698
|
+
|
|
4699
|
+
&:hover {
|
|
4700
|
+
background: rgba(255, 255, 255, 0.08);
|
|
4701
|
+
color: rgba(255, 255, 255, 0.92);
|
|
4702
|
+
}
|
|
4211
4703
|
`;
|
|
4212
4704
|
var Footer = styled14.div`
|
|
4213
|
-
|
|
4705
|
+
grid-area: footer;
|
|
4706
|
+
display: grid;
|
|
4707
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
4214
4708
|
align-items: flex-end;
|
|
4215
|
-
justify-content: stretch;
|
|
4216
4709
|
gap: 16px;
|
|
4217
4710
|
padding: 0 14px 14px;
|
|
4218
4711
|
`;
|
|
4219
|
-
var
|
|
4712
|
+
var LeadingActions = styled14.div`
|
|
4713
|
+
display: flex;
|
|
4714
|
+
align-items: center;
|
|
4715
|
+
justify-content: flex-start;
|
|
4716
|
+
gap: 8px;
|
|
4717
|
+
min-width: 0;
|
|
4718
|
+
`;
|
|
4719
|
+
var TrailingActions = styled14.div`
|
|
4220
4720
|
display: flex;
|
|
4221
4721
|
align-items: center;
|
|
4222
4722
|
flex-wrap: wrap;
|
|
4223
|
-
width: 100%;
|
|
4224
4723
|
min-width: 0;
|
|
4225
4724
|
justify-content: flex-end;
|
|
4226
4725
|
gap: 8px;
|