fix: ChatBubble crash and DeepSeek API compatibility

- Fix ChatBubble to handle non-string content with String() wrapper
- Fix API route to use generateText for non-streaming requests
- Add @ai-sdk/openai-compatible for non-OpenAI providers (DeepSeek, etc.)
- Use Chat Completions API instead of Responses API for compatible providers
- Update ChatBubble tests and fix component exports to kebab-case
- Remove stale PascalCase ChatBubble.tsx file
This commit is contained in:
Max
2026-01-26 16:55:05 +07:00
parent 6b113e0392
commit e9e6fadb1d
544 changed files with 113077 additions and 427 deletions

View File

@@ -1,12 +1,13 @@
'use client';
import { useState } from 'react';
import { Copy, Check, X } from 'lucide-react';
import { useState, useEffect } from 'react';
import { Copy, Check, X, Trash2 } from 'lucide-react';
import { useHistoryStore } from '@/lib/store/history-store';
import { DraftContent } from '@/components/features/draft/DraftContent';
import { CopySuccessToast } from '@/components/features/feedback/CopySuccessToast';
import { useChatStore } from '@/lib/store/chat-store';
import { Sheet } from '@/components/features/draft/Sheet';
import { DeleteConfirmDialog } from './DeleteConfirmDialog';
/**
* HistoryDetailSheet Component
@@ -17,11 +18,13 @@ import { Sheet } from '@/components/features/draft/Sheet';
* - Sheet component from DraftViewSheet (Story 2.2)
* - DraftContent component (Story 2.2)
* - CopyButton functionality (Story 2.4)
* - Delete functionality (Story 3.2.1)
*
* Features:
* - Displays full draft with Merriweather font
* - Copy button for clipboard export
* - Close button
* - Delete button
* - Swipe-to-dismiss support (via Sheet)
*
* Architecture Compliance:
@@ -31,14 +34,23 @@ import { Sheet } from '@/components/features/draft/Sheet';
export function HistoryDetailSheet() {
const selectedDraft = useHistoryStore((s) => s.selectedDraft);
const closeDetail = useHistoryStore((s) => s.closeDetail);
const deleteDraft = useHistoryStore((s) => s.deleteDraft);
// Reuse copy action from ChatStore
const copyDraftToClipboard = useChatStore((s) => s.copyDraftToClipboard);
// Dialog state
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
// Toast state
const [toastShow, setToastShow] = useState(false);
const [toastMessage, setToastMessage] = useState('');
// Fix: Reset toast when opening a new draft
useEffect(() => {
setToastShow(false);
}, [selectedDraft]);
const showCopyToast = (message: string = 'Copied to clipboard!') => {
setToastMessage(message);
setToastShow(true);
@@ -51,6 +63,19 @@ export function HistoryDetailSheet() {
}
};
const handleDelete = async () => {
if (selectedDraft) {
const success = await deleteDraft(selectedDraft.id);
if (success) {
setShowDeleteDialog(false);
showCopyToast('Post deleted successfully');
} else {
setShowDeleteDialog(false);
showCopyToast('Failed to delete post');
}
}
};
const handleClose = () => {
closeDetail();
};
@@ -64,8 +89,19 @@ export function HistoryDetailSheet() {
<Sheet open={!!selectedDraft} onClose={handleClose}>
<DraftContent draft={selectedDraft} />
{/* Footer with copy and close buttons */}
{/* Footer with copy, delete and close buttons */}
<nav className="sticky bottom-0 flex gap-3 p-4 bg-white border-t border-slate-200">
{/* Delete button (Story 3.2.1) */}
<button
onClick={() => setShowDeleteDialog(true)}
type="button"
className="min-h-[44px] px-4 py-3 border border-destructive text-destructive rounded-md hover:bg-destructive/10 transition-colors flex items-center justify-center gap-2"
aria-label="Delete this draft"
>
<Trash2 className="w-5 h-5" aria-hidden="true" />
<span className="sr-only">Delete</span>
</button>
{/* Copy button */}
<button
onClick={handleCopy}
@@ -90,7 +126,15 @@ export function HistoryDetailSheet() {
</nav>
</Sheet>
{/* Toast for copy feedback */}
{/* Delete Confirmation Dialog */}
<DeleteConfirmDialog
open={showDeleteDialog}
onOpenChange={setShowDeleteDialog}
onConfirm={handleDelete}
draftTitle={selectedDraft.title}
/>
{/* Toast for feedack */}
<CopySuccessToast
show={toastShow}
message={toastMessage}