@messenger-box/tailwind-ui-inbox 10.0.3-alpha.184 → 10.0.3-alpha.185
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/CHANGELOG.md +4 -0
- package/lib/components/AIAgent/AIAgent.d.ts +2 -0
- package/lib/components/AIAgent/AIAgent.d.ts.map +1 -1
- package/lib/components/AIAgent/AIAgent.js +232 -89
- package/lib/components/AIAgent/AIAgent.js.map +1 -1
- package/lib/components/InboxMessage/InputComponent.d.ts +3 -1
- package/lib/components/InboxMessage/InputComponent.d.ts.map +1 -1
- package/lib/components/InboxMessage/InputComponent.js +6 -2
- package/lib/components/InboxMessage/InputComponent.js.map +1 -1
- package/lib/components/InboxMessage/RightSidebarAi.d.ts +2 -0
- package/lib/components/InboxMessage/RightSidebarAi.d.ts.map +1 -1
- package/lib/components/InboxMessage/RightSidebarAi.js.map +1 -1
- package/lib/components/ModelConfigPanel.d.ts +4 -0
- package/lib/components/ModelConfigPanel.d.ts.map +1 -1
- package/lib/components/ModelConfigPanel.js +17 -2
- package/lib/components/ModelConfigPanel.js.map +1 -1
- package/lib/container/AiLandingInput.d.ts +2 -0
- package/lib/container/AiLandingInput.d.ts.map +1 -1
- package/lib/container/AiLandingInput.js +4 -0
- package/lib/container/AiLandingInput.js.map +1 -1
- package/lib/container/Inbox.js +1 -1
- package/lib/container/InboxAiMessagesLoader.d.ts +2 -0
- package/lib/container/InboxAiMessagesLoader.d.ts.map +1 -1
- package/lib/container/InboxAiMessagesLoader.js +5 -1
- package/lib/container/InboxAiMessagesLoader.js.map +1 -1
- package/lib/container/InboxContainer.d.ts +2 -0
- package/lib/container/InboxContainer.d.ts.map +1 -1
- package/lib/container/InboxContainer.js.map +1 -1
- package/lib/container/InboxWithAiLoader.d.ts +2 -0
- package/lib/container/InboxWithAiLoader.d.ts.map +1 -1
- package/lib/container/InboxWithAiLoader.js +9 -3
- package/lib/container/InboxWithAiLoader.js.map +1 -1
- package/lib/container/ServiceInbox.js +1 -1
- package/lib/container/ServiceInbox.js.map +1 -1
- package/lib/container/TestInboxWithAiLoader.d.ts.map +1 -1
- package/lib/container/TestInboxWithAiLoader.js +5 -1
- package/lib/container/TestInboxWithAiLoader.js.map +1 -1
- package/lib/container/ThreadMessages.js +1 -1
- package/lib/container/ThreadMessages.js.map +1 -1
- package/lib/container/ThreadMessagesInbox.js +1 -1
- package/lib/container/ThreadMessagesInbox.js.map +1 -1
- package/lib/container/Threads.js +1 -1
- package/lib/container/Threads.js.map +1 -1
- package/lib/templates/InboxWithAi.d.ts +2 -0
- package/lib/templates/InboxWithAi.d.ts.map +1 -1
- package/lib/templates/InboxWithAi.js +24 -5
- package/lib/templates/InboxWithAi.js.map +1 -1
- package/lib/templates/InboxWithAi.tsx +25 -2
- package/package.json +2 -2
- package/src/components/AIAgent/AIAgent.tsx +291 -112
- package/src/components/InboxMessage/InputComponent.tsx +6 -0
- package/src/components/InboxMessage/RightSidebarAi.tsx +2 -0
- package/src/components/ModelConfigPanel.tsx +55 -37
- package/src/container/AiLandingInput.tsx +6 -0
- package/src/container/InboxAiMessagesLoader.tsx +6 -0
- package/src/container/InboxContainer.tsx +2 -0
- package/src/container/InboxWithAiLoader.tsx +8 -0
- package/src/container/TestInboxWithAiLoader.tsx +4 -0
- package/src/templates/InboxWithAi.tsx +25 -2
|
@@ -48,6 +48,8 @@ interface AIAgentProps {
|
|
|
48
48
|
sendMessageInput?: ICreateChannelInput;
|
|
49
49
|
isShowOnlyInbox?: boolean;
|
|
50
50
|
showModeSelector?: boolean;
|
|
51
|
+
showStopButton?: boolean;
|
|
52
|
+
onStop?: () => void;
|
|
51
53
|
[key: string]: any; // Allow other props to be passed through to Inbox
|
|
52
54
|
}
|
|
53
55
|
|
|
@@ -69,9 +71,11 @@ export const AIAgent: React.FC<AIAgentProps> = ({
|
|
|
69
71
|
sendMessageInput,
|
|
70
72
|
isShowOnlyInbox = false,
|
|
71
73
|
showModeSelector = false,
|
|
74
|
+
showStopButton = false,
|
|
75
|
+
onStop,
|
|
72
76
|
}) => {
|
|
73
77
|
const [state, send] = useMachine(aiAgentMachine);
|
|
74
|
-
|
|
78
|
+
const apolloClient = useApolloClient();
|
|
75
79
|
const { startUpload } = useUploadFiles();
|
|
76
80
|
const [sendMsg] = useSendMessagesMutation();
|
|
77
81
|
const [createChannelWorkflowJob] = useCreateChannelWorkflowJobMutation();
|
|
@@ -116,7 +120,7 @@ export const AIAgent: React.FC<AIAgentProps> = ({
|
|
|
116
120
|
},
|
|
117
121
|
});
|
|
118
122
|
|
|
119
|
-
console.log('messagesQuery...', JSON.stringify(messagesQuery?.data?.messages?.data));
|
|
123
|
+
// console.log('messagesQuery...', JSON.stringify(messagesQuery?.data?.messages?.data));
|
|
120
124
|
|
|
121
125
|
const { messages: aiMessages, error, isTyping } = state.context;
|
|
122
126
|
const { t } = useTranslation('translations');
|
|
@@ -217,6 +221,48 @@ export const AIAgent: React.FC<AIAgentProps> = ({
|
|
|
217
221
|
return orderBy(uniqBy(allMessages, 'id'), ['createdAt'], ['asc']);
|
|
218
222
|
}, [messagesData?.messages?.data]);
|
|
219
223
|
|
|
224
|
+
// Check if any ASSISTANT message has isCreatingSandbox: true in fragment
|
|
225
|
+
// Only hide loader when isCreatingSandbox is explicitly false, not when it's undefined/missing
|
|
226
|
+
const isCreatingSandbox = useMemo(() => {
|
|
227
|
+
if (isShowOnlyInbox) return false; // Only check when isShowOnlyInbox is false
|
|
228
|
+
if (!regularMessages || regularMessages.length === 0) return false;
|
|
229
|
+
|
|
230
|
+
// Find the most recent ASSISTANT message
|
|
231
|
+
const mostRecentAssistant = regularMessages
|
|
232
|
+
.slice()
|
|
233
|
+
.reverse()
|
|
234
|
+
.find((m: any) => m?.propsConfiguration?.contents?.role === 'ASSISTANT');
|
|
235
|
+
|
|
236
|
+
if (!mostRecentAssistant) return false;
|
|
237
|
+
|
|
238
|
+
const fragment = mostRecentAssistant?.propsConfiguration?.contents?.fragment;
|
|
239
|
+
|
|
240
|
+
// If isCreatingSandbox is explicitly true, show loader
|
|
241
|
+
if (fragment?.isCreatingSandbox === true) {
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// If isCreatingSandbox is explicitly false, hide loader
|
|
246
|
+
if (fragment?.isCreatingSandbox === false) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// If isCreatingSandbox is undefined/missing, check if message is complete
|
|
251
|
+
// If incomplete (no files, no summary, no error), we're still creating - show loader
|
|
252
|
+
if (fragment) {
|
|
253
|
+
const hasFiles = fragment.files && Object.keys(fragment.files).length > 0;
|
|
254
|
+
const hasSummary = fragment.summary && fragment.summary.trim().length > 0;
|
|
255
|
+
const hasError = fragment.isError === true || fragment.type === 'ERROR';
|
|
256
|
+
|
|
257
|
+
// If message is incomplete (no files, no summary, no error), we're still creating
|
|
258
|
+
if (!hasFiles && !hasSummary && !hasError) {
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return false;
|
|
264
|
+
}, [regularMessages, isShowOnlyInbox]);
|
|
265
|
+
|
|
220
266
|
// Send regular messages to AI agent machine for context
|
|
221
267
|
useEffect(() => {
|
|
222
268
|
if (regularMessages && regularMessages.length > 0) {
|
|
@@ -345,6 +391,92 @@ export const AIAgent: React.FC<AIAgentProps> = ({
|
|
|
345
391
|
}
|
|
346
392
|
setIsSuccessThinking(true);
|
|
347
393
|
setIsLoading(true);
|
|
394
|
+
|
|
395
|
+
// Optimistic update: Add assistant message with isCreatingSandbox: true
|
|
396
|
+
if (!isShowOnlyInbox && actualChannelId) {
|
|
397
|
+
try {
|
|
398
|
+
const optimisticAssistantMessageId = objectId();
|
|
399
|
+
const optimisticAssistantMessage = {
|
|
400
|
+
__typename: 'Post',
|
|
401
|
+
id: optimisticAssistantMessageId,
|
|
402
|
+
content: '',
|
|
403
|
+
message: '',
|
|
404
|
+
createdAt: new Date().toISOString(),
|
|
405
|
+
updatedAt: new Date().toISOString(),
|
|
406
|
+
author: {
|
|
407
|
+
__typename: 'User',
|
|
408
|
+
id: 'ai-assistant',
|
|
409
|
+
username: 'ai-assistant',
|
|
410
|
+
givenName: 'AI',
|
|
411
|
+
familyName: 'Assistant',
|
|
412
|
+
fullName: 'AI Assistant',
|
|
413
|
+
email: 'ai@assistant.com',
|
|
414
|
+
picture: null,
|
|
415
|
+
alias: [],
|
|
416
|
+
tokens: [],
|
|
417
|
+
},
|
|
418
|
+
propsConfiguration: {
|
|
419
|
+
__typename: 'PostPropsConfiguration',
|
|
420
|
+
contents: {
|
|
421
|
+
__typename: 'PostContents',
|
|
422
|
+
role: 'ASSISTANT',
|
|
423
|
+
fragment: {
|
|
424
|
+
isCreatingSandbox: true,
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
props: {},
|
|
429
|
+
files: [],
|
|
430
|
+
replies: null,
|
|
431
|
+
channel: null,
|
|
432
|
+
isPinned: false,
|
|
433
|
+
isDelivered: false,
|
|
434
|
+
isRead: false,
|
|
435
|
+
parentId: null,
|
|
436
|
+
fromServer: null,
|
|
437
|
+
type: PostTypeEnum.Aiassistant,
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
// Update cache optimistically
|
|
441
|
+
const messagesQuery = {
|
|
442
|
+
query: MessagesDocument,
|
|
443
|
+
variables: {
|
|
444
|
+
channelId: actualChannelId.toString(),
|
|
445
|
+
parentId: null,
|
|
446
|
+
limit: 1,
|
|
447
|
+
},
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
try {
|
|
451
|
+
const existingData = apolloClient.readQuery(messagesQuery) as any;
|
|
452
|
+
if (existingData?.messages) {
|
|
453
|
+
// Check if optimistic message already exists
|
|
454
|
+
const existingOptimistic = existingData.messages.data?.find(
|
|
455
|
+
(m: any) => m.id === optimisticAssistantMessageId,
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
if (!existingOptimistic) {
|
|
459
|
+
apolloClient.writeQuery({
|
|
460
|
+
...messagesQuery,
|
|
461
|
+
data: {
|
|
462
|
+
messages: {
|
|
463
|
+
...existingData.messages,
|
|
464
|
+
data: [...(existingData.messages.data || []), optimisticAssistantMessage],
|
|
465
|
+
totalCount: (existingData.messages.totalCount || 0) + 1,
|
|
466
|
+
},
|
|
467
|
+
},
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
} catch (error) {
|
|
472
|
+
// Cache might not exist yet, that's okay
|
|
473
|
+
console.debug('Optimistic update failed (cache might not exist):', error);
|
|
474
|
+
}
|
|
475
|
+
} catch (error) {
|
|
476
|
+
console.error('Failed to create optimistic update:', error);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
348
480
|
// Safety auto-stop in case no event arrives
|
|
349
481
|
// successThinkingTimeoutRef.current = setTimeout(() => {
|
|
350
482
|
// setIsSuccessThinking(false);
|
|
@@ -402,6 +534,8 @@ export const AIAgent: React.FC<AIAgentProps> = ({
|
|
|
402
534
|
navigate,
|
|
403
535
|
createChannelWorkflowJob,
|
|
404
536
|
sendMessageInput,
|
|
537
|
+
apolloClient,
|
|
538
|
+
isShowOnlyInbox,
|
|
405
539
|
],
|
|
406
540
|
);
|
|
407
541
|
|
|
@@ -413,6 +547,15 @@ export const AIAgent: React.FC<AIAgentProps> = ({
|
|
|
413
547
|
[handleSend],
|
|
414
548
|
);
|
|
415
549
|
|
|
550
|
+
const handleStop = useCallback(() => {
|
|
551
|
+
// Stop the current operation
|
|
552
|
+
|
|
553
|
+
console.log('Stop button clicked - stopping current operation');
|
|
554
|
+
|
|
555
|
+
// Call the onStop prop if provided
|
|
556
|
+
onStop?.();
|
|
557
|
+
}, [setIsLoading, onStop]);
|
|
558
|
+
|
|
416
559
|
const handleRetry = useCallback(() => {
|
|
417
560
|
send({ type: 'RETRY' });
|
|
418
561
|
}, [send]);
|
|
@@ -441,11 +584,14 @@ export const AIAgent: React.FC<AIAgentProps> = ({
|
|
|
441
584
|
}, [regularMessages, currentUser]);
|
|
442
585
|
|
|
443
586
|
// Derive sandbox-style errors from message fragments so we can show the Fix Error UI
|
|
444
|
-
|
|
445
|
-
|
|
587
|
+
// Returns unique errors globally (deduplicated by error message/content)
|
|
588
|
+
// Map errors to their respective messages (messageId -> errors[])
|
|
589
|
+
const errorsByMessageId = useMemo(() => {
|
|
590
|
+
if (!regularMessages || regularMessages.length === 0) return new Map<string, any[]>();
|
|
446
591
|
|
|
447
|
-
const
|
|
592
|
+
const errorsMap = new Map<string, any[]>();
|
|
448
593
|
|
|
594
|
+
// Collect errors from all messages and map them to message IDs
|
|
449
595
|
(regularMessages || []).forEach((m: any) => {
|
|
450
596
|
const fragment = m?.propsConfiguration?.contents?.fragment;
|
|
451
597
|
if (!fragment) return;
|
|
@@ -453,24 +599,36 @@ export const AIAgent: React.FC<AIAgentProps> = ({
|
|
|
453
599
|
const isErrorFragment = fragment?.isError === true || fragment?.type === 'ERROR';
|
|
454
600
|
if (!isErrorFragment) return;
|
|
455
601
|
|
|
456
|
-
|
|
457
|
-
|
|
602
|
+
const errorId = fragment.id || m.id || objectId();
|
|
603
|
+
const messageId = m.id || 'unknown';
|
|
604
|
+
|
|
605
|
+
const errorMessage =
|
|
606
|
+
fragment.errorMessage ||
|
|
607
|
+
fragment.summary ||
|
|
608
|
+
(m as any).message ||
|
|
609
|
+
(m as any).content ||
|
|
610
|
+
'An error occurred in the AI sandbox.';
|
|
611
|
+
|
|
612
|
+
const error = {
|
|
613
|
+
id: errorId,
|
|
614
|
+
messageId: messageId,
|
|
458
615
|
errorType: fragment.errorType || 'RUNTIME_ERROR',
|
|
459
616
|
timestamp: fragment.timestamp || m.createdAt || new Date().toISOString(),
|
|
460
617
|
sandboxId: fragment.sandboxId || fragment.projectId || actualChannelId || 'unknown-sandbox',
|
|
461
|
-
message:
|
|
462
|
-
fragment.errorMessage ||
|
|
463
|
-
fragment.summary ||
|
|
464
|
-
(m as any).message ||
|
|
465
|
-
(m as any).content ||
|
|
466
|
-
'An error occurred in the AI sandbox.',
|
|
618
|
+
message: errorMessage,
|
|
467
619
|
stack: fragment.stack || '',
|
|
468
620
|
url: fragment.sandboxUrl || fragment.url,
|
|
469
|
-
fixable: fragment.fixable !== false,
|
|
470
|
-
}
|
|
621
|
+
fixable: fragment.fixable !== false,
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
// Add error to the message's error list
|
|
625
|
+
if (!errorsMap.has(messageId)) {
|
|
626
|
+
errorsMap.set(messageId, []);
|
|
627
|
+
}
|
|
628
|
+
errorsMap.get(messageId)!.push(error);
|
|
471
629
|
});
|
|
472
630
|
|
|
473
|
-
return
|
|
631
|
+
return errorsMap;
|
|
474
632
|
}, [regularMessages, actualChannelId]);
|
|
475
633
|
|
|
476
634
|
// Build list with date separators similar to MessagesBuilderUi
|
|
@@ -876,93 +1034,98 @@ export const AIAgent: React.FC<AIAgentProps> = ({
|
|
|
876
1034
|
)}
|
|
877
1035
|
|
|
878
1036
|
<div className={`${isDesktopView ? 'mb-2' : 'mb-1'}`}>
|
|
879
|
-
{section.messages.map((msg: any, msgIndex: number) =>
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1037
|
+
{section.messages.map((msg: any, msgIndex: number) => {
|
|
1038
|
+
// Get errors for this specific message
|
|
1039
|
+
const messageErrors = errorsByMessageId.get(msg.id) || [];
|
|
1040
|
+
|
|
1041
|
+
return (
|
|
1042
|
+
<div key={msg.id || msgIndex} className="mb-3">
|
|
1043
|
+
{/* AI Message Indicator */}
|
|
1044
|
+
{msg.isAIMessage && (
|
|
1045
|
+
<div className="flex items-center mb-2">
|
|
1046
|
+
<div className="w-2 h-2 bg-blue-500 rounded-full mr-2"></div>
|
|
1047
|
+
<span className="text-xs text-blue-600 font-medium">
|
|
1048
|
+
AI Assistant
|
|
1049
|
+
</span>
|
|
1050
|
+
</div>
|
|
1051
|
+
)}
|
|
1052
|
+
|
|
1053
|
+
{msg.isLoading ? (
|
|
1054
|
+
// Show loader for loading messages
|
|
1055
|
+
<div className="flex items-center space-x-2 bg-gray-50 border border-gray-200 px-4 py-3 rounded-lg">
|
|
1056
|
+
<div className="w-4 h-4 border-2 border-gray-300 border-t-gray-500 rounded-full animate-spin"></div>
|
|
1057
|
+
<span className="text-sm text-gray-600">
|
|
1058
|
+
{msg.isProcessing ? 'Thinking...' : 'Thinking...'}
|
|
1059
|
+
</span>
|
|
1060
|
+
</div>
|
|
1061
|
+
) : (
|
|
1062
|
+
// Show normal message for non-loading messages
|
|
1063
|
+
<ModernMessageGroupComponent
|
|
1064
|
+
messages={[
|
|
1065
|
+
{
|
|
1066
|
+
id: msg.id,
|
|
1067
|
+
// message: msg.message,
|
|
1068
|
+
message:
|
|
1069
|
+
(msg as any)?.propsConfiguration?.contents?.role ===
|
|
1070
|
+
'ASSISTANT'
|
|
1071
|
+
? msg.propsConfiguration?.contents?.fragment
|
|
1072
|
+
?.summary
|
|
1073
|
+
? extractCleanContent(
|
|
1074
|
+
msg.propsConfiguration?.contents
|
|
1075
|
+
?.fragment?.summary,
|
|
1076
|
+
)
|
|
1077
|
+
: msg.message
|
|
1078
|
+
: msg.message,
|
|
1079
|
+
author:
|
|
1080
|
+
msg.sender === 'user'
|
|
1081
|
+
? msg.author
|
|
1082
|
+
: {
|
|
1083
|
+
id: 'ai-assistant',
|
|
1084
|
+
givenName: 'AI',
|
|
1085
|
+
familyName: 'Assistant',
|
|
1086
|
+
fullName: 'AI Assistant',
|
|
1087
|
+
username: 'ai-assistant',
|
|
1088
|
+
email: 'ai@assistant.com',
|
|
1089
|
+
picture: null,
|
|
1090
|
+
alias: [],
|
|
1091
|
+
tokens: [],
|
|
1092
|
+
},
|
|
1093
|
+
createdAt: msg.createdAt,
|
|
1094
|
+
//type: 'Simple' as any,
|
|
1095
|
+
type: PostTypeEnum.Aiassistant,
|
|
1096
|
+
isDelivered: false,
|
|
1097
|
+
isRead: false,
|
|
1098
|
+
parentId: null,
|
|
1099
|
+
fromServer: null,
|
|
1100
|
+
updatedAt: msg.createdAt,
|
|
1101
|
+
propsConfiguration: msg.propsConfiguration,
|
|
1102
|
+
props: msg.props,
|
|
1103
|
+
files: msg.files,
|
|
1104
|
+
replies: null,
|
|
1105
|
+
channel: null,
|
|
1106
|
+
isPinned: false,
|
|
1107
|
+
},
|
|
1108
|
+
]}
|
|
1109
|
+
currentUser={currentUser as any}
|
|
1110
|
+
onOpen={onOpen}
|
|
1111
|
+
onMessageClick={(msg) => setSelectedPost(msg)}
|
|
1112
|
+
isDesktopView={isDesktopView}
|
|
1113
|
+
isSmallScreen={isSmallScreen}
|
|
1114
|
+
showTimestamp={false}
|
|
1115
|
+
sandboxErrors={messageErrors}
|
|
1116
|
+
currentFiles={currentFiles}
|
|
1117
|
+
onFixError={fixError}
|
|
1118
|
+
/>
|
|
1119
|
+
)}
|
|
1120
|
+
</div>
|
|
1121
|
+
);
|
|
1122
|
+
})}
|
|
960
1123
|
</div>
|
|
961
1124
|
</div>
|
|
962
1125
|
))}
|
|
963
1126
|
|
|
964
1127
|
{/* Typing indicator */}
|
|
965
|
-
{(isTyping || isSuccessThinking || isLoading) && (
|
|
1128
|
+
{(isTyping || isSuccessThinking || isLoading || isCreatingSandbox) && (
|
|
966
1129
|
<div className="px-4">
|
|
967
1130
|
<div className="flex justify-start">
|
|
968
1131
|
<div className="bg-gray-50 border border-gray-200 px-4 py-3 rounded-lg">
|
|
@@ -1034,20 +1197,36 @@ export const AIAgent: React.FC<AIAgentProps> = ({
|
|
|
1034
1197
|
)}
|
|
1035
1198
|
|
|
1036
1199
|
{/* Input Area - Only show for Chat tab */}
|
|
1037
|
-
{activeTab === 'chat' &&
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1200
|
+
{activeTab === 'chat' &&
|
|
1201
|
+
(() => {
|
|
1202
|
+
// Compute final showStopButton value: use prop if provided, otherwise compute from conditions
|
|
1203
|
+
// const finalShowStopButton =
|
|
1204
|
+
// showStopButton !== undefined
|
|
1205
|
+
// ? showStopButton
|
|
1206
|
+
// : !isShowOnlyInbox && (isCreatingSandbox || isLoading || isSuccessThinking);
|
|
1207
|
+
|
|
1208
|
+
const isShowStopButton =
|
|
1209
|
+
showStopButton && !isShowOnlyInbox ? isCreatingSandbox || isSuccessThinking : false;
|
|
1210
|
+
|
|
1211
|
+
return (
|
|
1212
|
+
<div className="border-t border-gray-200 bg-white">
|
|
1213
|
+
{/* Removed temporary test button */}
|
|
1214
|
+
<InputComponent
|
|
1215
|
+
channelId={actualChannelId}
|
|
1216
|
+
handleSend={handleSend}
|
|
1217
|
+
placeholder={placeholder}
|
|
1218
|
+
modelConfig={modelConfig}
|
|
1219
|
+
onModelConfigChange={updateModelConfig}
|
|
1220
|
+
textareaStyles={
|
|
1221
|
+
isShowOnlyInbox ? { height: '80px', minHeight: '80px', maxHeight: '80px' } : {}
|
|
1222
|
+
}
|
|
1223
|
+
showModeSelector={showModeSelector}
|
|
1224
|
+
showStopButton={isShowStopButton}
|
|
1225
|
+
onStop={isShowStopButton ? handleStop : undefined}
|
|
1226
|
+
/>
|
|
1227
|
+
</div>
|
|
1228
|
+
);
|
|
1229
|
+
})()}
|
|
1051
1230
|
|
|
1052
1231
|
{/* Optional Modal for user content like MessagesBuilderUi */}
|
|
1053
1232
|
{isOpen ? (
|
|
@@ -17,6 +17,8 @@ type MessageInputProps = {
|
|
|
17
17
|
showModelToolbarProjectSettings?: boolean;
|
|
18
18
|
isShowMeta?: boolean;
|
|
19
19
|
showModeSelector?: boolean;
|
|
20
|
+
showStopButton?: boolean;
|
|
21
|
+
onStop?: () => void;
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
export const InputComponent = ({
|
|
@@ -30,6 +32,8 @@ export const InputComponent = ({
|
|
|
30
32
|
showModelToolbarProjectSettings = false,
|
|
31
33
|
isShowMeta = false,
|
|
32
34
|
showModeSelector = false,
|
|
35
|
+
showStopButton = false,
|
|
36
|
+
onStop,
|
|
33
37
|
}: MessageInputProps) => {
|
|
34
38
|
const [message, setMessage] = useState('');
|
|
35
39
|
const [sending, setSending] = useState(false);
|
|
@@ -184,6 +188,8 @@ export const InputComponent = ({
|
|
|
184
188
|
showProjectSettings={showModelToolbarProjectSettings}
|
|
185
189
|
isShowMeta={isShowMeta}
|
|
186
190
|
showModeSelector={showModeSelector}
|
|
191
|
+
showStopButton={showStopButton}
|
|
192
|
+
onStop={onStop}
|
|
187
193
|
/>
|
|
188
194
|
</div>
|
|
189
195
|
</div>
|
|
@@ -29,6 +29,8 @@ export interface IRightSidebarAi extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
29
29
|
handleRecreateSandbox?: (messageId: string) => void | Promise<any>;
|
|
30
30
|
isCreatingSandbox?: boolean;
|
|
31
31
|
setIsCreatingSandbox?: (isCreatingSandbox: boolean) => void;
|
|
32
|
+
showStopButton?: boolean;
|
|
33
|
+
onStop?: () => void;
|
|
32
34
|
[key: string]: any;
|
|
33
35
|
}
|
|
34
36
|
|