feat: web components assistant (#422)

* chore: web components assistant

* chore: web components assistant

* docs: update notes
This commit is contained in:
BiggerRain
2025-04-23 18:23:40 +08:00
committed by GitHub
parent 9715a92f36
commit ee4a06b6de
18 changed files with 132 additions and 137 deletions

4
.env
View File

@@ -1,3 +1,3 @@
COCO_SERVER_URL=https://coco.infini.cloud #http://localhost:9000 COCO_SERVER_URL=http://localhost:9000 #https://coco.infini.cloud #http://localhost:9000
COCO_WEBSOCKET_URL=wss://coco.infini.cloud/ws #ws://localhost:9000/ws COCO_WEBSOCKET_URL=ws://localhost:9000/ws #wss://coco.infini.cloud/ws #ws://localhost:9000/ws

View File

@@ -27,6 +27,7 @@ Information about release notes of Coco Server is provided here.
- feat: add support for AI assistant #394 - feat: add support for AI assistant #394
- feat: add support for calculator function #399 - feat: add support for calculator function #399
- feat: auto selects the first item after searching #411 - feat: auto selects the first item after searching #411
- feat: web components assistant #422
### Bug fix ### Bug fix

File diff suppressed because one or more lines are too long

View File

@@ -12,12 +12,13 @@ import FontIcon from "@/components/Common/Icons/FontIcon";
import { useChatStore } from "@/stores/chatStore"; import { useChatStore } from "@/stores/chatStore";
import { AI_ASSISTANT_PANEL_ID } from "@/constants"; import { AI_ASSISTANT_PANEL_ID } from "@/constants";
import { useShortcutsStore } from "@/stores/shortcutsStore"; import { useShortcutsStore } from "@/stores/shortcutsStore";
import { Get } from "@/api/axiosRequest";
interface AssistantListProps { interface AssistantListProps {
showChatHistory?: boolean; assistantIDs?: string[];
} }
export function AssistantList({ showChatHistory = true }: AssistantListProps) { export function AssistantList({ assistantIDs = [] }: AssistantListProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const { connected } = useChatStore(); const { connected } = useChatStore();
const isTauri = useAppStore((state) => state.isTauri); const isTauri = useAppStore((state) => state.isTauri);
@@ -35,34 +36,49 @@ export function AssistantList({ showChatHistory = true }: AssistantListProps) {
useClickAway(menuRef, () => setIsOpen(false)); useClickAway(menuRef, () => setIsOpen(false));
const [assistants, setAssistants] = useState<any[]>([]); const [assistants, setAssistants] = useState<any[]>([]);
const fetchAssistant = useCallback(async (serverId: string) => { const fetchAssistant = useCallback(async (serverId?: string) => {
if (!isTauri) return; let response: any;
if (!serverId) return; if (isTauri) {
platformAdapter if (!serverId) return;
.commands("assistant_search", { try {
serverId, response = await platformAdapter.commands("assistant_search", {
}) serverId,
.then((res: any) => { });
res = res ? JSON.parse(res) : null; response = response ? JSON.parse(response) : null;
console.log("assistant_search", res); } catch (err) {
const assistantList = res?.hits?.hits || [];
setAssistants(assistantList);
if (assistantList.length > 0) {
const assistant = assistantList.find(
(item: any) => item._id === currentAssistant?._id
);
if (assistant) {
setCurrentAssistant(assistant);
} else {
setCurrentAssistant(assistantList[0]);
}
}
})
.catch((err: any) => {
setAssistants([]); setAssistants([]);
setCurrentAssistant(null); setCurrentAssistant(null);
console.log("assistant_search", err); console.error("assistant_search", err);
}); }
} else {
const [error, res] = await Get(`/assistant/_search`);
if (error) {
setAssistants([]);
setCurrentAssistant(null);
console.error("assistant_search", error);
return;
}
console.log("/assistant/_search", res);
response = res;
}
console.log("assistant_search", response);
let assistantList = response?.hits?.hits || [];
assistantList = assistantIDs.length > 0
? assistantList.filter((item: any) => assistantIDs.includes(item._id))
: assistantList;
setAssistants(assistantList);
if (assistantList.length > 0) {
const assistant = assistantList.find(
(item: any) => item._id === currentAssistant?._id
);
if (assistant) {
setCurrentAssistant(assistant);
} else {
setCurrentAssistant(assistantList[0]);
}
}
}, []); }, []);
useEffect(() => { useEffect(() => {
@@ -98,24 +114,22 @@ export function AssistantList({ showChatHistory = true }: AssistantListProps) {
<div className="max-w-[100px] truncate"> <div className="max-w-[100px] truncate">
{currentAssistant?._source?.name || "Coco AI"} {currentAssistant?._source?.name || "Coco AI"}
</div> </div>
{showChatHistory && isTauri && ( <VisibleKey
<VisibleKey aria-controls={isOpen ? AI_ASSISTANT_PANEL_ID : ""}
aria-controls={isOpen ? AI_ASSISTANT_PANEL_ID : ""} shortcut={aiAssistant}
shortcut={aiAssistant} onKeyPress={() => {
onKeyPress={() => { setIsOpen(!isOpen);
setIsOpen(!isOpen); }}
}} >
> <ChevronDownIcon
<ChevronDownIcon className={`size-4 text-gray-500 dark:text-gray-400 transition-transform ${
className={`size-4 text-gray-500 dark:text-gray-400 transition-transform ${ isOpen ? "rotate-180" : ""
isOpen ? "rotate-180" : "" }`}
}`} />
/> </VisibleKey>
</VisibleKey>
)}
</button> </button>
{showChatHistory && isTauri && isOpen && ( {isOpen && (
<div <div
id={isOpen ? AI_ASSISTANT_PANEL_ID : ""} id={isOpen ? AI_ASSISTANT_PANEL_ID : ""}
className="absolute z-50 top-full mt-1 left-0 w-64 rounded-xl bg-white dark:bg-[#202126] p-2 text-sm/6 text-gray-800 dark:text-white shadow-lg border border-gray-200 dark:border-gray-700 focus:outline-none max-h-[calc(100vh-80px)] overflow-y-auto" className="absolute z-50 top-full mt-1 left-0 w-64 rounded-xl bg-white dark:bg-[#202126] p-2 text-sm/6 text-gray-800 dark:text-white shadow-lg border border-gray-200 dark:border-gray-700 focus:outline-none max-h-[calc(100vh-80px)] overflow-y-auto"
@@ -140,6 +154,7 @@ export function AssistantList({ showChatHistory = true }: AssistantListProps) {
<button <button
key={assistant._id} key={assistant._id}
onClick={() => { onClick={() => {
console.log("assistant", assistant);
setCurrentAssistant(assistant); setCurrentAssistant(assistant);
setIsOpen(false); setIsOpen(false);
}} }}

View File

@@ -35,6 +35,7 @@ interface ChatAIProps {
isChatPage?: boolean; isChatPage?: boolean;
getFileUrl: (path: string) => string; getFileUrl: (path: string) => string;
showChatHistory?: boolean; showChatHistory?: boolean;
assistantIDs?: string[];
} }
export interface ChatAIRef { export interface ChatAIRef {
@@ -58,6 +59,7 @@ const ChatAI = memo(
isChatPage = false, isChatPage = false,
getFileUrl, getFileUrl,
showChatHistory, showChatHistory,
assistantIDs,
}, },
ref ref
) => { ) => {
@@ -376,6 +378,7 @@ const ChatAI = memo(
isLogin={isLogin} isLogin={isLogin}
setIsLogin={setIsLogin} setIsLogin={setIsLogin}
showChatHistory={showChatHistory} showChatHistory={showChatHistory}
assistantIDs={assistantIDs}
/> />
{isLogin ? ( {isLogin ? (
<ChatContent <ChatContent

View File

@@ -1,6 +1,4 @@
import { import { MessageSquarePlus } from "lucide-react";
MessageSquarePlus,
} from "lucide-react";
import clsx from "clsx"; import clsx from "clsx";
import HistoryIcon from "@/icons/History"; import HistoryIcon from "@/icons/History";
@@ -27,6 +25,7 @@ interface ChatHeaderProps {
setIsLogin: (isLogin: boolean) => void; setIsLogin: (isLogin: boolean) => void;
isChatPage?: boolean; isChatPage?: boolean;
showChatHistory?: boolean; showChatHistory?: boolean;
assistantIDs?: string[];
} }
export function ChatHeader({ export function ChatHeader({
@@ -40,8 +39,8 @@ export function ChatHeader({
setIsLogin, setIsLogin,
isChatPage = false, isChatPage = false,
showChatHistory = true, showChatHistory = true,
assistantIDs,
}: ChatHeaderProps) { }: ChatHeaderProps) {
const isPinned = useAppStore((state) => state.isPinned); const isPinned = useAppStore((state) => state.isPinned);
const setIsPinned = useAppStore((state) => state.setIsPinned); const setIsPinned = useAppStore((state) => state.setIsPinned);
@@ -94,7 +93,7 @@ export function ChatHeader({
</button> </button>
)} )}
<AssistantList showChatHistory={showChatHistory} /> <AssistantList assistantIDs={assistantIDs} />
{showChatHistory ? ( {showChatHistory ? (
<button <button

View File

@@ -1,9 +1,11 @@
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { ChatMessage } from "@/components/ChatMessage"; import { ChatMessage } from "@/components/ChatMessage";
import { useConnectStore } from "@/stores/connectStore";
export const Greetings = () => { export const Greetings = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const currentAssistant = useConnectStore((state) => state.currentAssistant);
return ( return (
<ChatMessage <ChatMessage
@@ -12,7 +14,9 @@ export const Greetings = () => {
_id: "greetings", _id: "greetings",
_source: { _source: {
type: "assistant", type: "assistant",
message: t("assistant.chat.greetings"), message:
currentAssistant?._source?.chat_settings?.greeting_message ||
t("assistant.chat.greetings"),
}, },
}} }}
/> />

View File

@@ -1,8 +1,7 @@
import { MoveRight } from "lucide-react"; import { MoveRight } from "lucide-react";
import { FC, useEffect, useState } from "react"; import { FC, useEffect, useState } from "react";
import { Get } from "@/api/axiosRequest"; import { useConnectStore } from "@/stores/connectStore";
import { useAppStore } from "@/stores/appStore";
interface PrevSuggestionProps { interface PrevSuggestionProps {
sendMessage: (message: string) => void; sendMessage: (message: string) => void;
@@ -11,35 +10,18 @@ interface PrevSuggestionProps {
const PrevSuggestion: FC<PrevSuggestionProps> = (props) => { const PrevSuggestion: FC<PrevSuggestionProps> = (props) => {
const { sendMessage } = props; const { sendMessage } = props;
const isTauri = useAppStore((state) => state.isTauri); const currentAssistant = useConnectStore((state) => state.currentAssistant);
const headersStr = localStorage.getItem("headers") || "{}";
const headers = JSON.parse(headersStr);
const id = headers["APP-INTEGRATION-ID"] || "cvkm9hmhpcemufsg3vug";
// console.log("id", id);
const [list, setList] = useState<string[]>([]); const [list, setList] = useState<string[]>([]);
useEffect(() => { useEffect(() => {
if (!isTauri) getList(); const suggested = currentAssistant?._source?.chat_settings?.suggested || {};
}, [id]); if (suggested.enabled) {
setList(suggested.questions || []);
const getList = async () => { } else {
if (!id) return; setList([]);
const url = `/integration/${id}/chat/_suggest`;
const [error, res] = await Get(`/integration/${id}/chat/_suggest`);
if (error) {
console.error(url, error);
return setList([]);
} }
}, [JSON.stringify(currentAssistant)]);
console.log("chat/_suggest", res);
setList(Array.isArray(res) ? res : []);
};
return ( return (
<ul className="absolute left-2 bottom-2 flex flex-col gap-2"> <ul className="absolute left-2 bottom-2 flex flex-col gap-2">

View File

@@ -15,7 +15,7 @@ import SearchPopover from "./SearchPopover";
// import AudioRecording from "../AudioRecording"; // import AudioRecording from "../AudioRecording";
import { DataSource } from "@/types/commands"; import { DataSource } from "@/types/commands";
// import InputExtra from "./InputExtra"; // import InputExtra from "./InputExtra";
// import { useConnectStore } from "@/stores/connectStore"; import { useConnectStore } from "@/stores/connectStore";
import { useShortcutsStore } from "@/stores/shortcutsStore"; import { useShortcutsStore } from "@/stores/shortcutsStore";
import Copyright from "@/components/Common/Copyright"; import Copyright from "@/components/Common/Copyright";
import VisibleKey from "@/components/Common/VisibleKey"; import VisibleKey from "@/components/Common/VisibleKey";
@@ -55,7 +55,6 @@ interface ChatInputProps {
getFileMetadata: (path: string) => Promise<any>; getFileMetadata: (path: string) => Promise<any>;
getFileIcon: (path: string, size: number) => Promise<string>; getFileIcon: (path: string, size: number) => Promise<string>;
hideCoco?: () => void; hideCoco?: () => void;
hasFeature?: string[];
hasModules?: string[]; hasModules?: string[];
searchPlaceholder?: string; searchPlaceholder?: string;
chatPlaceholder?: string; chatPlaceholder?: string;
@@ -77,7 +76,6 @@ export default function ChatInput({
isChatPage = false, isChatPage = false,
getDataSourcesByServer, getDataSourcesByServer,
setupWindowFocusListener, setupWindowFocusListener,
hasFeature = ["think", "search", "think_active", "search_active"],
hideCoco, hideCoco,
hasModules = [], hasModules = [],
searchPlaceholder, searchPlaceholder,
@@ -85,6 +83,9 @@ export default function ChatInput({
}: ChatInputProps) { }: ChatInputProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const currentAssistant = useConnectStore((state) => state.currentAssistant);
console.log("currentAssistant", currentAssistant);
const showTooltip = useAppStore((state) => state.showTooltip); const showTooltip = useAppStore((state) => state.showTooltip);
const isPinned = useAppStore((state) => state.isPinned); const isPinned = useAppStore((state) => state.isPinned);
@@ -437,7 +438,7 @@ export default function ChatInput({
/> />
)} */} )} */}
{hasFeature.includes("think") && ( {currentAssistant?._source?.config?.visible && (
<button <button
className={clsx( className={clsx(
"flex items-center gap-1 py-[3px] pl-1 pr-1.5 rounded-md transition hover:bg-[#EDEDED] dark:hover:bg-[#202126]", "flex items-center gap-1 py-[3px] pl-1 pr-1.5 rounded-md transition hover:bg-[#EDEDED] dark:hover:bg-[#202126]",
@@ -468,7 +469,7 @@ export default function ChatInput({
</button> </button>
)} )}
{hasFeature.includes("search") && ( {currentAssistant?._source?.datasource?.visible && (
<SearchPopover <SearchPopover
isSearchActive={isSearchActive} isSearchActive={isSearchActive}
setIsSearchActive={setIsSearchActive} setIsSearchActive={setIsSearchActive}
@@ -476,7 +477,7 @@ export default function ChatInput({
/> />
)} )}
{!hasFeature.includes("search") && !hasFeature.includes("think") ? ( {!currentAssistant?._source?.datasource?.visible && !currentAssistant?._source?.config?.visible ? (
<div className="px-[9px]"> <div className="px-[9px]">
<Copyright /> <Copyright />
</div> </div>

View File

@@ -49,14 +49,16 @@ const SearchListItem: React.FC<SearchListItemProps> = React.memo(
> >
<div <div
className={`${ className={`${
showListRight ? "max-w-[450px] mobile:w-full" : "flex-1" showListRight ? "max-w-[450px] mobile:max-w-full mobile:w-full" : "flex-1"
} min-w-0 flex gap-2 items-center justify-start `} } min-w-0 flex gap-2 items-center justify-start `}
> >
<ItemIcon item={item} /> <ItemIcon item={item} />
<span className={`text-sm truncate text-left`}>{item?.title}</span> <span className={`text-sm truncate text-left`}>{item?.title}</span>
</div> </div>
{!isTauri && isMobile ? ( {!isTauri && isMobile ? (
<div className="w-full text-xs truncate">{item?.summary}</div> <div className="w-full text-xs text-gray-500 dark:text-gray-400 truncate">
{item?.summary}
</div>
) : null} ) : null}
{showListRight && (isTauri || !isMobile) ? ( {showListRight && (isTauri || !isMobile) ? (
<ListRight <ListRight

View File

@@ -24,13 +24,13 @@ import { useStartupStore } from "@/stores/startupStore";
import { DataSource } from "@/types/commands"; import { DataSource } from "@/types/commands";
import { useThemeStore } from "@/stores/themeStore"; import { useThemeStore } from "@/stores/themeStore";
import { Get } from "@/api/axiosRequest"; import { Get } from "@/api/axiosRequest";
import { useConnectStore } from "@/stores/connectStore";
interface SearchChatProps { interface SearchChatProps {
isTauri?: boolean; isTauri?: boolean;
hasModules?: string[]; hasModules?: string[];
defaultModule?: "search" | "chat"; defaultModule?: "search" | "chat";
hasFeature?: string[];
showChatHistory?: boolean; showChatHistory?: boolean;
theme?: "auto" | "light" | "dark"; theme?: "auto" | "light" | "dark";
@@ -41,13 +41,13 @@ interface SearchChatProps {
setIsPinned?: (value: boolean) => void; setIsPinned?: (value: boolean) => void;
onModeChange?: (isChatMode: boolean) => void; onModeChange?: (isChatMode: boolean) => void;
isMobile?: boolean; isMobile?: boolean;
assistantIDs?: string[];
} }
function SearchChat({ function SearchChat({
isTauri = true, isTauri = true,
hasModules = ["search", "chat"], hasModules = ["search", "chat"],
defaultModule = "search", defaultModule = "search",
hasFeature = ["think", "search", "think_active", "search_active"],
theme, theme,
hideCoco, hideCoco,
searchPlaceholder, searchPlaceholder,
@@ -56,11 +56,14 @@ function SearchChat({
setIsPinned, setIsPinned,
onModeChange, onModeChange,
isMobile = false, isMobile = false,
assistantIDs,
}: SearchChatProps) { }: SearchChatProps) {
const currentAssistant = useConnectStore((state) => state.currentAssistant);
const customInitialState = { const customInitialState = {
...initialAppState, ...initialAppState,
isDeepThinkActive: hasFeature.includes("think_active"), isDeepThinkActive: currentAssistant?._source?.type === "deep_think",
isSearchActive: hasFeature.includes("search_active"), isSearchActive: currentAssistant?._source?.datasource?.enabled === true,
}; };
const [state, dispatch] = useReducer(appReducer, customInitialState); const [state, dispatch] = useReducer(appReducer, customInitialState);
@@ -172,26 +175,31 @@ function SearchChat({
query?: string; query?: string;
} }
): Promise<DataSource[]> => { ): Promise<DataSource[]> => {
let response: any;
if (isTauri) { if (isTauri) {
return platformAdapter.invokeBackend("get_datasources_by_server", { response = platformAdapter.invokeBackend("get_datasources_by_server", {
id: serverId, id: serverId,
options, options,
}); });
} else { } else {
const [error, response]: any = await Get("/datasource/_search"); const [error, res]: any = await Get("/datasource/_search");
if (error) { if (error) {
console.error("_search", error); console.error("_search", error);
return []; return [];
} }
const res = response?.hits?.hits?.map((item: any) => { response = res?.hits?.hits?.map((item: any) => {
return { return {
...item, ...item,
id: item._source.id, id: item._source.id,
name: item._source.name, name: item._source.name,
}; };
}); });
return res || [];
} }
let ids = currentAssistant?._source?.datasource?.ids;
if (Array.isArray(ids) && ids.length > 0 && !ids.includes("*")) {
response = response.filter((item: any) => ids.includes(item.id));
}
return response || [];
}, },
[] []
); );
@@ -300,7 +308,6 @@ function SearchChat({
setIsSearchActive={toggleSearchActive} setIsSearchActive={toggleSearchActive}
isDeepThinkActive={isDeepThinkActive} isDeepThinkActive={isDeepThinkActive}
setIsDeepThinkActive={toggleDeepThinkActive} setIsDeepThinkActive={toggleDeepThinkActive}
hasFeature={hasFeature}
getDataSourcesByServer={getDataSourcesByServer} getDataSourcesByServer={getDataSourcesByServer}
setupWindowFocusListener={setupWindowFocusListener} setupWindowFocusListener={setupWindowFocusListener}
checkScreenPermission={checkScreenPermission} checkScreenPermission={checkScreenPermission}
@@ -356,6 +363,7 @@ function SearchChat({
isDeepThinkActive={isDeepThinkActive} isDeepThinkActive={isDeepThinkActive}
getFileUrl={getFileUrl} getFileUrl={getFileUrl}
showChatHistory={showChatHistory} showChatHistory={showChatHistory}
assistantIDs={assistantIDs}
/> />
</Suspense> </Suspense>
</div> </div>

View File

@@ -30,7 +30,6 @@ import {
import { DataSource } from "@/types/commands"; import { DataSource } from "@/types/commands";
import HistoryList from "@/components/Common/HistoryList"; import HistoryList from "@/components/Common/HistoryList";
import { useSyncStore } from "@/hooks/useSyncStore"; import { useSyncStore } from "@/hooks/useSyncStore";
import { useFeatureControl } from "@/hooks/useFeatureControl";
interface ChatProps {} interface ChatProps {}
@@ -262,12 +261,6 @@ export default function Chat({}: ChatProps) {
await delete_session_chat(currentService.id, id); await delete_session_chat(currentService.id, id);
}; };
const hasFeature = useFeatureControl({
initialFeatures: ["think", "search"],
featureToToggle: "think",
condition: (item) => item?._source?.type === "simple"
});
return ( return (
<div className="h-screen"> <div className="h-screen">
<div className="h-full flex"> <div className="h-full flex">
@@ -337,7 +330,6 @@ export default function Chat({}: ChatProps) {
openFileDialog={openFileDialog} openFileDialog={openFileDialog}
getFileMetadata={getFileMetadata} getFileMetadata={getFileMetadata}
getFileIcon={getFileIcon} getFileIcon={getFileIcon}
hasFeature={hasFeature}
/> />
</div> </div>
</div> </div>

View File

@@ -4,7 +4,6 @@ import SearchChat from "@/components/SearchChat";
import platformAdapter from "@/utils/platformAdapter"; import platformAdapter from "@/utils/platformAdapter";
import { useAppStore } from "@/stores/appStore"; import { useAppStore } from "@/stores/appStore";
import { useSyncStore } from "@/hooks/useSyncStore"; import { useSyncStore } from "@/hooks/useSyncStore";
import { useFeatureControl } from "@/hooks/useFeatureControl";
function MainApp() { function MainApp() {
const setIsTauri = useAppStore((state) => state.setIsTauri); const setIsTauri = useAppStore((state) => state.setIsTauri);
@@ -16,18 +15,11 @@ function MainApp() {
useSyncStore(); useSyncStore();
const hasFeature = useFeatureControl({
initialFeatures: ["think", "search"],
featureToToggle: "think",
condition: (item) => item?._source?.type === "simple",
});
return ( return (
<SearchChat <SearchChat
isTauri={true} isTauri={true}
hideCoco={hideCoco} hideCoco={hideCoco}
hasModules={["search", "chat"]} hasModules={["search", "chat"]}
hasFeature={hasFeature}
/> />
); );
} }

View File

@@ -32,12 +32,6 @@
- **默认值**: `['search', 'chat']` - **默认值**: `['search', 'chat']`
- **描述**: 启用的功能模块列表,目前支持 'search' 和 'chat' 模块 - **描述**: 启用的功能模块列表,目前支持 'search' 和 'chat' 模块
### `hasFeature`
- **类型**: `string[]`
- **可选**: 是
- **默认值**: `['think', 'search', 'think_active', 'search_active']`
- **描述**: 启用的特性列表,支持 'think'、'search'、'think_active'、'search_active' 特性。其中 'think_active' 表示默认开启深度思考,'search_active' 表示默认开启搜索
### `hideCoco` ### `hideCoco`
- **类型**: `() => void` - **类型**: `() => void`
- **可选**: 是 - **可选**: 是
@@ -87,7 +81,6 @@ function App() {
width={680} width={680}
height={590} height={590}
hasModules={['search', 'chat']} hasModules={['search', 'chat']}
hasFeature={['think', 'search', 'think_active', 'search_active']}
hideCoco={() => console.log('hide')} hideCoco={() => console.log('hide')}
theme="dark" theme="dark"
searchPlaceholder="" searchPlaceholder=""

View File

@@ -5,7 +5,6 @@ import { useAppStore } from "@/stores/appStore";
import { useShortcutsStore } from "@/stores/shortcutsStore"; import { useShortcutsStore } from "@/stores/shortcutsStore";
import { useIsMobile } from "@/hooks/useIsMobile"; import { useIsMobile } from "@/hooks/useIsMobile";
import { useModifierKeyPress } from "@/hooks/useModifierKeyPress"; import { useModifierKeyPress } from "@/hooks/useModifierKeyPress";
import { useFeatureControl } from "@/hooks/useFeatureControl";
import "@/i18n"; import "@/i18n";
import "@/web.css"; import "@/web.css";
@@ -17,7 +16,7 @@ interface WebAppProps {
height?: number; height?: number;
hasModules?: string[]; hasModules?: string[];
defaultModule?: "search" | "chat"; defaultModule?: "search" | "chat";
hasFeature?: string[]; assistantIDs?: string[];
hideCoco?: () => void; hideCoco?: () => void;
theme?: "auto" | "light" | "dark"; theme?: "auto" | "light" | "dark";
searchPlaceholder?: string; searchPlaceholder?: string;
@@ -32,7 +31,7 @@ function WebApp({
height = 590, height = 590,
headers = { headers = {
"X-API-TOKEN": "X-API-TOKEN":
"cvvitp6hpceh0ip1q1706byts41c7213k4el22v3bp6f4ta2sar0u29jp4pg08h6xcyxn085x3lq1k7wojof", "cvqt6r02sdb2v3bkgip0x3ixv01f3r2lhnxoz1efbn160wm9og58wtv8t6wrv1ebvnvypuc23dx9pb33aemh",
"APP-INTEGRATION-ID": "cvkm9hmhpcemufsg3vug", "APP-INTEGRATION-ID": "cvkm9hmhpcemufsg3vug",
}, },
// token = "cva1j5ehpcenic3ir7k0h8fb8qtv35iwtywze248oscrej8yoivhb5b1hyovp24xejjk27jy9ddt69ewfi3n", // https://coco.infini.cloud // token = "cva1j5ehpcenic3ir7k0h8fb8qtv35iwtywze248oscrej8yoivhb5b1hyovp24xejjk27jy9ddt69ewfi3n", // https://coco.infini.cloud
@@ -42,7 +41,7 @@ function WebApp({
hideCoco = () => {}, hideCoco = () => {},
hasModules = ["search", "chat"], hasModules = ["search", "chat"],
defaultModule = "search", defaultModule = "search",
hasFeature = ["think_active", "search_active"], assistantIDs = [],
theme = "dark", theme = "dark",
searchPlaceholder = "", searchPlaceholder = "",
chatPlaceholder = "", chatPlaceholder = "",
@@ -71,12 +70,6 @@ function WebApp({
const [isChatMode, setIsChatMode] = useState(false); const [isChatMode, setIsChatMode] = useState(false);
const hasFeatureCopy = useFeatureControl({
initialFeatures: hasFeature,
featureToToggle: "think",
condition: (item) => item?._source?.type === "simple",
});
return ( return (
<div <div
id="searchChat-container" id="searchChat-container"
@@ -91,7 +84,7 @@ function WebApp({
{isMobile && ( {isMobile && (
<div <div
className={`fixed ${ className={`fixed ${
isChatMode ? "top-2" : "top-3" isChatMode ? "top-1" : "top-3"
} right-2 flex items-center justify-center w-8 h-8 rounded-full bg-black/10 dark:bg-white/10 cursor-pointer z-50`} } right-2 flex items-center justify-center w-8 h-8 rounded-full bg-black/10 dark:bg-white/10 cursor-pointer z-50`}
onClick={onCancel} onClick={onCancel}
> >
@@ -110,7 +103,6 @@ function WebApp({
hideCoco={hideCoco} hideCoco={hideCoco}
hasModules={hasModules} hasModules={hasModules}
defaultModule={defaultModule} defaultModule={defaultModule}
hasFeature={hasFeatureCopy}
theme={theme} theme={theme}
searchPlaceholder={searchPlaceholder} searchPlaceholder={searchPlaceholder}
chatPlaceholder={chatPlaceholder} chatPlaceholder={chatPlaceholder}
@@ -118,6 +110,7 @@ function WebApp({
setIsPinned={setIsPinned} setIsPinned={setIsPinned}
onModeChange={setIsChatMode} onModeChange={setIsChatMode}
isMobile={isMobile} isMobile={isMobile}
assistantIDs={assistantIDs}
/> />
</div> </div>
); );

View File

@@ -1,8 +1,8 @@
// manual modification // manual modification
//import { createWebAdapter } from './webAdapter'; import { createWebAdapter } from './webAdapter';
import { createTauriAdapter } from "./tauriAdapter"; //import { createTauriAdapter } from "./tauriAdapter";
let platformAdapter = createTauriAdapter(); //let platformAdapter = createTauriAdapter();
//let platformAdapter = createWebAdapter(); let platformAdapter = createWebAdapter();
export default platformAdapter; export default platformAdapter;

View File

@@ -67,7 +67,7 @@ export default defineConfig({
const packageJson = { const packageJson = {
name: "@infinilabs/search-chat", name: "@infinilabs/search-chat",
version: "1.1.4", version: "1.1.5",
main: "index.js", main: "index.js",
module: "index.js", module: "index.js",
type: "module", type: "module",

View File

@@ -61,6 +61,16 @@ export default defineConfig(async () => ({
changeOrigin: true, changeOrigin: true,
secure: false, secure: false,
}, },
"/assistant": {
target: process.env.COCO_SERVER_URL,
changeOrigin: true,
secure: false,
},
"/datasource": {
target: process.env.COCO_SERVER_URL,
changeOrigin: true,
secure: false,
},
}, },
}, },
build: { build: {