mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-07 18:07:47 +08:00
修复前端调试与基础交互问题
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { createApp, defineComponent, h, nextTick, type App } from 'vue'
|
||||
import { createApp, defineComponent, nextTick, type App } from 'vue'
|
||||
import { createMemoryHistory, createRouter } from 'vue-router'
|
||||
|
||||
import LoginDialog from '../LoginDialog.vue'
|
||||
|
||||
@@ -917,11 +917,6 @@ async function handleSubmit() {
|
||||
}
|
||||
form.value.supported_capabilities = caps.size > 0 ? [...caps] : []
|
||||
|
||||
// 清理空的 config
|
||||
const cleanConfig = form.value.config && Object.keys(form.value.config).length > 0
|
||||
? form.value.config
|
||||
: undefined
|
||||
|
||||
submitting.value = true
|
||||
try {
|
||||
if (isEditMode.value && props.model) {
|
||||
|
||||
@@ -216,8 +216,8 @@
|
||||
|
||||
<Button
|
||||
v-for="action in desktopPostProxyActions"
|
||||
:key="action.key"
|
||||
v-show="hasSelectedProvider"
|
||||
:key="action.key"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
class="h-8 w-8"
|
||||
|
||||
@@ -133,7 +133,10 @@ export function buildPoolProxyDistributionPlan(
|
||||
}
|
||||
|
||||
const assignments = nodeIds.map((nodeId) => {
|
||||
const assignment = mutableAssignments.get(nodeId)!
|
||||
const assignment = mutableAssignments.get(nodeId)
|
||||
if (!assignment) {
|
||||
throw new Error(`Missing proxy distribution assignment for node ${nodeId}`)
|
||||
}
|
||||
const nodeKeys = [...assignment.retainedKeys, ...assignment.assignedKeys]
|
||||
const changedKeys = nodeKeys.filter(key => getKeyProxyNodeId(key) !== nodeId)
|
||||
return {
|
||||
|
||||
@@ -54,8 +54,12 @@
|
||||
<div class="flex items-start gap-2">
|
||||
<AlertTriangle class="mt-0.5 h-4 w-4 flex-shrink-0" />
|
||||
<div class="min-w-0">
|
||||
<p class="font-medium">关联健康加载失败</p>
|
||||
<p class="mt-1 text-xs">{{ errorMessage }}</p>
|
||||
<p class="font-medium">
|
||||
关联健康加载失败
|
||||
</p>
|
||||
<p class="mt-1 text-xs">
|
||||
{{ errorMessage }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
|
||||
@@ -56,6 +56,11 @@ const props = withDefaults(defineProps<{
|
||||
entityLabel?: string
|
||||
entityName?: string | null
|
||||
}>(), {
|
||||
timeline: null,
|
||||
timelineDetails: null,
|
||||
timeRangeStart: null,
|
||||
timeRangeEnd: null,
|
||||
generatedAt: null,
|
||||
lookbackHours: 6,
|
||||
fallbackSegments: 60,
|
||||
entityLabel: '',
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<Card variant="default" class="overflow-hidden">
|
||||
<Card
|
||||
variant="default"
|
||||
class="overflow-hidden"
|
||||
>
|
||||
<HealthMonitorHeader
|
||||
v-model:lookback-hours="lookbackHours"
|
||||
:title="title"
|
||||
@@ -23,10 +26,15 @@
|
||||
>
|
||||
<Bot class="w-12 h-12 mb-3 opacity-30" />
|
||||
<p>暂无模型健康监控数据</p>
|
||||
<p class="text-xs mt-1">模型尚未产生请求记录</p>
|
||||
<p class="text-xs mt-1">
|
||||
模型尚未产生请求记录
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
|
||||
<div
|
||||
v-else
|
||||
class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4"
|
||||
>
|
||||
<div
|
||||
v-for="monitor in monitors"
|
||||
:key="monitor.model"
|
||||
@@ -46,7 +54,10 @@
|
||||
{{ monitor.display_name || monitor.model }}
|
||||
</h4>
|
||||
</div>
|
||||
<Badge :variant="getHealthBadgeVariant(monitor)" class="shrink-0">
|
||||
<Badge
|
||||
:variant="getHealthBadgeVariant(monitor)"
|
||||
class="shrink-0"
|
||||
>
|
||||
{{ getHealthLabel(monitor) }}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
@@ -597,9 +597,9 @@
|
||||
: 'text-muted-foreground hover:text-foreground'"
|
||||
:disabled="importing"
|
||||
@click="setWindsurfImportMethod(method.key)"
|
||||
>
|
||||
{{ legacyT(method.label) }}
|
||||
</button>
|
||||
>
|
||||
{{ legacyT(method.label) }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
|
||||
@@ -135,8 +135,6 @@ import { formatBillingType } from '@/utils/format'
|
||||
import type { BalanceExtraItem } from '@/features/providers/auth-templates'
|
||||
import { useI18n } from '@/i18n'
|
||||
|
||||
const { legacyT } = useI18n()
|
||||
|
||||
defineProps<{
|
||||
provider: ProviderWithEndpointsSummary
|
||||
isBalanceLoading: (providerId: string) => boolean
|
||||
@@ -150,4 +148,6 @@ defineProps<{
|
||||
formatResetCountdown: (resetsAt: number) => string
|
||||
getQuotaUsedColorClass: (provider: ProviderWithEndpointsSummary) => string
|
||||
}>()
|
||||
|
||||
const { legacyT } = useI18n()
|
||||
</script>
|
||||
|
||||
@@ -948,7 +948,6 @@ import {
|
||||
canExportOAuthCredential,
|
||||
canRefreshOAuthCredential,
|
||||
isOAuthManagedCredential,
|
||||
isServiceAccountCredential,
|
||||
getProviderMaskedSecretLabel,
|
||||
shouldShowOAuthRefreshControl,
|
||||
} from '@/utils/providerKeyAuth'
|
||||
@@ -1302,14 +1301,6 @@ async function toggleFormatConversion() {
|
||||
}
|
||||
}
|
||||
|
||||
// Provider 级别代理配置
|
||||
function handleProviderProxyPopoverToggle(open: boolean) {
|
||||
providerProxyPopoverOpen.value = open
|
||||
if (open) {
|
||||
proxyNodesStore.ensureLoaded()
|
||||
}
|
||||
}
|
||||
|
||||
function getProviderProxyNodeName(): string {
|
||||
const nodeId = provider.value?.proxy?.node_id
|
||||
if (!nodeId) return legacyT('未知节点')
|
||||
|
||||
@@ -124,7 +124,7 @@ import {
|
||||
summarizeHealthMonitorItems
|
||||
} from './health-monitor-utils'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
withDefaults(defineProps<{
|
||||
title?: string
|
||||
}>(), {
|
||||
title: '提供商健康监控'
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable vue/one-component-per-file, vue/require-default-prop */
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { createApp, nextTick, type App } from 'vue'
|
||||
import OAuthAccountDialog from '@/features/providers/components/OAuthAccountDialog.vue'
|
||||
|
||||
@@ -1496,7 +1496,7 @@ const formatConversionPair = (source: string, target: string): string =>
|
||||
`${formatApiFormat(source.trim())} → ${formatApiFormat(target.trim())}`
|
||||
|
||||
const extractFieldDetail = (message: string): string => {
|
||||
const fieldMatch = message.match(/field\s+([^;=]+?)\s*=\s*(\"(?:\\.|[^"\\])*\"|[^;]+)/i)
|
||||
const fieldMatch = message.match(/field\s+([^;=]+?)\s*=\s*("(?:\\.|[^"\\])*"|[^;]+)/i)
|
||||
const unsupportedFieldMatch = message.match(/field\s+([^;]+?)\s+is unsupported/i)
|
||||
if (fieldMatch?.[1]) {
|
||||
return `字段 ${normalizeDiagnosticFieldPath(fieldMatch[1])} = ${fieldMatch[2].trim()}`
|
||||
|
||||
@@ -876,7 +876,7 @@ import Skeleton from '@/components/ui/skeleton.vue'
|
||||
import Tabs from '@/components/ui/tabs.vue'
|
||||
import TabsContent from '@/components/ui/tabs-content.vue'
|
||||
import { AlertTriangle, Check, Columns2, RefreshCw, X, Monitor, Server, MessageSquareText, Code2, Terminal, Play } from 'lucide-vue-next'
|
||||
import { dashboardApi, type RequestDetail, type RequestErrorDomain } from '@/api/dashboard'
|
||||
import { dashboardApi, type RequestDetail } from '@/api/dashboard'
|
||||
import type { ImageProgress, RequestTrace } from '@/api/requestTrace'
|
||||
import { formatApiFormat } from '@/api/endpoints/types/api-format'
|
||||
import {
|
||||
@@ -889,7 +889,6 @@ import { log } from '@/utils/logger'
|
||||
import { getEffectiveInputTokens } from '../token-normalization'
|
||||
import {
|
||||
formatDurationMs,
|
||||
formatOutputRate,
|
||||
formatOutputRateValue,
|
||||
getDisplayOutputRate,
|
||||
} from '../performance'
|
||||
@@ -1006,15 +1005,6 @@ type JsonRecord = Record<string, unknown>
|
||||
|
||||
const METADATA_BYTE_FIELD_PATTERN = /(^bytes$|_bytes$|bytes$)/i
|
||||
|
||||
type NormalizedErrorDomain = {
|
||||
source?: string | null
|
||||
status_code?: number | null
|
||||
type?: string | null
|
||||
message: string
|
||||
code?: string | number | null
|
||||
category?: string | null
|
||||
}
|
||||
|
||||
function asRecord(value: unknown): JsonRecord | null {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) return null
|
||||
return value as JsonRecord
|
||||
@@ -1043,28 +1033,6 @@ function formatMetadataDisplayValue(value: unknown, key = ''): unknown {
|
||||
return value
|
||||
}
|
||||
|
||||
function normalizeErrorDomain(domain: RequestErrorDomain | null | undefined): NormalizedErrorDomain | null {
|
||||
if (!domain || typeof domain !== 'object') return null
|
||||
const message = typeof domain.message === 'string' ? domain.message.trim() : ''
|
||||
if (!message) return null
|
||||
return {
|
||||
source: domain.source ?? null,
|
||||
status_code: domain.status_code ?? null,
|
||||
type: domain.type ?? null,
|
||||
message,
|
||||
code: domain.code ?? null,
|
||||
category: domain.category ?? null,
|
||||
}
|
||||
}
|
||||
|
||||
function formatErrorDomainMeta(domain: NormalizedErrorDomain): string {
|
||||
const parts: string[] = []
|
||||
if (domain.status_code != null) parts.push(`HTTP ${domain.status_code}`)
|
||||
if (domain.type) parts.push(domain.type)
|
||||
if (domain.source) parts.push(`source=${domain.source}`)
|
||||
return parts.join(' · ')
|
||||
}
|
||||
|
||||
function mapTraceFinalStatusToRequestStatus(
|
||||
status?: RequestTrace['final_status'] | null
|
||||
): RequestStateStatus | undefined {
|
||||
|
||||
@@ -674,16 +674,18 @@ export class OpenAIParser implements ApiFormatParser {
|
||||
: typeof chunk.delta === 'string'
|
||||
? chunk.delta
|
||||
: null
|
||||
if (key && toolCalls.has(key) && args != null) {
|
||||
toolCalls.get(key)!.args = [args]
|
||||
const toolCall = key ? toolCalls.get(key) : undefined
|
||||
if (toolCall && args != null) {
|
||||
toolCall.args = [args]
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (eventType === 'response.custom_tool_call_input.done') {
|
||||
const key = resolveToolKey(chunk)
|
||||
if (key && toolCalls.has(key) && typeof chunk.input === 'string') {
|
||||
toolCalls.get(key)!.args = [chunk.input]
|
||||
const toolCall = key ? toolCalls.get(key) : undefined
|
||||
if (toolCall && typeof chunk.input === 'string') {
|
||||
toolCall.args = [chunk.input]
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
</Badge>
|
||||
<span
|
||||
v-else
|
||||
class="font-semibold tabular-nums"
|
||||
:class="[
|
||||
mobile ? 'text-base leading-none' : 'text-sm',
|
||||
'font-semibold tabular-nums',
|
||||
row.isNegativeBalance ? 'text-rose-600' : 'text-foreground',
|
||||
]"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user