Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions frontend/src/api/modules/ai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,13 @@ export const updateAgentAccount = (req: AI.AgentAccountUpdateReq) => {
return http.post(`/ai/agents/accounts/update`, req);
};

export const pageAgentAccounts = (req: AI.AgentAccountSearch) => {
return http.post<ResPage<AI.AgentAccountItem>>(`/ai/agents/accounts/search`, req);
export const pageAgentAccounts = (req: AI.AgentAccountSearch, currentNode?: string) => {
return http.post<ResPage<AI.AgentAccountItem>>(
`/ai/agents/accounts/search`,
req,
undefined,
currentNode ? { CurrentNode: currentNode } : undefined,
);
};

export const getAgentAccountModels = (req: AI.AgentAccountModelReq) => {
Expand Down
Binary file added frontend/src/assets/images/ai-providers/aliyun.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/images/ai-providers/deepseek.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions frontend/src/assets/images/ai-providers/kimi.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions frontend/src/assets/images/ai-providers/openai.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions frontend/src/assets/images/ai-providers/vllm.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file added frontend/src/assets/images/ai-providers/zai.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 56 additions & 0 deletions frontend/src/components/agent-provider-logo/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<template>
<span class="agent-provider-logo" :style="logoStyle" :aria-label="`${displayName || provider} logo`" role="img">
<img v-if="logo.src" class="agent-provider-logo__image" :src="logo.src" :alt="displayName || provider" />
<span v-else>{{ logo.mark }}</span>
</span>
</template>

<script setup lang="ts">
import { computed } from 'vue';
import { getAgentProviderLogo } from '@/utils/agent-provider-logo';

const props = withDefaults(
defineProps<{
provider: string;
displayName?: string;
size?: number;
}>(),
{
displayName: '',
size: 16,
},
);

const logo = computed(() => getAgentProviderLogo(props.provider, props.displayName));
const logoStyle = computed(() => ({
width: `${props.size}px`,
height: `${props.size}px`,
minWidth: `${props.size}px`,
background: logo.value.background,
color: logo.value.color,
fontSize: `${Math.max(10, Math.floor(props.size * 0.48))}px`,
}));
</script>

<style scoped lang="scss">
.agent-provider-logo {
display: inline-flex;
align-items: center;
justify-content: center;
font-weight: 700;
line-height: 1;
letter-spacing: 0;
user-select: none;
overflow: hidden;
box-sizing: border-box;
vertical-align: middle;
flex: 0 0 auto;
}

.agent-provider-logo__image {
display: block;
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
</style>
9 changes: 2 additions & 7 deletions frontend/src/components/mkdown-editor/index.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
<template>
<MdEditor
previewOnly
:model-value="props.content"
:sanitize="sanitizeHtml"
:theme="isDarkTheme ? 'dark' : 'light'"
/>
<MdPreview :model-value="props.content" :sanitize="sanitizeHtml" :theme="isDarkTheme ? 'dark' : 'light'" />
</template>

<script lang="ts" setup>
import { MdEditor } from 'md-editor-v3';
import { MdPreview } from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
import DOMPurify from 'dompurify';

Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,7 @@ const message = {
failedRequests: 'Failed Requests',
averageTokenPerRequest: 'Avg Tokens/Request',
callLogs: 'Call Logs',
usageKeywordPlaceholder: 'Search Request ID / model / upstream model / error message',
attemptChain: 'Attempt Chain',
attemptIndex: 'Call Order',
noAttemptDetails: 'This request hit once; no fallback details',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/es-es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,7 @@ const message = {
failedRequests: 'Solicitudes fallidas',
averageTokenPerRequest: 'Tokens promedio/solicitud',
callLogs: 'Registros de llamadas',
usageKeywordPlaceholder: 'Buscar Request ID / modelo / modelo upstream / mensaje de error',
attemptChain: 'Cadena de intentos',
attemptIndex: 'Orden de llamada',
noAttemptDetails: 'Esta solicitud acertó en el primer intento; no hay detalles de fallback',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,7 @@ const message = {
failedRequests: '失敗リクエスト',
averageTokenPerRequest: '平均 Token/リクエスト',
callLogs: '呼び出しログ',
usageKeywordPlaceholder: 'Request ID / モデル / 上流モデル / エラーメッセージを検索',
attemptChain: '試行チェーン',
attemptIndex: '呼び出し順',
noAttemptDetails: 'このリクエストは 1 回で命中しました。fallback 明細はありません',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -957,6 +957,7 @@ const message = {
failedRequests: '실패한 요청',
averageTokenPerRequest: '평균 Token/요청',
callLogs: '호출 로그',
usageKeywordPlaceholder: 'Request ID / 모델 / 업스트림 모델 / 오류 메시지 검색',
attemptChain: '시도 체인',
attemptIndex: '호출 순서',
noAttemptDetails: '이 요청은 한 번에 적중했으며 fallback 상세가 없습니다',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/ms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -982,6 +982,7 @@ const message = {
failedRequests: 'Permintaan gagal',
averageTokenPerRequest: 'Purata Token/permintaan',
callLogs: 'Log panggilan',
usageKeywordPlaceholder: 'Cari Request ID / model / model upstream / mesej ralat',
attemptChain: 'Rantaian percubaan',
attemptIndex: 'Urutan panggilan',
noAttemptDetails: 'Permintaan ini berjaya sekali percubaan; tiada butiran fallback',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/pt-br.ts
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,7 @@ const message = {
failedRequests: 'Requisições com falha',
averageTokenPerRequest: 'Média de Token/requisição',
callLogs: 'Logs de chamadas',
usageKeywordPlaceholder: 'Pesquisar Request ID / modelo / modelo upstream / mensagem de erro',
attemptChain: 'Cadeia de tentativas',
attemptIndex: 'Ordem de chamada',
noAttemptDetails: 'Esta requisição acertou na primeira tentativa; sem detalhes de fallback',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,7 @@ const message = {
failedRequests: 'Неуспешные запросы',
averageTokenPerRequest: 'Среднее Token/запрос',
callLogs: 'Журнал вызовов',
usageKeywordPlaceholder: 'Поиск по Request ID / модели / upstream-модели / сообщению об ошибке',
attemptChain: 'Цепочка попыток',
attemptIndex: 'Порядок вызова',
noAttemptDetails: 'Запрос выполнен с первой попытки, деталей fallback нет',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/tr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,7 @@ const message = {
failedRequests: 'Başarısız istekler',
averageTokenPerRequest: 'Ortalama Token/istek',
callLogs: 'Çağrı günlükleri',
usageKeywordPlaceholder: 'Request ID / model / upstream model / hata mesajı ara',
attemptChain: 'Deneme zinciri',
attemptIndex: 'Çağrı sırası',
noAttemptDetails: 'Bu istek tek denemede isabet etti; fallback ayrıntısı yok',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/zh-Hant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,7 @@ const message = {
failedRequests: '失敗請求',
averageTokenPerRequest: '平均 Token/請求',
callLogs: '呼叫日誌',
usageKeywordPlaceholder: '搜尋 Request ID / 模型 / 上游模型 / 錯誤資訊',
attemptChain: '呼叫鏈路',
attemptIndex: '調用順序',
noAttemptDetails: '本次請求一次命中,無 fallback 明細',
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,7 @@ const message = {
failedRequests: '失败请求',
averageTokenPerRequest: '平均 Token/请求',
callLogs: '调用日志',
usageKeywordPlaceholder: '搜索 Request ID / 模型 / 上游模型 / 错误信息',
attemptChain: '调用链路',
attemptIndex: '调用顺序',
noAttemptDetails: '本次请求一次命中,无 fallback 明细',
Expand Down
168 changes: 168 additions & 0 deletions frontend/src/utils/agent-provider-logo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
export interface AgentProviderLogo {
src?: string;
mark: string;
background: string;
color: string;
borderColor?: string;
source?: string;
}

const asset = (name: string) => new URL(`../assets/images/ai-providers/${name}`, import.meta.url).href;

const providerLogos: Record<string, AgentProviderLogo> = {
ollama: {
src: asset('ollama.webp'),
mark: 'OL',
background: '#ffffff',
color: '#111827',
borderColor: '#dcdfe6',
source: 'https://github.com/ollama/ollama/blob/main/docs/ollama-logo.svg',
},
vllm: {
src: asset('vllm.svg'),
mark: 'v',
background: '#ffffff',
color: '#4338ca',
borderColor: '#dcdfe6',
source: 'https://vllm.ai/vLLM-Logo.svg',
},
deepseek: {
src: asset('deepseek.png'),
mark: 'DS',
background: '#ffffff',
color: '#4d6bfe',
borderColor: '#dcdfe6',
source: 'https://cdn.deepseek.com/logo.png',
},
'bailian-coding-plan': {
src: asset('aliyun.webp'),
mark: 'QW',
background: '#ffffff',
color: '#ff6a00',
borderColor: '#dcdfe6',
source: 'https://www.alibabacloud.com/',
},
'ark-coding-plan': {
src: asset('volcengine.png'),
mark: 'AR',
background: '#ffffff',
color: '#1664ff',
borderColor: '#dcdfe6',
source: 'https://www.volcengine.com/',
},
zai: {
src: asset('zai.webp'),
mark: 'Z',
background: '#ffffff',
color: '#111827',
borderColor: '#dcdfe6',
source: 'https://z.ai/',
},
minimax: {
src: asset('minimax.ico'),
mark: 'MM',
background: '#ffffff',
color: '#2563eb',
borderColor: '#dcdfe6',
source: 'https://www.minimax.io/',
},
xiaomi: {
src: asset('xiaomi.ico'),
mark: 'MI',
background: '#ffffff',
color: '#ff6900',
borderColor: '#dcdfe6',
source: 'https://www.mi.com/favicon.ico',
},
kimi: {
src: asset('kimi.svg'),
mark: 'KM',
background: '#ffffff',
color: '#111827',
borderColor: '#dcdfe6',
source: 'https://moonshotai.github.io/Branding-Guide/',
},
'kimi-coding': {
src: asset('kimi.svg'),
mark: 'KC',
background: '#ffffff',
color: '#111827',
borderColor: '#dcdfe6',
source: 'https://moonshotai.github.io/Branding-Guide/',
},
openai: {
src: asset('openai.svg'),
mark: 'AI',
background: '#ffffff',
color: '#111827',
borderColor: '#dcdfe6',
source: 'https://openai.com/brand/',
},
openrouter: {
src: asset('openrouter.png'),
mark: 'OR',
background: '#ffffff',
color: '#101828',
borderColor: '#dcdfe6',
source: 'https://openrouter.ai/',
},
anthropic: {
src: asset('anthropic.png'),
mark: 'A',
background: '#ffffff',
color: '#141413',
borderColor: '#dcdfe6',
source: 'https://www.anthropic.com/',
},
gemini: {
src: asset('gemini.webp'),
mark: 'G',
background: '#ffffff',
color: '#1a73e8',
borderColor: '#dcdfe6',
source: 'https://gemini.google.com/',
},
moonshot: {
src: asset('kimi.svg'),
mark: 'MS',
background: '#ffffff',
color: '#111827',
borderColor: '#dcdfe6',
source: 'https://moonshotai.github.io/Branding-Guide/',
},
};

const fallbackLogo: AgentProviderLogo = {
mark: 'AI',
background: '#f5f7fa',
color: '#606266',
borderColor: '#dcdfe6',
};

const normalizeProvider = (provider?: string) =>
String(provider || '')
.trim()
.toLowerCase();

const buildFallbackMark = (provider?: string, displayName?: string) => {
const source = String(displayName || provider || '').trim();
const asciiWords = source.match(/[a-zA-Z0-9]+/g) || [];
if (asciiWords.length >= 2) {
return `${asciiWords[0][0]}${asciiWords[1][0]}`.toUpperCase();
}
if (asciiWords.length === 1) {
return asciiWords[0].slice(0, 2).toUpperCase();
}
return fallbackLogo.mark;
};

export const getAgentProviderLogo = (provider?: string, displayName?: string): AgentProviderLogo => {
const logo = providerLogos[normalizeProvider(provider)];
if (logo) {
return logo;
}
return {
...fallbackLogo,
mark: buildFallbackMark(provider, displayName),
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
import { reactive, ref } from 'vue';
import type { FormInstance } from 'element-plus';
import { ElMessageBox } from 'element-plus';
import { useMenuManagePermission } from '@/composables/useMenuManagePermission';
import { useI18n } from 'vue-i18n';
import { AI } from '@/api/interface/ai';
import { approveAgentChannelPairing, getAgentDiscordConfig, updateAgentDiscordConfig } from '@/api/modules/ai';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@
import { reactive, ref } from 'vue';
import type { FormInstance } from 'element-plus';
import { ElMessageBox } from 'element-plus';
import { useMenuManagePermission } from '@/composables/useMenuManagePermission';
import { useI18n } from 'vue-i18n';
import { AI } from '@/api/interface/ai';
import { approveAgentChannelPairing, getAgentTelegramConfig, updateAgentTelegramConfig } from '@/api/modules/ai';
Expand Down
Loading
Loading