feat: add minapps
@ -56,4 +56,4 @@ electronDownload:
|
||||
afterSign: scripts/notarize.js
|
||||
releaseInfo:
|
||||
releaseNotes: |
|
||||
添加 MiniMax 服务商
|
||||
新增AI小程序模块
|
||||
|
||||
@ -58,7 +58,9 @@
|
||||
window.api.minApp({
|
||||
url,
|
||||
windowOptions: {
|
||||
title: node.properties.title
|
||||
title: node.properties.title,
|
||||
width: 500,
|
||||
height: 800
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@ -62,10 +62,33 @@ export function createMainWindow() {
|
||||
})
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler((details) => {
|
||||
const websiteReg = /accounts.google.com/i
|
||||
|
||||
if (websiteReg.test(details.url)) {
|
||||
createMinappWindow({ url: details.url, windowOptions: { width: 1000, height: 680 } })
|
||||
} else {
|
||||
shell.openExternal(details.url)
|
||||
}
|
||||
|
||||
return { action: 'deny' }
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.webRequest.onHeadersReceived({ urls: ['*://*/*'] }, (details, callback) => {
|
||||
if (details.responseHeaders?.['X-Frame-Options']) {
|
||||
delete details.responseHeaders['X-Frame-Options']
|
||||
}
|
||||
if (details.responseHeaders?.['x-frame-options']) {
|
||||
delete details.responseHeaders['x-frame-options']
|
||||
}
|
||||
if (details.responseHeaders?.['Content-Security-Policy']) {
|
||||
delete details.responseHeaders['Content-Security-Policy']
|
||||
}
|
||||
if (details.responseHeaders?.['content-security-policy']) {
|
||||
delete details.responseHeaders['content-security-policy']
|
||||
}
|
||||
callback({ cancel: false, responseHeaders: details.responseHeaders })
|
||||
})
|
||||
|
||||
// HMR for renderer base on electron-vite cli.
|
||||
// Load the remote URL for development or the local html file for production.
|
||||
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
||||
@ -84,8 +107,8 @@ export function createMinappWindow({
|
||||
url: string
|
||||
windowOptions?: Electron.BrowserWindowConstructorOptions
|
||||
}) {
|
||||
const width = 500
|
||||
const height = 800
|
||||
const width = 1000
|
||||
const height = 680
|
||||
const headerHeight = 40
|
||||
|
||||
const minappWindow = new BrowserWindow({
|
||||
|
||||
@ -6,6 +6,7 @@ import { PersistGate } from 'redux-persist/integration/react'
|
||||
import Sidebar from './components/app/Sidebar'
|
||||
import TopViewContainer from './components/TopView'
|
||||
import AgentsPage from './pages/agents/AgentsPage'
|
||||
import AppsPage from './pages/apps/AppsPage'
|
||||
import HomePage from './pages/home/HomePage'
|
||||
import SettingsPage from './pages/settings/SettingsPage'
|
||||
import TranslatePage from './pages/translate/TranslatePage'
|
||||
@ -23,8 +24,9 @@ function App(): JSX.Element {
|
||||
<Sidebar />
|
||||
<Routes>
|
||||
<Route path="/" element={<HomePage />} />
|
||||
<Route path="/apps" element={<AgentsPage />} />
|
||||
<Route path="/agents" element={<AgentsPage />} />
|
||||
<Route path="/translate" element={<TranslatePage />} />
|
||||
<Route path="/apps" element={<AppsPage />} />
|
||||
<Route path="/settings/*" element={<SettingsPage />} />
|
||||
</Routes>
|
||||
</HashRouter>
|
||||
|
||||
@ -1,63 +1,64 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 4563475 */
|
||||
src: url('iconfont.woff2?t=1723186111414') format('woff2'),
|
||||
url('iconfont.woff?t=1723186111414') format('woff'),
|
||||
url('iconfont.ttf?t=1723186111414') format('truetype');
|
||||
font-family: 'iconfont'; /* Project id 4563475 */
|
||||
src: url('iconfont.woff2?t=1724204739157') format('woff2');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-family: 'iconfont' !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-business-smart-assistant:before {
|
||||
content: '\e601';
|
||||
}
|
||||
|
||||
.icon-copy:before {
|
||||
content: "\e6ae";
|
||||
content: '\e6ae';
|
||||
}
|
||||
|
||||
.icon-ic_send:before {
|
||||
content: "\e795";
|
||||
content: '\e795';
|
||||
}
|
||||
|
||||
.icon-dark1:before {
|
||||
content: "\e72f";
|
||||
content: '\e72f';
|
||||
}
|
||||
|
||||
.icon-theme-light:before {
|
||||
content: "\e6b7";
|
||||
content: '\e6b7';
|
||||
}
|
||||
|
||||
.icon-translate_line:before {
|
||||
content: "\e7de";
|
||||
content: '\e7de';
|
||||
}
|
||||
|
||||
.icon-history:before {
|
||||
content: "\e758";
|
||||
content: '\e758';
|
||||
}
|
||||
|
||||
.icon-hidesidebarhoriz:before {
|
||||
content: "\e8eb";
|
||||
content: '\e8eb';
|
||||
}
|
||||
|
||||
.icon-showsidebarhoriz:before {
|
||||
content: "\e944";
|
||||
content: '\e944';
|
||||
}
|
||||
|
||||
.icon-a-addchat:before {
|
||||
content: "\e658";
|
||||
content: '\e658';
|
||||
}
|
||||
|
||||
.icon-appstore:before {
|
||||
content: "\e792";
|
||||
content: '\e792';
|
||||
}
|
||||
|
||||
.icon-chat:before {
|
||||
content: "\e615";
|
||||
content: '\e615';
|
||||
}
|
||||
|
||||
.icon-setting:before {
|
||||
content: "\e78e";
|
||||
content: '\e78e';
|
||||
}
|
||||
|
||||
|
||||
BIN
src/renderer/src/assets/images/apps/360-ai.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
src/renderer/src/assets/images/apps/baidu-ai.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
src/renderer/src/assets/images/apps/baixiaoying.webp
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
src/renderer/src/assets/images/apps/kimi.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
src/renderer/src/assets/images/apps/yuewen.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
src/renderer/src/assets/images/models/yi.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
@ -1,7 +0,0 @@
|
||||
<svg width="600" height="600" viewBox="0 0 600 600" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="300" cy="300" r="300" fill="white"/>
|
||||
<rect x="409.733" y="340.032" width="42.3862" height="151.648" rx="21.1931" fill="#003425"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M422.005 133.354C413.089 125.771 399.714 126.851 392.131 135.768L273.699 275.021C270.643 278.614 268.994 282.932 268.698 287.302C268.532 288.371 268.446 289.466 268.446 290.581V468.603C268.446 480.308 277.934 489.796 289.639 489.796C301.344 489.796 310.832 480.308 310.832 468.603V296.784L424.419 163.228C432.002 154.312 430.921 140.937 422.005 133.354Z" fill="#003425"/>
|
||||
<rect x="113.972" y="134.25" width="42.3862" height="174.745" rx="21.1931" transform="rotate(-39.3441 113.972 134.25)" fill="#003425"/>
|
||||
<circle cx="460.126" cy="279.278" r="25.9027" fill="#00DD20"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 869 B |
|
Before Width: | Height: | Size: 6.5 KiB |
BIN
src/renderer/src/assets/images/providers/moonshot.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
src/renderer/src/assets/images/providers/yi.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
@ -1,7 +0,0 @@
|
||||
<svg width="600" height="600" viewBox="0 0 600 600" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="300" cy="300" r="300" fill="#003425"/>
|
||||
<rect x="409.733" y="340.031" width="42.3862" height="151.648" rx="21.1931" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M422.005 133.354C413.089 125.771 399.714 126.851 392.131 135.767L273.699 275.021C270.643 278.614 268.994 282.932 268.698 287.302C268.532 288.371 268.446 289.466 268.446 290.581V468.603C268.446 480.308 277.934 489.796 289.639 489.796C301.344 489.796 310.832 480.308 310.832 468.603V296.784L424.419 163.228C432.002 154.312 430.921 140.937 422.005 133.354Z" fill="white"/>
|
||||
<rect x="113.972" y="134.25" width="42.3862" height="174.745" rx="21.1931" transform="rotate(-39.3441 113.972 134.25)" fill="white"/>
|
||||
<circle cx="460.126" cy="279.278" r="25.9027" fill="#00FF25"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 865 B |
@ -1,7 +1,7 @@
|
||||
@import './markdown.scss';
|
||||
@import './scrollbar.scss';
|
||||
@import '../fonts/icon-fonts/iconfont.css';
|
||||
@import '../fonts/Ubuntu/Ubuntu.css';
|
||||
@import '../fonts/ubuntu/ubuntu.css';
|
||||
|
||||
:root {
|
||||
--color-white: #ffffff;
|
||||
@ -102,6 +102,14 @@ body[theme-mode='light'] {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
*:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
* {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
@ -175,6 +183,9 @@ body,
|
||||
}
|
||||
|
||||
.minapp-drawer {
|
||||
.ant-drawer-content-wrapper {
|
||||
box-shadow: none;
|
||||
}
|
||||
.ant-drawer-header {
|
||||
position: absolute;
|
||||
-webkit-app-region: drag;
|
||||
|
||||
7
src/renderer/src/components/Icons/CopyIcon.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import { FC } from 'react'
|
||||
|
||||
const CopyIcon: FC = () => {
|
||||
return <i className="iconfont icon-copy" />
|
||||
}
|
||||
|
||||
export default CopyIcon
|
||||
@ -3,28 +3,25 @@ import { isMac, isWindows } from '@renderer/config/constant'
|
||||
import { useBridge } from '@renderer/hooks/useBridge'
|
||||
import store from '@renderer/store'
|
||||
import { setMinappShow } from '@renderer/store/runtime'
|
||||
import { MinAppType } from '@renderer/types'
|
||||
import { Drawer } from 'antd'
|
||||
import { useRef, useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import { TopView } from '../TopView'
|
||||
|
||||
interface ShowParams {
|
||||
title?: string
|
||||
url: string
|
||||
}
|
||||
|
||||
interface Props extends ShowParams {
|
||||
interface Props {
|
||||
app: MinAppType
|
||||
resolve: (data: any) => void
|
||||
}
|
||||
|
||||
const PopupContainer: React.FC<Props> = ({ title, url, resolve }) => {
|
||||
const PopupContainer: React.FC<Props> = ({ app, resolve }) => {
|
||||
const [open, setOpen] = useState(true)
|
||||
const iframeRef = useRef<HTMLIFrameElement>(null)
|
||||
|
||||
useBridge()
|
||||
|
||||
const canOpenExternalLink = url.startsWith('http://') || url.startsWith('https://')
|
||||
const canOpenExternalLink = app.url.startsWith('http://') || app.url.startsWith('https://')
|
||||
|
||||
const onClose = () => {
|
||||
setOpen(false)
|
||||
@ -33,19 +30,19 @@ const PopupContainer: React.FC<Props> = ({ title, url, resolve }) => {
|
||||
|
||||
const onReload = () => {
|
||||
if (iframeRef.current) {
|
||||
iframeRef.current.src = url
|
||||
iframeRef.current.src = app.url
|
||||
}
|
||||
}
|
||||
|
||||
const onOpenLink = () => {
|
||||
window.api.openWebsite(url)
|
||||
window.api.openWebsite(app.url)
|
||||
}
|
||||
|
||||
const Title = () => {
|
||||
return (
|
||||
<TitleContainer style={{ justifyContent: isWindows ? 'flex-start' : 'space-between' }}>
|
||||
<TitleText>{title}</TitleText>
|
||||
<ButtonsGroup>
|
||||
<TitleContainer style={{ justifyContent: 'space-between' }}>
|
||||
<TitleText>{app.name}</TitleText>
|
||||
<ButtonsGroup className={isWindows ? 'windows' : ''}>
|
||||
<Button onClick={onReload}>
|
||||
<ReloadOutlined />
|
||||
</Button>
|
||||
@ -75,7 +72,7 @@ const PopupContainer: React.FC<Props> = ({ title, url, resolve }) => {
|
||||
maskClosable={false}
|
||||
closeIcon={null}
|
||||
style={{ marginLeft: 'var(--sidebar-width)' }}>
|
||||
<Frame src={url} ref={iframeRef} />
|
||||
<Frame src={app.url} ref={iframeRef} />
|
||||
</Drawer>
|
||||
)
|
||||
}
|
||||
@ -84,6 +81,7 @@ const Frame = styled.iframe`
|
||||
width: calc(100vw - var(--sidebar-width));
|
||||
height: calc(100vh - var(--navbar-height));
|
||||
border: none;
|
||||
background-color: white;
|
||||
`
|
||||
|
||||
const TitleContainer = styled.div`
|
||||
@ -113,6 +111,13 @@ const ButtonsGroup = styled.div`
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
-webkit-app-region: no-drag;
|
||||
&.windows {
|
||||
margin-right: ${isWindows ? '130px' : 0};
|
||||
background-color: var(--color-background-mute);
|
||||
border-radius: 50px;
|
||||
padding: 0 3px;
|
||||
overflow: hidden;
|
||||
}
|
||||
`
|
||||
|
||||
const Button = styled.div`
|
||||
@ -139,12 +144,12 @@ export default class MinApp {
|
||||
TopView.hide('MinApp')
|
||||
store.dispatch(setMinappShow(false))
|
||||
}
|
||||
static start(props: ShowParams) {
|
||||
static start(app: MinAppType) {
|
||||
store.dispatch(setMinappShow(true))
|
||||
return new Promise<any>((resolve) => {
|
||||
TopView.show(
|
||||
<PopupContainer
|
||||
{...props}
|
||||
app={app}
|
||||
resolve={(v) => {
|
||||
resolve(v)
|
||||
this.close()
|
||||
|
||||
@ -33,9 +33,9 @@ const Sidebar: FC = () => {
|
||||
<i className="iconfont icon-chat"></i>
|
||||
</Icon>
|
||||
</StyledLink>
|
||||
<StyledLink to="/apps">
|
||||
<Icon className={isRoute('/apps')}>
|
||||
<i className="iconfont icon-appstore"></i>
|
||||
<StyledLink to="/agents">
|
||||
<Icon className={isRoute('/agents')}>
|
||||
<i className="iconfont icon-business-smart-assistant"></i>
|
||||
</Icon>
|
||||
</StyledLink>
|
||||
<StyledLink to="/translate">
|
||||
@ -43,6 +43,11 @@ const Sidebar: FC = () => {
|
||||
<TranslationOutlined />
|
||||
</Icon>
|
||||
</StyledLink>
|
||||
<StyledLink to="/apps">
|
||||
<Icon className={isRoute('/apps')}>
|
||||
<i className="iconfont icon-appstore"></i>
|
||||
</Icon>
|
||||
</StyledLink>
|
||||
</Menus>
|
||||
</MainMenus>
|
||||
<Menus>
|
||||
@ -62,6 +67,7 @@ const Container = styled.div`
|
||||
align-items: center;
|
||||
padding: 8px 0;
|
||||
width: var(--sidebar-width);
|
||||
min-width: var(--sidebar-width);
|
||||
height: ${isMac ? 'calc(100vh - var(--navbar-height))' : '100vh'};
|
||||
-webkit-app-region: drag !important;
|
||||
border-right: 0.5px solid var(--color-border);
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
import BaicuanAppLogo from '@renderer/assets/images/apps/baixiaoying.webp'
|
||||
import KimiAppLogo from '@renderer/assets/images/apps/kimi.jpg'
|
||||
import YuewenAppLogo from '@renderer/assets/images/apps/yuewen.png'
|
||||
import BaichuanModelLogo from '@renderer/assets/images/models/baichuan.png'
|
||||
import ChatGLMModelLogo from '@renderer/assets/images/models/chatglm.jpeg'
|
||||
import ChatGPTModelLogo from '@renderer/assets/images/models/chatgpt.jpeg'
|
||||
@ -14,7 +17,7 @@ import MixtralModelLogo from '@renderer/assets/images/models/mixtral.jpeg'
|
||||
import PalmModelLogo from '@renderer/assets/images/models/palm.svg'
|
||||
import QwenModelLogo from '@renderer/assets/images/models/qwen.png'
|
||||
import StepModelLogo from '@renderer/assets/images/models/step.jpg'
|
||||
import YiModelLogo from '@renderer/assets/images/models/yi.svg'
|
||||
import YiModelLogo from '@renderer/assets/images/models/yi.png'
|
||||
import AiHubMixProviderLogo from '@renderer/assets/images/providers/aihubmix.jpg'
|
||||
import AnthropicProviderLogo from '@renderer/assets/images/providers/anthropic.jpeg'
|
||||
import BaichuanProviderLogo from '@renderer/assets/images/providers/baichuan.png'
|
||||
@ -25,14 +28,14 @@ import GeminiProviderLogo from '@renderer/assets/images/providers/gemini.png'
|
||||
import GraphRagProviderLogo from '@renderer/assets/images/providers/graph-rag.png'
|
||||
import GroqProviderLogo from '@renderer/assets/images/providers/groq.png'
|
||||
import MinimaxProviderLogo from '@renderer/assets/images/providers/minimax.png'
|
||||
import MoonshotProviderLogo from '@renderer/assets/images/providers/moonshot.jpeg'
|
||||
import MoonshotModelLogo from '@renderer/assets/images/providers/moonshot.jpeg'
|
||||
import MoonshotProviderLogo from '@renderer/assets/images/providers/moonshot.jpg'
|
||||
import MoonshotModelLogo from '@renderer/assets/images/providers/moonshot.jpg'
|
||||
import OllamaProviderLogo from '@renderer/assets/images/providers/ollama.png'
|
||||
import OpenAiProviderLogo from '@renderer/assets/images/providers/openai.png'
|
||||
import OpenRouterProviderLogo from '@renderer/assets/images/providers/openrouter.png'
|
||||
import SiliconFlowProviderLogo from '@renderer/assets/images/providers/silicon.png'
|
||||
import StepFunProviderLogo from '@renderer/assets/images/providers/stepfun.png'
|
||||
import YiProviderLogo from '@renderer/assets/images/providers/yi.svg'
|
||||
import YiProviderLogo from '@renderer/assets/images/providers/yi.png'
|
||||
import ZhipuProviderLogo from '@renderer/assets/images/providers/zhipu.png'
|
||||
|
||||
export function getProviderLogo(providerId: string) {
|
||||
@ -126,6 +129,11 @@ export const PROVIDER_CONFIG = {
|
||||
apiKey: 'https://platform.openai.com/api-keys',
|
||||
docs: 'https://platform.openai.com/docs',
|
||||
models: 'https://platform.openai.com/docs/models'
|
||||
},
|
||||
app: {
|
||||
name: 'ChatGPT',
|
||||
url: 'https://chatgpt.com/',
|
||||
logo: OpenAiProviderLogo
|
||||
}
|
||||
},
|
||||
gemini: {
|
||||
@ -138,6 +146,11 @@ export const PROVIDER_CONFIG = {
|
||||
apiKey: 'https://aistudio.google.com/app/apikey',
|
||||
docs: 'https://ai.google.dev/gemini-api/docs',
|
||||
models: 'https://ai.google.dev/gemini-api/docs/models/gemini'
|
||||
},
|
||||
app: {
|
||||
name: 'Gemini',
|
||||
url: 'https://gemini.google.com/',
|
||||
logo: GeminiProviderLogo
|
||||
}
|
||||
},
|
||||
silicon: {
|
||||
@ -150,6 +163,11 @@ export const PROVIDER_CONFIG = {
|
||||
apiKey: 'https://cloud.siliconflow.cn/account/ak?referrer=clxty1xuy0014lvqwh5z50i88',
|
||||
docs: 'https://docs.siliconflow.cn/',
|
||||
models: 'https://docs.siliconflow.cn/docs/model-names'
|
||||
},
|
||||
app: {
|
||||
name: 'SiliconFlow',
|
||||
url: 'https://cloud.siliconflow.cn/playground/chat',
|
||||
logo: SiliconFlowProviderLogo
|
||||
}
|
||||
},
|
||||
deepseek: {
|
||||
@ -162,6 +180,11 @@ export const PROVIDER_CONFIG = {
|
||||
apiKey: 'https://platform.deepseek.com/api_keys',
|
||||
docs: 'https://platform.deepseek.com/api-docs/',
|
||||
models: 'https://platform.deepseek.com/api-docs/'
|
||||
},
|
||||
app: {
|
||||
name: 'DeepSeek',
|
||||
url: 'https://chat.deepseek.com/',
|
||||
logo: DeepSeekProviderLogo
|
||||
}
|
||||
},
|
||||
yi: {
|
||||
@ -174,6 +197,11 @@ export const PROVIDER_CONFIG = {
|
||||
apiKey: 'https://platform.lingyiwanwu.com/apikeys',
|
||||
docs: 'https://platform.lingyiwanwu.com/docs',
|
||||
models: 'https://platform.lingyiwanwu.com/docs#%E6%A8%A1%E5%9E%8B'
|
||||
},
|
||||
app: {
|
||||
name: 'Yi',
|
||||
url: 'https://www.wanzhi.com/',
|
||||
logo: YiProviderLogo
|
||||
}
|
||||
},
|
||||
zhipu: {
|
||||
@ -186,6 +214,11 @@ export const PROVIDER_CONFIG = {
|
||||
apiKey: 'https://open.bigmodel.cn/usercenter/apikeys',
|
||||
docs: 'https://open.bigmodel.cn/dev/howuse/introduction',
|
||||
models: 'https://open.bigmodel.cn/modelcenter/square'
|
||||
},
|
||||
app: {
|
||||
name: '智谱',
|
||||
url: 'https://chatglm.cn/main/alltoolsdetail',
|
||||
logo: ZhipuProviderLogo
|
||||
}
|
||||
},
|
||||
moonshot: {
|
||||
@ -198,6 +231,11 @@ export const PROVIDER_CONFIG = {
|
||||
apiKey: 'https://platform.moonshot.cn/console/api-keys',
|
||||
docs: 'https://platform.moonshot.cn/docs/',
|
||||
models: 'https://platform.moonshot.cn/docs/intro#%E6%A8%A1%E5%9E%8B%E5%88%97%E8%A1%A8'
|
||||
},
|
||||
app: {
|
||||
name: 'Kimi',
|
||||
url: 'https://kimi.moonshot.cn/',
|
||||
logo: KimiAppLogo
|
||||
}
|
||||
},
|
||||
baichuan: {
|
||||
@ -210,6 +248,11 @@ export const PROVIDER_CONFIG = {
|
||||
apiKey: 'https://platform.baichuan-ai.com/console/apikey',
|
||||
docs: 'https://platform.baichuan-ai.com/docs',
|
||||
models: 'https://platform.baichuan-ai.com/price'
|
||||
},
|
||||
app: {
|
||||
name: '百小应',
|
||||
url: 'https://ying.baichuan-ai.com/chat',
|
||||
logo: BaicuanAppLogo
|
||||
}
|
||||
},
|
||||
dashscope: {
|
||||
@ -222,6 +265,11 @@ export const PROVIDER_CONFIG = {
|
||||
apiKey: 'https://help.aliyun.com/zh/dashscope/developer-reference/acquisition-and-configuration-of-api-key',
|
||||
docs: 'https://help.aliyun.com/zh/dashscope/',
|
||||
models: 'https://dashscope.console.aliyun.com/model'
|
||||
},
|
||||
app: {
|
||||
name: '通义千问',
|
||||
url: 'https://tongyi.aliyun.com/qianwen/',
|
||||
logo: QwenModelLogo
|
||||
}
|
||||
},
|
||||
stepfun: {
|
||||
@ -234,6 +282,11 @@ export const PROVIDER_CONFIG = {
|
||||
apiKey: 'https://platform.stepfun.com/interface-key',
|
||||
docs: 'https://platform.stepfun.com/docs/overview/concept',
|
||||
models: 'https://platform.stepfun.com/docs/llm/text'
|
||||
},
|
||||
app: {
|
||||
name: '跃问',
|
||||
url: 'https://yuewen.cn/chats/new',
|
||||
logo: YuewenAppLogo
|
||||
}
|
||||
},
|
||||
doubao: {
|
||||
@ -246,6 +299,11 @@ export const PROVIDER_CONFIG = {
|
||||
apiKey: 'https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey',
|
||||
docs: 'https://www.volcengine.com/docs/82379/1182403',
|
||||
models: 'https://console.volcengine.com/ark/region:ark+cn-beijing/endpoint'
|
||||
},
|
||||
app: {
|
||||
name: '豆包',
|
||||
url: 'https://www.doubao.com/chat/',
|
||||
logo: DoubaoProviderLogo
|
||||
}
|
||||
},
|
||||
minimax: {
|
||||
@ -258,6 +316,11 @@ export const PROVIDER_CONFIG = {
|
||||
apiKey: 'https://platform.minimaxi.com/user-center/basic-information/interface-key',
|
||||
docs: 'https://platform.minimaxi.com/document/Announcement',
|
||||
models: 'https://platform.minimaxi.com/document/Models'
|
||||
},
|
||||
app: {
|
||||
name: '海螺',
|
||||
url: 'https://hailuoai.com/',
|
||||
logo: HailuoModelLogo
|
||||
}
|
||||
},
|
||||
'graphrag-kylin-mountain': {
|
||||
@ -288,6 +351,11 @@ export const PROVIDER_CONFIG = {
|
||||
apiKey: 'https://console.groq.com/keys',
|
||||
docs: 'https://console.groq.com/docs/quickstart',
|
||||
models: 'https://console.groq.com/docs/models'
|
||||
},
|
||||
app: {
|
||||
name: 'Groq',
|
||||
url: 'https://groq.com/',
|
||||
logo: GroqProviderLogo
|
||||
}
|
||||
},
|
||||
ollama: {
|
||||
@ -311,6 +379,11 @@ export const PROVIDER_CONFIG = {
|
||||
apiKey: 'https://console.anthropic.com/settings/keys',
|
||||
docs: 'https://docs.anthropic.com/en/docs',
|
||||
models: 'https://docs.anthropic.com/en/docs/about-claude/models'
|
||||
},
|
||||
app: {
|
||||
name: 'Claude',
|
||||
url: 'https://claude.ai/',
|
||||
logo: AnthropicProviderLogo
|
||||
}
|
||||
},
|
||||
aihubmix: {
|
||||
|
||||
49
src/renderer/src/pages/apps/App.tsx
Normal file
@ -0,0 +1,49 @@
|
||||
import MinApp from '@renderer/components/MinApp'
|
||||
import { useTheme } from '@renderer/providers/ThemeProvider'
|
||||
import { MinAppType } from '@renderer/types'
|
||||
import { FC } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
interface Props {
|
||||
app: MinAppType
|
||||
}
|
||||
|
||||
const App: FC<Props> = ({ app }) => {
|
||||
const { theme } = useTheme()
|
||||
|
||||
const onClick = () => {
|
||||
MinApp.start(app)
|
||||
}
|
||||
|
||||
return (
|
||||
<Container onClick={onClick}>
|
||||
<AppIcon src={app.logo} style={{ border: theme === 'dark' ? 'none' : '1px solid var(--color-border' }} />
|
||||
<AppTitle>{app.name}</AppTitle>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
`
|
||||
|
||||
const AppIcon = styled.img`
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 16px;
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
`
|
||||
|
||||
const AppTitle = styled.div`
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
color: var(--color-text-soft);
|
||||
text-align: center;
|
||||
`
|
||||
|
||||
export default App
|
||||
77
src/renderer/src/pages/apps/AppsPage.tsx
Normal file
@ -0,0 +1,77 @@
|
||||
import AiAssistantAppLogo from '@renderer/assets/images/apps/360-ai.png'
|
||||
import BaiduAiAppLogo from '@renderer/assets/images/apps/baidu-ai.png'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import { PROVIDER_CONFIG } from '@renderer/config/provider'
|
||||
import { MinAppType } from '@renderer/types'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import App from './App'
|
||||
|
||||
const _apps: MinAppType[] = [
|
||||
{
|
||||
name: 'AI 助手',
|
||||
logo: AiAssistantAppLogo,
|
||||
url: 'https://bot.360.com/'
|
||||
},
|
||||
{
|
||||
name: '文心一言',
|
||||
logo: BaiduAiAppLogo,
|
||||
url: 'https://yiyan.baidu.com/'
|
||||
}
|
||||
]
|
||||
|
||||
const AppsPage: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const apps: MinAppType[] = (Object.entries(PROVIDER_CONFIG) as any[])
|
||||
.filter(([, config]) => config.app)
|
||||
.map(([key, config]) => ({ id: key, ...config.app }))
|
||||
.concat(_apps)
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Navbar>
|
||||
<NavbarCenter style={{ borderRight: 'none' }}>{t('agents.title')}</NavbarCenter>
|
||||
</Navbar>
|
||||
<ContentContainer>
|
||||
<AppsContainer>
|
||||
{apps.map((app) => (
|
||||
<App key={app.name} app={app} />
|
||||
))}
|
||||
</AppsContainer>
|
||||
</ContentContainer>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
`
|
||||
|
||||
const ContentContainer = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
background-color: var(--color-background);
|
||||
padding: 50px;
|
||||
`
|
||||
|
||||
const AppsContainer = styled.div`
|
||||
display: flex;
|
||||
min-width: 900px;
|
||||
max-width: 900px;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-start;
|
||||
gap: 50px;
|
||||
`
|
||||
|
||||
export default AppsPage
|
||||
@ -1,5 +1,5 @@
|
||||
import MinApp from '@renderer/components/MinApp'
|
||||
import { Provider } from '@renderer/types'
|
||||
import { MinAppType, Provider } from '@renderer/types'
|
||||
import { Button } from 'antd'
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -19,7 +19,14 @@ const GraphRAGSettings: FC<Props> = ({ provider }) => {
|
||||
const onShowGraphRAG = async () => {
|
||||
const { appPath } = await window.api.getAppInfo()
|
||||
const url = `file://${appPath}/resources/graphrag.html?apiUrl=${apiUrl}&modelId=${modalId}`
|
||||
MinApp.start({ url, title: t('words.knowledgeGraph') })
|
||||
|
||||
const app: MinAppType = {
|
||||
name: t('words.knowledgeGraph'),
|
||||
logo: '',
|
||||
url
|
||||
}
|
||||
|
||||
MinApp.start(app)
|
||||
}
|
||||
|
||||
if (!modalId) {
|
||||
|
||||
@ -1,12 +1,6 @@
|
||||
import {
|
||||
CheckOutlined,
|
||||
CopyOutlined,
|
||||
SendOutlined,
|
||||
SettingOutlined,
|
||||
SwapOutlined,
|
||||
WarningOutlined
|
||||
} from '@ant-design/icons'
|
||||
import { CheckOutlined, SendOutlined, SettingOutlined, SwapOutlined, WarningOutlined } from '@ant-design/icons'
|
||||
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
|
||||
import CopyIcon from '@renderer/components/Icons/CopyIcon'
|
||||
import { useDefaultModel } from '@renderer/hooks/useAssistant'
|
||||
import { fetchTranslate } from '@renderer/services/api'
|
||||
import { getDefaultAssistant } from '@renderer/services/assistant'
|
||||
@ -211,7 +205,7 @@ const TranslatePage: FC = () => {
|
||||
<CopyButton
|
||||
onClick={onCopy}
|
||||
disabled={!result}
|
||||
icon={copied ? <CheckOutlined style={{ color: 'var(--color-primary)' }} /> : <CopyOutlined />}
|
||||
icon={copied ? <CheckOutlined style={{ color: 'var(--color-primary)' }} /> : <CopyIcon />}
|
||||
/>
|
||||
</OutputContainer>
|
||||
</TranslateInputWrapper>
|
||||
|
||||
@ -75,3 +75,9 @@ export type Agent = {
|
||||
export type Suggestion = {
|
||||
content: string
|
||||
}
|
||||
|
||||
export type MinAppType = {
|
||||
name: string
|
||||
logo: string
|
||||
url: string
|
||||
}
|
||||
|
||||