Commit Graph
16 Commits
Author SHA1 Message Date
chihao.ou 21323c31f8 fix(monitor): support upstream base URL paths 2026-09-09 20:02:25 +08:00
刘佳林 19382f275e feat(minimax): 增加 MiniMax 平台支持
把 MiniMax 做成与 Kimi / 智谱 / DeepSeek 同级的国产供应商平台:账号创建/编辑、分组、Composite 路由、原生 Token Plan / Coding Plan 额度,以及 OpenAI 兼容模型列表。

额度走 GET api.minimaxi.com|io /v1/api/openplatform/coding_plan/remains(Bearer)。只解析 model_name=general 的 remaining percent;周窗口仅在 current_weekly_status=1 时计入。

Related to #6742
2026-09-07 18:22:56 +08:00
Randark c41ae19e52 fix(monitor): reject unusable quota data sources and invalid mode combos at write time
P2-2/P2-4/P2-5 from review:

- validateLinkedAccount/revalidateLinkedAccount now check
  monitorAccountQuotaCapability after the platform match, blocking combos
  that would permanently error at runtime: deepseek coding and
  custom-domain kimi coding (no quota endpoint), zhipu payg (no balance
  endpoint), anthropic/openai API-Key accounts (usage query requires
  oauth; anthropic setup-token still allowed via local estimation).
  gemini/grok/antigravity stay permissive. Quota mode surfaces
  CHANNEL_MONITOR_ACCOUNT_NOT_SUPPORTABLE on edit; probe mode silently
  unbinds (same as platform mismatch).
- applyMonitorUpdate re-runs validateCheckMode on the effective
  provider+check_mode whenever either field is patched, so a
  provider-only update can no longer persist antigravity+probe (the
  check is conditioned on provider/check_mode presence so legacy illegal
  rows can still be renamed/disabled).
- normalizeMonitorPrimaryModel only substitutes the "quota" placeholder
  for pure quota mode; quota_probe with an empty model now fails with
  MissingPrimaryModel instead of probing model="quota". The quota branch
  also moves ahead of the grok default, so grok+quota now gets "quota"
  rather than "grok-4.5" (review L-item).

Tests: capability matrix (15 cases incl. anti-over-blocking rows),
linked-account wiring, revalidate quota/probe split, provider-only
update bypass + legacy-row rename, quota_probe missing-model create,
normalize matrix.
2026-08-18 10:28:28 +00:00
Randark 22df600d09 fix(channel-monitor): 配额快照识别值通道失败并加 60s 负缓存与 singleflight
- fetchUsage 显式识别 UsageInfo.Error/ErrorCode/NeedsReauth/IsBanned/IsForbidden
  (antigravity/grok 等平台失败不走 Go error 通道,此前会被误判为 operational)
- 凭据失效语义(401/403)标记 CredentialInvalid → failed 状态;
  grok quota_unknown 已知未知态豁免不判失败
- 失败快照进 60s 负缓存,避免故障/凭据失效期间以最小 15s 间隔打上游
- 同账号并发抓取由 singleflight 合并(脱离调用方 ctx,45s 总超时兜底)
2026-08-18 09:14:20 +00:00
Randark 7376f4a48c fix(lint): gofmt 对齐 + 移除未使用的 isSupportedProvider
- 三个文件补 gofmt 规范对齐(结构体尾部注释、const 块字段对齐)
- isSupportedProvider 在 validateProvider 改用能力集合后无引用,删除
2026-08-18 05:57:41 +00:00
Randark c44711ac98 feat(channel-monitor): quota mode service layer (fetcher + dispatch + repo)
- 常量:MonitorProvider{Antigravity,Kimi,Zhipu,Deepseek}、MonitorCheckMode 三态、
  配额缓存/告警阈值参数;新增 check_mode 相关业务错误
- 校验:monitorProviders(8)/probeCapableProviders(7) 集合替代 adapter 表判定,
  validateCheckMode 矩阵(antigravity 仅 quota);quota 模式 primary_model
  默认占位 "quota",endpoint/api_key 条件必填
- checker:kimi/deepseek 复用 /v1/chat/completions、zhipu 走
  /api/paas/v4/chat/completions;merge 黑名单与 replace 校验同步扩容
- ChannelMonitorQuotaFetcher:窄接口聚合账号侧三个用量服务 + 账号加载,
  归一为 domain.MonitorQuotaSnapshot;成功快照 5min TTL 缓存防配额端点风暴;
  Fetch 永不返回 error(失败降级 Success=false 快照);状态推导
  operational/degraded(≥90% 或余额耗尽/账号未关联)/failed(401/403)/error
- RunCheck 按 check_mode 分派:quota 单行结果、quota_probe 探活+配额挂主行、
  probe 不变;Update 组合校验 + 关联账号复核(probe 自动解绑失效账号);
  Duplicate 拷贝新字段且 quota 模式空明文重加密(防 runner 误停摆)
- repo:Create/Update/entToServiceMonitor 透传 check_mode/account_id;
  InsertHistoryBatch 写 quota;ListLatestForMonitorIDs 裸 SQL 加 quota 列 +
  scanMonitorQuota JSONB 解包(NULL 安全);ListHistory 透传 quota
2026-08-18 04:03:13 +00:00
IanShaw027 ead73264c7 feat(channel-monitor-v2): 实现被动聚合、分层保留与只读 API
基于 usage_logs/ops_error_logs 做分钟聚合与 5m/1h/12h/1d rollup,提供
snapshot/matrix/errors/users 等接口;V1 在 mode=v2 时停用主动探测,
并对用户端按需脱敏绝对量与 RPM/TPM。
2026-08-07 11:05:32 +08:00
superman2003 0a64a6d8ce feat(monitor): support Grok channel health checks 2026-07-14 12:24:42 +08:00
bwlcandClaude Fable 5 c70c6a2659 feat(渠道监控): 检测间隔支持正负随机抖动配置
新增 jitter_seconds 配置:每轮调度在 interval 基础上 ± [0, jitter]
均匀随机偏移触发,避免多个监控以固定节奏同步请求上游。

- ent schema 新增 jitter_seconds 字段(默认 0),附迁移 151
- 校验:jitter >= 0 且 interval - jitter >= 15s(创建/更新均校验)
- runner 由固定 ticker 改为每轮重新随机化的 timer,0 抖动时行为不变
- 前端监控表单新增「随机抖动 (± 秒)」输入框,上限随间隔联动

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 22:09:53 +08:00
benjaminandSisyphus 9055612ddc feat(channel-monitor): 定义 OpenAI API 模式基础类型
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-19 22:05:43 +08:00
erio c2f9ad7a21 refactor(channel-monitor): event-driven scheduler + sidebar cleanup
后端 - ChannelMonitorRunner 重写为事件驱动调度
- 删除 5 秒轮询架构(每次 ListEnabled + listDueForCheck 全表扫描),
  改为每个 enabled monitor 一个独立 goroutine + ticker(按各自 IntervalSeconds)
- 新增 MonitorScheduler 接口,service 通过 setter 注入避免依赖环
- ChannelMonitorService.Create/Update/Delete 直接回调 scheduler.Schedule/Unschedule
- runner.Start 一次性加载所有 enabled monitor 建立任务表
- 新建/启用立即触发首次检测,禁用/删除即时撤销 ticker
- 保留 inFlight 去重 + pond 池并发上限 + 全局开关每次 fire 实时校验
- 删除 listDueForCheck / monitorTickerInterval / monitorListDueTimeout

前端 - 可用渠道改为用户级菜单
- 从 adminNavItems 移除 /available-channels(admin 主菜单不再重复出现)
- buildSelfNavItems 始终包含可用渠道入口,普通用户主菜单和
  管理员"我的账户"区都能看到
2026-04-22 19:17:08 +08:00
erio a7415d4d2e feat(monitor): 30-day raw retention + timeline 4-tier style + CC template seed + JSON format button
- History retention 1d → 30d(60s × 30d ≈ 43200 行/model,PG 无压力);
  ComputeAvailability* 不再 UNION rollup 表,直接扫 histories 精度更高。
- Timeline bar 四级高度+颜色双重编码:operational 高+绿 / degraded 中+黄 /
  failed+error 短+红 / 未测试 很短+灰。
- migration 113 seed「Claude Code 伪装」模板(ON CONFLICT DO NOTHING)。
  user_id 用 legacy 格式(user_<64hex>_account_<uuid>_session_<uuid>),
  避免新版 JSON 字符串内嵌 JSON 在编辑器里一长串 \" 难读。
- MonitorAdvancedRequestConfig 加「格式化」按钮 + white-space:pre
  让 body textarea 对长字符串不压扁。
2026-04-21 15:24:48 +08:00
erio b363bff1d8 feat(channel-monitor): preserve upstream error body
Monitor:
- callProvider now returns both textPath-extracted text and raw body;
  runCheckForModel uses rawBody on non-2xx so history.message stops being
  "upstream HTTP 503: " with empty body (gjson textPath produces "" for
  error responses like {"error":{"message":"No available accounts..."}})
- truncateForErrorBody collapses whitespace then caps at 300 bytes
  (monitorErrorBodySnippetMaxBytes); final truncateMessage still enforces
  the 500-byte DB column cap

Frontend:
- MonitorFormDialog: primary_model input text color and ModelTagInput tags
  now both track form.provider (via new getPlatformTextClass + existing
  getPlatformTagClass with platform prop).

(cherry-picked from 1d3b0418; dropped gateway_handler logging改动,不在本 PR 范围)
2026-04-21 11:59:11 +08:00
erio 8cf83c984e feat(channel-monitor): aggregate history to daily rollups + soft delete
明细只保留 1 天,超过 1 天聚合到新表 channel_monitor_daily_rollups(按
monitor_id/model/bucket_date 维度),聚合保留 30 天。两张表都用 SoftDeleteMixin
软删除(DELETE 自动改为 UPDATE deleted_at = NOW())。

聚合 + 清理任务由 OpsCleanupService 的 cron 统一调度,与运维监控的清理共享
schedule(默认 0 2 * * *)和 leader lock。ChannelMonitorRunner 的 cleanupLoop
被移除,只保留 dueCheckLoop。

读取路径 ComputeAvailability* 改为 UNION 明细(今天 deleted_at IS NULL)+
聚合(过去 windowDays 天 deleted_at IS NULL),SUM(ok)/SUM(total) 自然加权
计算可用率,AVG latency 用 SUM(sum_latency_ms)/SUM(count_latency)。

watermark 表 channel_monitor_aggregation_watermark 单行(id=1),记录
last_aggregated_date,重启后从该日期 +1 继续聚合,首次为 nil 则从
today - 30d 开始回填,单次最多 35 天上限避免长事务。

raw SQL 的 ListLatestPerModel / ListLatestForMonitorIDs / ListRecentHistoryForMonitors
都补上 deleted_at IS NULL 过滤(SoftDeleteMixin interceptor 只对 ent query 生效)。

bump version to 0.1.114.28

GroupBadge 在 MonitorKeyPickerDialog 中复用平台主题色 + 倍率/专属倍率
(顺手优化)。
2026-04-21 10:10:56 +08:00
erio a1425b457d feat(channel-monitor): redesign user dashboard as card grid
Reference check-cx UI: INTELLIGENCE MONITOR hero + 3-column card grid
with 60-point timeline bars.

Backend:
- Add PrimaryPingLatencyMs + Timeline[60] to UserMonitorView
- ListRecentHistoryForMonitors: batch CTE + ROW_NUMBER() window query
- indexLatestByModel / indexAvailabilityByModel helpers

Frontend:
- 7 new components: ProviderIcon, MonitorMetricPair, MonitorAvailabilityRow,
  MonitorTimeline, MonitorHero, MonitorCard, MonitorCardGrid
- ChannelStatusView 381→~180 lines (delegated to subcomponents)
- AbortController reload concurrency protection
- HSL 0-120° availability color mapping
- Replace emoji with Icon component (bolt / globe)
- i18n: monitorCommon.* shared namespace, channelStatus.hero.*

Bump VERSION to 0.1.114.24
2026-04-20 23:38:59 +08:00
erio 20a4e41872 feat(monitor): admin channel monitor MVP with SSRF protection and batch aggregation
新增 admin「渠道监控」模块(参考 BingZi-233/check-cx),独立于现有 Channel 体系。
admin 配置 + 后台定时调用上游 LLM chat completions 健康检查 + 所有登录用户只读可见。

后端:
- ent: channel_monitor + channel_monitor_history(AES-256-GCM 加密 api_key)
- service 按职责拆分:service/aggregator/validate/checker/runner/ssrf
- provider strategy map 替代 switch(openai/anthropic/gemini)
- repository batch 聚合(ListLatestForMonitorIDs + ComputeAvailabilityForMonitors)消除 N+1
- runner: ticker(5s) + pond worker pool(5) + inFlight 防并发 + TrySubmit 防雪崩
  + 凌晨 3 点 cron 清理 30 天历史
- SSRF 防护:强制 https + 私网/loopback/云元数据 IP 拒绝(127/8、10/8、172.16/12、
  192.168/16、169.254/16、100.64/10、::1、fc00::/7、fe80::/10)+ DialContext
  在 socket 层防 DNS rebinding
- API key sanitize:擦除 url.Error 与上游响应 body 中的 sk-/sk-ant-/AIza/JWT 模式
- APIKeyDecryptFailed 标志位 + 单 monitor 路径检测,避免空 key 调用上游

handler:
- admin: CRUD + 手动触发 + 历史接口(api_key 脱敏)
- user: 只读列表 + 状态详情(去除 api_key/endpoint)
- ParseChannelMonitorID 共用 + dto.ChannelMonitorExtraModelStatus 共用

前端:
- 路由 /admin/channels/{pricing,monitor} + /monitor(用户只读)
- AppSidebar 父项 expandOnly 支持
- ChannelMonitorView 拆为 8 个子组件 + ChannelStatusView 拆出 detail dialog
- composables/useChannelMonitorFormat + constants/channelMonitor 共享
- i18n monitorCommon namespace 消除 admin/user 两 view 重复

合规:所有文件符合 CLAUDE.md(Go ≤ 500 行 / Vue ≤ 300 行 / 函数 ≤ 30 行)
CI: go build / gofmt / golangci-lint(0 issues) / make test-unit / pnpm build 全绿
2026-04-20 20:21:02 +08:00