feat(sync): integrate upstream v0.2.7 while preserving fork features - #133
Conversation
OAuth mimic 路径无条件删除 system[*].cache_control,不打日志也不报错。 把稳定前缀锚在 system 上的客户端因此拿到 cache_creation 与 cache_read 双 0 —— 不是没命中,是连写都没写。 这个动作是 46e5ac9 引进时「system 必然被整个重写」的配套:客户端的 system 内容都搬进 messages 了,残留断点指着空气,删它是对的。后来 system 注入变成可配置,于是长出了原设计里不存在的组合 —— system 没被 重写,断点照删。剥离失去了赖以成立的前提,代码却还在。 三处调用点里 count_tokens 那处还是硬编码 true,与另两处的 !systemRewritten 语义不一致。 直接移除该选项而不是再加一个开关:注入开启时 system 已被整个替换、 留在上面的断点是我们自己拼进去的稳定锚点;注入关闭时断点就是客户端的 缓存意图。两种情形都没有删它的理由,而需要开关的是有取舍的行为。 顺带补上 count_tokens 的 4 块上限兜底:五条出口里只有它没在自己的转发 路径上调过 enforceCacheControlLimit,原先那句 strip 是这条路上唯一压制 断点数量的东西。拿掉之后「客户端 system + 客户端 messages + 刚注入的 tools[-1]」实测顶到 5 块,而上游对超限是 400。 messages 层的同类改写见 Wei-Shaw#2369,那次只落地了 messages 一半。 此前该行为零测试覆盖(stripSystemCacheControl 在 _test.go 里零命中), 本次补 4 个用例,其中上限兜底那条撤掉修复即红。 Claude-Session: https://claude.ai/code/session_01WnTW52pmELGy3g7KPEUXj2
user_platform_quotas 只保存至少配置了一档限额的记录;不存在的行等价于不限额。 - 注册播种只为配置了限额的平台建行,一个都没有时不写入 - IncrementUsageWithReset 无行时不再 fail-open 建行 - BatchSnapshotUsage 改为只更新既有活跃行,不再插入无限额的新行 - 仓储 BulkInsertInitial/UpsertForUser 把三档全空的记录视为未配置; 管理员全量替换接口同样剔除,清空限额即软删并放弃累计用量 - 迁移 238 删除三档全 NULL 的历史行 - 用户仪表盘平台卡片 = 有用量的平台 ∪ 配置了限额的平台,计数改为卡片数 - 管理员限额弹窗对未保存限额的平台禁用"重置窗口"
- flash 低谷价更新为 $0.15/$0.60/$0.003 per MTok(2026-09-10 官方降价) - deepseek-v4-pro 自 2026-09-14 04:00 UTC 起按 Flash 价计费(上游路由变更) - 计费时点显式驱动 pro→Flash 切换,定价展示与计费两条路径同源 - deepseek-flash 保留 reasoning_effort=max;补 Codex 模型清单与前端白名单 - 价表 JSON 新增 deepseek-flash 条目并同步 flash 系价格
后台功能开关页新增「站点类型」单选:充值 & 订阅(默认,即现状)/ 仅充值 / 仅订阅。 它由两个后端开关派生并在保存时同时写回: - subscription_enabled(新增;默认 true,缺省/空值视为开启,仅显式 false 关闭),按既有 开关模式贯通常量、公共设置、SSR 注入载荷、默认值、更新写入、DTO、审计 diff 与前端注册表; - payment_balance_disabled(支付配置里既有的 BALANCE_PAYMENT_DISABLED,此前只能走接口/数据库 改),补进公共设置与注入载荷,让用户端在任何鉴权请求之前就能推导站点类型。 两者都关闭是接口层可表达但 UI 不提供的组合,前端归为「仅充值」,后台保存时会把余额充值重新打开。 「仅充值」时的表现: - 用户侧边栏隐藏「我的订阅」,「充值/订阅」入口收窄为「充值」;管理端侧边栏隐藏「订阅管理」 入口(页面仍可通过地址访问); - 购买页不再渲染「订阅」tab,只剩单个 tab 时顶部切换器随之隐藏;tab 列表变化时当前 tab 自动收敛到可用项(关闭订阅回到充值、仅订阅站点重新打开订阅进入订阅),列表为空时展示 「充值与订阅均暂未开放」而不是一个必定被后端拒绝的充值表单; - /purchase 的页头标题/描述与 document.title 改走 resolveRouteMetaKeys 按站点类型切换; - /subscriptions 路由新增 requiresSubscription 守卫,直达时重定向到仪表盘; - 顶栏订阅进度徽章不再挂载,App.vue、PaymentView 与徽章组件都不再预加载/轮询订阅接口; - 用量页隐藏「计费类型(余额/订阅)」筛选,Key 用量公开页「订阅类型」行改为「计费方式」。 「仅订阅」时侧边栏入口与页头显示为「订阅」,购买页只剩订阅 tab(余额下单由后端既有逻辑拒绝)。 购买订阅接口、已有订阅的计费、兑换码发放订阅与管理端订阅管理页面本身均不受影响。 featureFlags 抽出纯函数 resolveFeatureFlag,新增 utils/siteBillingMode 承载三态派生与反解, PaymentView 测试改用响应式 store mock 覆盖开关双向切换。
prolite -> Pro 5x (violet, same as Pro), pro/chatgptpro -> Pro 20x, self_serve_business_prolite -> Business Premium (indigo, same as Team), team -> Business Standard. The tier naming stays OpenAI-only so Antigravity Pro and Grok pro keep their own labels; planTypeDisplayLabel now shares openAIPlanTypeLabel with PlatformTypeBadge instead of duplicating the mapping, and the manual plan_type dropdown gains the Pro 5x / Business Premium presets.
…6931 feat(gateway): retrieve models from the visible catalogue
…em-cache-control fix(gateway): 不再剥离客户端 system 上的 cache_control / stop stripping client system cache_control
…or-base-path fix(monitor): support upstream base URL paths
…napshot fix(scheduler): preserve threshold metadata
…velope-fields fix(openai): accept full heartbeat bootstrap envelopes
…r-utc-buckets fix: anchor channel monitor date_bin buckets to UTC
…strap fix(setup): avoid hardcoded postgres connection
…t-validation fix: validate Codex User-Agent before identity parsing
…delete-users feat(admin): support deleting selected users
…ription-user-search fix(subscriptions): exclude deleted users from assignment search
Kimi reports Coding Plan window exhaustion (5h/weekly) as a 403 with error.type=access_terminated_error instead of 429. It fell into the generic handleOpenAI403 escalation, so three 403s within 180 minutes permanently disabled accounts that recover by themselves at the window reset. Detect the quota-exhausted 403 for CN coding-plan accounts and cool it down exactly like the 429 path: SetRateLimited until the earliest future window reset from the quota snapshot, falling back to a short temp-unschedulable window when the snapshot is missing. Non-coding-plan accounts keep the generic 403 escalation since the rolling-window recovery mechanism does not apply to them. Also extract cooldownCNProviderToQuotaSnapshotReset and setCNProviderTempUnschedulable so the 429 (OpenCodeGo / Coding Plan) and 403 branches stop carrying three copies of the same sequence. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codex 会把 codex_app 等内置工具的 parameters 根节点声明成对象分支的 oneOf/anyOf,Anthropic 拒绝工具 input_schema 顶层的 oneOf/anyOf/allOf,导致 /v1/responses -> /v1/messages 直接 400。 Responses->Anthropic 转换时摊平顶层联合:属性取各分支并集,同名属性用嵌套联合保留两侧约束,required 在 oneOf/anyOf 下取分支交集、allOf 下取并集;嵌套联合保持不变。
Extend the local plugin system's host<->plugin contract with generic, capability-neutral facilities, so transport plugins can be built on top without embedding plugin-specific logic in the host. Host services (plugin dials a broker-provided HostService gRPC): - per-plugin namespaced KV store (key/value size and TTL bounded) - account directory: ListAccounts + ResolveOutboundIdentity, restricted to the accounts a plugin's declared capability already covers - InitHostServices lifecycle hook; plugins that don't implement it run unchanged and are simply offered no host services Read-only runtime status channel: - HealthResponse gains an opaque, plugin-defined status_json produced passively (no config apply, no upstream call, no side effects) - GET /admin/plugins/:id/status (ungated) and the plugin.status UI-bridge verb map to Health, so a status UI can poll live state without a step-up prompt or a "test" side effect - config.test no longer force-shows a host success toast; the plugin UI owns result presentation, so plugins that read status do not spam toasts Document the UI-bridge verb taxonomy (read vs mutate/test gating) and the status contract under pkg/pluginapi.
…ces-status-bridge feat(plugin): generic host services + read-only status bridge channel
…asoning-content fix(openai): pass DeepSeek thinking-mode reasoning_content on chat fallback
…ot-union-schema fix(apicompat): 摊平 Responses→Anthropic 工具 schema 顶层联合,修复 Codex 内置工具导致的 400
…te-limit-pause fix(ratelimit): CN coding-plan 账号配额耗尽的 403 按限流暂停调度,而非永久禁用
ui(header): 手机竖屏顶栏保留模型广场图标入口
…ini-sse-comment-keepalive fix(antigravity): Gemini 原生流对 go-genai / python-genai 客户端不发 SSE 注释心跳
…ini-bare-model-thinking-variant fix(antigravity): Gemini 原生请求的裸模型名按 thinkingConfig 解析到 -low/-medium/-high 变体
feat: 支持 Seedance / Ark 原生视频任务 API
CatStack-pixe
left a comment
There was a problem hiding this comment.
Independent preservation and integration review of 80a71b6 (including the lint-only cleanup of 5aa5d72).
No remaining P1/P2 findings in the reviewed scope. The review checked custom provider routing and mixed pools, SenseNova cooldowns, model listing/alias configuration versus the independent upstream allowlist, API-key model filtering and ETags, proxy groups, pricing windows, Heartbeat, parallel-tool streaming recovery, WebSocket image usage on disconnect, and migration compatibility.
The preservation scan covered 225 fork-modified/added non-gateway Go files. All 295 historical SQL files remain byte-identical to the fork baseline; the production read-only preflight also found no applied-migration checksum mismatch. New migrations accept the existing provider union and retain model listing JSON independently of request admission policy. The reverse integration scan found all 104 newly introduced upstream function/type declarations in the reviewed conflict files.
Frontend regression/build, generated-source consistency, shell checks, and security scans passed on the preceding revision. Backend unit/integration checks and the latest revision's full checks are still required before merge. This review does not replace those runtime checks.
CatStack-pixe
left a comment
There was a problem hiding this comment.
Final independent review of be0c8ad47628e5c9a2be4d91829f8967338fff33, following the sync label classification.
No outstanding actionable findings in the reviewed scope. All 295 historical SQL files remain byte-identical to fork baseline eff0f5292b12ced80201c219fd097d0025c477bf; the nine added migrations preserve existing columns and custom provider constraints. The preservation audit retained all 540 audited fork struct fields and 259 JSON names, plus schema, route, binding and Heartbeat behavior. Grok's inconclusive-billing change was traced to upstream a774230: the baseline implementation was identical to the previous upstream baseline, so this is an inherited upstream fix rather than a lost fork customization.
Behavioral review covered authoritative cooldowns, mixed provider routing, independent model display/alias and admission settings, API-key model filters/ETags, pricing windows and one-hour cache writes, parallel tool streams, partial usage billing, and upstream timeout versus client cancellation. The final test-fixture changes preserve the fork's actual hard-disable and DeepSeek normalization behavior and retain token-cap/filter assertions. Unit and integration CI jobs run the same targets independently.
GitHub Actions passed all generation, formatting, backend unit, PostgreSQL integration/migration, frontend regression/full tests/build, lint, shell and security checks on this exact head (PR CI 35434473224; security 35434473232; push checks also green). No local Go tooling was used for these checks. Deployment validation remains separate and will verify the published image, protected backup, existing configuration, applied migration checksums, and unchanged PostgreSQL/Redis containers.
|
Release and deployment completed for The final squash tree matches the reviewed PR head exactly. Main/tag CI and security checks passed; Release workflow 35434950566 successfully published and inspected the GHCR amd64 image. Production verification passed: image version/full revision/digest, application health, applied migration checksums, existing group configuration/account mappings/API-key whitelist fingerprints, and unchanged PostgreSQL/Redis containers. A protected PostgreSQL archive and configuration backup were validated before application-only replacement. OpenAI and Kimi model-list smoke requests returned 200 with valid JSON and no duplicates; no paid inference was requested. |
Integrate upstream v0.2.7 on fork baseline
eff0f5292b12ced80201c219fd097d0025c477bfand set the application version to0.2.7-harbor.1. Retain the fork's custom providers, compatible mixed account pools, provider quota handling, proxy groups, Heartbeat, model aliases, and pricing windows.Keep existing model listing/alias configuration independent of the new group request allowlist, which defaults to disabled. Preserve all 295 historical SQL files byte-for-byte; new migrations accept existing custom provider rows and preserve model listing JSON. Record the integrated upstream commit and fork baseline in
.github/upstream-sync.jsonso future synchronization can recover the correct baseline after squash merges.Resolve integration conflicts while preserving SenseNova's minimum five-minute cooldown, authoritative runtime cooldowns, API-key model filtering/ETags, observed-tier billing, and existing Kimi adaptive routing. Combine upstream stream completion handling with parallel tools, disconnect usage accounting, watchdogs, and proxy quarantine. Support independent one-hour cache-write prices alongside the fork's pricing windows.
Validation passed on
be0c8ad47628e5c9a2be4d91829f8967338fff33: Ent/Wire generation and formatting consistency, backend unit tests, PostgreSQL integration/migration tests, frontend regression/full tests/build, lint, shell checks, and security scans. PR CI and security scan are green; push checks passed as well. No local Go toolchain is used for this validation. Independent preservation and behavioral reviews are recorded on this PR.