chore: update live chat and work server changes

This commit is contained in:
2026-04-26 16:37:06 +09:00
parent 63e5d263a7
commit 20a6333ed2
38 changed files with 2078 additions and 2281 deletions

View File

@@ -2,6 +2,19 @@ import { useCallback } from 'react';
import { chatGateway } from '../data/chatGateway';
import type { ChatComposerAttachment, ChatConversationRequest, ChatMessage } from '../../mainChatPanel/types';
export type ComposerFilePickResult = {
items: {
key: string;
fileName: string;
status: 'uploaded' | 'failed';
reason?: string;
}[];
};
function buildComposerFilePickKey(file: File) {
return `${file.name}:${file.size}:${file.type}:${file.lastModified}`;
}
type PendingChatRequest = {
sessionId: string;
requestId: string;
@@ -107,9 +120,9 @@ export function useConversationComposerController({
scrollViewportToBottom,
}: UseConversationComposerControllerOptions) {
const handleComposerFilesPicked = useCallback(
async (files: File[]) => {
async (files: File[]): Promise<ComposerFilePickResult> => {
if (files.length === 0 || isComposerAttachmentUploading) {
return;
return { items: [] };
}
setIsComposerAttachmentUploading(true);
@@ -117,7 +130,7 @@ export function useConversationComposerController({
files.map((file) => chatGateway.uploadComposerFile(activeSessionId, file)),
);
const uploadedItems: ChatComposerAttachment[] = [];
const failedFileNames: string[] = [];
const failedItems: Array<{ fileName: string; reason: string }> = [];
uploadResults.forEach((result, index) => {
if (result.status === 'fulfilled') {
@@ -125,7 +138,12 @@ export function useConversationComposerController({
return;
}
failedFileNames.push(files[index]?.name || `파일 ${index + 1}`);
const fileName = files[index]?.name || `파일 ${index + 1}`;
const reason =
result.reason instanceof Error && result.reason.message.trim()
? result.reason.message.trim()
: '업로드 실패';
failedItems.push({ fileName, reason });
});
if (uploadedItems.length > 0) {
@@ -134,14 +152,29 @@ export function useConversationComposerController({
setShowScrollToBottom(false);
}
if (failedFileNames.length > 0) {
if (failedItems.length > 0) {
setMessages((previous) => [
...previous.slice(-39),
createLocalMessage(`파일 업로드에 실패했습니다: ${failedFileNames.join(', ')}`),
createLocalMessage(
['파일 업로드에 실패했습니다:', ...failedItems.map((item) => `- ${item.fileName}: ${item.reason}`)].join('\n'),
),
]);
}
setIsComposerAttachmentUploading(false);
return {
items: uploadResults.map((result, index) => ({
key: buildComposerFilePickKey(files[index] as File),
fileName: files[index]?.name || `파일 ${index + 1}`,
status: result.status === 'fulfilled' ? 'uploaded' : 'failed',
reason:
result.status === 'fulfilled'
? undefined
: result.reason instanceof Error && result.reason.message.trim()
? result.reason.message.trim()
: '업로드 실패',
})),
};
},
[
activeSessionId,