Skip to content

Commit db66d81

Browse files
fix: fixed several search & chat bugs (#412)
* fix: chat error * chore: add querysource * refactor: filter query source rather than data source * fix: fixed several search bugs * docs: update notes * feat: chat error * chore: websocket * chore: chat * chore: chat * fix: history search error --------- Co-authored-by: Steve Lau <stevelauc@outlook.com>
1 parent 5b0fdbc commit db66d81

26 files changed

Lines changed: 391 additions & 365 deletions

File tree

docs/content.en/docs/release-notes/_index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ Information about release notes of Coco Server is provided here.
3333
- fix: fixed the problem of not being able to search in secondary directories #338
3434
- fix: active shadow setting #354
3535
- fix: chat history was not show up #377
36-
- fix: get attachments in chat sessioins
36+
- fix: get attachments in chat sessions
3737
- fix: filter http query_args and convert only supported values
38+
- fix:fixed several search & chat bugs #412
3839

3940
### Improvements
4041

src-tauri/src/search/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub async fn query_coco_fusion<R: Runtime>(
1818
query_strings: HashMap<String, String>,
1919
query_timeout: u64,
2020
) -> Result<MultiSourceQueryResponse, SearchError> {
21-
let data_source_to_search = query_strings.get("datasource");
21+
let query_source_to_search = query_strings.get("querysource");
2222

2323
let search_sources = app_handle.state::<SearchSourceRegistry>();
2424

@@ -35,9 +35,9 @@ pub async fn query_coco_fusion<R: Runtime>(
3535
for query_source in sources_list {
3636
let query_source_type = query_source.get_type().clone();
3737

38-
if let Some(data_source_to_search) = data_source_to_search {
38+
if let Some(query_source_to_search) = query_source_to_search {
3939
// We should not search this data source
40-
if &query_source_type.id != data_source_to_search {
40+
if &query_source_type.id != query_source_to_search {
4141
continue;
4242
}
4343
}

src/commands/servers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ async function invokeWithErrorHandler<T>(
4646
return result;
4747
} catch (error: any) {
4848
const errorMessage = error || "Command execution failed";
49-
addError(errorMessage, "error");
49+
addError(command + ":" + errorMessage, "error");
5050
throw error;
5151
}
5252
}

src/components/Assistant/AssistantList.tsx

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { useClickAway } from "@/hooks/useClickAway";
99
import VisibleKey from "@/components/Common/VisibleKey";
1010
import { useConnectStore } from "@/stores/connectStore";
1111
import FontIcon from "@/components/Common/Icons/FontIcon";
12+
import { useChatStore } from "@/stores/chatStore";
1213
import { AI_ASSISTANT_PANEL_ID } from "@/constants";
1314
import { useShortcutsStore } from "@/stores/shortcutsStore";
1415

@@ -18,58 +19,69 @@ interface AssistantListProps {
1819

1920
export function AssistantList({ showChatHistory = true }: AssistantListProps) {
2021
const { t } = useTranslation();
22+
const { connected } = useChatStore();
2123
const isTauri = useAppStore((state) => state.isTauri);
2224
const currentService = useConnectStore((state) => state.currentService);
2325
const currentAssistant = useConnectStore((state) => state.currentAssistant);
2426
const setCurrentAssistant = useConnectStore(
2527
(state) => state.setCurrentAssistant
2628
);
29+
const aiAssistant = useShortcutsStore((state) => state.aiAssistant);
2730

2831
const [isOpen, setIsOpen] = useState(false);
2932
const [isRefreshing, setIsRefreshing] = useState(false);
30-
const aiAssistant = useShortcutsStore((state) => {
31-
return state.aiAssistant;
32-
});
3333
const menuRef = useRef<HTMLDivElement>(null);
3434

3535
useClickAway(menuRef, () => setIsOpen(false));
3636
const [assistants, setAssistants] = useState<any[]>([]);
3737

38-
const fetchAssistant = useCallback(async () => {
38+
const fetchAssistant = useCallback(async (serverId: string) => {
3939
if (!isTauri) return;
40-
if (!currentService?.id) return;
40+
if (!serverId) return;
4141
platformAdapter
4242
.commands("assistant_search", {
43-
serverId: currentService?.id,
43+
serverId,
4444
})
4545
.then((res: any) => {
4646
res = res ? JSON.parse(res) : null;
4747
console.log("assistant_search", res);
4848
const assistantList = res?.hits?.hits || [];
4949
setAssistants(assistantList);
50-
if (assistantList.length > 0 && !currentAssistant) {
51-
setCurrentAssistant(assistantList[0]);
50+
if (assistantList.length > 0) {
51+
const assistant = assistantList.find(
52+
(item: any) => item._id === currentAssistant?._id
53+
);
54+
if (assistant) {
55+
setCurrentAssistant(assistant);
56+
} else {
57+
setCurrentAssistant(assistantList[0]);
58+
}
5259
}
60+
})
61+
.catch((err: any) => {
62+
setAssistants([]);
63+
setCurrentAssistant(null);
64+
console.log("assistant_search", err);
5365
});
5466
}, []);
5567

5668
useEffect(() => {
57-
fetchAssistant();
58-
}, []);
69+
connected && fetchAssistant(currentService?.id);
70+
}, [connected, currentService?.id]);
5971

60-
const handleRefresh = async () => {
72+
const handleRefresh = useCallback(async () => {
6173
setIsRefreshing(true);
62-
await fetchAssistant();
74+
await fetchAssistant(currentService?.id);
6375
setTimeout(() => setIsRefreshing(false), 1000);
64-
};
76+
}, [currentService?.id]);
6577

6678
return (
6779
<div className="relative" ref={menuRef}>
6880
<button
6981
onClick={() => setIsOpen(!isOpen)}
7082
className="h-6 p-1 px-1.5 flex items-center gap-1 rounded-full bg-white dark:bg-[#202126] text-sm/6 font-semibold text-gray-800 dark:text-[#d8d8d8] border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none"
7183
>
72-
<div className="w-4 h-4 flex justify-center items-center rounded-full bg-gray-200 dark:bg-gray-800">
84+
<div className="w-4 h-4 flex justify-center items-center rounded-full bg-white">
7385
{currentAssistant?._source?.icon?.startsWith("font_") ? (
7486
<FontIcon
7587
name={currentAssistant._source.icon}
@@ -139,11 +151,16 @@ export function AssistantList({ showChatHistory = true }: AssistantListProps) {
139151
}`}
140152
>
141153
{assistant._source?.icon?.startsWith("font_") ? (
142-
<FontIcon name={assistant._source?.icon} className="w-4 h-4" />
154+
<div className="w-7 h-7 flex items-center justify-center rounded-full bg-white">
155+
<FontIcon
156+
name={assistant._source?.icon}
157+
className="w-5 h-5"
158+
/>
159+
</div>
143160
) : (
144161
<img
145162
src={logoImg}
146-
className="w-4 h-4 rounded-full"
163+
className="w-5 h-5 rounded-full"
147164
alt={assistant.name}
148165
/>
149166
)}

src/components/Assistant/Chat.tsx

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import PrevSuggestion from "@/components/ChatMessage/PrevSuggestion";
2525
import { useAppStore } from "@/stores/appStore";
2626

2727
interface ChatAIProps {
28-
isTransitioned: boolean;
2928
isSearchActive?: boolean;
3029
isDeepThinkActive?: boolean;
3130
activeChatProp?: Chat;
@@ -49,7 +48,6 @@ const ChatAI = memo(
4948
forwardRef<ChatAIRef, ChatAIProps>(
5049
(
5150
{
52-
isTransitioned,
5351
changeInput,
5452
isSearchActive,
5553
isDeepThinkActive,
@@ -63,8 +61,6 @@ const ChatAI = memo(
6361
},
6462
ref
6563
) => {
66-
if (!isTransitioned) return null;
67-
6864
useImperativeHandle(ref, () => ({
6965
init: init,
7066
cancelChat: () => cancelChat(activeChat),
@@ -307,20 +303,6 @@ const ChatAI = memo(
307303
};
308304
}, [isSidebarOpenChat, handleOutsideClick]);
309305

310-
// const fetchChatHistory = useCallback(async () => {
311-
// const hits = await getChatHistory();
312-
// setChats(hits);
313-
// }, [getChatHistory]);
314-
315-
const setIsLoginChat = useCallback(
316-
(value: boolean) => {
317-
setIsLogin(value);
318-
value && currentService && !setIsSidebarOpen && getChatHistory();
319-
!value && setChats([]);
320-
},
321-
[currentService, setIsSidebarOpen, getChatHistory]
322-
);
323-
324306
const toggleSidebar = useCallback(() => {
325307
setIsSidebarOpenChat(!isSidebarOpenChat);
326308
setIsSidebarOpen && setIsSidebarOpen(!isSidebarOpenChat);
@@ -388,7 +370,7 @@ const ChatAI = memo(
388370
reconnect={reconnect}
389371
isChatPage={isChatPage}
390372
isLogin={isLogin}
391-
setIsLogin={setIsLoginChat}
373+
setIsLogin={setIsLogin}
392374
showChatHistory={showChatHistory}
393375
/>
394376
{isLogin ? (

src/components/Assistant/ChatHeader.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,6 @@ export function ChatHeader({
4545
const isPinned = useAppStore((state) => state.isPinned);
4646
const setIsPinned = useAppStore((state) => state.setIsPinned);
4747

48-
49-
5048
const isTauri = useAppStore((state) => state.isTauri);
5149
const historicalRecords = useShortcutsStore((state) => {
5250
return state.historicalRecords;

src/components/ChatMessage/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ export const ChatMessage = memo(function ChatMessage({
133133
>
134134
<div className="w-full flex items-center gap-1 font-semibold text-sm text-[#333] dark:text-[#d8d8d8]">
135135
{isAssistant ? (
136-
<div className="w-6 h-6 flex justify-center items-center rounded-full bg-gray-200 dark:bg-gray-800">
136+
<div className="w-6 h-6 flex justify-center items-center rounded-full bg-white">
137137
{currentAssistant?._source?.icon?.startsWith("font_") ? (
138138
<FontIcon
139139
name={currentAssistant._source.icon}

src/components/Common/HistoryList/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ const HistoryList: FC<HistoryListProps> = (props) => {
107107
];
108108

109109
const debouncedSearch = useMemo(() => {
110-
return debounce((value: string) => onSearch(value), 500);
110+
return debounce((value: string) => onSearch(value), 300);
111111
}, [onSearch]);
112112

113113
useKeyPress(["uparrow", "downarrow"], (_, key) => {
@@ -159,7 +159,7 @@ const HistoryList: FC<HistoryListProps> = (props) => {
159159
ref={listRef}
160160
id={id}
161161
className={clsx(
162-
"flex flex-col h-full overflow-auto px-3 py-2 text-sm bg-[#F3F4F6] dark:bg-[#1F2937]"
162+
"flex flex-col h-full overflow-auto px-3 py-2 text-sm bg-[#F3F4F6] dark:bg-[#1F2937] custom-scrollbar"
163163
)}
164164
>
165165
<div className="flex gap-1 children:h-8">

src/components/Search/DocumentDetail.tsx

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { formatter } from "@/utils/index";
55
import TypeIcon from "@/components/Common/Icons/TypeIcon";
66
import defaultThumbnail from "@/assets/coconut-tree.png";
77
import ItemIcon from "@/components/Common/Icons/ItemIcon";
8+
import { RichCategories } from "./ListRight";
89

910
interface DocumentDetailProps {
1011
document: any;
@@ -19,13 +20,13 @@ interface DetailItemProps {
1920

2021
const DetailItem: React.FC<DetailItemProps> = ({ label, value, icon }) => (
2122
<div className="flex justify-between flex-wrap font-normal text-xs mb-2.5 border-t border-[rgba(238,240,243,1)] dark:border-[#272626] pt-2.5">
22-
<div className="text-[rgba(153,153,153,1)] dark:text-[#666]">{label}</div>
23+
<div className="text-[rgba(153,153,153,1)] dark:text-[#666] min-w-[80px]">{label}</div>
2324
<div
24-
className="text-[rgba(51,51,51,1);] dark:text-[#D8D8D8] flex justify-end text-right w-56 truncate group relative"
25+
className="text-[rgba(51,51,51,1);] dark:text-[#D8D8D8] flex justify-end text-right flex-1 truncate group relative"
2526
title={typeof value === "string" ? value : undefined}
2627
>
2728
{icon}
28-
<span className="truncate">{value}</span>
29+
<div className="truncate">{value}</div>
2930
</div>
3031
</div>
3132
);
@@ -39,6 +40,52 @@ export const DocumentDetail: React.FC<DocumentDetailProps> = ({ document }) => {
3940
return `${url.slice(0, 20)}...${url.slice(-20)}`;
4041
};
4142

43+
// categories: null
44+
45+
// category: null
46+
47+
// content: null
48+
49+
// cover: null
50+
51+
// created: null
52+
53+
// icon: "http://localhost:9000/assets/icons/connector/hugo_site/web.png"
54+
55+
// id: "31a8db836fe503d8f1d3ce2ea7c2fe6d"
56+
57+
// lang: null
58+
59+
// last_updated_by: null
60+
61+
// metadata: null
62+
63+
// owner: null
64+
65+
// payload: null
66+
67+
// rich_categories: null
68+
69+
// size: null
70+
71+
// source: {type: "connector", name: "INFINI Labs 官网", id: "cu4vj5o2sdb34a5pcbfg", icon: "http://localhost:9000/assets/icons/connector/hugo_site/icon.png"}
72+
73+
// subcategory: null
74+
75+
// summary: null
76+
77+
// tags: null
78+
79+
// thumbnail: null
80+
81+
// title: "dump_hash"
82+
83+
// type: "web_page"
84+
85+
// updated: null
86+
87+
// url: "https://infi
88+
4289
return (
4390
<div className="p-3">
4491
{/* <div className="font-normal text-xs text-[#666] dark:text-[#999] mb-2">
@@ -93,6 +140,18 @@ export const DocumentDetail: React.FC<DocumentDetailProps> = ({ document }) => {
93140
icon={<TypeIcon item={document} className="w-4 h-4 mr-1" />}
94141
/>
95142

143+
{/* Rich Categories */}
144+
{document?.rich_categories && (
145+
<DetailItem
146+
label={t("search.document.richCategories")}
147+
value={
148+
<div className="min-w-[160px] flex items-center justify-end w-full text-[12px] relative">
149+
<RichCategories item={document} isSelected={false} />
150+
</div>
151+
}
152+
/>
153+
)}
154+
96155
{/* Document URL */}
97156
{document?.url && (
98157
<DetailItem

0 commit comments

Comments
 (0)