diff --git a/src/components/logs/AiCallLogPanel.vue b/src/components/logs/AiCallLogPanel.vue index 9c024f4..e8d7944 100644 --- a/src/components/logs/AiCallLogPanel.vue +++ b/src/components/logs/AiCallLogPanel.vue @@ -69,7 +69,7 @@ function statusCell(row: AiCallLog) { function tokensCell(row: AiCallLog) { if (row.errMsg && !row.totalTokens) return h('span', { class: 'text-[13px] text-ink-3' }, '—') const flow = row.stream ? ' · 流' : '' - return h('span', { class: 'mono text-[13px]' }, `${row.promptTokens} / ${row.completionTokens}${flow}`) + return h('span', { class: 'mono text-[13px] whitespace-nowrap' }, `${row.promptTokens} / ${row.completionTokens}${flow}`) } const columns: DataTableColumns = [ @@ -79,7 +79,7 @@ const columns: DataTableColumns = [ { title: '模型', key: 'model', minWidth: 220, ellipsis: { tooltip: true }, render: (r) => h('span', { class: 'mono text-xs' }, r.model) }, { title: '渠道', key: 'channelName', minWidth: 180, ellipsis: { tooltip: true }, render: (r) => h('span', { class: 'text-[13px]' }, r.channelName || '—') }, { title: '状态', key: 'status', width: 80, render: statusCell }, - { title: 'Tokens(入/出)', key: 'tokens', width: 150, render: tokensCell }, + { title: 'Tokens(入/出)', key: 'tokens', width: 190, render: tokensCell }, { title: '耗时', key: 'latencyMs', width: 80, render: (r) => h('span', { class: 'mono text-[13px]' }, fmtLatency(r.latencyMs)) }, { title: '重试', key: 'retries', width: 60, render: (r) => h('span', { class: 'mono text-[13px]' }, String(r.retries)) }, ] diff --git a/src/components/proxy/ProxyPanel.vue b/src/components/proxy/ProxyPanel.vue index 0f07bc3..921713b 100644 --- a/src/components/proxy/ProxyPanel.vue +++ b/src/components/proxy/ProxyPanel.vue @@ -190,6 +190,13 @@ function renderGeo(row: ProxyInfo) { return h('span', { class: 'text-[13px]' }, row.city ? `${row.country}·${row.city}` : row.country) } +/** 状态单元格:与地区探测同源 —— 探测经该代理链路发起,失败即代理不可用 */ +function renderStatus(row: ProxyInfo) { + if (!row.geoAt) return h(StatusBadge, { kind: 'check', label: '检测中' }) + const ok = !!row.country + return h(StatusBadge, { kind: ok ? 'run' : 'term', label: ok ? '正常' : '异常' }) +} + // 新增 / 批量导入入口由页面标题行触发(ProxyListView),这里暴露打开方法 defineExpose({ openCreate, openImport }) @@ -215,6 +222,7 @@ const columns: DataTableColumns = [ render: (row) => h('span', { class: 'mono text-[12.5px] text-ink-2' }, `${row.host}:${row.port}`), }, { title: '地区', key: 'geo', minWidth: 120, render: renderGeo }, + { title: '状态', key: 'status', width: 88, render: renderStatus }, { title: '认证', key: 'username', @@ -272,7 +280,7 @@ const columns: DataTableColumns = [ :row-key="(r: ProxyInfo) => r.id" /> - 支持 SOCKS5 / HTTP / HTTPS;密码 AES 加密存储、不回显明文;地区为经代理实测的出口位置(ip-api.com),创建后自动检测;被租户关联的代理不可删除,请先解除关联 + 支持 SOCKS5 / HTTP / HTTPS;密码 AES 加密存储、不回显明文;地区与状态为经代理实测的出口探测结果(ip-api.com),创建后自动检测,探测失败即视为异常,可点「重测」复查;被租户关联的代理不可删除,请先解除关联 ({ streamGuardKB: 60, grokWebSearch: true, grokXSearch: true, + upstreamWaitSeconds: 300, }) watch( @@ -58,6 +59,12 @@ function commitGuardKB(v: number | null) { setField('streamGuardKB', v) } +/** 上游无响应预算失焦/回车提交 */ +function commitUpstreamWait(v: number | null) { + if (v == null || v === form.upstreamWaitSeconds) return + setField('upstreamWaitSeconds', v) +} + const removing = ref(0) async function doRemove(id: number, name: string) { removing.value = id @@ -83,15 +90,15 @@ function onBlacklistChanged() {
- +
-
流式保险丝
+
Responses 直通
-
+
-
instructions + tools 阈值
+
流式保险丝:instructions + tools 阈值
系统提示与工具定义合计超过阈值的流式请求,预防性改走非流式上游并合成 SSE:丢增量输出,保会话不中断 @@ -119,6 +126,31 @@ function onBlacklistChanged() { />
+
+
+
上游无响应预算
+
+ 非流式为单次尝试总超时,流式为等待响应头上限,响应头到达后不限制流时长; + multi-agent / 搜索类模型单次调用可达 3 分钟,建议 ≥300 秒 +
+
+
+ + + + +
+
修改即时生效,无需重启 · 仅作用于 Responses 直通面;Chat / Messages 已有断流自动重做兜底 diff --git a/src/types/api.ts b/src/types/api.ts index fd04386..170d0a7 100644 --- a/src/types/api.ts +++ b/src/types/api.ts @@ -986,6 +986,8 @@ export interface AiSettings { /** grok(xai. 前缀)服务端搜索工具默认注入;请求已带同名工具时不覆盖 */ grokWebSearch: boolean grokXSearch: boolean + /** 上游无响应预算(秒):非流式为单次尝试总超时,流式为等待响应头上限;限 30..900 */ + upstreamWaitSeconds: number } /** 聚合模型目录条目(黑名单添加弹窗):能力为 CHAT / EMBEDDING / RERANK / TTS */