From e2680e3f96e8934dc2d1750a8735a37c968c7196 Mon Sep 17 00:00:00 2001
From: MasonTao <yingchun_tao@163.com>
Date: Tue, 11 Jun 2024 14:18:34 +0800
Subject: [PATCH] fix: fix subdmain bugs

---
 components/Chat/Chat.tsx         |   2 +-
 components/Chat/SystemNodes.tsx  |  25 +-
 components/Settings/QueryUrl.tsx | 130 ++---
 hooks/useHost.ts                 |   6 +
 pages/api/home/home.tsx          | 935 +++++++++++++++++--------------
 5 files changed, 577 insertions(+), 521 deletions(-)

diff --git a/components/Chat/Chat.tsx b/components/Chat/Chat.tsx
index d6f812f..8dc5ee1 100644
--- a/components/Chat/Chat.tsx
+++ b/components/Chat/Chat.tsx
@@ -535,7 +535,7 @@ export const Chat = memo(({ stopConversationRef }: Props) => {
             ref={chatContainerRef}
             onScroll={handleScroll}
           >
-            <div className="sticky z-10 top-0 flex w-full items-center justify-end gap-3 h-[84px] bg-white border-b border-[rgba(0,0,0,0.15)] pr-5">
+            <div className="sticky z-10 top-0 flex w-full items-center justify-end gap-3 h-[84px] bg-white border-b border-[rgba(0,0,0,0.15)] pl-4 md:pl-0 pr-4 md:pr-5">
               {/* <div className="inline-flex items-center justify-center rounded-lg px-3 h-[44px] text-[13px] bg-white text-black border border-[rgba(0, 0, 0, 0.08)] cursor-pointer hover:border-black transition-all">
                 <p>{selectedConversation?.model?.id || defaultModelId}</p>
               </div> */}
diff --git a/components/Chat/SystemNodes.tsx b/components/Chat/SystemNodes.tsx
index 60256d3..bd46844 100644
--- a/components/Chat/SystemNodes.tsx
+++ b/components/Chat/SystemNodes.tsx
@@ -8,8 +8,6 @@ import React, {
   useState,
 } from 'react';
 
-import { useRouter } from 'next/router';
-
 import { dappHosts } from '@/hooks/useHost';
 
 import HomeContext from '@/pages/api/home/home.context';
@@ -18,10 +16,9 @@ const SystemNodes: React.FC = () => {
   const [tippyInstance, setTippyInstance] = useState<any>(null);
   const [nodes, setNodes] = useState<any[]>([]);
   const [searchWords, setSearchWords] = useState('');
-  const { query } = useRouter();
 
   const {
-    state: { api, selectedConversation, defaultModelId },
+    state: { api, selectedConversation, modelError },
     dispatch: homeDispatch,
   } = useContext(HomeContext);
 
@@ -66,22 +63,6 @@ const SystemNodes: React.FC = () => {
     fetchNodes();
   }, [channelIsDapp]);
 
-  useEffect(() => {
-    if (typeof window === 'undefined' || !channelIsDapp) return;
-    if (query?.subdomain) {
-      handleApiChange(`https://${query?.subdomain}`);
-    } else {
-      if (api === '' || api === '..') {
-        const host = window.location.host;
-        if (host === 'gaianet.ai' || host === 'www.gaianet.ai') {
-          handleApiChange(`https://knowledge.gaianet.network`);
-        } else {
-          handleApiChange(`https://knowledge.gaianet.xyz`);
-        }
-      }
-    }
-  }, [api, channelIsDapp, handleApiChange, query?.subdomain]);
-
   const handleSearch = (e: any) => {
     setSearchWords(e.target.value || '');
   };
@@ -173,13 +154,13 @@ const SystemNodes: React.FC = () => {
       onCreate={(instance) => setTippyInstance(instance)}
       className="gaianet-tippy"
     >
-      <div className="inline-flex items-center justify-between rounded-lg gap-3 px-3 w-[405px] h-[44px] text-[13px] bg-white text-black border border-[rgba(0, 0, 0, 0.08)] cursor-pointer hover:border-black transition-all">
+      <div className="inline-flex items-center justify-between rounded-lg gap-3 px-3 w-auto md:min-w-[405px] h-[44px] text-[13px] bg-white text-black border border-[rgba(0, 0, 0, 0.08)] cursor-pointer hover:border-black transition-all">
         <div className="flex flex-col">
           <p className="text-[13px] leading-[16px] ">
             {selectedModelSubdomin || '-'}
           </p>
           <p className="text-[10px] leading-[13px] uppercase mt-[2px] text-[#888888]">
-            {selectedConversation?.model?.id || defaultModelId}
+            {modelError ? '-' : selectedConversation?.model?.id}
           </p>
         </div>
         <IconChevronDown size="18" color="#C0C0C0" />
diff --git a/components/Settings/QueryUrl.tsx b/components/Settings/QueryUrl.tsx
index 37ef7fb..76f4f3e 100644
--- a/components/Settings/QueryUrl.tsx
+++ b/components/Settings/QueryUrl.tsx
@@ -1,79 +1,81 @@
-import {IconCheck, IconLink, IconX} from '@tabler/icons-react';
-import {FC, KeyboardEvent, useEffect, useRef, useState} from 'react';
+import { IconCheck, IconLink, IconX } from '@tabler/icons-react';
+import { FC, KeyboardEvent, useEffect, useRef, useState } from 'react';
 
-import {useTranslation} from 'next-i18next';
+import { useTranslation } from 'next-i18next';
 
-import {SidebarButton} from '../Sidebar/SidebarButton';
+import { SidebarButton } from '../Sidebar/SidebarButton';
 
 interface Props {
-    api: string;
-    onApiChange: (apiKey: string) => void;
+  api: string;
+  onApiChange: (apiKey: string) => void;
 }
 
-export const QueryUrl: FC<Props> = ({api, onApiChange}) => {
-    const {t} = useTranslation('sidebar');
-    const [isChanging, setIsChanging] = useState(false);
-    const [newKey, setNewKey] = useState(api);
-    const inputRef = useRef<HTMLInputElement>(null);
+export const QueryUrl: FC<Props> = ({ api, onApiChange }) => {
+  const { t } = useTranslation('sidebar');
+  const [isChanging, setIsChanging] = useState(false);
+//   const [newKey, setNewKey] = useState(api);
+  const inputRef = useRef<HTMLInputElement>(null);
 
-    const handleEnterDown = (e: KeyboardEvent<HTMLDivElement>) => {
-        if (e.key === 'Enter') {
-            e.preventDefault();
-            handleUpdateKey(newKey);
-        }
-    };
+  const handleEnterDown = (e: KeyboardEvent<HTMLDivElement>) => {
+    if (e.key === 'Enter') {
+      e.preventDefault();
+      if (inputRef.current?.value)
+        handleUpdateKey(inputRef.current?.value?.trim());
+    }
+  };
 
-    const handleUpdateKey = (newKey: string) => {
-        onApiChange(newKey.trim());
-        setIsChanging(false);
-    };
+  const handleUpdateKey = (newKey: string) => {
+    onApiChange(newKey.trim());
+    setIsChanging(false);
+  };
 
-    useEffect(() => {
-        if (isChanging) {
-            inputRef.current?.focus();
-        }
-    }, [isChanging]);
+  useEffect(() => {
+    if (isChanging) {
+      inputRef.current?.focus();
+    }
+  }, [isChanging]);
 
-    return isChanging ? (
-        <div
-            className="duration:200 flex w-full cursor-pointer items-center rounded-md py-[11px] px-4 transition-colors hover:bg-gray-500/10">
-            <IconLink size={18} color="#322221" />
+  return isChanging ? (
+    <div className="duration:200 flex w-full cursor-pointer items-center rounded-md py-[11px] px-4 transition-colors hover:bg-gray-500/10">
+      <IconLink size={18} color="#322221" />
 
-            <input
-                ref={inputRef}
-                className="ml-2 h-[20px] flex-1 overflow-hidden overflow-ellipsis border-b border-neutral-400 bg-transparent pr-1 text-[12.5px] leading-3 text-left text-[#322221] outline-none focus:border-neutral-100"
-                value={newKey}
-                onChange={(e) => setNewKey(e.target.value)}
-                onKeyDown={handleEnterDown}
-                placeholder={t('API Url') || 'API Url'}
-            />
+      <input
+        ref={inputRef}
+        className="ml-2 h-[20px] flex-1 overflow-hidden overflow-ellipsis border-b border-neutral-400 bg-transparent pr-1 text-[12.5px] leading-3 text-left text-[#322221] outline-none focus:border-neutral-100"
+        // value={newKey}
+        defaultValue={api}
+        // onChange={(e) => setNewKey(e.target.value)}
+        onKeyDown={handleEnterDown}
+        placeholder={t('API Url') || 'API Url'}
+      />
 
-            <div className="flex w-[40px]">
-                <IconCheck
-                    className="ml-auto min-w-[20px] text-neutral-400 hover:text-[#322221]"
-                    size={18}
-                    onClick={(e) => {
-                        e.stopPropagation();
-                        handleUpdateKey(newKey);
-                    }}
-                />
+      <div className="flex w-[40px]">
+        <IconCheck
+          className="ml-auto min-w-[20px] text-neutral-400 hover:text-[#322221]"
+          size={18}
+          onClick={(e) => {
+            e.stopPropagation();
+            if (inputRef.current?.value)
+              handleUpdateKey(inputRef.current?.value?.trim());
+          }}
+        />
 
-                <IconX
-                    className="ml-auto min-w-[20px] text-neutral-400 hover:text-[#322221]"
-                    size={18}
-                    onClick={(e) => {
-                        e.stopPropagation();
-                        setIsChanging(false);
-                        setNewKey(api);
-                    }}
-                />
-            </div>
-        </div>
-    ) : (
-        <SidebarButton
-            text={t('Chat API Url')}
-            icon={<IconLink size={18}/>}
-            onClick={() => setIsChanging(true)}
+        <IconX
+          className="ml-auto min-w-[20px] text-neutral-400 hover:text-[#322221]"
+          size={18}
+          onClick={(e) => {
+            e.stopPropagation();
+            setIsChanging(false);
+            // setNewKey(api);
+          }}
         />
-    );
+      </div>
+    </div>
+  ) : (
+    <SidebarButton
+      text={t('Chat API Url')}
+      icon={<IconLink size={18} />}
+      onClick={() => setIsChanging(true)}
+    />
+  );
 };
diff --git a/hooks/useHost.ts b/hooks/useHost.ts
index e16008c..7be5814 100644
--- a/hooks/useHost.ts
+++ b/hooks/useHost.ts
@@ -24,3 +24,9 @@ export const dappHosts = [
     apiUrl: 'https://api.gaianet-test.link/',
   },
 ];
+
+export const useChannelIsPortal = () => {
+  if (typeof window === 'undefined') return false;
+  const host = window.location.host;
+  if (dappHosts.find((item) => item?.host === host)) return true;
+};
diff --git a/pages/api/home/home.tsx b/pages/api/home/home.tsx
index 96e0bd1..04fa871 100644
--- a/pages/api/home/home.tsx
+++ b/pages/api/home/home.tsx
@@ -1,499 +1,566 @@
-import {useEffect, useRef} from 'react';
+import { useCallback, useEffect, useRef } from 'react';
 
-import {GetStaticProps} from 'next';
-import {useTranslation} from 'next-i18next';
-import {serverSideTranslations} from 'next-i18next/serverSideTranslations';
+import { GetStaticProps } from 'next';
+import { useTranslation } from 'next-i18next';
+import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
 import Head from 'next/head';
+import { useRouter } from 'next/router';
 
-import {useCreateReducer} from '@/hooks/useCreateReducer';
-import useApiService from '@/services/useApiService';
-
-import {cleanConversationHistory, cleanSelectedConversation,} from '@/utils/app/clean';
-import {DEFAULT_TEMPERATURE} from '@/utils/app/const';
-import {saveConversation, saveConversations, updateConversation,} from '@/utils/app/conversation';
-import {saveFolders} from '@/utils/app/folders';
-import {savePrompts} from '@/utils/app/prompts';
-import {getSettings} from '@/utils/app/settings';
+import { useCreateReducer } from '@/hooks/useCreateReducer';
+import { useChannelIsPortal } from '@/hooks/useHost';
 
-import {Conversation} from '@/types/chat';
-import {KeyValuePair} from '@/types/data';
-import {FolderInterface, FolderType} from '@/types/folder';
-import {fallbackModelID, OpenAIModel, OpenAIModelID} from '@/types/openai';
-import {Prompt} from '@/types/prompt';
+import useApiService from '@/services/useApiService';
 
-import {Chat} from '@/components/Chat/Chat';
-import {Chatbar} from '@/components/Chatbar/Chatbar';
-import {Navbar} from '@/components/Mobile/Navbar';
+import {
+  cleanConversationHistory,
+  cleanSelectedConversation,
+} from '@/utils/app/clean';
+import { DEFAULT_TEMPERATURE } from '@/utils/app/const';
+import {
+  saveConversation,
+  saveConversations,
+  updateConversation,
+} from '@/utils/app/conversation';
+import { saveFolders } from '@/utils/app/folders';
+import { savePrompts } from '@/utils/app/prompts';
+import { getSettings } from '@/utils/app/settings';
+
+import { Conversation } from '@/types/chat';
+import { KeyValuePair } from '@/types/data';
+import { FolderInterface, FolderType } from '@/types/folder';
+import { OpenAIModel, OpenAIModelID, fallbackModelID } from '@/types/openai';
+import { Prompt } from '@/types/prompt';
+
+import { Chat } from '@/components/Chat/Chat';
+import { promptsList } from '@/components/Chat/PromptsList';
+import { Chatbar } from '@/components/Chatbar/Chatbar';
+import { Navbar } from '@/components/Mobile/Navbar';
 
 import HomeContext from './home.context';
-import {HomeInitialState, initialState} from './home.state';
+import { HomeInitialState, initialState } from './home.state';
 
-import {v4 as uuidv4} from 'uuid';
-import {promptsList} from "@/components/Chat/PromptsList";
+import { v4 as uuidv4 } from 'uuid';
 
 interface Props {
-    serverSideApiKeyIsSet: boolean;
-    serverSidePluginKeysSet: boolean;
-    defaultModelId: OpenAIModelID;
+  serverSideApiKeyIsSet: boolean;
+  serverSidePluginKeysSet: boolean;
+  defaultModelId: OpenAIModelID;
 }
 
 interface DispatchData {
-    id: String;
-    name: String | null;
-    messages: [];
-    model?: Object;
-    prompt?: String;
-    promptState?: Number;
-    temperature: Number;
-    folderId: String | null;
+  id: String;
+  name: String | null;
+  messages: [];
+  model?: Object;
+  prompt?: String;
+  promptState?: Number;
+  temperature: Number;
+  folderId: String | null;
 }
 
 const Home = ({
-                  serverSideApiKeyIsSet,
-                  serverSidePluginKeysSet,
-                  defaultModelId,
-              }: Props) => {
-    const {t} = useTranslation('chat');
-    const {getModels} = useApiService();
-
-    const contextValue = useCreateReducer<HomeInitialState>({
-        initialState,
-    });
-
-    const {
-        state: {
-            api,
-            apiKey,
-            lightMode,
-            folders,
-            conversations,
-            selectedConversation,
-            prompts,
-            modelError,
-            models
-        },
-        dispatch,
-    } = contextValue;
-
-    const stopConversationRef = useRef<boolean>(false);
-
-    const getData = async () => {
-        try {
-            const data = await getModels(
-                {
-                    url: api,
-                    key: apiKey,
-                },
-            );
-            if (dispatch) {
-                dispatch({field: 'models', value: data});
-            }
-        } catch (e) {
-            if (dispatch && !modelError) {
-                dispatch({field: 'modelError', value: {code: "500", title: "false", messageLines: []}});
-            }
-            console.log(e)
-        }
-    }
-
-    useEffect(() => {
-        if (models && (!conversations || conversations && conversations.length === 0) && handleNewConversation) {
-            handleNewConversation()
-        }
-    }, [models])
-
-    useEffect(() => {
-        if (typeof window !== 'undefined' && api) {
-            getData()
-        }
-    }, [api])
-
-    // FETCH MODELS ----------------------------------------------
-
-    const handleSelectConversation = (conversation: Conversation) => {
+  serverSideApiKeyIsSet,
+  serverSidePluginKeysSet,
+  defaultModelId,
+}: Props) => {
+  const { t } = useTranslation('chat');
+  const { getModels } = useApiService();
+  const { query } = useRouter();
+  const channelIsPortal = useChannelIsPortal();
+
+  const contextValue = useCreateReducer<HomeInitialState>({
+    initialState,
+  });
+
+  const {
+    state: {
+      api,
+      apiKey,
+      lightMode,
+      folders,
+      conversations,
+      selectedConversation,
+      prompts,
+      modelError,
+      models,
+    },
+    dispatch,
+  } = contextValue;
+
+  const stopConversationRef = useRef<boolean>(false);
+
+  const getData = async () => {
+    try {
+      const data = await getModels({
+        url: api,
+        key: apiKey,
+      });
+      if (dispatch) {
+        dispatch({ field: 'models', value: data });
         dispatch({
-            field: 'selectedConversation',
-            value: conversation,
+          field: 'modelError',
+          value: null,
         });
-
-        saveConversation(conversation);
-    };
-
-    // FOLDER OPERATIONS  --------------------------------------------
-
-    function checkObjectExistence(objectList: OpenAIModel[], object: OpenAIModel): boolean {
-        for (let obj of objectList) {
-            if (obj.id === object.id) {
-                return true;
-            }
-        }
-        return false;
+      }
+    } catch (e) {
+      if (dispatch && !modelError) {
+        dispatch({
+          field: 'modelError',
+          value: { code: '500', title: 'false', messageLines: [] },
+        });
+      }
+      console.log(e);
     }
+  };
+
+  useEffect(() => {
+    if (
+      models &&
+      (!conversations || (conversations && conversations.length === 0)) &&
+      handleNewConversation
+    ) {
+      handleNewConversation();
+    }
+  }, [models]);
 
-    const handleCreateFolder = async (name: string, type: FolderType) => {
-        const newFolder: FolderInterface = {
-            id: uuidv4(),
-            name,
-            type,
-        };
-
-        const updatedFolders = [...folders, newFolder];
+  useEffect(() => {
+    if (typeof window !== 'undefined' && api) {
+      getData();
+    }
+  }, [api]);
 
-        dispatch({field: 'folders', value: updatedFolders});
-        saveFolders(updatedFolders);
-    };
+  // FETCH MODELS ----------------------------------------------
 
-    const handleDeleteFolder = (folderId: string) => {
-        const updatedFolders = folders.filter((f) => f.id !== folderId);
-        dispatch({field: 'folders', value: updatedFolders});
-        saveFolders(updatedFolders);
+  const handleSelectConversation = (conversation: Conversation) => {
+    dispatch({
+      field: 'selectedConversation',
+      value: conversation,
+    });
 
-        const updatedConversations: Conversation[] = conversations.map((c) => {
-            if (c.folderId === folderId) {
-                return {
-                    ...c,
-                    folderId: null,
-                };
-            }
+    saveConversation(conversation);
+  };
 
-            return c;
-        });
+  // FOLDER OPERATIONS  --------------------------------------------
 
-        dispatch({field: 'conversations', value: updatedConversations});
-        saveConversations(updatedConversations);
+  function checkObjectExistence(
+    objectList: OpenAIModel[],
+    object: OpenAIModel,
+  ): boolean {
+    for (let obj of objectList) {
+      if (obj.id === object.id) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  const handleCreateFolder = async (name: string, type: FolderType) => {
+    const newFolder: FolderInterface = {
+      id: uuidv4(),
+      name,
+      type,
+    };
 
-        const updatedPrompts: Prompt[] = prompts.map((p) => {
-            if (p.folderId === folderId) {
-                return {
-                    ...p,
-                    folderId: null,
-                };
-            }
+    const updatedFolders = [...folders, newFolder];
 
-            return p;
-        });
+    dispatch({ field: 'folders', value: updatedFolders });
+    saveFolders(updatedFolders);
+  };
 
-        dispatch({field: 'prompts', value: updatedPrompts});
-        savePrompts(updatedPrompts);
-    };
+  const handleDeleteFolder = (folderId: string) => {
+    const updatedFolders = folders.filter((f) => f.id !== folderId);
+    dispatch({ field: 'folders', value: updatedFolders });
+    saveFolders(updatedFolders);
 
-    const handleUpdateFolder = (folderId: string, name: string) => {
-        const updatedFolders = folders.map((f) => {
-            if (f.id === folderId) {
-                return {
-                    ...f,
-                    name,
-                };
-            }
+    const updatedConversations: Conversation[] = conversations.map((c) => {
+      if (c.folderId === folderId) {
+        return {
+          ...c,
+          folderId: null,
+        };
+      }
 
-            return f;
-        });
+      return c;
+    });
 
-        dispatch({field: 'folders', value: updatedFolders});
+    dispatch({ field: 'conversations', value: updatedConversations });
+    saveConversations(updatedConversations);
 
-        saveFolders(updatedFolders);
-    };
+    const updatedPrompts: Prompt[] = prompts.map((p) => {
+      if (p.folderId === folderId) {
+        return {
+          ...p,
+          folderId: null,
+        };
+      }
 
-    // CONVERSATION OPERATIONS  --------------------------------------------
-
-    const handleNewConversation = async () => {
-        await getData()
-        const lastConversation = conversations[conversations.length - 1];
-        let getPrompt
-        if (models && models.length > 0) {
-            await fetch('/config_pub.json')
-                .then(response => response.json())
-                .then(data => {
-                    getPrompt = data.system_prompt;
-                })
-                .catch(error => console.error('Error fetching JSON:', error));
-            const newConversation: Conversation = {
-                id: uuidv4(),
-                name: t('New Conversation'),
-                messages: [],
-                model: (lastConversation?.model && checkObjectExistence(models, lastConversation?.model) && lastConversation?.model) || models[0],
-                prompt: getPrompt || promptsList.find(prompt =>
-                    prompt.id?.toLowerCase() === models[0].name?.toLowerCase()
-                )?.content || "",
-                promptState: promptsList.find(prompt =>
-                    prompt.id?.toLowerCase() === models[0].name?.toLowerCase()
-                )?.controlState || 0,
-                temperature: lastConversation?.temperature ?? DEFAULT_TEMPERATURE,
-                folderId: null,
-            };
-
-            const updatedConversations = [...conversations, newConversation];
-
-            dispatch({field: 'selectedConversation', value: newConversation});
-            dispatch({field: 'conversations', value: updatedConversations});
-
-            saveConversation(newConversation);
-            saveConversations(updatedConversations);
-
-            dispatch({field: 'loading', value: false});
-        }
+      return p;
+    });
 
-    };
+    dispatch({ field: 'prompts', value: updatedPrompts });
+    savePrompts(updatedPrompts);
+  };
 
-    const handleUpdateConversation = (
-        conversation: Conversation,
-        data: KeyValuePair,
-    ) => {
-        const updatedConversation = {
-            ...conversation,
-            [data.key]: data.value,
+  const handleUpdateFolder = (folderId: string, name: string) => {
+    const updatedFolders = folders.map((f) => {
+      if (f.id === folderId) {
+        return {
+          ...f,
+          name,
         };
+      }
 
-        const {single, all} = updateConversation(
-            updatedConversation,
-            conversations,
-        );
+      return f;
+    });
 
-        dispatch({field: 'selectedConversation', value: single});
-        dispatch({field: 'conversations', value: all});
+    dispatch({ field: 'folders', value: updatedFolders });
+
+    saveFolders(updatedFolders);
+  };
+
+  // CONVERSATION OPERATIONS  --------------------------------------------
+
+  const handleNewConversation = async () => {
+    await getData();
+    const lastConversation = conversations[conversations.length - 1];
+    let getPrompt;
+    if (models && models.length > 0) {
+      await fetch('/config_pub.json')
+        .then((response) => response.json())
+        .then((data) => {
+          getPrompt = data.system_prompt;
+        })
+        .catch((error) => console.error('Error fetching JSON:', error));
+      const newConversation: Conversation = {
+        id: uuidv4(),
+        name: t('New Conversation'),
+        messages: [],
+        model:
+          (lastConversation?.model &&
+            checkObjectExistence(models, lastConversation?.model) &&
+            lastConversation?.model) ||
+          models[0],
+        prompt:
+          getPrompt ||
+          promptsList.find(
+            (prompt) =>
+              prompt.id?.toLowerCase() === models[0].name?.toLowerCase(),
+          )?.content ||
+          '',
+        promptState:
+          promptsList.find(
+            (prompt) =>
+              prompt.id?.toLowerCase() === models[0].name?.toLowerCase(),
+          )?.controlState || 0,
+        temperature: lastConversation?.temperature ?? DEFAULT_TEMPERATURE,
+        folderId: null,
+      };
+
+      const updatedConversations = [...conversations, newConversation];
+
+      dispatch({ field: 'selectedConversation', value: newConversation });
+      dispatch({ field: 'conversations', value: updatedConversations });
+
+      saveConversation(newConversation);
+      saveConversations(updatedConversations);
+
+      dispatch({ field: 'loading', value: false });
+    }
+  };
+
+  const handleUpdateConversation = (
+    conversation: Conversation,
+    data: KeyValuePair,
+  ) => {
+    const updatedConversation = {
+      ...conversation,
+      [data.key]: data.value,
     };
 
-    const handleUpdateConversationAll = (
-        conversation: Conversation,
-        data: KeyValuePair[],
-    ) => {
-        const updatedConversation = Object.assign(conversation)
-        data.forEach(item => {
-                updatedConversation[item.key] = item.value
-            }
-        )
-
-        const {single, all} = updateConversation(
-            updatedConversation,
-            conversations,
-        );
-
-        dispatch({field: 'selectedConversation', value: single});
-        dispatch({field: 'conversations', value: all});
-    };
+    const { single, all } = updateConversation(
+      updatedConversation,
+      conversations,
+    );
 
-    // EFFECTS  --------------------------------------------
+    dispatch({ field: 'selectedConversation', value: single });
+    dispatch({ field: 'conversations', value: all });
+  };
+
+  const handleUpdateConversationAll = (
+    conversation: Conversation,
+    data: KeyValuePair[],
+  ) => {
+    const updatedConversation = Object.assign(conversation);
+    data.forEach((item) => {
+      updatedConversation[item.key] = item.value;
+    });
 
-    useEffect(() => {
-        if (window.innerWidth < 640) {
-            dispatch({field: 'showChatbar', value: false});
-        }
-    }, [selectedConversation]);
+    const { single, all } = updateConversation(
+      updatedConversation,
+      conversations,
+    );
 
-    useEffect(() => {
-        serverSideApiKeyIsSet &&
-        dispatch({
-            field: 'serverSideApiKeyIsSet',
-            value: serverSideApiKeyIsSet,
-        });
-        serverSidePluginKeysSet &&
-        dispatch({
-            field: 'serverSidePluginKeysSet',
-            value: serverSidePluginKeysSet,
-        });
-    }, [serverSideApiKeyIsSet, serverSidePluginKeysSet]);
+    dispatch({ field: 'selectedConversation', value: single });
+    dispatch({ field: 'conversations', value: all });
+  };
 
-    // ON LOAD --------------------------------------------
+  // EFFECTS  --------------------------------------------
 
-    useEffect(() => {
-        const settings = getSettings();
-        if (settings.theme) {
-            dispatch({
-                field: 'lightMode',
-                value: settings.theme,
-            });
-        }
-        if (settings.isStream) {
-            dispatch({
-                field: 'isStream',
-                value: settings.isStream,
-            });
-        }
+  useEffect(() => {
+    if (window.innerWidth < 640) {
+      dispatch({ field: 'showChatbar', value: false });
+    }
+  }, [selectedConversation]);
+
+  useEffect(() => {
+    serverSideApiKeyIsSet &&
+      dispatch({
+        field: 'serverSideApiKeyIsSet',
+        value: serverSideApiKeyIsSet,
+      });
+    serverSidePluginKeysSet &&
+      dispatch({
+        field: 'serverSidePluginKeysSet',
+        value: serverSidePluginKeysSet,
+      });
+  }, [serverSideApiKeyIsSet, serverSidePluginKeysSet]);
+
+  // ON LOAD --------------------------------------------
+
+  useEffect(() => {
+    const settings = getSettings();
+    if (settings.theme) {
+      dispatch({
+        field: 'lightMode',
+        value: settings.theme,
+      });
+    }
+    if (settings.isStream) {
+      dispatch({
+        field: 'isStream',
+        value: settings.isStream,
+      });
+    }
 
-        const api = localStorage.getItem('api');
-        const apiKey = localStorage.getItem('apiKey');
+    const apiKey = localStorage.getItem('apiKey');
 
-        if (serverSideApiKeyIsSet) {
-            dispatch({field: 'apiKey', value: ''});
+    if (serverSideApiKeyIsSet) {
+      dispatch({ field: 'apiKey', value: '' });
 
-            localStorage.removeItem('apiKey');
-        } else if (apiKey) {
-            dispatch({field: 'apiKey', value: apiKey});
-        }
+      localStorage.removeItem('apiKey');
+    } else if (apiKey) {
+      dispatch({ field: 'apiKey', value: apiKey });
+    }
 
-        if (api) {
-            dispatch({field: 'api', value: api});
-        }
+    const pluginKeys = localStorage.getItem('pluginKeys');
+    if (serverSidePluginKeysSet) {
+      dispatch({ field: 'pluginKeys', value: [] });
+      localStorage.removeItem('pluginKeys');
+    } else if (pluginKeys) {
+      dispatch({ field: 'pluginKeys', value: pluginKeys });
+    }
 
-        const pluginKeys = localStorage.getItem('pluginKeys');
-        if (serverSidePluginKeysSet) {
-            dispatch({field: 'pluginKeys', value: []});
-            localStorage.removeItem('pluginKeys');
-        } else if (pluginKeys) {
-            dispatch({field: 'pluginKeys', value: pluginKeys});
-        }
+    if (window.innerWidth < 640) {
+      dispatch({ field: 'showChatbar', value: false });
+    }
 
-        if (window.innerWidth < 640) {
-            dispatch({field: 'showChatbar', value: false});
-        }
+    const showChatbar = localStorage.getItem('showChatbar');
+    if (showChatbar) {
+      dispatch({ field: 'showChatbar', value: showChatbar === 'true' });
+    }
 
-        const showChatbar = localStorage.getItem('showChatbar');
-        if (showChatbar) {
-            dispatch({field: 'showChatbar', value: showChatbar === 'true'});
-        }
+    const folders = localStorage.getItem('folders');
+    if (folders) {
+      dispatch({ field: 'folders', value: JSON.parse(folders) });
+    }
 
-        const folders = localStorage.getItem('folders');
-        if (folders) {
-            dispatch({field: 'folders', value: JSON.parse(folders)});
-        }
+    const prompts = localStorage.getItem('prompts');
+    if (prompts) {
+      dispatch({ field: 'prompts', value: JSON.parse(prompts) });
+    }
 
-        const prompts = localStorage.getItem('prompts');
-        if (prompts) {
-            dispatch({field: 'prompts', value: JSON.parse(prompts)});
-        }
+    const conversationHistory = localStorage.getItem('conversationHistory');
+    if (conversationHistory) {
+      const parsedConversationHistory: Conversation[] =
+        JSON.parse(conversationHistory);
+      const cleanedConversationHistory = cleanConversationHistory(
+        parsedConversationHistory,
+      );
 
-        const conversationHistory = localStorage.getItem('conversationHistory');
-        if (conversationHistory) {
-            const parsedConversationHistory: Conversation[] =
-                JSON.parse(conversationHistory);
-            const cleanedConversationHistory = cleanConversationHistory(
-                parsedConversationHistory,
-            );
+      dispatch({ field: 'conversations', value: cleanedConversationHistory });
+    }
 
-            dispatch({field: 'conversations', value: cleanedConversationHistory});
+    const selectedConversation = localStorage.getItem('selectedConversation');
+    if (selectedConversation) {
+      const parsedSelectedConversation: Conversation =
+        JSON.parse(selectedConversation);
+      const cleanedSelectedConversation = cleanSelectedConversation(
+        parsedSelectedConversation,
+      );
+
+      if (cleanedSelectedConversation.model && models && models.length > 0) {
+        const haveThisSelectedModels = models.filter(
+          (model) => model.id === cleanedSelectedConversation.model.id,
+        );
+        if (!haveThisSelectedModels || haveThisSelectedModels.length === 0) {
+          cleanedSelectedConversation.model = models[0];
+          cleanedSelectedConversation.prompt =
+            promptsList.find(
+              (prompt) =>
+                prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase(),
+            )?.content || '';
+          cleanedSelectedConversation.promptState =
+            promptsList.find(
+              (prompt) =>
+                prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase(),
+            )?.controlState || 0;
         }
+      }
+
+      dispatch({
+        field: 'selectedConversation',
+        value: cleanedSelectedConversation,
+      });
+    } else {
+      const lastConversation = conversations[conversations.length - 1];
+      let dispatchData: DispatchData = {
+        id: uuidv4(),
+        name: t('New Conversation'),
+        messages: [],
+        temperature: lastConversation?.temperature ?? DEFAULT_TEMPERATURE,
+        folderId: null,
+      };
+      if (models && models.length > 0) {
+        dispatchData.model = models[0];
+        dispatchData.prompt =
+          promptsList.find(
+            (prompt) =>
+              prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase(),
+          )?.content || '';
+        dispatchData.promptState =
+          promptsList.find(
+            (prompt) =>
+              prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase(),
+          )?.controlState || 0;
+      }
+      dispatch({
+        field: 'selectedConversation',
+        value: dispatchData,
+      });
+    }
+  }, [dispatch, models, serverSideApiKeyIsSet, serverSidePluginKeysSet]);
+
+  useEffect(() => {
+    const localStorageApi = localStorage.getItem('api');
+    if (query?.subdomain && channelIsPortal) {
+      dispatch({ field: 'api', value: `https://${query?.subdomain}` });
+      localStorage.setItem('api', `https://${query?.subdomain}`);
+      return;
+    }
 
-        const selectedConversation = localStorage.getItem('selectedConversation');
-        if (selectedConversation) {
-            const parsedSelectedConversation: Conversation =
-                JSON.parse(selectedConversation);
-            const cleanedSelectedConversation = cleanSelectedConversation(
-                parsedSelectedConversation,
-            );
-
-            if (cleanedSelectedConversation.model && models && models.length > 0) {
-                const haveThisSelectedModels = models.filter(model => model.id === cleanedSelectedConversation.model.id)
-                if (!haveThisSelectedModels || haveThisSelectedModels.length === 0) {
-                    cleanedSelectedConversation.model = models[0]
-                    cleanedSelectedConversation.prompt = promptsList.find(prompt =>
-                        prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase()
-                    )?.content || ""
-                    cleanedSelectedConversation.promptState = promptsList.find(prompt =>
-                        prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase()
-                    )?.controlState || 0
-                }
-            }
-
-            dispatch({
-                field: 'selectedConversation',
-                value: cleanedSelectedConversation,
-            });
+    if (localStorageApi)
+      return dispatch({ field: 'api', value: localStorageApi });
+
+    if (!localStorageApi) {
+      if (channelIsPortal) {
+        const host = window.location.host;
+        if (host === 'gaianet.ai' || host === 'www.gaianet.ai') {
+          dispatch({
+            field: 'api',
+            value: 'https://knowledge.gaianet.network',
+          });
+          localStorage.setItem('api', 'https://knowledge.gaianet.network');
         } else {
-            const lastConversation = conversations[conversations.length - 1];
-            let dispatchData: DispatchData = {
-                id: uuidv4(),
-                name: t('New Conversation'),
-                messages: [],
-                temperature: lastConversation?.temperature ?? DEFAULT_TEMPERATURE,
-                folderId: null,
-            }
-            if (models && models.length > 0) {
-                dispatchData.model = models[0]
-                dispatchData.prompt = promptsList.find(prompt =>
-                    prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase()
-                )?.content || ""
-                dispatchData.promptState = promptsList.find(prompt =>
-                    prompt.id?.toLowerCase() === models[0]?.name?.toLowerCase()
-                )?.controlState || 0
-            }
-            dispatch({
-                field: 'selectedConversation', value: dispatchData
-            });
+          dispatch({ field: 'api', value: 'https://knowledge.gaianet.xyz' });
+          localStorage.setItem('api', 'https://knowledge.gaianet.xyz');
+        }
+      } else {
+        const host = window.location.host;
+        if (!host.startsWith('localhost')) {
+          dispatch({ field: 'api', value: `https://${host}` });
+          localStorage.setItem('api', `https://${host}`);
         }
-    }, [
-        dispatch,
-        models,
-        serverSideApiKeyIsSet,
-        serverSidePluginKeysSet,
-    ]);
-
-    return (
-        <HomeContext.Provider
-            value={{
-                ...contextValue,
-                handleNewConversation,
-                handleCreateFolder,
-                handleDeleteFolder,
-                handleUpdateFolder,
-                handleSelectConversation,
-                handleUpdateConversation,
-                handleUpdateConversationAll
-            }}
+      }
+    }
+  }, [channelIsPortal, dispatch, query?.subdomain]);
+
+  return (
+    <HomeContext.Provider
+      value={{
+        ...contextValue,
+        handleNewConversation,
+        handleCreateFolder,
+        handleDeleteFolder,
+        handleUpdateFolder,
+        handleSelectConversation,
+        handleUpdateConversation,
+        handleUpdateConversationAll,
+      }}
+    >
+      <Head>
+        <title>GaiaNet</title>
+        <meta name="description" content="ChatGPT but better." />
+        <meta
+          name="viewport"
+          content="height=device-height ,width=device-width, initial-scale=1, user-scalable=no"
+        />
+        <link rel="icon" href="./favicon.png" />
+      </Head>
+      {selectedConversation && (
+        <main
+          className={`flex h-screen w-screen flex-col text-sm text-white dark:text-white ${lightMode}`}
         >
-            <Head>
-                <title>GaiaNet</title>
-                <meta name="description" content="ChatGPT but better."/>
-                <meta
-                    name="viewport"
-                    content="height=device-height ,width=device-width, initial-scale=1, user-scalable=no"
-                />
-                <link rel="icon" href="./favicon.png"/>
-            </Head>
-            {selectedConversation && (
-                <main
-                    className={`flex h-screen w-screen flex-col text-sm text-white dark:text-white ${lightMode}`}
-                >
-                    <div className="fixed top-0 w-full sm:hidden ">
-                        <Navbar
-                            selectedConversation={selectedConversation}
-                            onNewConversation={handleNewConversation}
-                        />
-                    </div>
-
-                    <div className="flex h-full w-full pt-[49px] sm:pt-0">
-                        <Chatbar/>
-
-                        <div className="flex flex-1">
-                            <Chat stopConversationRef={stopConversationRef}/>
-                        </div>
-                    </div>
-                </main>
-            )}
-        </HomeContext.Provider>
-    );
+          <div className="fixed top-0 w-full sm:hidden ">
+            <Navbar
+              selectedConversation={selectedConversation}
+              onNewConversation={handleNewConversation}
+            />
+          </div>
+
+          <div className="flex h-full w-full pt-[49px] sm:pt-0">
+            <Chatbar />
+
+            <div className="flex flex-1">
+              <Chat stopConversationRef={stopConversationRef} />
+            </div>
+          </div>
+        </main>
+      )}
+    </HomeContext.Provider>
+  );
 };
 export default Home;
 
-export const getStaticProps: GetStaticProps = async ({locale}) => {
-    const defaultModelId =
-        (process.env.DEFAULT_MODEL &&
-            Object.values(OpenAIModelID).includes(
-                process.env.DEFAULT_MODEL as OpenAIModelID,
-            ) &&
-            process.env.DEFAULT_MODEL) ||
-        fallbackModelID;
-
-    let serverSidePluginKeysSet = false;
-
-    const googleApiKey = process.env.GOOGLE_API_KEY;
-    const googleCSEId = process.env.GOOGLE_CSE_ID;
-
-    if (googleApiKey && googleCSEId) {
-        serverSidePluginKeysSet = true;
-    }
-
-    return {
-        props: {
-            serverSideApiKeyIsSet: !!process.env.OPENAI_API_KEY,
-            defaultModelId,
-            serverSidePluginKeysSet,
-            ...(await serverSideTranslations(locale ?? 'en', [
-                'common',
-                'chat',
-                'sidebar',
-                'markdown',
-                'settings',
-            ])),
-        },
-    };
+export const getStaticProps: GetStaticProps = async ({ locale }) => {
+  const defaultModelId =
+    (process.env.DEFAULT_MODEL &&
+      Object.values(OpenAIModelID).includes(
+        process.env.DEFAULT_MODEL as OpenAIModelID,
+      ) &&
+      process.env.DEFAULT_MODEL) ||
+    fallbackModelID;
+
+  let serverSidePluginKeysSet = false;
+
+  const googleApiKey = process.env.GOOGLE_API_KEY;
+  const googleCSEId = process.env.GOOGLE_CSE_ID;
+
+  if (googleApiKey && googleCSEId) {
+    serverSidePluginKeysSet = true;
+  }
+
+  return {
+    props: {
+      serverSideApiKeyIsSet: !!process.env.OPENAI_API_KEY,
+      defaultModelId,
+      serverSidePluginKeysSet,
+      ...(await serverSideTranslations(locale ?? 'en', [
+        'common',
+        'chat',
+        'sidebar',
+        'markdown',
+        'settings',
+      ])),
+    },
+  };
 };