- 23 Apr, 2026 5 commits
-
-
erio authored
-
erio authored
-
erio authored
- Change overall status logic: >50% failed = UNAVAILABLE, any failed or degraded = DEGRADED, all ok = OPERATIONAL - Extract useAutoRefresh composable with localStorage persistence - Create AutoRefreshButton dropdown component (reusable) - Integrate auto-refresh into channel status page via MonitorHero
-
erio authored
Revert payment/wechat, sora/claude-max cleanup, fork-only migrations, and cosmetic changes that were brought in by the release sync commit. Keep only channel-monitor related improvements: - PublicSettingsInjectionPayload named struct with drift test - ChannelMonitorRunner graceful shutdown in wire - image_output_price in SupportedModelChip - Simplified buildSelfNavItems in AppSidebar - Gateway WARN logs for 503 branches
-
erio authored
- Extract PublicSettingsInjectionPayload named struct with drift test - Add channel_monitor_default_interval_seconds to SSR injection - Add image_output_price to SupportedModelChip - Simplify AppSidebar buildSelfNavItems (admins see available channels) - Add gateway WARN logs for 503 no-available-accounts branches - Wire ChannelMonitorRunner into provideCleanup for graceful shutdown - Add migrations 130/131 (CC template userid fix + mimicry field cleanup) - Clean up fork-only features (sora, claude max simulation, client affinity) - Remove ~320 obsolete i18n keys - Add codexUsage utility, WechatServiceButton, BulkEditAccountModal - Tidy go.sum
-
- 22 Apr, 2026 5 commits
-
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
- 21 Apr, 2026 6 commits
-
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
- 22 Apr, 2026 1 commit
-
-
erio authored
- 描述独立成列:渠道名与描述各占一列,均用 rowspan 纵向合并 - 渠道名单元格 text-center + align-middle,合并后视觉居中 - table-fixed:给 name/description/platform 显式宽度,groups 和 supported_models 在剩余空间均分。支持模型列此前在 table-auto 下 不会换行导致横向溢出遮挡(反馈截图),加 table-fixed 后天然 flex-wrap - i18n 增加 availableChannels.columns.description(zh/en)
-
- 21 Apr, 2026 5 commits
-
-
erio authored
Pricing popover: - Teleport to body + fixed-position re-measuring on hover/scroll/resize so it escapes the card's overflow-hidden clip that was chopping off the lower half of the panel. - Header + border adopt the platform theme via platformBorderClass / platformBadgeLightClass so each model card reads at a glance. Accessible groups: - Backend AvailableGroupRef / user DTO now expose subscription_type, rate_multiplier and is_exclusive. User-specific rates continue to come from /groups/rates (same pattern as the API keys page). - Table renders groups through the shared GroupBadge, which already deepens subscription-type colors and shows default vs custom rate as <s>default</s> <b>custom</b>. - Exclusive groups are labelled with a purple shield row, public groups with a grey globe row so admins and users can tell at a glance which groups they got via explicit grant vs. public access. i18n keys for exclusive / public / their tooltips added to zh + en.
-
erio authored
Switch the user-facing 'Available Channels' view from "one row per platform" to "one channel row-group with N platform sections". Backend: userAvailableChannel now holds Platforms []section instead of being exploded. buildPlatformSections replaces explodeChannelByPlatform with the same per-platform grouping logic. Frontend: drop the DataTable wrapper for this view and write a four-column grid table (渠道名 / 平台 / 分组 / 支持模型) where the channel name only renders on the first platform row of each channel — visual rowspan without hacking DataTable. - api/channels.ts: UserChannelPlatformSection + platforms[] - AvailableChannelsTable: rewritten as native grid (header + per- channel section with hover row highlight) - AvailableChannelsView: search now filters platforms sub-array; channel-name / description hits still keep the whole channel - i18n: add availableChannels.columns.platform (zh/en)
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
- 20 Apr, 2026 18 commits
-
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-
erio authored
Add a read-only aggregate view per channel: its linked groups and a deterministic wildcard-free supported-model list with pricing details. Backend - service.Channel.SupportedModels(): combine ModelMapping keys with same-platform ModelPricing.Models; trailing "*" keys expand via pricing prefix match; platforms without a mapping produce no entries (intentional "no mapping = not shown" rule). - Extract splitWildcardSuffix() shared with toModelEntry. - Build a per-call pricing lookup map (platform+lowerName -> *pricing) to avoid O(N*M) scans in SupportedModels. - ChannelService.ListAvailable() aggregates channels + active groups; filters out group IDs no longer active. - Admin route GET /api/v1/admin/channels/available returns the full DTO (id, status, billing_model_source, restrict_models, groups, supported_models). - User route GET /api/v1/channels/available applies three filters: Status==active, visible-group intersection, and platform filter on supported_models (prevents cross-platform leak when a channel links to both a user-accessible group and an inaccessible one on another platform). Response is a plain array (matches the /groups/available sibling shape). Field whitelist omits billing_model_source, restrict_models, ids, status, sort_order. Frontend - New /admin/available-channels and /available-channels views backed by a shared AvailableChannelsTable component (admin adds status + billing-source columns via slots). - PricingRow extracted to its own SFC; SupportedModelChip references shared billing-mode constants in constants/channel.ts. - Sidebar: new entry above "渠道管理" for admin; matching entry in user nav. - i18n: zh + en coverage for both namespaces. Tests - SupportedModels: wildcard-only pricing skipped, prefix-matches- nothing, cross-platform bleed, case-insensitive dedup, empty platform mapping. - ListAvailable: nil groupRepo, inactive-group-ID dropped, stable case-insensitive name sort. - User handler: 401 on unauthenticated, visible-group intersection, platform filter on supported_models, JSON whitelist. - Admin handler: full DTO including default BillingModelSource fallback. Refs: issue #1729
-
erio authored
- AppSidebar 三处菜单项(管理端渠道监控、用户端/个人页渠道状态)按 channel_monitor_enabled 条件展开,关闭时隐藏 - ChannelStatusView setInterval 随开关启停:关闭 clearInterval, 开启/未知态自动启动,避免禁用功能后仍在轮询 - MonitorFormDialog provider Select 改为 3 色单选按钮 (openai=emerald / anthropic=orange / gemini=sky),i18n 文案 供应商 → 平台 / Provider → Platform - MonitorKeyPickerDialog 按钮列表改为 name/key/group 三列表格 + 搜索框,按 key.group.platform === provider 过滤,避免跨平台误选 - form.provider 变化时清空 api_key,修复切换平台仍保留旧 key 的 错配 bug - providerPickerClass 抽取到 useChannelMonitorFormat composable, 统一 emerald/orange/sky 颜色语义,消除硬编码 Tailwind class 重复 - maskApiKey 工具函数统一(utils/maskApiKey.ts),KeysView 与 MonitorKeyPickerDialog 共用 slice(0,6)...slice(-4) 策略 - bump version to 0.1.114.27
-
IanShaw027 authored
-
IanShaw027 authored
-
erio authored
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
-
IanShaw027 authored
-
IanShaw027 authored
-
erio authored
Pairs with the backend structured payment errors (reason + metadata). The frontend now maps reason codes to localized messages with metadata as interpolation variables, and automatically localizes raw config-field names (e.g. "certSerial" → "证书序列号") using the existing UI-label i18n namespace. - frontend/src/utils/apiError.ts - extractApiErrorCode now prefers the string `reason` over the numeric HTTP `code`; reason is granular enough to drive i18n lookup, HTTP code is not. - New extractApiErrorMetadata to pull interpolation params off the error. - New extractI18nErrorMessage(err, t, namespace, fallback): looks up `<namespace>.<REASON>` in i18n and substitutes metadata. Before substitution, `metadata.key` and `metadata.keys` (slash-joined) are re-translated through `admin.settings.payment.field_<key>` so users see "缺少必填项:证书序列号" instead of "缺少必填项:certSerial". - frontend/src/i18n/locales/{zh,en}.ts - Add payment.errors entries for every structured reason code returned by the backend (PAYMENT_DISABLED, INVALID_AMOUNT, TOO_MANY_PENDING, DAILY_LIMIT_EXCEEDED, NO_AVAILABLE_INSTANCE, PAYMENT_PROVIDER_MISCONFIGURED, WXPAY_CONFIG_MISSING_KEY / INVALID_KEY_LENGTH / INVALID_KEY, NOT_FOUND, FORBIDDEN, CONFLICT, INVALID_ORDER_TYPE, INVALID_STATUS, BALANCE_NOT_ENOUGH, REFUND_AMOUNT_EXCEEDED, REFUND_FAILED, and more), with placeholders for template variables. - 13 payment-related Vue files - Migrate catch-block error reporting from extractApiErrorMessage to extractI18nErrorMessage(err, t, 'payment.errors', fallback). - Remove the ad-hoc paymentErrorMap computed in SettingsView.vue, which the new helper supersedes (it reads i18n directly via t). - frontend/src/components/payment/providerConfig.ts - wxpay: publicKey and publicKeyId are now required (was optional), matching the pubkey-only verifier direction; certSerial is already required. This PR is drop-in safe: reason-preferring extractApiErrorCode is backward compatible with callers that pass their own i18nMap, and error codes missing from i18n fall back to the existing message-based path. -
IanShaw027 authored
-
erio authored
新增 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 全绿 -
IanShaw027 authored
-
IanShaw027 authored
-
IanShaw027 authored
-